All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/6] OMAP4: Temperature sensor driver
@ 2011-08-10 12:37 ` Keerthy
  0 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:25 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

Hello,

The rfc patch series for the on die temperature sensor driver. I need
feedback on the overall structure of the driver.
The rfc patch set has the device file, omap4 on die temperature sensor
hwmon driver. hwmod, clk support. The patch set compiles
on top of LO tree Master branch.

This patch series is tested for boot-up on OMAP4460. The temperature
reading and the interrupts generation on crossing the temperature
thresholds also tested.

Keerthy (6):
  OMAP4: Clock: Associate clocks for OMAP temperature sensor
  OMAP4: Adding the temperature sensor register set bit fields
  OMAP4: Hwmod: OMAP temperature sensor
  OMAP4: Temperature sensor device support
  OMAP4460: Temperature sensor data
  OMAP4: On die temperature sensor driver

 arch/arm/mach-omap2/Makefile                       |    3 +-
 arch/arm/mach-omap2/clock44xx_data.c               |    2 +-
 .../include/mach/ctrl_module_core_44xx.h           |   70 ++-
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |   61 ++
 arch/arm/mach-omap2/temp_sensor4460_data.c         |   63 ++
 arch/arm/mach-omap2/temp_sensor_device.c           |   85 ++
 arch/arm/plat-omap/Kconfig                         |   12 +
 .../plat-omap/include/plat/temperature_sensor.h    |   87 ++
 drivers/hwmon/Kconfig                              |   11 +
 drivers/hwmon/Makefile                             |    1 +
 drivers/hwmon/omap_temp_sensor.c                   |  950 ++++++++++++++++++++
 11 files changed, 1330 insertions(+), 15 deletions(-)
 create mode 100644 arch/arm/mach-omap2/temp_sensor4460_data.c
 create mode 100644 arch/arm/mach-omap2/temp_sensor_device.c
 create mode 100644 arch/arm/plat-omap/include/plat/temperature_sensor.h
 create mode 100644 drivers/hwmon/omap_temp_sensor.c


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 1/6] OMAP4: Clock: Associate clocks for OMAP temperature sensor
  2011-08-10 12:37 ` [lm-sensors] " Keerthy
@ 2011-08-10 12:37   ` Keerthy
  -1 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:25 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

div_ts_ck feeds only the temperature sensor functional clock
and also has a clksel associated (for divider selection). Mapping this
as the functional clock for the temperature sensor in clkdev table,
so a clk_set_rate() in the driver would have the effect of changing the
temperature sensor clock rate indirectly.

Reviewd-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 arch/arm/mach-omap2/clock44xx_data.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 2af0e3f..4a788f4 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3187,7 +3187,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"bandgap_fclk",			&bandgap_fclk,	CK_443X),
 	CLK(NULL,	"bandgap_ts_fclk",		&bandgap_ts_fclk,	CK_446X),
 	CLK(NULL,	"des3des_fck",			&des3des_fck,	CK_443X),
-	CLK(NULL,	"div_ts_ck",			&div_ts_ck,	CK_446X),
+	CLK("omap_temp_sensor.0",	"fck",			&div_ts_ck,	CK_446X),
 	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
 	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [RFC PATCH 2/6] OMAP4: Adding the temperature sensor register set bit fields
  2011-08-10 12:37 ` [lm-sensors] " Keerthy
@ 2011-08-10 12:37   ` Keerthy
  -1 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:25 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

OMAP4460 specific temperature sensor register bit fields are added.

Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 .../include/mach/ctrl_module_core_44xx.h           |   70 ++++++++++++++++----
 1 files changed, 57 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
index 2f7ac70..725c1e1 100644
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
@@ -256,19 +256,63 @@
 #define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT	0
 #define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
 
-/* TEMP_SENSOR */
-#define OMAP4_BGAP_TEMPSOFF_SHIFT			12
-#define OMAP4_BGAP_TEMPSOFF_MASK			(1 << 12)
-#define OMAP4_BGAP_TSHUT_SHIFT				11
-#define OMAP4_BGAP_TSHUT_MASK				(1 << 11)
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1 << 10)
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT		9
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK			(1 << 9)
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
+/* 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		(0x3ff << 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)
 
 /* DPLL_NWELL_TRIM_0 */
 #define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT	29
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [RFC PATCH 3/6] OMAP4: Hwmod: OMAP temperature sensor
  2011-08-10 12:37 ` [lm-sensors] " Keerthy
@ 2011-08-10 12:37   ` Keerthy
  -1 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:25 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

From: Benoit Cousson <b-cousson@ti.com>

OMAP4460 temperature sensor hwmod cannot be auto generated
since it is part of ctrl module. Hence populating the
necessary hwmod info manually.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   61 ++++++++++++++++++++++++++++
 1 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6201422..28bf6d3 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -29,6 +29,7 @@
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
 #include <plat/i2c.h>
+#include <plat/temperature_sensor.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -832,6 +833,63 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
 };
 
 /*
+ * 'temperature_sensor' class
+ * temperature sensor module inside the bandgap / control module
+ */
+
+static struct omap_hwmod_class omap44xx_temperature_sensor_hwmod_class = {
+	.name   = "temperature_sensor",
+};
+
+static struct omap_hwmod_irq_info omap44xx_temperature_sensor_irqs[] = {
+	{ .name = "thermal_alert", .irq = 126 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_temperature_sensor_addrs[] = {
+	{
+		.pa_start       = 0x4a00232c,
+		.pa_end         = 0x4a00238b,
+	},
+};
+
+static struct omap_hwmod omap44xx_temperature_sensor_hwmod;
+/* l4_cfg -> ctrl_module_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__temperature_sensor = {
+	.master         = &omap44xx_l4_cfg_hwmod,
+	.slave          = &omap44xx_temperature_sensor_hwmod,
+	.clk            = "l4_div_ck",
+	.addr           = omap44xx_temperature_sensor_addrs,
+	.user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ctrl_module_core slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_temperature_sensor_slaves[] = {
+	&omap44xx_l4_cfg__temperature_sensor,
+};
+
+/* temperature sensor dev_attr */
+static struct omap_temp_sensor_dev_attr temp_sensor_dev_attr = {
+	.name	= "mpu",
+};
+
+static struct omap_hwmod omap44xx_temperature_sensor_hwmod = {
+	.name           = "temperature_sensor_mpu",
+	.class          = &omap44xx_temperature_sensor_hwmod_class,
+	.mpu_irqs       = omap44xx_temperature_sensor_irqs,
+	.main_clk       = "bandgap_ts_fclk",
+	.slaves		= omap44xx_temperature_sensor_slaves,
+	.slaves_cnt     = ARRAY_SIZE(omap44xx_temperature_sensor_slaves),
+	.clkdm_name     = "l4_wkup_clkdm",
+	.prcm           = {
+		.omap4 = {
+		.clkctrl_offs = OMAP4_CM_WKUP_BANDGAP_CLKCTRL_OFFSET,
+		},
+	},
+	.dev_attr	= &temp_sensor_dev_attr,
+	.omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'bandgap' class
  * bangap reference for ldo regulators
  */
@@ -5469,6 +5527,9 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	&omap44xx_timer10_hwmod,
 	&omap44xx_timer11_hwmod,
 
+	/* temperature sensor hwmod */
+	&omap44xx_temperature_sensor_hwmod,
+
 	/* uart class */
 	&omap44xx_uart1_hwmod,
 	&omap44xx_uart2_hwmod,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-10 12:37 ` [lm-sensors] " Keerthy
@ 2011-08-10 12:37   ` Keerthy
  -1 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:25 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

The device file adds the device support for OMAP4
on die temperature sensor.

Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 arch/arm/mach-omap2/Makefile                       |    3 +-
 arch/arm/mach-omap2/temp_sensor_device.c           |   85 +++++++++++++++++++
 arch/arm/plat-omap/Kconfig                         |   12 +++
 .../plat-omap/include/plat/temperature_sensor.h    |   87 ++++++++++++++++++++
 4 files changed, 186 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/temp_sensor_device.c
 create mode 100644 arch/arm/plat-omap/include/plat/temperature_sensor.h

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index fb02937..5812fb4 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
+obj-$(CONFIG_OMAP_TEMP_SENSOR)          += temp_sensor_device.o
 obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
 
 # SMP support ONLY available for OMAP4
@@ -86,7 +87,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
 obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
 					   cm44xx.o prcm_mpu44xx.o \
 					   prminst44xx.o vc44xx_data.o \
-					   vp44xx_data.o
+					   vp44xx_data.o temp_sensor4460_data.o
 
 # OMAP voltage domains
 ifeq ($(CONFIG_PM),y)
diff --git a/arch/arm/mach-omap2/temp_sensor_device.c b/arch/arm/mach-omap2/temp_sensor_device.c
new file mode 100644
index 0000000..5d5e92f
--- /dev/null
+++ b/arch/arm/mach-omap2/temp_sensor_device.c
@@ -0,0 +1,85 @@
+/*
+ * OMAP on die Temperature sensor device file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@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/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <plat/omap_device.h>
+#include "control.h"
+#include "pm.h"
+#include <plat/temperature_sensor.h>
+
+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
+	{
+	 .deactivate_func = omap_device_idle_hwmods,
+	 .activate_func = omap_device_enable_hwmods,
+	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};
+
+static int temp_sensor_dev_init(struct omap_hwmod *oh, void *user)
+{
+	struct	omap_temp_sensor_pdata		*temp_sensor_pdata;
+	struct	omap_device			*od;
+	struct	omap_temp_sensor_dev_attr	*temp_sensor_dev_attr;
+	int					ret;
+	static int				device_count;
+
+	ret = 0;
+	temp_sensor_pdata =
+	    kzalloc(sizeof(*temp_sensor_pdata), GFP_KERNEL);
+	if (!temp_sensor_pdata) {
+		dev_err(&oh->od->pdev.dev,
+			"Unable to allocate memory for temp sensor pdata\n");
+		return -ENOMEM;
+	}
+
+	temp_sensor_dev_attr = oh->dev_attr;
+	if (!strcmp(temp_sensor_dev_attr->name, "mpu"))
+		temp_sensor_pdata->registers = &omap_mpu_temp_sensor_registers;
+
+	od = omap_device_build("omap_temp_sensor", device_count++,
+		oh, temp_sensor_pdata, sizeof(*temp_sensor_pdata),
+	       omap_temp_sensor_latency,
+			ARRAY_SIZE(omap_temp_sensor_latency), 0);
+	if (IS_ERR(od)) {
+		dev_warn(&oh->od->pdev.dev,
+			"Could not build omap_device for %s\n", oh->name);
+		ret = PTR_ERR(od);
+	}
+
+	kfree(temp_sensor_pdata);
+
+	return ret;
+}
+
+int __init omap_devinit_temp_sensor(void)
+{
+	if (!cpu_is_omap446x())
+		return 0;
+
+	return omap_hwmod_for_each_by_class("temperature_sensor",
+			temp_sensor_dev_init, NULL);
+}
+
+arch_initcall(omap_devinit_temp_sensor);
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 6e6735f..8fd8e80 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -115,6 +115,18 @@ config OMAP_MCBSP
 	  Say Y here if you want support for the OMAP Multichannel
 	  Buffered Serial Port.
 
+config OMAP_TEMP_SENSOR
+	bool "OMAP Temp Sensor Support"
+	depends on ARCH_OMAP
+	default n
+	help
+	  Say Y here if you want support for the temp sensor
+	  on OMAP4460.
+
+	  This provides the temperature of the MPU
+	  subsystem. Only one instance of on die temperature
+	  sensor is present.
+
 config OMAP_MBOX_FWK
 	tristate "Mailbox framework support"
 	depends on ARCH_OMAP
diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
new file mode 100644
index 0000000..692ebdc
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
@@ -0,0 +1,87 @@
+/*
+ * OMAP Temperature sensor header file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
+
+/* Offsets from the base of temperature sensor registers */
+
+#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET	0x00
+#define OMAP4460_BGAP_CTRL_OFFSET		0x4c
+#define OMAP4460_BGAP_COUNTER_OFFSET		0x50
+#define OMAP4460_BGAP_THRESHOLD_OFFSET		0x54
+#define OMAP4460_BGAP_TSHUT_OFFSET		0x58
+#define OMAP4460_BGAP_STATUS_OFFSET		0x5c
+#define OMAP4460_FUSE_OPP_BGAP			-0xcc
+
+struct omap_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	thsut_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;
+};
+
+/*
+ * @name: Name of the domain of the temperature sensor
+ */
+struct omap_temp_sensor_dev_attr {
+	const char *name;
+};
+
+extern struct omap_temp_sensor_registers omap_mpu_temp_sensor_registers;
+
+/*
+ * omap_temp_sensor platform data
+ * @registers - pointer to register set and thier bit fields information
+ */
+struct omap_temp_sensor_pdata {
+	struct omap_temp_sensor_registers *registers;
+};
+
+#endif
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [RFC PATCH 5/6] OMAP4460: Temperature sensor data
  2011-08-10 12:37 ` [lm-sensors] " Keerthy
@ 2011-08-10 12:37   ` Keerthy
  -1 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:25 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

The register set and the
bit fields might vary across OMAP versions. Hence
creating a structure comprising of all the registers
and bit fields to make the driver uniform for all the
versions with different register sets. The data file
contains the structure populated with register offsets
and bit fields corresponding to OMAP4460 on die sensor.

Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 arch/arm/mach-omap2/temp_sensor4460_data.c |   63 ++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/temp_sensor4460_data.c

diff --git a/arch/arm/mach-omap2/temp_sensor4460_data.c b/arch/arm/mach-omap2/temp_sensor4460_data.c
new file mode 100644
index 0000000..294963d
--- /dev/null
+++ b/arch/arm/mach-omap2/temp_sensor4460_data.c
@@ -0,0 +1,63 @@
+/*
+ * OMAP4460 on die Temperature sensor data file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@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/slab.h>
+#include "control.h"
+#include <plat/temperature_sensor.h>
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+struct omap_temp_sensor_registers omap_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,
+
+	.thsut_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,
+};
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-10 12:37 ` [lm-sensors] " Keerthy
@ 2011-08-10 12:37   ` Keerthy
  -1 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:25 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

On chip temperature sensor driver. The driver monitors the temperature of
the MPU subsystem of the OMAP4. It sends notifications to the user space if
the temperature crosses user defined thresholds via kobject_uevent interface.
The user is allowed to configure the temperature thresholds vis sysfs nodes
exposed using hwmon interface.

Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 drivers/hwmon/Kconfig            |   11 +
 drivers/hwmon/Makefile           |    1 +
 drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 962 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/omap_temp_sensor.c

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5f888f7..9c9cd8b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -323,6 +323,17 @@ config SENSORS_F71805F
 	  This driver can also be built as a module.  If so, the module
 	  will be called f71805f.
 
+config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
+	bool "OMAP on-die temperature sensor hwmon driver"
+	depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
+	help
+	  If you say yes here you get support for hardware
+	  monitoring features of the OMAP on die temperature
+	  sensor.
+
+	  Continuous conversion programmable delay
+	  mode is used for temperature conversion.
+
 config SENSORS_F71882FG
 	tristate "Fintek F71882FG and compatibles"
 	help
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 28061cf..d0f89f5 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
 obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
+obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
new file mode 100644
index 0000000..15e2559
--- /dev/null
+++ b/drivers/hwmon/omap_temp_sensor.c
@@ -0,0 +1,950 @@
+/*
+ * OMAP4 Temperature sensor driver file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@ti.com>
+ * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <plat/omap_device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/stddef.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <plat/common.h>
+#include <plat/temperature_sensor.h>
+#include <mach/ctrl_module_core_44xx.h>
+#include <mach/gpio.h>
+
+#define TSHUT_THRESHOLD_HOT	122000	/* 122 deg C */
+#define TSHUT_THRESHOLD_COLD	100000	/* 100 deg C */
+#define BGAP_THRESHOLD_T_HOT	73000	/* 73 deg C */
+#define BGAP_THRESHOLD_T_COLD	71000	/* 71 deg C */
+#define OMAP_ADC_START_VALUE	530
+#define OMAP_ADC_END_VALUE	923
+
+/*
+ * omap_temp_sensor structure
+ * @hwmon_dev - device pointer
+ * @clock - Clock pointer
+ * @registers - Pointer to structure with register offsets and bitfields
+ * @sensor_mutex - Mutex for sysfs, irq and PM
+ * @irq - MPU Irq number for thermal alert
+ * @phy_base - Physical base of the temp I/O
+ * @clk_rate - Holds current clock rate
+ * @temp_sensor_ctrl - temp sensor control register value
+ * @bg_ctrl - bandgap ctrl register value
+ * @bg_counter - bandgap counter value
+ * @bg_threshold - bandgap threshold register value
+ * @temp_sensor_tshut_threshold - bandgap tshut register value
+ * @is_efuse_valid - Flag to determine if efuse is valid or not
+ * @clk_on - Manages the current clock state
+ */
+struct omap_temp_sensor {
+	struct device		*hwmon_dev;
+	struct clk		*clock;
+	struct omap_temp_sensor_registers *registers;
+	struct mutex		sensor_mutex; /* Mutex for sysfs, irq and PM */
+	unsigned int		irq;
+	void __iomem		*phy_base;
+	u32			clk_rate;
+	u32			temp_sensor_ctrl;
+	u32			bg_ctrl;
+	u32			bg_counter;
+	u32			bg_threshold;
+	u32			temp_sensor_tshut_threshold;
+	bool                    is_efuse_valid;
+	bool                    clk_on;
+};
+
+/*
+ * Temperature values in milli degree celsius
+ * ADC code values from 530 to 923
+ */
+static int adc_to_temp[] = {
+	-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
+};
+
+static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
+					    *temp_sensor, u32 reg)
+{
+	return __raw_readl(temp_sensor->phy_base + reg);
+}
+
+static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
+				    u32 val, u32 reg)
+{
+	__raw_writel(val, (temp_sensor->phy_base + reg));
+}
+
+static int adc_to_temp_conversion(int adc_val)
+{
+	return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
+}
+
+static int temp_to_adc_conversion(long temp)
+{
+	int i;
+
+	for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
+		if (temp < adc_to_temp[i])
+			return OMAP_ADC_START_VALUE + i - 1;
+
+	return -EINVAL;
+}
+
+static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
+						  *temp_sensor)
+{
+	u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
+
+	t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
+	t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
+
+	/* Configure the TALERT thresholds */
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
+		(t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
+	omap_temp_sensor_writel(temp_sensor, temp,
+		temp_sensor->registers->bgap_threshold);
+
+	tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
+	tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
+
+	/* Configure the TSHUT thresholds */
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->thsut_threshold);
+	temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
+	    | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
+	omap_temp_sensor_writel(temp_sensor, temp,
+			temp_sensor->registers->thsut_threshold);
+}
+
+static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
+					       *temp_sensor, u32 counter)
+{
+	u32 val;
+
+	val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_counter);
+	val &= ~(temp_sensor->registers->counter_mask);
+	val |= (counter << __ffs(temp_sensor->registers->counter_mask));
+	omap_temp_sensor_writel(temp_sensor, val,
+			temp_sensor->registers->bgap_counter);
+}
+
+static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
+					bool enable)
+{
+	u32 val;
+
+	val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_mode_ctrl);
+
+	if (enable)
+		val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
+	else
+		val &= ~(temp_sensor->registers->mode_ctrl_mask);
+
+	omap_temp_sensor_writel(temp_sensor, val,
+			temp_sensor->registers->bgap_mode_ctrl);
+}
+
+/* Sysfs hook functions */
+
+static ssize_t show_temp_max(struct device *dev,
+			struct device_attribute *devattr, char *buf)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+	int temp;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	temp = (temp & temp_sensor->registers->threshold_thot_mask)
+			>> __ffs(temp_sensor->registers->threshold_thot_mask);
+
+	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
+		dev_err(dev, "invalid value\n");
+		goto out;
+	}
+	temp = adc_to_temp_conversion(temp);
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+
+	return snprintf(buf, 16, "%d\n", temp);
+}
+
+static ssize_t set_temp_max(struct device *dev,
+			    struct device_attribute *devattr,
+			    const char *buf, size_t count)
+{
+	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
+	long			val;
+	u32			reg_val, t_cold, t_hot, temp;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	if (strict_strtol(buf, 10, &val)) {
+		count = -EINVAL;
+		goto out;
+	}
+
+	t_hot = temp_to_adc_conversion(val);
+	if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
+		dev_err(dev, "invalid range\n");
+		count = -EINVAL;
+		goto out;
+	}
+
+	/* obtain the T cold value */
+	t_cold = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
+			__ffs(temp_sensor->registers->threshold_tcold_mask);
+
+	if (t_hot < t_cold) {
+		dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
+		count = -EINVAL;
+		goto out;
+	}
+
+	/* write the new t_hot value */
+	reg_val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
+	reg_val |= (t_hot <<
+			__ffs(temp_sensor->registers->threshold_thot_mask));
+	omap_temp_sensor_writel(temp_sensor, reg_val,
+			temp_sensor->registers->bgap_threshold);
+
+	/* Read the current temperature */
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->temp_sensor_ctrl);
+	temp &= (temp_sensor->registers->bgap_dtemp_mask);
+
+	/*
+	 * If user sets the HIGH threshold(t_hot) greater than the current
+	 * temperature(temp) unmask the HOT interrupts
+	 */
+	if (t_hot > temp) {
+		reg_val = omap_temp_sensor_readl(temp_sensor,
+				temp_sensor->registers->bgap_mask_ctrl);
+		reg_val &= ~(temp_sensor->registers->mask_cold_mask);
+		reg_val |= temp_sensor->registers->mask_hot_mask;
+		omap_temp_sensor_writel(temp_sensor, reg_val,
+				temp_sensor->registers->bgap_mask_ctrl);
+	}
+
+	/*
+	 * If current temperature is in-between the hot and cold thresholds,
+	 * Enable both masks.
+	 */
+	if (temp > t_cold && temp < t_hot) {
+		reg_val = omap_temp_sensor_readl(temp_sensor,
+				temp_sensor->registers->bgap_mask_ctrl);
+		reg_val |= temp_sensor->registers->mask_cold_mask;
+		reg_val |= temp_sensor->registers->mask_hot_mask;
+		omap_temp_sensor_writel(temp_sensor, reg_val,
+				OMAP4460_BGAP_CTRL_OFFSET);
+	}
+	/*
+	 * else no need to do anything since HW will immediately compare
+	 * the new threshold and generate interrupt accordingly
+	 */
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	return count;
+}
+
+static ssize_t show_temp_max_hyst(struct device *dev,
+		struct device_attribute *devattr, char *buf)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+	u32			temp;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_threshold);
+	temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
+		__ffs(temp_sensor->registers->threshold_tcold_mask);
+
+	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
+		dev_err(dev, "invalid value\n");
+		goto out;
+	}
+
+	temp = adc_to_temp_conversion(temp);
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+
+	return snprintf(buf, 16, "%d\n", temp);
+}
+
+static ssize_t set_temp_max_hyst(struct device *dev,
+				 struct device_attribute *devattr,
+				 const char *buf, size_t count)
+{
+	struct omap_temp_sensor		*temp_sensor = dev_get_drvdata(dev);
+	u32				reg_val, t_hot, t_cold, temp;
+	long				val;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	if (strict_strtol(buf, 10, &val)) {
+		count = -EINVAL;
+		goto out;
+	}
+
+	t_cold = temp_to_adc_conversion(val);
+	if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
+		dev_err(dev, "invalid range");
+		count = -EINVAL;
+		goto out;
+	}
+
+	/* obtain the T HOT value */
+	t_hot = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
+			__ffs(temp_sensor->registers->threshold_thot_mask);
+
+	if (t_cold > t_hot) {
+		dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
+		count = -EINVAL;
+		goto out;
+	}
+
+	/* write the new t_cold value */
+	reg_val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
+	reg_val |= (t_cold <<
+			__ffs(temp_sensor->registers->threshold_tcold_mask));
+	omap_temp_sensor_writel(temp_sensor, reg_val,
+			temp_sensor->registers->bgap_threshold);
+
+	/* Read the current temperature */
+	temp = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->temp_sensor_ctrl);
+	temp &= (temp_sensor->registers->bgap_dtemp_mask);
+
+	/*
+	 * If user sets the LOW threshold(t_cold) lower than the current
+	 * temperature(temp) unmask the COLD interrupts
+	 */
+	if (t_cold < temp) {
+		reg_val = omap_temp_sensor_readl(temp_sensor,
+				temp_sensor->registers->bgap_mask_ctrl);
+		reg_val &= ~(temp_sensor->registers->mask_hot_mask);
+		reg_val |= temp_sensor->registers->mask_cold_mask;
+		omap_temp_sensor_writel(temp_sensor, reg_val,
+			temp_sensor->registers->bgap_mask_ctrl);
+	}
+
+	/*
+	 * If current temperature is in-between the hot and cold thresholds,
+	 * Enable both masks.
+	 */
+	if (temp < t_hot && temp > t_cold) {
+		reg_val = omap_temp_sensor_readl(temp_sensor,
+				temp_sensor->registers->bgap_mask_ctrl);
+		reg_val |= temp_sensor->registers->mask_cold_mask;
+		reg_val |= temp_sensor->registers->mask_hot_mask;
+		omap_temp_sensor_writel(temp_sensor, reg_val,
+				temp_sensor->registers->bgap_mask_ctrl);
+	}
+
+	/*
+	 * else no need to do anything since HW will immediately compare
+	 * the new threshold and generate interrupt accordingly
+	 */
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	return count;
+}
+
+static ssize_t show_update_rate(struct device *dev,
+			struct device_attribute *devattr, char *buf)
+{
+	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
+	u32			temp = 0, ret = 0;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	if (!temp_sensor->clk_rate) {
+		dev_err(dev, "clk_rate is NULL\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_counter);
+	temp = (temp & temp_sensor->registers->counter_mask) >>
+			__ffs(temp_sensor->registers->counter_mask);
+	temp = temp * 1000 / (temp_sensor->clk_rate);
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	if (!ret)
+		return sprintf(buf, "%d\n", temp);
+	else
+		return ret;
+}
+
+static ssize_t set_update_rate(struct device *dev,
+			       struct device_attribute *devattr,
+			       const char *buf, size_t count)
+{
+	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
+	u32			reg_val;
+	long			val;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	if (strict_strtol(buf, 10, &val)) {
+		count = -EINVAL;
+		goto out;
+	}
+
+	val *= temp_sensor->clk_rate / 1000;
+	reg_val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_counter);
+
+	reg_val &= ~(temp_sensor->registers->counter_mask);
+	reg_val |= val;
+	omap_temp_sensor_writel(temp_sensor, reg_val,
+			temp_sensor->registers->bgap_counter);
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	return count;
+}
+
+static int omap_temp_sensor_read_temp(struct device *dev,
+				      struct device_attribute *devattr,
+				      char *buf)
+{
+	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
+	int			temp, ret = 0;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->temp_sensor_ctrl);
+	temp &= temp_sensor->registers->bgap_dtemp_mask;
+
+	if (!temp_sensor->is_efuse_valid)
+		dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
+
+	/* look up for temperature in the table and return the temperature */
+	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
+		dev_err(dev, "invalid adc code reported %d", temp);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	if (!ret)
+		return sprintf(buf, "%d\n", temp);
+	else
+		return ret;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
+			  NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
+			  set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
+			  set_temp_max_hyst, 0);
+static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
+			  set_update_rate, 0);
+
+static struct attribute *omap_temp_sensor_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_update_rate.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group omap_temp_sensor_group = {
+	.attrs = omap_temp_sensor_attributes,
+};
+
+static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
+{
+	u32 ret = 0, temp;
+
+	if (temp_sensor->clk_on) {
+		dev_err(temp_sensor->hwmon_dev, "clock already on\n");
+		goto out;
+	}
+
+	ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
+	if (ret < 0) {
+		dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->temp_sensor_ctrl);
+	temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
+	/* BGAP_TEMPSOFF should be reset to 0 */
+	omap_temp_sensor_writel(temp_sensor, temp,
+				temp_sensor->registers->temp_sensor_ctrl);
+	temp_sensor->clk_on = 1;
+out:
+	return ret;
+}
+
+static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
+{
+	u32 temp, ret = 0;
+	unsigned long timeout;
+
+	if (!temp_sensor->clk_on) {
+		dev_err(temp_sensor->hwmon_dev, "clock already off\n");
+		goto out;
+	}
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->temp_sensor_ctrl);
+	temp |= temp_sensor->registers->bgap_tempsoff_mask;
+
+	/* BGAP_TEMPSOFF should be set to 1 before gating clock */
+	omap_temp_sensor_writel(temp_sensor, temp,
+			temp_sensor->registers->temp_sensor_ctrl);
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_status);
+	timeout = jiffies + msecs_to_jiffies(5);
+
+	/* wait till the clean stop bit is set or till the timeout exppires */
+	while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
+		!(time_after(jiffies, timeout))) {
+		temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_status);
+		usleep_range(500, 2000);
+	}
+
+	if (time_after(jiffies, timeout))
+		dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
+	/* Gate the clock */
+	ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
+	if (ret < 0) {
+		dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
+		ret = -EINVAL;
+		goto out;
+	}
+	temp_sensor->clk_on = 0;
+out:
+	return ret;
+}
+static irqreturn_t omap_talert_irq_handler(int irq, void *data)
+{
+	struct omap_temp_sensor		*temp_sensor;
+	int				t_hot, t_cold, temp;
+
+	temp_sensor = data;
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	/* Read the status of t_hot */
+	t_hot = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_status)
+			& temp_sensor->registers->status_hot_mask;
+
+	/* Read the status of t_cold */
+	t_cold = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_status)
+			& temp_sensor->registers->status_cold_mask;
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_mask_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) {
+		temp &= ~(temp_sensor->registers->mask_hot_mask);
+		temp |= temp_sensor->registers->mask_cold_mask;
+	} else if (t_cold) {
+		temp &= ~(temp_sensor->registers->mask_cold_mask);
+		temp |= temp_sensor->registers->mask_hot_mask;
+	}
+
+	omap_temp_sensor_writel(temp_sensor, temp,
+		temp_sensor->registers->bgap_mask_ctrl);
+
+	/* kobject_uvent to user space telling thermal threshold crossed */
+	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
+
+	mutex_unlock(&temp_sensor->sensor_mutex);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
+{
+	struct omap_temp_sensor_pdata	*pdata	= pdev->dev.platform_data;
+	struct omap_temp_sensor		*temp_sensor;
+	struct resource			*mem;
+	int				ret = 0;
+	int				val, clk_rate;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data missing\n");
+		return -EINVAL;
+	}
+
+	temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
+	if (!temp_sensor)
+		return -ENOMEM;
+
+	mutex_init(&temp_sensor->sensor_mutex);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource\n");
+		ret = -EINVAL;
+		goto plat_res_err;
+	}
+
+	temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
+	if (temp_sensor->irq == -ENXIO) {
+		dev_err(&pdev->dev, "get_irq_byname failed\n");
+		ret = temp_sensor->irq;
+		goto plat_res_err;
+	}
+
+	temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
+	temp_sensor->clock = NULL;
+	temp_sensor->registers = pdata->registers;
+	temp_sensor->hwmon_dev = &pdev->dev;
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_irq_safe(&pdev->dev);
+
+	/*
+	 * check if the efuse has a non-zero value if not
+	 * it is an untrimmed sample and the temperatures
+	 * may not be accurate
+	 */
+
+	if (omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_efuse))
+		temp_sensor->is_efuse_valid = 1;
+
+	platform_set_drvdata(pdev, temp_sensor);
+	dev_set_drvdata(&pdev->dev, temp_sensor);
+	temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
+	if (IS_ERR(temp_sensor->clock)) {
+		ret = PTR_ERR(temp_sensor->clock);
+		dev_err(temp_sensor->hwmon_dev,
+			"unable to get fclk: %d\n", ret);
+		ret = -EINVAL;
+		goto plat_res_err;
+	}
+
+	ret = omap_temp_sensor_clk_enable(temp_sensor);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot enable temp sensor\n");
+		goto clken_err;
+	}
+
+	clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
+	if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
+		dev_err(&pdev->dev, "Error round rate\n");
+		goto clken_err;
+	}
+
+	ret = clk_set_rate(temp_sensor->clock, clk_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot set clock rate\n");
+		goto clken_err;
+	}
+
+	temp_sensor->clk_rate = clk_rate;
+	omap_enable_continuous_mode(temp_sensor, 1);
+	omap_configure_temp_sensor_thresholds(temp_sensor);
+	/* 1 ms */
+	omap_configure_temp_sensor_counter(temp_sensor, 1);
+
+	/* Wait till the first conversion is done wait for at least 1ms */
+	usleep_range(1000, 2000);
+
+	/* Read the temperature once due to hw issue*/
+	omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->temp_sensor_ctrl);
+
+	/* Set 2 seconds time as default counter */
+	omap_configure_temp_sensor_counter(temp_sensor,
+						temp_sensor->clk_rate * 2);
+
+	temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(temp_sensor->hwmon_dev)) {
+		dev_err(&pdev->dev, "hwmon_device_register failed.\n");
+		ret = PTR_ERR(temp_sensor->hwmon_dev);
+		goto hwmon_reg_err;
+	}
+
+	ret = sysfs_create_group(&pdev->dev.kobj,
+				 &omap_temp_sensor_group);
+	if (ret) {
+		dev_err(&pdev->dev, "could not create sysfs files\n");
+		goto sysfs_create_err;
+	}
+
+	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
+
+	ret = request_threaded_irq(temp_sensor->irq, NULL,
+		omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+			"temp_sensor", temp_sensor);
+	if (ret) {
+		dev_err(&pdev->dev, "Request threaded irq failed.\n");
+		goto req_irq_err;
+	}
+
+	/* unmask the T_COLD and unmask T_HOT at init */
+	val = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_mask_ctrl);
+	val |= temp_sensor->registers->mask_cold_mask
+		| temp_sensor->registers->mask_hot_mask;
+
+	omap_temp_sensor_writel(temp_sensor, val,
+		temp_sensor->registers->bgap_mask_ctrl);
+
+	return 0;
+
+req_irq_err:
+	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
+	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
+				&omap_temp_sensor_group);
+sysfs_create_err:
+	hwmon_device_unregister(&pdev->dev);
+hwmon_reg_err:
+	omap_temp_sensor_clk_disable(temp_sensor);
+clken_err:
+	if (temp_sensor->clock)
+		clk_put(temp_sensor->clock);
+plat_res_err:
+	mutex_destroy(&temp_sensor->sensor_mutex);
+	kfree(temp_sensor);
+	return ret;
+}
+
+static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
+{
+	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(&pdev->dev);
+	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
+	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
+			&omap_temp_sensor_group);
+	omap_temp_sensor_clk_disable(temp_sensor);
+	clk_put(temp_sensor->clock);
+	platform_set_drvdata(pdev, NULL);
+	free_irq(temp_sensor->irq, temp_sensor);
+	mutex_destroy(&temp_sensor->sensor_mutex);
+	kfree(temp_sensor);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
+{
+	temp_sensor->temp_sensor_ctrl = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->temp_sensor_ctrl);
+	temp_sensor->bg_ctrl = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_mask_ctrl);
+	temp_sensor->bg_counter = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_counter);
+	temp_sensor->bg_threshold = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_threshold);
+	temp_sensor->temp_sensor_tshut_threshold =
+		omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->thsut_threshold);
+}
+
+static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
+{
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->temp_sensor_ctrl,
+				temp_sensor->registers->temp_sensor_ctrl);
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->bg_ctrl,
+				temp_sensor->registers->bgap_mask_ctrl);
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->bg_counter,
+				temp_sensor->registers->bgap_counter);
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->bg_threshold,
+				temp_sensor->registers->bgap_threshold);
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->temp_sensor_tshut_threshold,
+				temp_sensor->registers->thsut_threshold);
+}
+
+static int omap_temp_sensor_suspend(struct device *dev)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+
+	omap_temp_sensor_save_ctxt(temp_sensor);
+
+	return 0;
+}
+
+static int omap_temp_sensor_resume(struct device *dev)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+
+	omap_temp_sensor_restore_ctxt(temp_sensor);
+
+	return 0;
+}
+
+static int omap_temp_sensor_runtime_suspend(struct device *dev)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+
+	omap_temp_sensor_save_ctxt(temp_sensor);
+
+	return 0;
+}
+
+static int omap_temp_sensor_runtime_resume(struct device *dev)
+{
+	static int context_loss_count;
+	int temp;
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+
+	temp = omap_device_get_context_loss_count(to_platform_device(dev));
+
+	if (temp != context_loss_count && context_loss_count != 0)
+		omap_temp_sensor_restore_ctxt(temp_sensor);
+
+	context_loss_count = temp;
+
+	return 0;
+}
+
+static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
+	.suspend = omap_temp_sensor_suspend,
+	.resume = omap_temp_sensor_resume,
+	.runtime_suspend = omap_temp_sensor_runtime_suspend,
+	.runtime_resume = omap_temp_sensor_runtime_resume,
+};
+
+#endif
+
+static struct platform_driver omap_temp_sensor_driver = {
+	.probe = omap_temp_sensor_probe,
+	.remove = omap_temp_sensor_remove,
+	.driver = {
+			.name = "omap_temp_sensor",
+#ifdef CONFIG_PM
+			.pm = &omap_temp_sensor_dev_pm_ops,
+#endif
+		   },
+};
+
+int __init omap_temp_sensor_init(void)
+{
+	return platform_driver_register(&omap_temp_sensor_driver);
+}
+module_init(omap_temp_sensor_init);
+
+static void __exit omap_temp_sensor_exit(void)
+{
+	platform_driver_unregister(&omap_temp_sensor_driver);
+}
+module_exit(omap_temp_sensor_exit);
+
+MODULE_DESCRIPTION("OMAP446X temperature sensor Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-10 12:37   ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Keerthy
@ 2011-08-10 12:36     ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:36 UTC (permalink / raw)
  To: Keerthy; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

[-- Attachment #1: Type: text/plain, Size: 8222 bytes --]

Hi,

(you should Cc Tony, as he's OMAP maintainer)

On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
> The device file adds the device support for OMAP4
> on die temperature sensor.
> 
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  arch/arm/mach-omap2/Makefile                       |    3 +-
>  arch/arm/mach-omap2/temp_sensor_device.c           |   85 +++++++++++++++++++
>  arch/arm/plat-omap/Kconfig                         |   12 +++
>  .../plat-omap/include/plat/temperature_sensor.h    |   87 ++++++++++++++++++++
>  4 files changed, 186 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/temp_sensor_device.c
>  create mode 100644 arch/arm/plat-omap/include/plat/temperature_sensor.h
> 
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index fb02937..5812fb4 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
>  
>  obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
>  
> +obj-$(CONFIG_OMAP_TEMP_SENSOR)          += temp_sensor_device.o
>  obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
>  
>  # SMP support ONLY available for OMAP4
> @@ -86,7 +87,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
>  obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
>  					   cm44xx.o prcm_mpu44xx.o \
>  					   prminst44xx.o vc44xx_data.o \
> -					   vp44xx_data.o
> +					   vp44xx_data.o temp_sensor4460_data.o
>  
>  # OMAP voltage domains
>  ifeq ($(CONFIG_PM),y)
> diff --git a/arch/arm/mach-omap2/temp_sensor_device.c b/arch/arm/mach-omap2/temp_sensor_device.c
> new file mode 100644
> index 0000000..5d5e92f
> --- /dev/null
> +++ b/arch/arm/mach-omap2/temp_sensor_device.c
> @@ -0,0 +1,85 @@
> +/*
> + * OMAP on die Temperature sensor device file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@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/err.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
> +#include <linux/pm_runtime.h>
> +#include <plat/omap_device.h>
> +#include "control.h"
> +#include "pm.h"
> +#include <plat/temperature_sensor.h>
> +
> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> +	{
> +	 .deactivate_func = omap_device_idle_hwmods,
> +	 .activate_func = omap_device_enable_hwmods,
> +	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> +	}

wrong indentation.

> +};
> +
> +static int temp_sensor_dev_init(struct omap_hwmod *oh, void *user)
> +{
> +	struct	omap_temp_sensor_pdata		*temp_sensor_pdata;
> +	struct	omap_device			*od;
> +	struct	omap_temp_sensor_dev_attr	*temp_sensor_dev_attr;
> +	int					ret;
> +	static int				device_count;

use an IDR here (see include/linux/idr.h)

> +	ret = 0;

initialize on the declarion and you can avoid this line.

> +	temp_sensor_pdata =
> +	    kzalloc(sizeof(*temp_sensor_pdata), GFP_KERNEL);
> +	if (!temp_sensor_pdata) {
> +		dev_err(&oh->od->pdev.dev,
> +			"Unable to allocate memory for temp sensor pdata\n");
> +		return -ENOMEM;
> +	}
> +
> +	temp_sensor_dev_attr = oh->dev_attr;
> +	if (!strcmp(temp_sensor_dev_attr->name, "mpu"))
> +		temp_sensor_pdata->registers = &omap_mpu_temp_sensor_registers;
> +
> +	od = omap_device_build("omap_temp_sensor", device_count++,
> +		oh, temp_sensor_pdata, sizeof(*temp_sensor_pdata),
> +	       omap_temp_sensor_latency,
> +			ARRAY_SIZE(omap_temp_sensor_latency), 0);
> +	if (IS_ERR(od)) {
> +		dev_warn(&oh->od->pdev.dev,
> +			"Could not build omap_device for %s\n", oh->name);
> +		ret = PTR_ERR(od);
> +	}
> +
> +	kfree(temp_sensor_pdata);
> +
> +	return ret;
> +}
> +
> +int __init omap_devinit_temp_sensor(void)
> +{
> +	if (!cpu_is_omap446x())
> +		return 0;
> +
> +	return omap_hwmod_for_each_by_class("temperature_sensor",
> +			temp_sensor_dev_init, NULL);
> +}
> +
> +arch_initcall(omap_devinit_temp_sensor);

I really dislike people adding more and more *initcall() to their pieces
of code. But Tony is the final Judge.

> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> index 6e6735f..8fd8e80 100644
> --- a/arch/arm/plat-omap/Kconfig
> +++ b/arch/arm/plat-omap/Kconfig
> @@ -115,6 +115,18 @@ config OMAP_MCBSP
>  	  Say Y here if you want support for the OMAP Multichannel
>  	  Buffered Serial Port.
>  
> +config OMAP_TEMP_SENSOR
> +	bool "OMAP Temp Sensor Support"
> +	depends on ARCH_OMAP
> +	default n
> +	help
> +	  Say Y here if you want support for the temp sensor
> +	  on OMAP4460.
> +
> +	  This provides the temperature of the MPU
> +	  subsystem. Only one instance of on die temperature
> +	  sensor is present.

if there's only one instance, why do you use
omap_hwmod_for_each_by_class() ??

> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> new file mode 100644
> index 0000000..692ebdc
> --- /dev/null
> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> @@ -0,0 +1,87 @@
> +/*
> + * OMAP Temperature sensor header file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> +
> +/* Offsets from the base of temperature sensor registers */
> +
> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET	0x00
> +#define OMAP4460_BGAP_CTRL_OFFSET		0x4c
> +#define OMAP4460_BGAP_COUNTER_OFFSET		0x50
> +#define OMAP4460_BGAP_THRESHOLD_OFFSET		0x54
> +#define OMAP4460_BGAP_TSHUT_OFFSET		0x58
> +#define OMAP4460_BGAP_STATUS_OFFSET		0x5c
> +#define OMAP4460_FUSE_OPP_BGAP			-0xcc
> +
> +struct omap_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	thsut_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;
> +};

I find it unnecessary to pass the register map to driver using
platform_data.

> +/*
> + * @name: Name of the domain of the temperature sensor
> + */

comment fits in one line.


-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-10 12:36     ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:36 UTC (permalink / raw)
  To: Keerthy; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak


[-- Attachment #1.1: Type: text/plain, Size: 8222 bytes --]

Hi,

(you should Cc Tony, as he's OMAP maintainer)

On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
> The device file adds the device support for OMAP4
> on die temperature sensor.
> 
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  arch/arm/mach-omap2/Makefile                       |    3 +-
>  arch/arm/mach-omap2/temp_sensor_device.c           |   85 +++++++++++++++++++
>  arch/arm/plat-omap/Kconfig                         |   12 +++
>  .../plat-omap/include/plat/temperature_sensor.h    |   87 ++++++++++++++++++++
>  4 files changed, 186 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/temp_sensor_device.c
>  create mode 100644 arch/arm/plat-omap/include/plat/temperature_sensor.h
> 
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index fb02937..5812fb4 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
>  
>  obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
>  
> +obj-$(CONFIG_OMAP_TEMP_SENSOR)          += temp_sensor_device.o
>  obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
>  
>  # SMP support ONLY available for OMAP4
> @@ -86,7 +87,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
>  obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
>  					   cm44xx.o prcm_mpu44xx.o \
>  					   prminst44xx.o vc44xx_data.o \
> -					   vp44xx_data.o
> +					   vp44xx_data.o temp_sensor4460_data.o
>  
>  # OMAP voltage domains
>  ifeq ($(CONFIG_PM),y)
> diff --git a/arch/arm/mach-omap2/temp_sensor_device.c b/arch/arm/mach-omap2/temp_sensor_device.c
> new file mode 100644
> index 0000000..5d5e92f
> --- /dev/null
> +++ b/arch/arm/mach-omap2/temp_sensor_device.c
> @@ -0,0 +1,85 @@
> +/*
> + * OMAP on die Temperature sensor device file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@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/err.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
> +#include <linux/pm_runtime.h>
> +#include <plat/omap_device.h>
> +#include "control.h"
> +#include "pm.h"
> +#include <plat/temperature_sensor.h>
> +
> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> +	{
> +	 .deactivate_func = omap_device_idle_hwmods,
> +	 .activate_func = omap_device_enable_hwmods,
> +	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> +	}

wrong indentation.

> +};
> +
> +static int temp_sensor_dev_init(struct omap_hwmod *oh, void *user)
> +{
> +	struct	omap_temp_sensor_pdata		*temp_sensor_pdata;
> +	struct	omap_device			*od;
> +	struct	omap_temp_sensor_dev_attr	*temp_sensor_dev_attr;
> +	int					ret;
> +	static int				device_count;

use an IDR here (see include/linux/idr.h)

> +	ret = 0;

initialize on the declarion and you can avoid this line.

> +	temp_sensor_pdata =
> +	    kzalloc(sizeof(*temp_sensor_pdata), GFP_KERNEL);
> +	if (!temp_sensor_pdata) {
> +		dev_err(&oh->od->pdev.dev,
> +			"Unable to allocate memory for temp sensor pdata\n");
> +		return -ENOMEM;
> +	}
> +
> +	temp_sensor_dev_attr = oh->dev_attr;
> +	if (!strcmp(temp_sensor_dev_attr->name, "mpu"))
> +		temp_sensor_pdata->registers = &omap_mpu_temp_sensor_registers;
> +
> +	od = omap_device_build("omap_temp_sensor", device_count++,
> +		oh, temp_sensor_pdata, sizeof(*temp_sensor_pdata),
> +	       omap_temp_sensor_latency,
> +			ARRAY_SIZE(omap_temp_sensor_latency), 0);
> +	if (IS_ERR(od)) {
> +		dev_warn(&oh->od->pdev.dev,
> +			"Could not build omap_device for %s\n", oh->name);
> +		ret = PTR_ERR(od);
> +	}
> +
> +	kfree(temp_sensor_pdata);
> +
> +	return ret;
> +}
> +
> +int __init omap_devinit_temp_sensor(void)
> +{
> +	if (!cpu_is_omap446x())
> +		return 0;
> +
> +	return omap_hwmod_for_each_by_class("temperature_sensor",
> +			temp_sensor_dev_init, NULL);
> +}
> +
> +arch_initcall(omap_devinit_temp_sensor);

I really dislike people adding more and more *initcall() to their pieces
of code. But Tony is the final Judge.

> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> index 6e6735f..8fd8e80 100644
> --- a/arch/arm/plat-omap/Kconfig
> +++ b/arch/arm/plat-omap/Kconfig
> @@ -115,6 +115,18 @@ config OMAP_MCBSP
>  	  Say Y here if you want support for the OMAP Multichannel
>  	  Buffered Serial Port.
>  
> +config OMAP_TEMP_SENSOR
> +	bool "OMAP Temp Sensor Support"
> +	depends on ARCH_OMAP
> +	default n
> +	help
> +	  Say Y here if you want support for the temp sensor
> +	  on OMAP4460.
> +
> +	  This provides the temperature of the MPU
> +	  subsystem. Only one instance of on die temperature
> +	  sensor is present.

if there's only one instance, why do you use
omap_hwmod_for_each_by_class() ??

> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> new file mode 100644
> index 0000000..692ebdc
> --- /dev/null
> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> @@ -0,0 +1,87 @@
> +/*
> + * OMAP Temperature sensor header file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> +
> +/* Offsets from the base of temperature sensor registers */
> +
> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET	0x00
> +#define OMAP4460_BGAP_CTRL_OFFSET		0x4c
> +#define OMAP4460_BGAP_COUNTER_OFFSET		0x50
> +#define OMAP4460_BGAP_THRESHOLD_OFFSET		0x54
> +#define OMAP4460_BGAP_TSHUT_OFFSET		0x58
> +#define OMAP4460_BGAP_STATUS_OFFSET		0x5c
> +#define OMAP4460_FUSE_OPP_BGAP			-0xcc
> +
> +struct omap_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	thsut_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;
> +};

I find it unnecessary to pass the register map to driver using
platform_data.

> +/*
> + * @name: Name of the domain of the temperature sensor
> + */

comment fits in one line.


-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [lm-sensors] [RFC PATCH 0/6] OMAP4: Temperature sensor driver
@ 2011-08-10 12:37 ` Keerthy
  0 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:37 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

Hello,

The rfc patch series for the on die temperature sensor driver. I need
feedback on the overall structure of the driver.
The rfc patch set has the device file, omap4 on die temperature sensor
hwmon driver. hwmod, clk support. The patch set compiles
on top of LO tree Master branch.

This patch series is tested for boot-up on OMAP4460. The temperature
reading and the interrupts generation on crossing the temperature
thresholds also tested.

Keerthy (6):
  OMAP4: Clock: Associate clocks for OMAP temperature sensor
  OMAP4: Adding the temperature sensor register set bit fields
  OMAP4: Hwmod: OMAP temperature sensor
  OMAP4: Temperature sensor device support
  OMAP4460: Temperature sensor data
  OMAP4: On die temperature sensor driver

 arch/arm/mach-omap2/Makefile                       |    3 +-
 arch/arm/mach-omap2/clock44xx_data.c               |    2 +-
 .../include/mach/ctrl_module_core_44xx.h           |   70 ++-
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |   61 ++
 arch/arm/mach-omap2/temp_sensor4460_data.c         |   63 ++
 arch/arm/mach-omap2/temp_sensor_device.c           |   85 ++
 arch/arm/plat-omap/Kconfig                         |   12 +
 .../plat-omap/include/plat/temperature_sensor.h    |   87 ++
 drivers/hwmon/Kconfig                              |   11 +
 drivers/hwmon/Makefile                             |    1 +
 drivers/hwmon/omap_temp_sensor.c                   |  950 ++++++++++++++++++++
 11 files changed, 1330 insertions(+), 15 deletions(-)
 create mode 100644 arch/arm/mach-omap2/temp_sensor4460_data.c
 create mode 100644 arch/arm/mach-omap2/temp_sensor_device.c
 create mode 100644 arch/arm/plat-omap/include/plat/temperature_sensor.h
 create mode 100644 drivers/hwmon/omap_temp_sensor.c


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [lm-sensors] [RFC PATCH 1/6] OMAP4: Clock: Associate clocks for
@ 2011-08-10 12:37   ` Keerthy
  0 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:37 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

div_ts_ck feeds only the temperature sensor functional clock
and also has a clksel associated (for divider selection). Mapping this
as the functional clock for the temperature sensor in clkdev table,
so a clk_set_rate() in the driver would have the effect of changing the
temperature sensor clock rate indirectly.

Reviewd-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 arch/arm/mach-omap2/clock44xx_data.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 2af0e3f..4a788f4 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3187,7 +3187,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"bandgap_fclk",			&bandgap_fclk,	CK_443X),
 	CLK(NULL,	"bandgap_ts_fclk",		&bandgap_ts_fclk,	CK_446X),
 	CLK(NULL,	"des3des_fck",			&des3des_fck,	CK_443X),
-	CLK(NULL,	"div_ts_ck",			&div_ts_ck,	CK_446X),
+	CLK("omap_temp_sensor.0",	"fck",			&div_ts_ck,	CK_446X),
 	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
 	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
-- 
1.7.0.4


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [lm-sensors] [RFC PATCH 2/6] OMAP4: Adding the temperature sensor
@ 2011-08-10 12:37   ` Keerthy
  0 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:37 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

OMAP4460 specific temperature sensor register bit fields are added.

Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 .../include/mach/ctrl_module_core_44xx.h           |   70 ++++++++++++++++----
 1 files changed, 57 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
index 2f7ac70..725c1e1 100644
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
@@ -256,19 +256,63 @@
 #define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT	0
 #define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
 
-/* TEMP_SENSOR */
-#define OMAP4_BGAP_TEMPSOFF_SHIFT			12
-#define OMAP4_BGAP_TEMPSOFF_MASK			(1 << 12)
-#define OMAP4_BGAP_TSHUT_SHIFT				11
-#define OMAP4_BGAP_TSHUT_MASK				(1 << 11)
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1 << 10)
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT		9
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK			(1 << 9)
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
+/* 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		(0x3ff << 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)
 
 /* DPLL_NWELL_TRIM_0 */
 #define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT	29
-- 
1.7.0.4


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [lm-sensors] [RFC PATCH 3/6] OMAP4: Hwmod: OMAP temperature sensor
@ 2011-08-10 12:37   ` Keerthy
  0 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:37 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

From: Benoit Cousson <b-cousson@ti.com>

OMAP4460 temperature sensor hwmod cannot be auto generated
since it is part of ctrl module. Hence populating the
necessary hwmod info manually.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   61 ++++++++++++++++++++++++++++
 1 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6201422..28bf6d3 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -29,6 +29,7 @@
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
 #include <plat/i2c.h>
+#include <plat/temperature_sensor.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -832,6 +833,63 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
 };
 
 /*
+ * 'temperature_sensor' class
+ * temperature sensor module inside the bandgap / control module
+ */
+
+static struct omap_hwmod_class omap44xx_temperature_sensor_hwmod_class = {
+	.name   = "temperature_sensor",
+};
+
+static struct omap_hwmod_irq_info omap44xx_temperature_sensor_irqs[] = {
+	{ .name = "thermal_alert", .irq = 126 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_temperature_sensor_addrs[] = {
+	{
+		.pa_start       = 0x4a00232c,
+		.pa_end         = 0x4a00238b,
+	},
+};
+
+static struct omap_hwmod omap44xx_temperature_sensor_hwmod;
+/* l4_cfg -> ctrl_module_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__temperature_sensor = {
+	.master         = &omap44xx_l4_cfg_hwmod,
+	.slave          = &omap44xx_temperature_sensor_hwmod,
+	.clk            = "l4_div_ck",
+	.addr           = omap44xx_temperature_sensor_addrs,
+	.user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ctrl_module_core slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_temperature_sensor_slaves[] = {
+	&omap44xx_l4_cfg__temperature_sensor,
+};
+
+/* temperature sensor dev_attr */
+static struct omap_temp_sensor_dev_attr temp_sensor_dev_attr = {
+	.name	= "mpu",
+};
+
+static struct omap_hwmod omap44xx_temperature_sensor_hwmod = {
+	.name           = "temperature_sensor_mpu",
+	.class          = &omap44xx_temperature_sensor_hwmod_class,
+	.mpu_irqs       = omap44xx_temperature_sensor_irqs,
+	.main_clk       = "bandgap_ts_fclk",
+	.slaves		= omap44xx_temperature_sensor_slaves,
+	.slaves_cnt     = ARRAY_SIZE(omap44xx_temperature_sensor_slaves),
+	.clkdm_name     = "l4_wkup_clkdm",
+	.prcm           = {
+		.omap4 = {
+		.clkctrl_offs = OMAP4_CM_WKUP_BANDGAP_CLKCTRL_OFFSET,
+		},
+	},
+	.dev_attr	= &temp_sensor_dev_attr,
+	.omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'bandgap' class
  * bangap reference for ldo regulators
  */
@@ -5469,6 +5527,9 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	&omap44xx_timer10_hwmod,
 	&omap44xx_timer11_hwmod,
 
+	/* temperature sensor hwmod */
+	&omap44xx_temperature_sensor_hwmod,
+
 	/* uart class */
 	&omap44xx_uart1_hwmod,
 	&omap44xx_uart2_hwmod,
-- 
1.7.0.4


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-10 12:37   ` Keerthy
  0 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:37 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

The device file adds the device support for OMAP4
on die temperature sensor.

Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 arch/arm/mach-omap2/Makefile                       |    3 +-
 arch/arm/mach-omap2/temp_sensor_device.c           |   85 +++++++++++++++++++
 arch/arm/plat-omap/Kconfig                         |   12 +++
 .../plat-omap/include/plat/temperature_sensor.h    |   87 ++++++++++++++++++++
 4 files changed, 186 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/temp_sensor_device.c
 create mode 100644 arch/arm/plat-omap/include/plat/temperature_sensor.h

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index fb02937..5812fb4 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
+obj-$(CONFIG_OMAP_TEMP_SENSOR)          += temp_sensor_device.o
 obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
 
 # SMP support ONLY available for OMAP4
@@ -86,7 +87,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
 obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
 					   cm44xx.o prcm_mpu44xx.o \
 					   prminst44xx.o vc44xx_data.o \
-					   vp44xx_data.o
+					   vp44xx_data.o temp_sensor4460_data.o
 
 # OMAP voltage domains
 ifeq ($(CONFIG_PM),y)
diff --git a/arch/arm/mach-omap2/temp_sensor_device.c b/arch/arm/mach-omap2/temp_sensor_device.c
new file mode 100644
index 0000000..5d5e92f
--- /dev/null
+++ b/arch/arm/mach-omap2/temp_sensor_device.c
@@ -0,0 +1,85 @@
+/*
+ * OMAP on die Temperature sensor device file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@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/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <plat/omap_device.h>
+#include "control.h"
+#include "pm.h"
+#include <plat/temperature_sensor.h>
+
+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
+	{
+	 .deactivate_func = omap_device_idle_hwmods,
+	 .activate_func = omap_device_enable_hwmods,
+	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};
+
+static int temp_sensor_dev_init(struct omap_hwmod *oh, void *user)
+{
+	struct	omap_temp_sensor_pdata		*temp_sensor_pdata;
+	struct	omap_device			*od;
+	struct	omap_temp_sensor_dev_attr	*temp_sensor_dev_attr;
+	int					ret;
+	static int				device_count;
+
+	ret = 0;
+	temp_sensor_pdata +	    kzalloc(sizeof(*temp_sensor_pdata), GFP_KERNEL);
+	if (!temp_sensor_pdata) {
+		dev_err(&oh->od->pdev.dev,
+			"Unable to allocate memory for temp sensor pdata\n");
+		return -ENOMEM;
+	}
+
+	temp_sensor_dev_attr = oh->dev_attr;
+	if (!strcmp(temp_sensor_dev_attr->name, "mpu"))
+		temp_sensor_pdata->registers = &omap_mpu_temp_sensor_registers;
+
+	od = omap_device_build("omap_temp_sensor", device_count++,
+		oh, temp_sensor_pdata, sizeof(*temp_sensor_pdata),
+	       omap_temp_sensor_latency,
+			ARRAY_SIZE(omap_temp_sensor_latency), 0);
+	if (IS_ERR(od)) {
+		dev_warn(&oh->od->pdev.dev,
+			"Could not build omap_device for %s\n", oh->name);
+		ret = PTR_ERR(od);
+	}
+
+	kfree(temp_sensor_pdata);
+
+	return ret;
+}
+
+int __init omap_devinit_temp_sensor(void)
+{
+	if (!cpu_is_omap446x())
+		return 0;
+
+	return omap_hwmod_for_each_by_class("temperature_sensor",
+			temp_sensor_dev_init, NULL);
+}
+
+arch_initcall(omap_devinit_temp_sensor);
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 6e6735f..8fd8e80 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -115,6 +115,18 @@ config OMAP_MCBSP
 	  Say Y here if you want support for the OMAP Multichannel
 	  Buffered Serial Port.
 
+config OMAP_TEMP_SENSOR
+	bool "OMAP Temp Sensor Support"
+	depends on ARCH_OMAP
+	default n
+	help
+	  Say Y here if you want support for the temp sensor
+	  on OMAP4460.
+
+	  This provides the temperature of the MPU
+	  subsystem. Only one instance of on die temperature
+	  sensor is present.
+
 config OMAP_MBOX_FWK
 	tristate "Mailbox framework support"
 	depends on ARCH_OMAP
diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
new file mode 100644
index 0000000..692ebdc
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
@@ -0,0 +1,87 @@
+/*
+ * OMAP Temperature sensor header file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
+
+/* Offsets from the base of temperature sensor registers */
+
+#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET	0x00
+#define OMAP4460_BGAP_CTRL_OFFSET		0x4c
+#define OMAP4460_BGAP_COUNTER_OFFSET		0x50
+#define OMAP4460_BGAP_THRESHOLD_OFFSET		0x54
+#define OMAP4460_BGAP_TSHUT_OFFSET		0x58
+#define OMAP4460_BGAP_STATUS_OFFSET		0x5c
+#define OMAP4460_FUSE_OPP_BGAP			-0xcc
+
+struct omap_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	thsut_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;
+};
+
+/*
+ * @name: Name of the domain of the temperature sensor
+ */
+struct omap_temp_sensor_dev_attr {
+	const char *name;
+};
+
+extern struct omap_temp_sensor_registers omap_mpu_temp_sensor_registers;
+
+/*
+ * omap_temp_sensor platform data
+ * @registers - pointer to register set and thier bit fields information
+ */
+struct omap_temp_sensor_pdata {
+	struct omap_temp_sensor_registers *registers;
+};
+
+#endif
-- 
1.7.0.4


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [lm-sensors] [RFC PATCH 5/6] OMAP4460: Temperature sensor data
@ 2011-08-10 12:37   ` Keerthy
  0 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:37 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

The register set and the
bit fields might vary across OMAP versions. Hence
creating a structure comprising of all the registers
and bit fields to make the driver uniform for all the
versions with different register sets. The data file
contains the structure populated with register offsets
and bit fields corresponding to OMAP4460 on die sensor.

Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 arch/arm/mach-omap2/temp_sensor4460_data.c |   63 ++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/temp_sensor4460_data.c

diff --git a/arch/arm/mach-omap2/temp_sensor4460_data.c b/arch/arm/mach-omap2/temp_sensor4460_data.c
new file mode 100644
index 0000000..294963d
--- /dev/null
+++ b/arch/arm/mach-omap2/temp_sensor4460_data.c
@@ -0,0 +1,63 @@
+/*
+ * OMAP4460 on die Temperature sensor data file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@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/slab.h>
+#include "control.h"
+#include <plat/temperature_sensor.h>
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+struct omap_temp_sensor_registers omap_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,
+
+	.thsut_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,
+};
-- 
1.7.0.4


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply related	[flat|nested] 105+ messages in thread

* [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-10 12:37   ` Keerthy
  0 siblings, 0 replies; 105+ messages in thread
From: Keerthy @ 2011-08-10 12:37 UTC (permalink / raw)
  To: lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, j-keerthy

On chip temperature sensor driver. The driver monitors the temperature of
the MPU subsystem of the OMAP4. It sends notifications to the user space if
the temperature crosses user defined thresholds via kobject_uevent interface.
The user is allowed to configure the temperature thresholds vis sysfs nodes
exposed using hwmon interface.

Signed-off-by: Keerthy <j-keerthy@ti.com>
---
 drivers/hwmon/Kconfig            |   11 +
 drivers/hwmon/Makefile           |    1 +
 drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 962 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/omap_temp_sensor.c

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5f888f7..9c9cd8b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -323,6 +323,17 @@ config SENSORS_F71805F
 	  This driver can also be built as a module.  If so, the module
 	  will be called f71805f.
 
+config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
+	bool "OMAP on-die temperature sensor hwmon driver"
+	depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
+	help
+	  If you say yes here you get support for hardware
+	  monitoring features of the OMAP on die temperature
+	  sensor.
+
+	  Continuous conversion programmable delay
+	  mode is used for temperature conversion.
+
 config SENSORS_F71882FG
 	tristate "Fintek F71882FG and compatibles"
 	help
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 28061cf..d0f89f5 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
 obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
+obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
new file mode 100644
index 0000000..15e2559
--- /dev/null
+++ b/drivers/hwmon/omap_temp_sensor.c
@@ -0,0 +1,950 @@
+/*
+ * OMAP4 Temperature sensor driver file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@ti.com>
+ * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <plat/omap_device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/stddef.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <plat/common.h>
+#include <plat/temperature_sensor.h>
+#include <mach/ctrl_module_core_44xx.h>
+#include <mach/gpio.h>
+
+#define TSHUT_THRESHOLD_HOT	122000	/* 122 deg C */
+#define TSHUT_THRESHOLD_COLD	100000	/* 100 deg C */
+#define BGAP_THRESHOLD_T_HOT	73000	/* 73 deg C */
+#define BGAP_THRESHOLD_T_COLD	71000	/* 71 deg C */
+#define OMAP_ADC_START_VALUE	530
+#define OMAP_ADC_END_VALUE	923
+
+/*
+ * omap_temp_sensor structure
+ * @hwmon_dev - device pointer
+ * @clock - Clock pointer
+ * @registers - Pointer to structure with register offsets and bitfields
+ * @sensor_mutex - Mutex for sysfs, irq and PM
+ * @irq - MPU Irq number for thermal alert
+ * @phy_base - Physical base of the temp I/O
+ * @clk_rate - Holds current clock rate
+ * @temp_sensor_ctrl - temp sensor control register value
+ * @bg_ctrl - bandgap ctrl register value
+ * @bg_counter - bandgap counter value
+ * @bg_threshold - bandgap threshold register value
+ * @temp_sensor_tshut_threshold - bandgap tshut register value
+ * @is_efuse_valid - Flag to determine if efuse is valid or not
+ * @clk_on - Manages the current clock state
+ */
+struct omap_temp_sensor {
+	struct device		*hwmon_dev;
+	struct clk		*clock;
+	struct omap_temp_sensor_registers *registers;
+	struct mutex		sensor_mutex; /* Mutex for sysfs, irq and PM */
+	unsigned int		irq;
+	void __iomem		*phy_base;
+	u32			clk_rate;
+	u32			temp_sensor_ctrl;
+	u32			bg_ctrl;
+	u32			bg_counter;
+	u32			bg_threshold;
+	u32			temp_sensor_tshut_threshold;
+	bool                    is_efuse_valid;
+	bool                    clk_on;
+};
+
+/*
+ * Temperature values in milli degree celsius
+ * ADC code values from 530 to 923
+ */
+static int adc_to_temp[] = {
+	-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
+};
+
+static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
+					    *temp_sensor, u32 reg)
+{
+	return __raw_readl(temp_sensor->phy_base + reg);
+}
+
+static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
+				    u32 val, u32 reg)
+{
+	__raw_writel(val, (temp_sensor->phy_base + reg));
+}
+
+static int adc_to_temp_conversion(int adc_val)
+{
+	return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
+}
+
+static int temp_to_adc_conversion(long temp)
+{
+	int i;
+
+	for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
+		if (temp < adc_to_temp[i])
+			return OMAP_ADC_START_VALUE + i - 1;
+
+	return -EINVAL;
+}
+
+static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
+						  *temp_sensor)
+{
+	u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
+
+	t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
+	t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
+
+	/* Configure the TALERT thresholds */
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
+		(t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
+	omap_temp_sensor_writel(temp_sensor, temp,
+		temp_sensor->registers->bgap_threshold);
+
+	tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
+	tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
+
+	/* Configure the TSHUT thresholds */
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->thsut_threshold);
+	temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
+	    | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
+	omap_temp_sensor_writel(temp_sensor, temp,
+			temp_sensor->registers->thsut_threshold);
+}
+
+static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
+					       *temp_sensor, u32 counter)
+{
+	u32 val;
+
+	val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_counter);
+	val &= ~(temp_sensor->registers->counter_mask);
+	val |= (counter << __ffs(temp_sensor->registers->counter_mask));
+	omap_temp_sensor_writel(temp_sensor, val,
+			temp_sensor->registers->bgap_counter);
+}
+
+static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
+					bool enable)
+{
+	u32 val;
+
+	val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_mode_ctrl);
+
+	if (enable)
+		val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
+	else
+		val &= ~(temp_sensor->registers->mode_ctrl_mask);
+
+	omap_temp_sensor_writel(temp_sensor, val,
+			temp_sensor->registers->bgap_mode_ctrl);
+}
+
+/* Sysfs hook functions */
+
+static ssize_t show_temp_max(struct device *dev,
+			struct device_attribute *devattr, char *buf)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+	int temp;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	temp = (temp & temp_sensor->registers->threshold_thot_mask)
+			>> __ffs(temp_sensor->registers->threshold_thot_mask);
+
+	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
+		dev_err(dev, "invalid value\n");
+		goto out;
+	}
+	temp = adc_to_temp_conversion(temp);
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+
+	return snprintf(buf, 16, "%d\n", temp);
+}
+
+static ssize_t set_temp_max(struct device *dev,
+			    struct device_attribute *devattr,
+			    const char *buf, size_t count)
+{
+	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
+	long			val;
+	u32			reg_val, t_cold, t_hot, temp;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	if (strict_strtol(buf, 10, &val)) {
+		count = -EINVAL;
+		goto out;
+	}
+
+	t_hot = temp_to_adc_conversion(val);
+	if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
+		dev_err(dev, "invalid range\n");
+		count = -EINVAL;
+		goto out;
+	}
+
+	/* obtain the T cold value */
+	t_cold = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
+			__ffs(temp_sensor->registers->threshold_tcold_mask);
+
+	if (t_hot < t_cold) {
+		dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
+		count = -EINVAL;
+		goto out;
+	}
+
+	/* write the new t_hot value */
+	reg_val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
+	reg_val |= (t_hot <<
+			__ffs(temp_sensor->registers->threshold_thot_mask));
+	omap_temp_sensor_writel(temp_sensor, reg_val,
+			temp_sensor->registers->bgap_threshold);
+
+	/* Read the current temperature */
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->temp_sensor_ctrl);
+	temp &= (temp_sensor->registers->bgap_dtemp_mask);
+
+	/*
+	 * If user sets the HIGH threshold(t_hot) greater than the current
+	 * temperature(temp) unmask the HOT interrupts
+	 */
+	if (t_hot > temp) {
+		reg_val = omap_temp_sensor_readl(temp_sensor,
+				temp_sensor->registers->bgap_mask_ctrl);
+		reg_val &= ~(temp_sensor->registers->mask_cold_mask);
+		reg_val |= temp_sensor->registers->mask_hot_mask;
+		omap_temp_sensor_writel(temp_sensor, reg_val,
+				temp_sensor->registers->bgap_mask_ctrl);
+	}
+
+	/*
+	 * If current temperature is in-between the hot and cold thresholds,
+	 * Enable both masks.
+	 */
+	if (temp > t_cold && temp < t_hot) {
+		reg_val = omap_temp_sensor_readl(temp_sensor,
+				temp_sensor->registers->bgap_mask_ctrl);
+		reg_val |= temp_sensor->registers->mask_cold_mask;
+		reg_val |= temp_sensor->registers->mask_hot_mask;
+		omap_temp_sensor_writel(temp_sensor, reg_val,
+				OMAP4460_BGAP_CTRL_OFFSET);
+	}
+	/*
+	 * else no need to do anything since HW will immediately compare
+	 * the new threshold and generate interrupt accordingly
+	 */
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	return count;
+}
+
+static ssize_t show_temp_max_hyst(struct device *dev,
+		struct device_attribute *devattr, char *buf)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+	u32			temp;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_threshold);
+	temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
+		__ffs(temp_sensor->registers->threshold_tcold_mask);
+
+	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
+		dev_err(dev, "invalid value\n");
+		goto out;
+	}
+
+	temp = adc_to_temp_conversion(temp);
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+
+	return snprintf(buf, 16, "%d\n", temp);
+}
+
+static ssize_t set_temp_max_hyst(struct device *dev,
+				 struct device_attribute *devattr,
+				 const char *buf, size_t count)
+{
+	struct omap_temp_sensor		*temp_sensor = dev_get_drvdata(dev);
+	u32				reg_val, t_hot, t_cold, temp;
+	long				val;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	if (strict_strtol(buf, 10, &val)) {
+		count = -EINVAL;
+		goto out;
+	}
+
+	t_cold = temp_to_adc_conversion(val);
+	if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
+		dev_err(dev, "invalid range");
+		count = -EINVAL;
+		goto out;
+	}
+
+	/* obtain the T HOT value */
+	t_hot = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
+			__ffs(temp_sensor->registers->threshold_thot_mask);
+
+	if (t_cold > t_hot) {
+		dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
+		count = -EINVAL;
+		goto out;
+	}
+
+	/* write the new t_cold value */
+	reg_val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_threshold);
+	reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
+	reg_val |= (t_cold <<
+			__ffs(temp_sensor->registers->threshold_tcold_mask));
+	omap_temp_sensor_writel(temp_sensor, reg_val,
+			temp_sensor->registers->bgap_threshold);
+
+	/* Read the current temperature */
+	temp = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->temp_sensor_ctrl);
+	temp &= (temp_sensor->registers->bgap_dtemp_mask);
+
+	/*
+	 * If user sets the LOW threshold(t_cold) lower than the current
+	 * temperature(temp) unmask the COLD interrupts
+	 */
+	if (t_cold < temp) {
+		reg_val = omap_temp_sensor_readl(temp_sensor,
+				temp_sensor->registers->bgap_mask_ctrl);
+		reg_val &= ~(temp_sensor->registers->mask_hot_mask);
+		reg_val |= temp_sensor->registers->mask_cold_mask;
+		omap_temp_sensor_writel(temp_sensor, reg_val,
+			temp_sensor->registers->bgap_mask_ctrl);
+	}
+
+	/*
+	 * If current temperature is in-between the hot and cold thresholds,
+	 * Enable both masks.
+	 */
+	if (temp < t_hot && temp > t_cold) {
+		reg_val = omap_temp_sensor_readl(temp_sensor,
+				temp_sensor->registers->bgap_mask_ctrl);
+		reg_val |= temp_sensor->registers->mask_cold_mask;
+		reg_val |= temp_sensor->registers->mask_hot_mask;
+		omap_temp_sensor_writel(temp_sensor, reg_val,
+				temp_sensor->registers->bgap_mask_ctrl);
+	}
+
+	/*
+	 * else no need to do anything since HW will immediately compare
+	 * the new threshold and generate interrupt accordingly
+	 */
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	return count;
+}
+
+static ssize_t show_update_rate(struct device *dev,
+			struct device_attribute *devattr, char *buf)
+{
+	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
+	u32			temp = 0, ret = 0;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	if (!temp_sensor->clk_rate) {
+		dev_err(dev, "clk_rate is NULL\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_counter);
+	temp = (temp & temp_sensor->registers->counter_mask) >>
+			__ffs(temp_sensor->registers->counter_mask);
+	temp = temp * 1000 / (temp_sensor->clk_rate);
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	if (!ret)
+		return sprintf(buf, "%d\n", temp);
+	else
+		return ret;
+}
+
+static ssize_t set_update_rate(struct device *dev,
+			       struct device_attribute *devattr,
+			       const char *buf, size_t count)
+{
+	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
+	u32			reg_val;
+	long			val;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	if (strict_strtol(buf, 10, &val)) {
+		count = -EINVAL;
+		goto out;
+	}
+
+	val *= temp_sensor->clk_rate / 1000;
+	reg_val = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_counter);
+
+	reg_val &= ~(temp_sensor->registers->counter_mask);
+	reg_val |= val;
+	omap_temp_sensor_writel(temp_sensor, reg_val,
+			temp_sensor->registers->bgap_counter);
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	return count;
+}
+
+static int omap_temp_sensor_read_temp(struct device *dev,
+				      struct device_attribute *devattr,
+				      char *buf)
+{
+	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
+	int			temp, ret = 0;
+
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->temp_sensor_ctrl);
+	temp &= temp_sensor->registers->bgap_dtemp_mask;
+
+	if (!temp_sensor->is_efuse_valid)
+		dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
+
+	/* look up for temperature in the table and return the temperature */
+	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
+		dev_err(dev, "invalid adc code reported %d", temp);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
+
+out:
+	mutex_unlock(&temp_sensor->sensor_mutex);
+	if (!ret)
+		return sprintf(buf, "%d\n", temp);
+	else
+		return ret;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
+			  NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
+			  set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
+			  set_temp_max_hyst, 0);
+static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
+			  set_update_rate, 0);
+
+static struct attribute *omap_temp_sensor_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_update_rate.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group omap_temp_sensor_group = {
+	.attrs = omap_temp_sensor_attributes,
+};
+
+static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
+{
+	u32 ret = 0, temp;
+
+	if (temp_sensor->clk_on) {
+		dev_err(temp_sensor->hwmon_dev, "clock already on\n");
+		goto out;
+	}
+
+	ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
+	if (ret < 0) {
+		dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->temp_sensor_ctrl);
+	temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
+	/* BGAP_TEMPSOFF should be reset to 0 */
+	omap_temp_sensor_writel(temp_sensor, temp,
+				temp_sensor->registers->temp_sensor_ctrl);
+	temp_sensor->clk_on = 1;
+out:
+	return ret;
+}
+
+static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
+{
+	u32 temp, ret = 0;
+	unsigned long timeout;
+
+	if (!temp_sensor->clk_on) {
+		dev_err(temp_sensor->hwmon_dev, "clock already off\n");
+		goto out;
+	}
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->temp_sensor_ctrl);
+	temp |= temp_sensor->registers->bgap_tempsoff_mask;
+
+	/* BGAP_TEMPSOFF should be set to 1 before gating clock */
+	omap_temp_sensor_writel(temp_sensor, temp,
+			temp_sensor->registers->temp_sensor_ctrl);
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_status);
+	timeout = jiffies + msecs_to_jiffies(5);
+
+	/* wait till the clean stop bit is set or till the timeout exppires */
+	while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
+		!(time_after(jiffies, timeout))) {
+		temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_status);
+		usleep_range(500, 2000);
+	}
+
+	if (time_after(jiffies, timeout))
+		dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
+	/* Gate the clock */
+	ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
+	if (ret < 0) {
+		dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
+		ret = -EINVAL;
+		goto out;
+	}
+	temp_sensor->clk_on = 0;
+out:
+	return ret;
+}
+static irqreturn_t omap_talert_irq_handler(int irq, void *data)
+{
+	struct omap_temp_sensor		*temp_sensor;
+	int				t_hot, t_cold, temp;
+
+	temp_sensor = data;
+	mutex_lock(&temp_sensor->sensor_mutex);
+
+	/* Read the status of t_hot */
+	t_hot = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_status)
+			& temp_sensor->registers->status_hot_mask;
+
+	/* Read the status of t_cold */
+	t_cold = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_status)
+			& temp_sensor->registers->status_cold_mask;
+
+	temp = omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_mask_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) {
+		temp &= ~(temp_sensor->registers->mask_hot_mask);
+		temp |= temp_sensor->registers->mask_cold_mask;
+	} else if (t_cold) {
+		temp &= ~(temp_sensor->registers->mask_cold_mask);
+		temp |= temp_sensor->registers->mask_hot_mask;
+	}
+
+	omap_temp_sensor_writel(temp_sensor, temp,
+		temp_sensor->registers->bgap_mask_ctrl);
+
+	/* kobject_uvent to user space telling thermal threshold crossed */
+	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
+
+	mutex_unlock(&temp_sensor->sensor_mutex);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
+{
+	struct omap_temp_sensor_pdata	*pdata	= pdev->dev.platform_data;
+	struct omap_temp_sensor		*temp_sensor;
+	struct resource			*mem;
+	int				ret = 0;
+	int				val, clk_rate;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data missing\n");
+		return -EINVAL;
+	}
+
+	temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
+	if (!temp_sensor)
+		return -ENOMEM;
+
+	mutex_init(&temp_sensor->sensor_mutex);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource\n");
+		ret = -EINVAL;
+		goto plat_res_err;
+	}
+
+	temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
+	if (temp_sensor->irq = -ENXIO) {
+		dev_err(&pdev->dev, "get_irq_byname failed\n");
+		ret = temp_sensor->irq;
+		goto plat_res_err;
+	}
+
+	temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
+	temp_sensor->clock = NULL;
+	temp_sensor->registers = pdata->registers;
+	temp_sensor->hwmon_dev = &pdev->dev;
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_irq_safe(&pdev->dev);
+
+	/*
+	 * check if the efuse has a non-zero value if not
+	 * it is an untrimmed sample and the temperatures
+	 * may not be accurate
+	 */
+
+	if (omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->bgap_efuse))
+		temp_sensor->is_efuse_valid = 1;
+
+	platform_set_drvdata(pdev, temp_sensor);
+	dev_set_drvdata(&pdev->dev, temp_sensor);
+	temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
+	if (IS_ERR(temp_sensor->clock)) {
+		ret = PTR_ERR(temp_sensor->clock);
+		dev_err(temp_sensor->hwmon_dev,
+			"unable to get fclk: %d\n", ret);
+		ret = -EINVAL;
+		goto plat_res_err;
+	}
+
+	ret = omap_temp_sensor_clk_enable(temp_sensor);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot enable temp sensor\n");
+		goto clken_err;
+	}
+
+	clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
+	if (clk_rate < 1000000 || clk_rate = 0xffffffff) {
+		dev_err(&pdev->dev, "Error round rate\n");
+		goto clken_err;
+	}
+
+	ret = clk_set_rate(temp_sensor->clock, clk_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot set clock rate\n");
+		goto clken_err;
+	}
+
+	temp_sensor->clk_rate = clk_rate;
+	omap_enable_continuous_mode(temp_sensor, 1);
+	omap_configure_temp_sensor_thresholds(temp_sensor);
+	/* 1 ms */
+	omap_configure_temp_sensor_counter(temp_sensor, 1);
+
+	/* Wait till the first conversion is done wait for at least 1ms */
+	usleep_range(1000, 2000);
+
+	/* Read the temperature once due to hw issue*/
+	omap_temp_sensor_readl(temp_sensor,
+			temp_sensor->registers->temp_sensor_ctrl);
+
+	/* Set 2 seconds time as default counter */
+	omap_configure_temp_sensor_counter(temp_sensor,
+						temp_sensor->clk_rate * 2);
+
+	temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(temp_sensor->hwmon_dev)) {
+		dev_err(&pdev->dev, "hwmon_device_register failed.\n");
+		ret = PTR_ERR(temp_sensor->hwmon_dev);
+		goto hwmon_reg_err;
+	}
+
+	ret = sysfs_create_group(&pdev->dev.kobj,
+				 &omap_temp_sensor_group);
+	if (ret) {
+		dev_err(&pdev->dev, "could not create sysfs files\n");
+		goto sysfs_create_err;
+	}
+
+	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
+
+	ret = request_threaded_irq(temp_sensor->irq, NULL,
+		omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+			"temp_sensor", temp_sensor);
+	if (ret) {
+		dev_err(&pdev->dev, "Request threaded irq failed.\n");
+		goto req_irq_err;
+	}
+
+	/* unmask the T_COLD and unmask T_HOT at init */
+	val = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_mask_ctrl);
+	val |= temp_sensor->registers->mask_cold_mask
+		| temp_sensor->registers->mask_hot_mask;
+
+	omap_temp_sensor_writel(temp_sensor, val,
+		temp_sensor->registers->bgap_mask_ctrl);
+
+	return 0;
+
+req_irq_err:
+	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
+	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
+				&omap_temp_sensor_group);
+sysfs_create_err:
+	hwmon_device_unregister(&pdev->dev);
+hwmon_reg_err:
+	omap_temp_sensor_clk_disable(temp_sensor);
+clken_err:
+	if (temp_sensor->clock)
+		clk_put(temp_sensor->clock);
+plat_res_err:
+	mutex_destroy(&temp_sensor->sensor_mutex);
+	kfree(temp_sensor);
+	return ret;
+}
+
+static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
+{
+	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(&pdev->dev);
+	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
+	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
+			&omap_temp_sensor_group);
+	omap_temp_sensor_clk_disable(temp_sensor);
+	clk_put(temp_sensor->clock);
+	platform_set_drvdata(pdev, NULL);
+	free_irq(temp_sensor->irq, temp_sensor);
+	mutex_destroy(&temp_sensor->sensor_mutex);
+	kfree(temp_sensor);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
+{
+	temp_sensor->temp_sensor_ctrl = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->temp_sensor_ctrl);
+	temp_sensor->bg_ctrl = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_mask_ctrl);
+	temp_sensor->bg_counter = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_counter);
+	temp_sensor->bg_threshold = omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->bgap_threshold);
+	temp_sensor->temp_sensor_tshut_threshold +		omap_temp_sensor_readl(temp_sensor,
+		temp_sensor->registers->thsut_threshold);
+}
+
+static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
+{
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->temp_sensor_ctrl,
+				temp_sensor->registers->temp_sensor_ctrl);
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->bg_ctrl,
+				temp_sensor->registers->bgap_mask_ctrl);
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->bg_counter,
+				temp_sensor->registers->bgap_counter);
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->bg_threshold,
+				temp_sensor->registers->bgap_threshold);
+	omap_temp_sensor_writel(temp_sensor,
+				temp_sensor->temp_sensor_tshut_threshold,
+				temp_sensor->registers->thsut_threshold);
+}
+
+static int omap_temp_sensor_suspend(struct device *dev)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+
+	omap_temp_sensor_save_ctxt(temp_sensor);
+
+	return 0;
+}
+
+static int omap_temp_sensor_resume(struct device *dev)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+
+	omap_temp_sensor_restore_ctxt(temp_sensor);
+
+	return 0;
+}
+
+static int omap_temp_sensor_runtime_suspend(struct device *dev)
+{
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+
+	omap_temp_sensor_save_ctxt(temp_sensor);
+
+	return 0;
+}
+
+static int omap_temp_sensor_runtime_resume(struct device *dev)
+{
+	static int context_loss_count;
+	int temp;
+	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
+
+	temp = omap_device_get_context_loss_count(to_platform_device(dev));
+
+	if (temp != context_loss_count && context_loss_count != 0)
+		omap_temp_sensor_restore_ctxt(temp_sensor);
+
+	context_loss_count = temp;
+
+	return 0;
+}
+
+static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
+	.suspend = omap_temp_sensor_suspend,
+	.resume = omap_temp_sensor_resume,
+	.runtime_suspend = omap_temp_sensor_runtime_suspend,
+	.runtime_resume = omap_temp_sensor_runtime_resume,
+};
+
+#endif
+
+static struct platform_driver omap_temp_sensor_driver = {
+	.probe = omap_temp_sensor_probe,
+	.remove = omap_temp_sensor_remove,
+	.driver = {
+			.name = "omap_temp_sensor",
+#ifdef CONFIG_PM
+			.pm = &omap_temp_sensor_dev_pm_ops,
+#endif
+		   },
+};
+
+int __init omap_temp_sensor_init(void)
+{
+	return platform_driver_register(&omap_temp_sensor_driver);
+}
+module_init(omap_temp_sensor_init);
+
+static void __exit omap_temp_sensor_exit(void)
+{
+	platform_driver_unregister(&omap_temp_sensor_driver);
+}
+module_exit(omap_temp_sensor_exit);
+
+MODULE_DESCRIPTION("OMAP446X temperature sensor Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
-- 
1.7.0.4


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply related	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 5/6] OMAP4460: Temperature sensor data
  2011-08-10 12:37   ` [lm-sensors] " Keerthy
@ 2011-08-10 12:37     ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:37 UTC (permalink / raw)
  To: Keerthy; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

[-- Attachment #1: Type: text/plain, Size: 2233 bytes --]

Hi,

On Wed, Aug 10, 2011 at 05:55:21PM +0530, Keerthy wrote:
> The register set and the
> bit fields might vary across OMAP versions. Hence
> creating a structure comprising of all the registers
> and bit fields to make the driver uniform for all the
> versions with different register sets. The data file
> contains the structure populated with register offsets
> and bit fields corresponding to OMAP4460 on die sensor.
> 
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  arch/arm/mach-omap2/temp_sensor4460_data.c |   63 ++++++++++++++++++++++++++++
>  1 files changed, 63 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/temp_sensor4460_data.c
> 
> diff --git a/arch/arm/mach-omap2/temp_sensor4460_data.c b/arch/arm/mach-omap2/temp_sensor4460_data.c
> new file mode 100644
> index 0000000..294963d
> --- /dev/null
> +++ b/arch/arm/mach-omap2/temp_sensor4460_data.c
> @@ -0,0 +1,63 @@
> +/*
> + * OMAP4460 on die Temperature sensor data file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@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/slab.h>
> +#include "control.h"
> +#include <plat/temperature_sensor.h>
> +
> +/*
> + * OMAP4460 has one instance of thermal sensor for MPU
> + * need to describe the individual bit fields
> + */
> +struct omap_temp_sensor_registers omap_mpu_temp_sensor_registers = {

this is used on previous patch, so you have a compilation error.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 5/6] OMAP4460: Temperature sensor data
@ 2011-08-10 12:37     ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:37 UTC (permalink / raw)
  To: Keerthy; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak


[-- Attachment #1.1: Type: text/plain, Size: 2233 bytes --]

Hi,

On Wed, Aug 10, 2011 at 05:55:21PM +0530, Keerthy wrote:
> The register set and the
> bit fields might vary across OMAP versions. Hence
> creating a structure comprising of all the registers
> and bit fields to make the driver uniform for all the
> versions with different register sets. The data file
> contains the structure populated with register offsets
> and bit fields corresponding to OMAP4460 on die sensor.
> 
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  arch/arm/mach-omap2/temp_sensor4460_data.c |   63 ++++++++++++++++++++++++++++
>  1 files changed, 63 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/temp_sensor4460_data.c
> 
> diff --git a/arch/arm/mach-omap2/temp_sensor4460_data.c b/arch/arm/mach-omap2/temp_sensor4460_data.c
> new file mode 100644
> index 0000000..294963d
> --- /dev/null
> +++ b/arch/arm/mach-omap2/temp_sensor4460_data.c
> @@ -0,0 +1,63 @@
> +/*
> + * OMAP4460 on die Temperature sensor data file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@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/slab.h>
> +#include "control.h"
> +#include <plat/temperature_sensor.h>
> +
> +/*
> + * OMAP4460 has one instance of thermal sensor for MPU
> + * need to describe the individual bit fields
> + */
> +struct omap_temp_sensor_registers omap_mpu_temp_sensor_registers = {

this is used on previous patch, so you have a compilation error.

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-10 12:36     ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
@ 2011-08-10 12:41       ` Tony Lindgren
  -1 siblings, 0 replies; 105+ messages in thread
From: Tony Lindgren @ 2011-08-10 12:41 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Keerthy, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

* Felipe Balbi <balbi@ti.com> [110810 05:31]:
> 
> On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
> > +
> > +int __init omap_devinit_temp_sensor(void)
> > +{
> > +	if (!cpu_is_omap446x())
> > +		return 0;
> > +
> > +	return omap_hwmod_for_each_by_class("temperature_sensor",
> > +			temp_sensor_dev_init, NULL);
> > +}
> > +
> > +arch_initcall(omap_devinit_temp_sensor);
> 
> I really dislike people adding more and more *initcall() to their pieces
> of code. But Tony is the final Judge.

Yes how about making this just a regular device driver and have it
live under drivers/ somewhere?

Or is there some reason why this could not be a loadable module?

Regards,

Tony

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-10 12:41       ` Tony Lindgren
  0 siblings, 0 replies; 105+ messages in thread
From: Tony Lindgren @ 2011-08-10 12:41 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Keerthy, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

* Felipe Balbi <balbi@ti.com> [110810 05:31]:
> 
> On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
> > +
> > +int __init omap_devinit_temp_sensor(void)
> > +{
> > +	if (!cpu_is_omap446x())
> > +		return 0;
> > +
> > +	return omap_hwmod_for_each_by_class("temperature_sensor",
> > +			temp_sensor_dev_init, NULL);
> > +}
> > +
> > +arch_initcall(omap_devinit_temp_sensor);
> 
> I really dislike people adding more and more *initcall() to their pieces
> of code. But Tony is the final Judge.

Yes how about making this just a regular device driver and have it
live under drivers/ somewhere?

Or is there some reason why this could not be a loadable module?

Regards,

Tony

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-10 12:37   ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Keerthy
  (?)
@ 2011-08-10 12:46     ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:46 UTC (permalink / raw)
  To: Keerthy
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

[-- Attachment #1: Type: text/plain, Size: 36388 bytes --]

Hi,

(why aren't below in Cc ?

HARDWARE MONITORING
M:	Jean Delvare <khali@linux-fr.org>
M:	Guenter Roeck <guenter.roeck@ericsson.com>
L:	lm-sensors@lm-sensors.org
W:	http://www.lm-sensors.org/
T:	quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
S:	Maintained
F:	Documentation/hwmon/
F:	drivers/hwmon/
F:	include/linux/hwmon*.h)

On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
> On chip temperature sensor driver. The driver monitors the temperature of
> the MPU subsystem of the OMAP4. It sends notifications to the user space if
> the temperature crosses user defined thresholds via kobject_uevent interface.
> The user is allowed to configure the temperature thresholds vis sysfs nodes
> exposed using hwmon interface.
> 
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  drivers/hwmon/Kconfig            |   11 +
>  drivers/hwmon/Makefile           |    1 +
>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 962 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 5f888f7..9c9cd8b 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called f71805f.
>  
> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
> +	bool "OMAP on-die temperature sensor hwmon driver"
> +	depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
> +	help
> +	  If you say yes here you get support for hardware
> +	  monitoring features of the OMAP on die temperature
> +	  sensor.
> +
> +	  Continuous conversion programmable delay
> +	  mode is used for temperature conversion.
> +
>  config SENSORS_F71882FG
>  	tristate "Fintek F71882FG and compatibles"
>  	help
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 28061cf..d0f89f5 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
>  obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
>  obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>  obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
>  obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
>  obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> new file mode 100644
> index 0000000..15e2559
> --- /dev/null
> +++ b/drivers/hwmon/omap_temp_sensor.c
> @@ -0,0 +1,950 @@
> +/*
> + * OMAP4 Temperature sensor driver file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@ti.com>
> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> +#include <linux/clk.h>

why ??

> +#include <linux/io.h>
> +#include <linux/debugfs.h>

why ??

> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/init.h>
> +#include <plat/omap_device.h>

why ??

> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/jiffies.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/stddef.h>
> +#include <linux/sysfs.h>
> +#include <linux/err.h>
> +#include <linux/types.h>
> +#include <linux/mutex.h>
> +#include <linux/pm_runtime.h>
> +#include <plat/common.h>

why ?

> +#include <plat/temperature_sensor.h>

why ?

> +#include <mach/ctrl_module_core_44xx.h>

why ?

> +#include <mach/gpio.h>

linux/gpio.h for crying out loud... how many times Russell has to say
the exact same thing ??????

> +#define TSHUT_THRESHOLD_HOT	122000	/* 122 deg C */
> +#define TSHUT_THRESHOLD_COLD	100000	/* 100 deg C */
> +#define BGAP_THRESHOLD_T_HOT	73000	/* 73 deg C */
> +#define BGAP_THRESHOLD_T_COLD	71000	/* 71 deg C */
> +#define OMAP_ADC_START_VALUE	530
> +#define OMAP_ADC_END_VALUE	923
> +
> +/*
> + * omap_temp_sensor structure
> + * @hwmon_dev - device pointer
> + * @clock - Clock pointer
> + * @registers - Pointer to structure with register offsets and bitfields
> + * @sensor_mutex - Mutex for sysfs, irq and PM
> + * @irq - MPU Irq number for thermal alert
> + * @phy_base - Physical base of the temp I/O
> + * @clk_rate - Holds current clock rate
> + * @temp_sensor_ctrl - temp sensor control register value
> + * @bg_ctrl - bandgap ctrl register value
> + * @bg_counter - bandgap counter value
> + * @bg_threshold - bandgap threshold register value
> + * @temp_sensor_tshut_threshold - bandgap tshut register value
> + * @is_efuse_valid - Flag to determine if efuse is valid or not
> + * @clk_on - Manages the current clock state
> + */
> +struct omap_temp_sensor {
> +	struct device		*hwmon_dev;
> +	struct clk		*clock;
> +	struct omap_temp_sensor_registers *registers;
> +	struct mutex		sensor_mutex; /* Mutex for sysfs, irq and PM */
> +	unsigned int		irq;
> +	void __iomem		*phy_base;
> +	u32			clk_rate;
> +	u32			temp_sensor_ctrl;
> +	u32			bg_ctrl;
> +	u32			bg_counter;
> +	u32			bg_threshold;
> +	u32			temp_sensor_tshut_threshold;
> +	bool                    is_efuse_valid;
> +	bool                    clk_on;
> +};
> +
> +/*
> + * Temperature values in milli degree celsius
> + * ADC code values from 530 to 923
> + */
> +static int adc_to_temp[] = {
> +	-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
> +};
> +
> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
> +					    *temp_sensor, u32 reg)
> +{
> +	return __raw_readl(temp_sensor->phy_base + reg);
> +}
> +
> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
> +				    u32 val, u32 reg)
> +{
> +	__raw_writel(val, (temp_sensor->phy_base + reg));
> +}
> +
> +static int adc_to_temp_conversion(int adc_val)
> +{
> +	return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
> +}
> +
> +static int temp_to_adc_conversion(long temp)
> +{
> +	int i;
> +
> +	for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
> +		if (temp < adc_to_temp[i])
> +			return OMAP_ADC_START_VALUE + i - 1;
> +
> +	return -EINVAL;
> +}
> +
> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
> +						  *temp_sensor)
> +{
> +	u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
> +
> +	t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
> +	t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
> +
> +	/* Configure the TALERT thresholds */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
> +		(t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +		temp_sensor->registers->bgap_threshold);
> +
> +	tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
> +	tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
> +
> +	/* Configure the TSHUT thresholds */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->thsut_threshold);
> +	temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
> +	    | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +			temp_sensor->registers->thsut_threshold);
> +}
> +
> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
> +					       *temp_sensor, u32 counter)
> +{
> +	u32 val;
> +
> +	val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +	val &= ~(temp_sensor->registers->counter_mask);
> +	val |= (counter << __ffs(temp_sensor->registers->counter_mask));
> +	omap_temp_sensor_writel(temp_sensor, val,
> +			temp_sensor->registers->bgap_counter);
> +}
> +
> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
> +					bool enable)
> +{
> +	u32 val;
> +
> +	val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_mode_ctrl);
> +
> +	if (enable)
> +		val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
> +	else
> +		val &= ~(temp_sensor->registers->mode_ctrl_mask);
> +
> +	omap_temp_sensor_writel(temp_sensor, val,
> +			temp_sensor->registers->bgap_mode_ctrl);
> +}
> +
> +/* Sysfs hook functions */
> +
> +static ssize_t show_temp_max(struct device *dev,
> +			struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +	int temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	temp = (temp & temp_sensor->registers->threshold_thot_mask)
> +			>> __ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid value\n");
> +		goto out;
> +	}
> +	temp = adc_to_temp_conversion(temp);
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return snprintf(buf, 16, "%d\n", temp);
> +}
> +
> +static ssize_t set_temp_max(struct device *dev,
> +			    struct device_attribute *devattr,
> +			    const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	long			val;
> +	u32			reg_val, t_cold, t_hot, temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	t_hot = temp_to_adc_conversion(val);
> +	if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
> +		dev_err(dev, "invalid range\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* obtain the T cold value */
> +	t_cold = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
> +			__ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +	if (t_hot < t_cold) {
> +		dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* write the new t_hot value */
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
> +	reg_val |= (t_hot <<
> +			__ffs(temp_sensor->registers->threshold_thot_mask));
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_threshold);
> +
> +	/* Read the current temperature */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +	/*
> +	 * If user sets the HIGH threshold(t_hot) greater than the current
> +	 * temperature(temp) unmask the HOT interrupts
> +	 */
> +	if (t_hot > temp) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val &= ~(temp_sensor->registers->mask_cold_mask);
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * If current temperature is in-between the hot and cold thresholds,
> +	 * Enable both masks.
> +	 */
> +	if (temp > t_cold && temp < t_hot) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				OMAP4460_BGAP_CTRL_OFFSET);
> +	}
> +	/*
> +	 * else no need to do anything since HW will immediately compare
> +	 * the new threshold and generate interrupt accordingly
> +	 */
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static ssize_t show_temp_max_hyst(struct device *dev,
> +		struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +	u32			temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_threshold);
> +	temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
> +		__ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid value\n");
> +		goto out;
> +	}
> +
> +	temp = adc_to_temp_conversion(temp);
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return snprintf(buf, 16, "%d\n", temp);
> +}
> +
> +static ssize_t set_temp_max_hyst(struct device *dev,
> +				 struct device_attribute *devattr,
> +				 const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor		*temp_sensor = dev_get_drvdata(dev);
> +	u32				reg_val, t_hot, t_cold, temp;
> +	long				val;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	t_cold = temp_to_adc_conversion(val);
> +	if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid range");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* obtain the T HOT value */
> +	t_hot = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
> +			__ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +	if (t_cold > t_hot) {
> +		dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* write the new t_cold value */
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
> +	reg_val |= (t_cold <<
> +			__ffs(temp_sensor->registers->threshold_tcold_mask));
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_threshold);
> +
> +	/* Read the current temperature */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +	/*
> +	 * If user sets the LOW threshold(t_cold) lower than the current
> +	 * temperature(temp) unmask the COLD interrupts
> +	 */
> +	if (t_cold < temp) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val &= ~(temp_sensor->registers->mask_hot_mask);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * If current temperature is in-between the hot and cold thresholds,
> +	 * Enable both masks.
> +	 */
> +	if (temp < t_hot && temp > t_cold) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * else no need to do anything since HW will immediately compare
> +	 * the new threshold and generate interrupt accordingly
> +	 */
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static ssize_t show_update_rate(struct device *dev,
> +			struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	u32			temp = 0, ret = 0;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (!temp_sensor->clk_rate) {
> +		dev_err(dev, "clk_rate is NULL\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +	temp = (temp & temp_sensor->registers->counter_mask) >>
> +			__ffs(temp_sensor->registers->counter_mask);

	temp &= ??

> +	temp = temp * 1000 / (temp_sensor->clk_rate);

	temp *= ??

> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	if (!ret)
> +		return sprintf(buf, "%d\n", temp);
> +	else
> +		return ret;
> +}
> +
> +static ssize_t set_update_rate(struct device *dev,
> +			       struct device_attribute *devattr,
> +			       const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	u32			reg_val;
> +	long			val;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	val *= temp_sensor->clk_rate / 1000;
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +
> +	reg_val &= ~(temp_sensor->registers->counter_mask);
> +	reg_val |= val;
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_counter);
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static int omap_temp_sensor_read_temp(struct device *dev,
> +				      struct device_attribute *devattr,
> +				      char *buf)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	int			temp, ret = 0;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= temp_sensor->registers->bgap_dtemp_mask;
> +
> +	if (!temp_sensor->is_efuse_valid)
> +		dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
> +
> +	/* look up for temperature in the table and return the temperature */
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid adc code reported %d", temp);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	if (!ret)
> +		return sprintf(buf, "%d\n", temp);
> +	else
> +		return ret;
> +}
> +
> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
> +			  NULL, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
> +			  set_temp_max, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
> +			  set_temp_max_hyst, 0);
> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
> +			  set_update_rate, 0);
> +
> +static struct attribute *omap_temp_sensor_attributes[] = {
> +	&sensor_dev_attr_temp1_input.dev_attr.attr,
> +	&sensor_dev_attr_temp1_max.dev_attr.attr,
> +	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
> +	&sensor_dev_attr_update_rate.dev_attr.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group omap_temp_sensor_group = {
> +	.attrs = omap_temp_sensor_attributes,
> +};
> +
> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
> +{
> +	u32 ret = 0, temp;
> +
> +	if (temp_sensor->clk_on) {
> +		dev_err(temp_sensor->hwmon_dev, "clock already on\n");
> +		goto out;
> +	}
> +
> +	ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
> +	if (ret < 0) {
> +		dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
> +	/* BGAP_TEMPSOFF should be reset to 0 */
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +				temp_sensor->registers->temp_sensor_ctrl);
> +	temp_sensor->clk_on = 1;

why isn't pm_runtime_get_sync() enough ??

> +out:
> +	return ret;
> +}
> +
> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
> +{
> +	u32 temp, ret = 0;
> +	unsigned long timeout;
> +
> +	if (!temp_sensor->clk_on) {
> +		dev_err(temp_sensor->hwmon_dev, "clock already off\n");
> +		goto out;
> +	}
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp |= temp_sensor->registers->bgap_tempsoff_mask;
> +
> +	/* BGAP_TEMPSOFF should be set to 1 before gating clock */
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status);
> +	timeout = jiffies + msecs_to_jiffies(5);
> +
> +	/* wait till the clean stop bit is set or till the timeout exppires */
> +	while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
> +		!(time_after(jiffies, timeout))) {
> +		temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status);
> +		usleep_range(500, 2000);
> +	}
> +
> +	if (time_after(jiffies, timeout))
> +		dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
> +	/* Gate the clock */
> +	ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
> +	if (ret < 0) {
> +		dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	temp_sensor->clk_on = 0;
> +out:
> +	return ret;
> +}
> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
> +{
> +	struct omap_temp_sensor		*temp_sensor;
> +	int				t_hot, t_cold, temp;
> +
> +	temp_sensor = data;
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	/* Read the status of t_hot */
> +	t_hot = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status)
> +			& temp_sensor->registers->status_hot_mask;
> +
> +	/* Read the status of t_cold */
> +	t_cold = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status)
> +			& temp_sensor->registers->status_cold_mask;
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_mask_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) {
> +		temp &= ~(temp_sensor->registers->mask_hot_mask);
> +		temp |= temp_sensor->registers->mask_cold_mask;
> +	} else if (t_cold) {
> +		temp &= ~(temp_sensor->registers->mask_cold_mask);
> +		temp |= temp_sensor->registers->mask_hot_mask;
> +	}
> +
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +
> +	/* kobject_uvent to user space telling thermal threshold crossed */
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
> +
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
> +{
> +	struct omap_temp_sensor_pdata	*pdata	= pdev->dev.platform_data;
> +	struct omap_temp_sensor		*temp_sensor;
> +	struct resource			*mem;
> +	int				ret = 0;
> +	int				val, clk_rate;
> +
> +	if (!pdata) {
> +		dev_err(&pdev->dev, "platform data missing\n");
> +		return -EINVAL;
> +	}
> +
> +	temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
> +	if (!temp_sensor)
> +		return -ENOMEM;
> +
> +	mutex_init(&temp_sensor->sensor_mutex);
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem) {
> +		dev_err(&pdev->dev, "no mem resource\n");
> +		ret = -EINVAL;
> +		goto plat_res_err;
> +	}
> +
> +	temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
> +	if (temp_sensor->irq == -ENXIO) {
> +		dev_err(&pdev->dev, "get_irq_byname failed\n");
> +		ret = temp_sensor->irq;
> +		goto plat_res_err;
> +	}
> +
> +	temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
> +	temp_sensor->clock = NULL;
> +	temp_sensor->registers = pdata->registers;
> +	temp_sensor->hwmon_dev = &pdev->dev;
> +
> +	pm_runtime_enable(&pdev->dev);
> +	pm_runtime_irq_safe(&pdev->dev);

won't pm_runtime_irq_safe() keep the parent always running, thus
preventing MPU from reaching lower power states ??

> +	/*
> +	 * check if the efuse has a non-zero value if not
> +	 * it is an untrimmed sample and the temperatures
> +	 * may not be accurate
> +	 */
> +
> +	if (omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_efuse))
> +		temp_sensor->is_efuse_valid = 1;
> +
> +	platform_set_drvdata(pdev, temp_sensor);
> +	dev_set_drvdata(&pdev->dev, temp_sensor);

why are you doing the same thing twice ???

> +	temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");

why ?

> +	if (IS_ERR(temp_sensor->clock)) {
> +		ret = PTR_ERR(temp_sensor->clock);
> +		dev_err(temp_sensor->hwmon_dev,
> +			"unable to get fclk: %d\n", ret);
> +		ret = -EINVAL;
> +		goto plat_res_err;
> +	}
> +
> +	ret = omap_temp_sensor_clk_enable(temp_sensor);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Cannot enable temp sensor\n");
> +		goto clken_err;
> +	}
> +
> +	clk_rate = clk_round_rate(temp_sensor->clock, 2000000);

why ?

> +	if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
> +		dev_err(&pdev->dev, "Error round rate\n");
> +		goto clken_err;
> +	}
> +
> +	ret = clk_set_rate(temp_sensor->clock, clk_rate);

why ??

> +	if (ret) {
> +		dev_err(&pdev->dev, "Cannot set clock rate\n");
> +		goto clken_err;
> +	}
> +
> +	temp_sensor->clk_rate = clk_rate;
> +	omap_enable_continuous_mode(temp_sensor, 1);
> +	omap_configure_temp_sensor_thresholds(temp_sensor);
> +	/* 1 ms */
> +	omap_configure_temp_sensor_counter(temp_sensor, 1);
> +
> +	/* Wait till the first conversion is done wait for at least 1ms */
> +	usleep_range(1000, 2000);
> +
> +	/* Read the temperature once due to hw issue*/
> +	omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +
> +	/* Set 2 seconds time as default counter */
> +	omap_configure_temp_sensor_counter(temp_sensor,
> +						temp_sensor->clk_rate * 2);
> +
> +	temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
> +	if (IS_ERR(temp_sensor->hwmon_dev)) {
> +		dev_err(&pdev->dev, "hwmon_device_register failed.\n");
> +		ret = PTR_ERR(temp_sensor->hwmon_dev);
> +		goto hwmon_reg_err;
> +	}
> +
> +	ret = sysfs_create_group(&pdev->dev.kobj,
> +				 &omap_temp_sensor_group);
> +	if (ret) {
> +		dev_err(&pdev->dev, "could not create sysfs files\n");
> +		goto sysfs_create_err;
> +	}
> +
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
> +
> +	ret = request_threaded_irq(temp_sensor->irq, NULL,
> +		omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> +			"temp_sensor", temp_sensor);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Request threaded irq failed.\n");
> +		goto req_irq_err;
> +	}
> +
> +	/* unmask the T_COLD and unmask T_HOT at init */
> +	val = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +	val |= temp_sensor->registers->mask_cold_mask
> +		| temp_sensor->registers->mask_hot_mask;
> +
> +	omap_temp_sensor_writel(temp_sensor, val,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +
> +	return 0;
> +
> +req_irq_err:
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
> +	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
> +				&omap_temp_sensor_group);
> +sysfs_create_err:
> +	hwmon_device_unregister(&pdev->dev);
> +hwmon_reg_err:
> +	omap_temp_sensor_clk_disable(temp_sensor);
> +clken_err:
> +	if (temp_sensor->clock)
> +		clk_put(temp_sensor->clock);
> +plat_res_err:
> +	mutex_destroy(&temp_sensor->sensor_mutex);
> +	kfree(temp_sensor);
> +	return ret;
> +}
> +
> +static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
> +{
> +	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
> +
> +	hwmon_device_unregister(&pdev->dev);
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
> +	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
> +			&omap_temp_sensor_group);
> +	omap_temp_sensor_clk_disable(temp_sensor);
> +	clk_put(temp_sensor->clock);
> +	platform_set_drvdata(pdev, NULL);
> +	free_irq(temp_sensor->irq, temp_sensor);
> +	mutex_destroy(&temp_sensor->sensor_mutex);
> +	kfree(temp_sensor);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
> +{
> +	temp_sensor->temp_sensor_ctrl = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp_sensor->bg_ctrl = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +	temp_sensor->bg_counter = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_counter);
> +	temp_sensor->bg_threshold = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_threshold);
> +	temp_sensor->temp_sensor_tshut_threshold =
> +		omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->thsut_threshold);
> +}
> +
> +static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
> +{
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->temp_sensor_ctrl,
> +				temp_sensor->registers->temp_sensor_ctrl);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_ctrl,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_counter,
> +				temp_sensor->registers->bgap_counter);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_threshold,
> +				temp_sensor->registers->bgap_threshold);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->temp_sensor_tshut_threshold,
> +				temp_sensor->registers->thsut_threshold);
> +}
> +
> +static int omap_temp_sensor_suspend(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_save_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_resume(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_restore_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_runtime_suspend(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_save_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_runtime_resume(struct device *dev)
> +{
> +	static int context_loss_count;
> +	int temp;
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	temp = omap_device_get_context_loss_count(to_platform_device(dev));
> +
> +	if (temp != context_loss_count && context_loss_count != 0)
> +		omap_temp_sensor_restore_ctxt(temp_sensor);
> +
> +	context_loss_count = temp;
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
> +	.suspend = omap_temp_sensor_suspend,
> +	.resume = omap_temp_sensor_resume,
> +	.runtime_suspend = omap_temp_sensor_runtime_suspend,
> +	.runtime_resume = omap_temp_sensor_runtime_resume,
> +};
> +
> +#endif
> +
> +static struct platform_driver omap_temp_sensor_driver = {
> +	.probe = omap_temp_sensor_probe,
> +	.remove = omap_temp_sensor_remove,
> +	.driver = {
> +			.name = "omap_temp_sensor",
> +#ifdef CONFIG_PM
> +			.pm = &omap_temp_sensor_dev_pm_ops,
> +#endif
> +		   },
> +};
> +
> +int __init omap_temp_sensor_init(void)
> +{
> +	return platform_driver_register(&omap_temp_sensor_driver);
> +}
> +module_init(omap_temp_sensor_init);
> +
> +static void __exit omap_temp_sensor_exit(void)
> +{
> +	platform_driver_unregister(&omap_temp_sensor_driver);
> +}
> +module_exit(omap_temp_sensor_exit);
> +
> +MODULE_DESCRIPTION("OMAP446X temperature sensor Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> +MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
> -- 
> 1.7.0.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-10 12:46     ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

(why aren't below in Cc ?

HARDWARE MONITORING
M:	Jean Delvare <khali@linux-fr.org>
M:	Guenter Roeck <guenter.roeck@ericsson.com>
L:	lm-sensors at lm-sensors.org
W:	http://www.lm-sensors.org/
T:	quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
S:	Maintained
F:	Documentation/hwmon/
F:	drivers/hwmon/
F:	include/linux/hwmon*.h)

On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
> On chip temperature sensor driver. The driver monitors the temperature of
> the MPU subsystem of the OMAP4. It sends notifications to the user space if
> the temperature crosses user defined thresholds via kobject_uevent interface.
> The user is allowed to configure the temperature thresholds vis sysfs nodes
> exposed using hwmon interface.
> 
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  drivers/hwmon/Kconfig            |   11 +
>  drivers/hwmon/Makefile           |    1 +
>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 962 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 5f888f7..9c9cd8b 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called f71805f.
>  
> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
> +	bool "OMAP on-die temperature sensor hwmon driver"
> +	depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
> +	help
> +	  If you say yes here you get support for hardware
> +	  monitoring features of the OMAP on die temperature
> +	  sensor.
> +
> +	  Continuous conversion programmable delay
> +	  mode is used for temperature conversion.
> +
>  config SENSORS_F71882FG
>  	tristate "Fintek F71882FG and compatibles"
>  	help
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 28061cf..d0f89f5 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
>  obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
>  obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>  obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
>  obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
>  obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> new file mode 100644
> index 0000000..15e2559
> --- /dev/null
> +++ b/drivers/hwmon/omap_temp_sensor.c
> @@ -0,0 +1,950 @@
> +/*
> + * OMAP4 Temperature sensor driver file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@ti.com>
> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> +#include <linux/clk.h>

why ??

> +#include <linux/io.h>
> +#include <linux/debugfs.h>

why ??

> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/init.h>
> +#include <plat/omap_device.h>

why ??

> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/jiffies.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/stddef.h>
> +#include <linux/sysfs.h>
> +#include <linux/err.h>
> +#include <linux/types.h>
> +#include <linux/mutex.h>
> +#include <linux/pm_runtime.h>
> +#include <plat/common.h>

why ?

> +#include <plat/temperature_sensor.h>

why ?

> +#include <mach/ctrl_module_core_44xx.h>

why ?

> +#include <mach/gpio.h>

linux/gpio.h for crying out loud... how many times Russell has to say
the exact same thing ??????

> +#define TSHUT_THRESHOLD_HOT	122000	/* 122 deg C */
> +#define TSHUT_THRESHOLD_COLD	100000	/* 100 deg C */
> +#define BGAP_THRESHOLD_T_HOT	73000	/* 73 deg C */
> +#define BGAP_THRESHOLD_T_COLD	71000	/* 71 deg C */
> +#define OMAP_ADC_START_VALUE	530
> +#define OMAP_ADC_END_VALUE	923
> +
> +/*
> + * omap_temp_sensor structure
> + * @hwmon_dev - device pointer
> + * @clock - Clock pointer
> + * @registers - Pointer to structure with register offsets and bitfields
> + * @sensor_mutex - Mutex for sysfs, irq and PM
> + * @irq - MPU Irq number for thermal alert
> + * @phy_base - Physical base of the temp I/O
> + * @clk_rate - Holds current clock rate
> + * @temp_sensor_ctrl - temp sensor control register value
> + * @bg_ctrl - bandgap ctrl register value
> + * @bg_counter - bandgap counter value
> + * @bg_threshold - bandgap threshold register value
> + * @temp_sensor_tshut_threshold - bandgap tshut register value
> + * @is_efuse_valid - Flag to determine if efuse is valid or not
> + * @clk_on - Manages the current clock state
> + */
> +struct omap_temp_sensor {
> +	struct device		*hwmon_dev;
> +	struct clk		*clock;
> +	struct omap_temp_sensor_registers *registers;
> +	struct mutex		sensor_mutex; /* Mutex for sysfs, irq and PM */
> +	unsigned int		irq;
> +	void __iomem		*phy_base;
> +	u32			clk_rate;
> +	u32			temp_sensor_ctrl;
> +	u32			bg_ctrl;
> +	u32			bg_counter;
> +	u32			bg_threshold;
> +	u32			temp_sensor_tshut_threshold;
> +	bool                    is_efuse_valid;
> +	bool                    clk_on;
> +};
> +
> +/*
> + * Temperature values in milli degree celsius
> + * ADC code values from 530 to 923
> + */
> +static int adc_to_temp[] = {
> +	-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
> +};
> +
> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
> +					    *temp_sensor, u32 reg)
> +{
> +	return __raw_readl(temp_sensor->phy_base + reg);
> +}
> +
> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
> +				    u32 val, u32 reg)
> +{
> +	__raw_writel(val, (temp_sensor->phy_base + reg));
> +}
> +
> +static int adc_to_temp_conversion(int adc_val)
> +{
> +	return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
> +}
> +
> +static int temp_to_adc_conversion(long temp)
> +{
> +	int i;
> +
> +	for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
> +		if (temp < adc_to_temp[i])
> +			return OMAP_ADC_START_VALUE + i - 1;
> +
> +	return -EINVAL;
> +}
> +
> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
> +						  *temp_sensor)
> +{
> +	u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
> +
> +	t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
> +	t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
> +
> +	/* Configure the TALERT thresholds */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
> +		(t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +		temp_sensor->registers->bgap_threshold);
> +
> +	tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
> +	tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
> +
> +	/* Configure the TSHUT thresholds */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->thsut_threshold);
> +	temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
> +	    | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +			temp_sensor->registers->thsut_threshold);
> +}
> +
> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
> +					       *temp_sensor, u32 counter)
> +{
> +	u32 val;
> +
> +	val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +	val &= ~(temp_sensor->registers->counter_mask);
> +	val |= (counter << __ffs(temp_sensor->registers->counter_mask));
> +	omap_temp_sensor_writel(temp_sensor, val,
> +			temp_sensor->registers->bgap_counter);
> +}
> +
> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
> +					bool enable)
> +{
> +	u32 val;
> +
> +	val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_mode_ctrl);
> +
> +	if (enable)
> +		val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
> +	else
> +		val &= ~(temp_sensor->registers->mode_ctrl_mask);
> +
> +	omap_temp_sensor_writel(temp_sensor, val,
> +			temp_sensor->registers->bgap_mode_ctrl);
> +}
> +
> +/* Sysfs hook functions */
> +
> +static ssize_t show_temp_max(struct device *dev,
> +			struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +	int temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	temp = (temp & temp_sensor->registers->threshold_thot_mask)
> +			>> __ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid value\n");
> +		goto out;
> +	}
> +	temp = adc_to_temp_conversion(temp);
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return snprintf(buf, 16, "%d\n", temp);
> +}
> +
> +static ssize_t set_temp_max(struct device *dev,
> +			    struct device_attribute *devattr,
> +			    const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	long			val;
> +	u32			reg_val, t_cold, t_hot, temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	t_hot = temp_to_adc_conversion(val);
> +	if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
> +		dev_err(dev, "invalid range\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* obtain the T cold value */
> +	t_cold = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
> +			__ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +	if (t_hot < t_cold) {
> +		dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* write the new t_hot value */
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
> +	reg_val |= (t_hot <<
> +			__ffs(temp_sensor->registers->threshold_thot_mask));
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_threshold);
> +
> +	/* Read the current temperature */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +	/*
> +	 * If user sets the HIGH threshold(t_hot) greater than the current
> +	 * temperature(temp) unmask the HOT interrupts
> +	 */
> +	if (t_hot > temp) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val &= ~(temp_sensor->registers->mask_cold_mask);
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * If current temperature is in-between the hot and cold thresholds,
> +	 * Enable both masks.
> +	 */
> +	if (temp > t_cold && temp < t_hot) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				OMAP4460_BGAP_CTRL_OFFSET);
> +	}
> +	/*
> +	 * else no need to do anything since HW will immediately compare
> +	 * the new threshold and generate interrupt accordingly
> +	 */
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static ssize_t show_temp_max_hyst(struct device *dev,
> +		struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +	u32			temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_threshold);
> +	temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
> +		__ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid value\n");
> +		goto out;
> +	}
> +
> +	temp = adc_to_temp_conversion(temp);
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return snprintf(buf, 16, "%d\n", temp);
> +}
> +
> +static ssize_t set_temp_max_hyst(struct device *dev,
> +				 struct device_attribute *devattr,
> +				 const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor		*temp_sensor = dev_get_drvdata(dev);
> +	u32				reg_val, t_hot, t_cold, temp;
> +	long				val;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	t_cold = temp_to_adc_conversion(val);
> +	if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid range");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* obtain the T HOT value */
> +	t_hot = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
> +			__ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +	if (t_cold > t_hot) {
> +		dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* write the new t_cold value */
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
> +	reg_val |= (t_cold <<
> +			__ffs(temp_sensor->registers->threshold_tcold_mask));
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_threshold);
> +
> +	/* Read the current temperature */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +	/*
> +	 * If user sets the LOW threshold(t_cold) lower than the current
> +	 * temperature(temp) unmask the COLD interrupts
> +	 */
> +	if (t_cold < temp) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val &= ~(temp_sensor->registers->mask_hot_mask);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * If current temperature is in-between the hot and cold thresholds,
> +	 * Enable both masks.
> +	 */
> +	if (temp < t_hot && temp > t_cold) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * else no need to do anything since HW will immediately compare
> +	 * the new threshold and generate interrupt accordingly
> +	 */
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static ssize_t show_update_rate(struct device *dev,
> +			struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	u32			temp = 0, ret = 0;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (!temp_sensor->clk_rate) {
> +		dev_err(dev, "clk_rate is NULL\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +	temp = (temp & temp_sensor->registers->counter_mask) >>
> +			__ffs(temp_sensor->registers->counter_mask);

	temp &= ??

> +	temp = temp * 1000 / (temp_sensor->clk_rate);

	temp *= ??

> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	if (!ret)
> +		return sprintf(buf, "%d\n", temp);
> +	else
> +		return ret;
> +}
> +
> +static ssize_t set_update_rate(struct device *dev,
> +			       struct device_attribute *devattr,
> +			       const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	u32			reg_val;
> +	long			val;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	val *= temp_sensor->clk_rate / 1000;
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +
> +	reg_val &= ~(temp_sensor->registers->counter_mask);
> +	reg_val |= val;
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_counter);
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static int omap_temp_sensor_read_temp(struct device *dev,
> +				      struct device_attribute *devattr,
> +				      char *buf)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	int			temp, ret = 0;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= temp_sensor->registers->bgap_dtemp_mask;
> +
> +	if (!temp_sensor->is_efuse_valid)
> +		dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
> +
> +	/* look up for temperature in the table and return the temperature */
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid adc code reported %d", temp);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	if (!ret)
> +		return sprintf(buf, "%d\n", temp);
> +	else
> +		return ret;
> +}
> +
> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
> +			  NULL, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
> +			  set_temp_max, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
> +			  set_temp_max_hyst, 0);
> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
> +			  set_update_rate, 0);
> +
> +static struct attribute *omap_temp_sensor_attributes[] = {
> +	&sensor_dev_attr_temp1_input.dev_attr.attr,
> +	&sensor_dev_attr_temp1_max.dev_attr.attr,
> +	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
> +	&sensor_dev_attr_update_rate.dev_attr.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group omap_temp_sensor_group = {
> +	.attrs = omap_temp_sensor_attributes,
> +};
> +
> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
> +{
> +	u32 ret = 0, temp;
> +
> +	if (temp_sensor->clk_on) {
> +		dev_err(temp_sensor->hwmon_dev, "clock already on\n");
> +		goto out;
> +	}
> +
> +	ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
> +	if (ret < 0) {
> +		dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
> +	/* BGAP_TEMPSOFF should be reset to 0 */
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +				temp_sensor->registers->temp_sensor_ctrl);
> +	temp_sensor->clk_on = 1;

why isn't pm_runtime_get_sync() enough ??

> +out:
> +	return ret;
> +}
> +
> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
> +{
> +	u32 temp, ret = 0;
> +	unsigned long timeout;
> +
> +	if (!temp_sensor->clk_on) {
> +		dev_err(temp_sensor->hwmon_dev, "clock already off\n");
> +		goto out;
> +	}
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp |= temp_sensor->registers->bgap_tempsoff_mask;
> +
> +	/* BGAP_TEMPSOFF should be set to 1 before gating clock */
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status);
> +	timeout = jiffies + msecs_to_jiffies(5);
> +
> +	/* wait till the clean stop bit is set or till the timeout exppires */
> +	while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
> +		!(time_after(jiffies, timeout))) {
> +		temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status);
> +		usleep_range(500, 2000);
> +	}
> +
> +	if (time_after(jiffies, timeout))
> +		dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
> +	/* Gate the clock */
> +	ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
> +	if (ret < 0) {
> +		dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	temp_sensor->clk_on = 0;
> +out:
> +	return ret;
> +}
> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
> +{
> +	struct omap_temp_sensor		*temp_sensor;
> +	int				t_hot, t_cold, temp;
> +
> +	temp_sensor = data;
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	/* Read the status of t_hot */
> +	t_hot = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status)
> +			& temp_sensor->registers->status_hot_mask;
> +
> +	/* Read the status of t_cold */
> +	t_cold = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status)
> +			& temp_sensor->registers->status_cold_mask;
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_mask_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) {
> +		temp &= ~(temp_sensor->registers->mask_hot_mask);
> +		temp |= temp_sensor->registers->mask_cold_mask;
> +	} else if (t_cold) {
> +		temp &= ~(temp_sensor->registers->mask_cold_mask);
> +		temp |= temp_sensor->registers->mask_hot_mask;
> +	}
> +
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +
> +	/* kobject_uvent to user space telling thermal threshold crossed */
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
> +
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
> +{
> +	struct omap_temp_sensor_pdata	*pdata	= pdev->dev.platform_data;
> +	struct omap_temp_sensor		*temp_sensor;
> +	struct resource			*mem;
> +	int				ret = 0;
> +	int				val, clk_rate;
> +
> +	if (!pdata) {
> +		dev_err(&pdev->dev, "platform data missing\n");
> +		return -EINVAL;
> +	}
> +
> +	temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
> +	if (!temp_sensor)
> +		return -ENOMEM;
> +
> +	mutex_init(&temp_sensor->sensor_mutex);
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem) {
> +		dev_err(&pdev->dev, "no mem resource\n");
> +		ret = -EINVAL;
> +		goto plat_res_err;
> +	}
> +
> +	temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
> +	if (temp_sensor->irq == -ENXIO) {
> +		dev_err(&pdev->dev, "get_irq_byname failed\n");
> +		ret = temp_sensor->irq;
> +		goto plat_res_err;
> +	}
> +
> +	temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
> +	temp_sensor->clock = NULL;
> +	temp_sensor->registers = pdata->registers;
> +	temp_sensor->hwmon_dev = &pdev->dev;
> +
> +	pm_runtime_enable(&pdev->dev);
> +	pm_runtime_irq_safe(&pdev->dev);

won't pm_runtime_irq_safe() keep the parent always running, thus
preventing MPU from reaching lower power states ??

> +	/*
> +	 * check if the efuse has a non-zero value if not
> +	 * it is an untrimmed sample and the temperatures
> +	 * may not be accurate
> +	 */
> +
> +	if (omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_efuse))
> +		temp_sensor->is_efuse_valid = 1;
> +
> +	platform_set_drvdata(pdev, temp_sensor);
> +	dev_set_drvdata(&pdev->dev, temp_sensor);

why are you doing the same thing twice ???

> +	temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");

why ?

> +	if (IS_ERR(temp_sensor->clock)) {
> +		ret = PTR_ERR(temp_sensor->clock);
> +		dev_err(temp_sensor->hwmon_dev,
> +			"unable to get fclk: %d\n", ret);
> +		ret = -EINVAL;
> +		goto plat_res_err;
> +	}
> +
> +	ret = omap_temp_sensor_clk_enable(temp_sensor);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Cannot enable temp sensor\n");
> +		goto clken_err;
> +	}
> +
> +	clk_rate = clk_round_rate(temp_sensor->clock, 2000000);

why ?

> +	if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
> +		dev_err(&pdev->dev, "Error round rate\n");
> +		goto clken_err;
> +	}
> +
> +	ret = clk_set_rate(temp_sensor->clock, clk_rate);

why ??

> +	if (ret) {
> +		dev_err(&pdev->dev, "Cannot set clock rate\n");
> +		goto clken_err;
> +	}
> +
> +	temp_sensor->clk_rate = clk_rate;
> +	omap_enable_continuous_mode(temp_sensor, 1);
> +	omap_configure_temp_sensor_thresholds(temp_sensor);
> +	/* 1 ms */
> +	omap_configure_temp_sensor_counter(temp_sensor, 1);
> +
> +	/* Wait till the first conversion is done wait for at least 1ms */
> +	usleep_range(1000, 2000);
> +
> +	/* Read the temperature once due to hw issue*/
> +	omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +
> +	/* Set 2 seconds time as default counter */
> +	omap_configure_temp_sensor_counter(temp_sensor,
> +						temp_sensor->clk_rate * 2);
> +
> +	temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
> +	if (IS_ERR(temp_sensor->hwmon_dev)) {
> +		dev_err(&pdev->dev, "hwmon_device_register failed.\n");
> +		ret = PTR_ERR(temp_sensor->hwmon_dev);
> +		goto hwmon_reg_err;
> +	}
> +
> +	ret = sysfs_create_group(&pdev->dev.kobj,
> +				 &omap_temp_sensor_group);
> +	if (ret) {
> +		dev_err(&pdev->dev, "could not create sysfs files\n");
> +		goto sysfs_create_err;
> +	}
> +
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
> +
> +	ret = request_threaded_irq(temp_sensor->irq, NULL,
> +		omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> +			"temp_sensor", temp_sensor);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Request threaded irq failed.\n");
> +		goto req_irq_err;
> +	}
> +
> +	/* unmask the T_COLD and unmask T_HOT at init */
> +	val = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +	val |= temp_sensor->registers->mask_cold_mask
> +		| temp_sensor->registers->mask_hot_mask;
> +
> +	omap_temp_sensor_writel(temp_sensor, val,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +
> +	return 0;
> +
> +req_irq_err:
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
> +	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
> +				&omap_temp_sensor_group);
> +sysfs_create_err:
> +	hwmon_device_unregister(&pdev->dev);
> +hwmon_reg_err:
> +	omap_temp_sensor_clk_disable(temp_sensor);
> +clken_err:
> +	if (temp_sensor->clock)
> +		clk_put(temp_sensor->clock);
> +plat_res_err:
> +	mutex_destroy(&temp_sensor->sensor_mutex);
> +	kfree(temp_sensor);
> +	return ret;
> +}
> +
> +static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
> +{
> +	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
> +
> +	hwmon_device_unregister(&pdev->dev);
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
> +	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
> +			&omap_temp_sensor_group);
> +	omap_temp_sensor_clk_disable(temp_sensor);
> +	clk_put(temp_sensor->clock);
> +	platform_set_drvdata(pdev, NULL);
> +	free_irq(temp_sensor->irq, temp_sensor);
> +	mutex_destroy(&temp_sensor->sensor_mutex);
> +	kfree(temp_sensor);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
> +{
> +	temp_sensor->temp_sensor_ctrl = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp_sensor->bg_ctrl = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +	temp_sensor->bg_counter = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_counter);
> +	temp_sensor->bg_threshold = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_threshold);
> +	temp_sensor->temp_sensor_tshut_threshold =
> +		omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->thsut_threshold);
> +}
> +
> +static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
> +{
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->temp_sensor_ctrl,
> +				temp_sensor->registers->temp_sensor_ctrl);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_ctrl,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_counter,
> +				temp_sensor->registers->bgap_counter);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_threshold,
> +				temp_sensor->registers->bgap_threshold);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->temp_sensor_tshut_threshold,
> +				temp_sensor->registers->thsut_threshold);
> +}
> +
> +static int omap_temp_sensor_suspend(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_save_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_resume(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_restore_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_runtime_suspend(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_save_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_runtime_resume(struct device *dev)
> +{
> +	static int context_loss_count;
> +	int temp;
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	temp = omap_device_get_context_loss_count(to_platform_device(dev));
> +
> +	if (temp != context_loss_count && context_loss_count != 0)
> +		omap_temp_sensor_restore_ctxt(temp_sensor);
> +
> +	context_loss_count = temp;
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
> +	.suspend = omap_temp_sensor_suspend,
> +	.resume = omap_temp_sensor_resume,
> +	.runtime_suspend = omap_temp_sensor_runtime_suspend,
> +	.runtime_resume = omap_temp_sensor_runtime_resume,
> +};
> +
> +#endif
> +
> +static struct platform_driver omap_temp_sensor_driver = {
> +	.probe = omap_temp_sensor_probe,
> +	.remove = omap_temp_sensor_remove,
> +	.driver = {
> +			.name = "omap_temp_sensor",
> +#ifdef CONFIG_PM
> +			.pm = &omap_temp_sensor_dev_pm_ops,
> +#endif
> +		   },
> +};
> +
> +int __init omap_temp_sensor_init(void)
> +{
> +	return platform_driver_register(&omap_temp_sensor_driver);
> +}
> +module_init(omap_temp_sensor_init);
> +
> +static void __exit omap_temp_sensor_exit(void)
> +{
> +	platform_driver_unregister(&omap_temp_sensor_driver);
> +}
> +module_exit(omap_temp_sensor_exit);
> +
> +MODULE_DESCRIPTION("OMAP446X temperature sensor Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> +MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
> -- 
> 1.7.0.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110810/622f9f83/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-10 12:46     ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:46 UTC (permalink / raw)
  To: Keerthy
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck


[-- Attachment #1.1: Type: text/plain, Size: 36388 bytes --]

Hi,

(why aren't below in Cc ?

HARDWARE MONITORING
M:	Jean Delvare <khali@linux-fr.org>
M:	Guenter Roeck <guenter.roeck@ericsson.com>
L:	lm-sensors@lm-sensors.org
W:	http://www.lm-sensors.org/
T:	quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
S:	Maintained
F:	Documentation/hwmon/
F:	drivers/hwmon/
F:	include/linux/hwmon*.h)

On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
> On chip temperature sensor driver. The driver monitors the temperature of
> the MPU subsystem of the OMAP4. It sends notifications to the user space if
> the temperature crosses user defined thresholds via kobject_uevent interface.
> The user is allowed to configure the temperature thresholds vis sysfs nodes
> exposed using hwmon interface.
> 
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  drivers/hwmon/Kconfig            |   11 +
>  drivers/hwmon/Makefile           |    1 +
>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 962 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 5f888f7..9c9cd8b 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called f71805f.
>  
> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
> +	bool "OMAP on-die temperature sensor hwmon driver"
> +	depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
> +	help
> +	  If you say yes here you get support for hardware
> +	  monitoring features of the OMAP on die temperature
> +	  sensor.
> +
> +	  Continuous conversion programmable delay
> +	  mode is used for temperature conversion.
> +
>  config SENSORS_F71882FG
>  	tristate "Fintek F71882FG and compatibles"
>  	help
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 28061cf..d0f89f5 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
>  obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
>  obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>  obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
>  obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
>  obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> new file mode 100644
> index 0000000..15e2559
> --- /dev/null
> +++ b/drivers/hwmon/omap_temp_sensor.c
> @@ -0,0 +1,950 @@
> +/*
> + * OMAP4 Temperature sensor driver file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@ti.com>
> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> +#include <linux/clk.h>

why ??

> +#include <linux/io.h>
> +#include <linux/debugfs.h>

why ??

> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/init.h>
> +#include <plat/omap_device.h>

why ??

> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/jiffies.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/stddef.h>
> +#include <linux/sysfs.h>
> +#include <linux/err.h>
> +#include <linux/types.h>
> +#include <linux/mutex.h>
> +#include <linux/pm_runtime.h>
> +#include <plat/common.h>

why ?

> +#include <plat/temperature_sensor.h>

why ?

> +#include <mach/ctrl_module_core_44xx.h>

why ?

> +#include <mach/gpio.h>

linux/gpio.h for crying out loud... how many times Russell has to say
the exact same thing ??????

> +#define TSHUT_THRESHOLD_HOT	122000	/* 122 deg C */
> +#define TSHUT_THRESHOLD_COLD	100000	/* 100 deg C */
> +#define BGAP_THRESHOLD_T_HOT	73000	/* 73 deg C */
> +#define BGAP_THRESHOLD_T_COLD	71000	/* 71 deg C */
> +#define OMAP_ADC_START_VALUE	530
> +#define OMAP_ADC_END_VALUE	923
> +
> +/*
> + * omap_temp_sensor structure
> + * @hwmon_dev - device pointer
> + * @clock - Clock pointer
> + * @registers - Pointer to structure with register offsets and bitfields
> + * @sensor_mutex - Mutex for sysfs, irq and PM
> + * @irq - MPU Irq number for thermal alert
> + * @phy_base - Physical base of the temp I/O
> + * @clk_rate - Holds current clock rate
> + * @temp_sensor_ctrl - temp sensor control register value
> + * @bg_ctrl - bandgap ctrl register value
> + * @bg_counter - bandgap counter value
> + * @bg_threshold - bandgap threshold register value
> + * @temp_sensor_tshut_threshold - bandgap tshut register value
> + * @is_efuse_valid - Flag to determine if efuse is valid or not
> + * @clk_on - Manages the current clock state
> + */
> +struct omap_temp_sensor {
> +	struct device		*hwmon_dev;
> +	struct clk		*clock;
> +	struct omap_temp_sensor_registers *registers;
> +	struct mutex		sensor_mutex; /* Mutex for sysfs, irq and PM */
> +	unsigned int		irq;
> +	void __iomem		*phy_base;
> +	u32			clk_rate;
> +	u32			temp_sensor_ctrl;
> +	u32			bg_ctrl;
> +	u32			bg_counter;
> +	u32			bg_threshold;
> +	u32			temp_sensor_tshut_threshold;
> +	bool                    is_efuse_valid;
> +	bool                    clk_on;
> +};
> +
> +/*
> + * Temperature values in milli degree celsius
> + * ADC code values from 530 to 923
> + */
> +static int adc_to_temp[] = {
> +	-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
> +};
> +
> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
> +					    *temp_sensor, u32 reg)
> +{
> +	return __raw_readl(temp_sensor->phy_base + reg);
> +}
> +
> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
> +				    u32 val, u32 reg)
> +{
> +	__raw_writel(val, (temp_sensor->phy_base + reg));
> +}
> +
> +static int adc_to_temp_conversion(int adc_val)
> +{
> +	return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
> +}
> +
> +static int temp_to_adc_conversion(long temp)
> +{
> +	int i;
> +
> +	for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
> +		if (temp < adc_to_temp[i])
> +			return OMAP_ADC_START_VALUE + i - 1;
> +
> +	return -EINVAL;
> +}
> +
> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
> +						  *temp_sensor)
> +{
> +	u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
> +
> +	t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
> +	t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
> +
> +	/* Configure the TALERT thresholds */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
> +		(t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +		temp_sensor->registers->bgap_threshold);
> +
> +	tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
> +	tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
> +
> +	/* Configure the TSHUT thresholds */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->thsut_threshold);
> +	temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
> +	    | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +			temp_sensor->registers->thsut_threshold);
> +}
> +
> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
> +					       *temp_sensor, u32 counter)
> +{
> +	u32 val;
> +
> +	val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +	val &= ~(temp_sensor->registers->counter_mask);
> +	val |= (counter << __ffs(temp_sensor->registers->counter_mask));
> +	omap_temp_sensor_writel(temp_sensor, val,
> +			temp_sensor->registers->bgap_counter);
> +}
> +
> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
> +					bool enable)
> +{
> +	u32 val;
> +
> +	val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_mode_ctrl);
> +
> +	if (enable)
> +		val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
> +	else
> +		val &= ~(temp_sensor->registers->mode_ctrl_mask);
> +
> +	omap_temp_sensor_writel(temp_sensor, val,
> +			temp_sensor->registers->bgap_mode_ctrl);
> +}
> +
> +/* Sysfs hook functions */
> +
> +static ssize_t show_temp_max(struct device *dev,
> +			struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +	int temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	temp = (temp & temp_sensor->registers->threshold_thot_mask)
> +			>> __ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid value\n");
> +		goto out;
> +	}
> +	temp = adc_to_temp_conversion(temp);
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return snprintf(buf, 16, "%d\n", temp);
> +}
> +
> +static ssize_t set_temp_max(struct device *dev,
> +			    struct device_attribute *devattr,
> +			    const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	long			val;
> +	u32			reg_val, t_cold, t_hot, temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	t_hot = temp_to_adc_conversion(val);
> +	if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
> +		dev_err(dev, "invalid range\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* obtain the T cold value */
> +	t_cold = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
> +			__ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +	if (t_hot < t_cold) {
> +		dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* write the new t_hot value */
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
> +	reg_val |= (t_hot <<
> +			__ffs(temp_sensor->registers->threshold_thot_mask));
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_threshold);
> +
> +	/* Read the current temperature */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +	/*
> +	 * If user sets the HIGH threshold(t_hot) greater than the current
> +	 * temperature(temp) unmask the HOT interrupts
> +	 */
> +	if (t_hot > temp) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val &= ~(temp_sensor->registers->mask_cold_mask);
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * If current temperature is in-between the hot and cold thresholds,
> +	 * Enable both masks.
> +	 */
> +	if (temp > t_cold && temp < t_hot) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				OMAP4460_BGAP_CTRL_OFFSET);
> +	}
> +	/*
> +	 * else no need to do anything since HW will immediately compare
> +	 * the new threshold and generate interrupt accordingly
> +	 */
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static ssize_t show_temp_max_hyst(struct device *dev,
> +		struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +	u32			temp;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_threshold);
> +	temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
> +		__ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid value\n");
> +		goto out;
> +	}
> +
> +	temp = adc_to_temp_conversion(temp);
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return snprintf(buf, 16, "%d\n", temp);
> +}
> +
> +static ssize_t set_temp_max_hyst(struct device *dev,
> +				 struct device_attribute *devattr,
> +				 const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor		*temp_sensor = dev_get_drvdata(dev);
> +	u32				reg_val, t_hot, t_cold, temp;
> +	long				val;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	t_cold = temp_to_adc_conversion(val);
> +	if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid range");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* obtain the T HOT value */
> +	t_hot = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
> +			__ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +	if (t_cold > t_hot) {
> +		dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* write the new t_cold value */
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_threshold);
> +	reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
> +	reg_val |= (t_cold <<
> +			__ffs(temp_sensor->registers->threshold_tcold_mask));
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_threshold);
> +
> +	/* Read the current temperature */
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +	/*
> +	 * If user sets the LOW threshold(t_cold) lower than the current
> +	 * temperature(temp) unmask the COLD interrupts
> +	 */
> +	if (t_cold < temp) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val &= ~(temp_sensor->registers->mask_hot_mask);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * If current temperature is in-between the hot and cold thresholds,
> +	 * Enable both masks.
> +	 */
> +	if (temp < t_hot && temp > t_cold) {
> +		reg_val = omap_temp_sensor_readl(temp_sensor,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +		reg_val |= temp_sensor->registers->mask_cold_mask;
> +		reg_val |= temp_sensor->registers->mask_hot_mask;
> +		omap_temp_sensor_writel(temp_sensor, reg_val,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	}
> +
> +	/*
> +	 * else no need to do anything since HW will immediately compare
> +	 * the new threshold and generate interrupt accordingly
> +	 */
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static ssize_t show_update_rate(struct device *dev,
> +			struct device_attribute *devattr, char *buf)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	u32			temp = 0, ret = 0;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (!temp_sensor->clk_rate) {
> +		dev_err(dev, "clk_rate is NULL\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +	temp = (temp & temp_sensor->registers->counter_mask) >>
> +			__ffs(temp_sensor->registers->counter_mask);

	temp &= ??

> +	temp = temp * 1000 / (temp_sensor->clk_rate);

	temp *= ??

> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	if (!ret)
> +		return sprintf(buf, "%d\n", temp);
> +	else
> +		return ret;
> +}
> +
> +static ssize_t set_update_rate(struct device *dev,
> +			       struct device_attribute *devattr,
> +			       const char *buf, size_t count)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	u32			reg_val;
> +	long			val;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	if (strict_strtol(buf, 10, &val)) {
> +		count = -EINVAL;
> +		goto out;
> +	}
> +
> +	val *= temp_sensor->clk_rate / 1000;
> +	reg_val = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_counter);
> +
> +	reg_val &= ~(temp_sensor->registers->counter_mask);
> +	reg_val |= val;
> +	omap_temp_sensor_writel(temp_sensor, reg_val,
> +			temp_sensor->registers->bgap_counter);
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	return count;
> +}
> +
> +static int omap_temp_sensor_read_temp(struct device *dev,
> +				      struct device_attribute *devattr,
> +				      char *buf)
> +{
> +	struct omap_temp_sensor	*temp_sensor = dev_get_drvdata(dev);
> +	int			temp, ret = 0;
> +
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= temp_sensor->registers->bgap_dtemp_mask;
> +
> +	if (!temp_sensor->is_efuse_valid)
> +		dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
> +
> +	/* look up for temperature in the table and return the temperature */
> +	if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +		dev_err(dev, "invalid adc code reported %d", temp);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
> +
> +out:
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +	if (!ret)
> +		return sprintf(buf, "%d\n", temp);
> +	else
> +		return ret;
> +}
> +
> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
> +			  NULL, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
> +			  set_temp_max, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
> +			  set_temp_max_hyst, 0);
> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
> +			  set_update_rate, 0);
> +
> +static struct attribute *omap_temp_sensor_attributes[] = {
> +	&sensor_dev_attr_temp1_input.dev_attr.attr,
> +	&sensor_dev_attr_temp1_max.dev_attr.attr,
> +	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
> +	&sensor_dev_attr_update_rate.dev_attr.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group omap_temp_sensor_group = {
> +	.attrs = omap_temp_sensor_attributes,
> +};
> +
> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
> +{
> +	u32 ret = 0, temp;
> +
> +	if (temp_sensor->clk_on) {
> +		dev_err(temp_sensor->hwmon_dev, "clock already on\n");
> +		goto out;
> +	}
> +
> +	ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
> +	if (ret < 0) {
> +		dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
> +	/* BGAP_TEMPSOFF should be reset to 0 */
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +				temp_sensor->registers->temp_sensor_ctrl);
> +	temp_sensor->clk_on = 1;

why isn't pm_runtime_get_sync() enough ??

> +out:
> +	return ret;
> +}
> +
> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
> +{
> +	u32 temp, ret = 0;
> +	unsigned long timeout;
> +
> +	if (!temp_sensor->clk_on) {
> +		dev_err(temp_sensor->hwmon_dev, "clock already off\n");
> +		goto out;
> +	}
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp |= temp_sensor->registers->bgap_tempsoff_mask;
> +
> +	/* BGAP_TEMPSOFF should be set to 1 before gating clock */
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status);
> +	timeout = jiffies + msecs_to_jiffies(5);
> +
> +	/* wait till the clean stop bit is set or till the timeout exppires */
> +	while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
> +		!(time_after(jiffies, timeout))) {
> +		temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status);
> +		usleep_range(500, 2000);
> +	}
> +
> +	if (time_after(jiffies, timeout))
> +		dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
> +	/* Gate the clock */
> +	ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
> +	if (ret < 0) {
> +		dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	temp_sensor->clk_on = 0;
> +out:
> +	return ret;
> +}
> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
> +{
> +	struct omap_temp_sensor		*temp_sensor;
> +	int				t_hot, t_cold, temp;
> +
> +	temp_sensor = data;
> +	mutex_lock(&temp_sensor->sensor_mutex);
> +
> +	/* Read the status of t_hot */
> +	t_hot = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status)
> +			& temp_sensor->registers->status_hot_mask;
> +
> +	/* Read the status of t_cold */
> +	t_cold = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_status)
> +			& temp_sensor->registers->status_cold_mask;
> +
> +	temp = omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_mask_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) {
> +		temp &= ~(temp_sensor->registers->mask_hot_mask);
> +		temp |= temp_sensor->registers->mask_cold_mask;
> +	} else if (t_cold) {
> +		temp &= ~(temp_sensor->registers->mask_cold_mask);
> +		temp |= temp_sensor->registers->mask_hot_mask;
> +	}
> +
> +	omap_temp_sensor_writel(temp_sensor, temp,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +
> +	/* kobject_uvent to user space telling thermal threshold crossed */
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
> +
> +	mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
> +{
> +	struct omap_temp_sensor_pdata	*pdata	= pdev->dev.platform_data;
> +	struct omap_temp_sensor		*temp_sensor;
> +	struct resource			*mem;
> +	int				ret = 0;
> +	int				val, clk_rate;
> +
> +	if (!pdata) {
> +		dev_err(&pdev->dev, "platform data missing\n");
> +		return -EINVAL;
> +	}
> +
> +	temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
> +	if (!temp_sensor)
> +		return -ENOMEM;
> +
> +	mutex_init(&temp_sensor->sensor_mutex);
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem) {
> +		dev_err(&pdev->dev, "no mem resource\n");
> +		ret = -EINVAL;
> +		goto plat_res_err;
> +	}
> +
> +	temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
> +	if (temp_sensor->irq == -ENXIO) {
> +		dev_err(&pdev->dev, "get_irq_byname failed\n");
> +		ret = temp_sensor->irq;
> +		goto plat_res_err;
> +	}
> +
> +	temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
> +	temp_sensor->clock = NULL;
> +	temp_sensor->registers = pdata->registers;
> +	temp_sensor->hwmon_dev = &pdev->dev;
> +
> +	pm_runtime_enable(&pdev->dev);
> +	pm_runtime_irq_safe(&pdev->dev);

won't pm_runtime_irq_safe() keep the parent always running, thus
preventing MPU from reaching lower power states ??

> +	/*
> +	 * check if the efuse has a non-zero value if not
> +	 * it is an untrimmed sample and the temperatures
> +	 * may not be accurate
> +	 */
> +
> +	if (omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->bgap_efuse))
> +		temp_sensor->is_efuse_valid = 1;
> +
> +	platform_set_drvdata(pdev, temp_sensor);
> +	dev_set_drvdata(&pdev->dev, temp_sensor);

why are you doing the same thing twice ???

> +	temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");

why ?

> +	if (IS_ERR(temp_sensor->clock)) {
> +		ret = PTR_ERR(temp_sensor->clock);
> +		dev_err(temp_sensor->hwmon_dev,
> +			"unable to get fclk: %d\n", ret);
> +		ret = -EINVAL;
> +		goto plat_res_err;
> +	}
> +
> +	ret = omap_temp_sensor_clk_enable(temp_sensor);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Cannot enable temp sensor\n");
> +		goto clken_err;
> +	}
> +
> +	clk_rate = clk_round_rate(temp_sensor->clock, 2000000);

why ?

> +	if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
> +		dev_err(&pdev->dev, "Error round rate\n");
> +		goto clken_err;
> +	}
> +
> +	ret = clk_set_rate(temp_sensor->clock, clk_rate);

why ??

> +	if (ret) {
> +		dev_err(&pdev->dev, "Cannot set clock rate\n");
> +		goto clken_err;
> +	}
> +
> +	temp_sensor->clk_rate = clk_rate;
> +	omap_enable_continuous_mode(temp_sensor, 1);
> +	omap_configure_temp_sensor_thresholds(temp_sensor);
> +	/* 1 ms */
> +	omap_configure_temp_sensor_counter(temp_sensor, 1);
> +
> +	/* Wait till the first conversion is done wait for at least 1ms */
> +	usleep_range(1000, 2000);
> +
> +	/* Read the temperature once due to hw issue*/
> +	omap_temp_sensor_readl(temp_sensor,
> +			temp_sensor->registers->temp_sensor_ctrl);
> +
> +	/* Set 2 seconds time as default counter */
> +	omap_configure_temp_sensor_counter(temp_sensor,
> +						temp_sensor->clk_rate * 2);
> +
> +	temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
> +	if (IS_ERR(temp_sensor->hwmon_dev)) {
> +		dev_err(&pdev->dev, "hwmon_device_register failed.\n");
> +		ret = PTR_ERR(temp_sensor->hwmon_dev);
> +		goto hwmon_reg_err;
> +	}
> +
> +	ret = sysfs_create_group(&pdev->dev.kobj,
> +				 &omap_temp_sensor_group);
> +	if (ret) {
> +		dev_err(&pdev->dev, "could not create sysfs files\n");
> +		goto sysfs_create_err;
> +	}
> +
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
> +
> +	ret = request_threaded_irq(temp_sensor->irq, NULL,
> +		omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> +			"temp_sensor", temp_sensor);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Request threaded irq failed.\n");
> +		goto req_irq_err;
> +	}
> +
> +	/* unmask the T_COLD and unmask T_HOT at init */
> +	val = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +	val |= temp_sensor->registers->mask_cold_mask
> +		| temp_sensor->registers->mask_hot_mask;
> +
> +	omap_temp_sensor_writel(temp_sensor, val,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +
> +	return 0;
> +
> +req_irq_err:
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
> +	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
> +				&omap_temp_sensor_group);
> +sysfs_create_err:
> +	hwmon_device_unregister(&pdev->dev);
> +hwmon_reg_err:
> +	omap_temp_sensor_clk_disable(temp_sensor);
> +clken_err:
> +	if (temp_sensor->clock)
> +		clk_put(temp_sensor->clock);
> +plat_res_err:
> +	mutex_destroy(&temp_sensor->sensor_mutex);
> +	kfree(temp_sensor);
> +	return ret;
> +}
> +
> +static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
> +{
> +	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
> +
> +	hwmon_device_unregister(&pdev->dev);
> +	kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
> +	sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
> +			&omap_temp_sensor_group);
> +	omap_temp_sensor_clk_disable(temp_sensor);
> +	clk_put(temp_sensor->clock);
> +	platform_set_drvdata(pdev, NULL);
> +	free_irq(temp_sensor->irq, temp_sensor);
> +	mutex_destroy(&temp_sensor->sensor_mutex);
> +	kfree(temp_sensor);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
> +{
> +	temp_sensor->temp_sensor_ctrl = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->temp_sensor_ctrl);
> +	temp_sensor->bg_ctrl = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_mask_ctrl);
> +	temp_sensor->bg_counter = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_counter);
> +	temp_sensor->bg_threshold = omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->bgap_threshold);
> +	temp_sensor->temp_sensor_tshut_threshold =
> +		omap_temp_sensor_readl(temp_sensor,
> +		temp_sensor->registers->thsut_threshold);
> +}
> +
> +static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
> +{
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->temp_sensor_ctrl,
> +				temp_sensor->registers->temp_sensor_ctrl);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_ctrl,
> +				temp_sensor->registers->bgap_mask_ctrl);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_counter,
> +				temp_sensor->registers->bgap_counter);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->bg_threshold,
> +				temp_sensor->registers->bgap_threshold);
> +	omap_temp_sensor_writel(temp_sensor,
> +				temp_sensor->temp_sensor_tshut_threshold,
> +				temp_sensor->registers->thsut_threshold);
> +}
> +
> +static int omap_temp_sensor_suspend(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_save_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_resume(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_restore_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_runtime_suspend(struct device *dev)
> +{
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	omap_temp_sensor_save_ctxt(temp_sensor);
> +
> +	return 0;
> +}
> +
> +static int omap_temp_sensor_runtime_resume(struct device *dev)
> +{
> +	static int context_loss_count;
> +	int temp;
> +	struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +
> +	temp = omap_device_get_context_loss_count(to_platform_device(dev));
> +
> +	if (temp != context_loss_count && context_loss_count != 0)
> +		omap_temp_sensor_restore_ctxt(temp_sensor);
> +
> +	context_loss_count = temp;
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
> +	.suspend = omap_temp_sensor_suspend,
> +	.resume = omap_temp_sensor_resume,
> +	.runtime_suspend = omap_temp_sensor_runtime_suspend,
> +	.runtime_resume = omap_temp_sensor_runtime_resume,
> +};
> +
> +#endif
> +
> +static struct platform_driver omap_temp_sensor_driver = {
> +	.probe = omap_temp_sensor_probe,
> +	.remove = omap_temp_sensor_remove,
> +	.driver = {
> +			.name = "omap_temp_sensor",
> +#ifdef CONFIG_PM
> +			.pm = &omap_temp_sensor_dev_pm_ops,
> +#endif
> +		   },
> +};
> +
> +int __init omap_temp_sensor_init(void)
> +{
> +	return platform_driver_register(&omap_temp_sensor_driver);
> +}
> +module_init(omap_temp_sensor_init);
> +
> +static void __exit omap_temp_sensor_exit(void)
> +{
> +	platform_driver_unregister(&omap_temp_sensor_driver);
> +}
> +module_exit(omap_temp_sensor_exit);
> +
> +MODULE_DESCRIPTION("OMAP446X temperature sensor Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> +MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
> -- 
> 1.7.0.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-10 12:41       ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Tony Lindgren
@ 2011-08-10 12:48         ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:48 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Felipe Balbi, Keerthy, lm-sensors, vishwanath.bs, linux-omap,
	b-cousson, rnayak

[-- Attachment #1: Type: text/plain, Size: 1058 bytes --]

Hi,

On Wed, Aug 10, 2011 at 05:41:02AM -0700, Tony Lindgren wrote:
> * Felipe Balbi <balbi@ti.com> [110810 05:31]:
> > 
> > On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
> > > +
> > > +int __init omap_devinit_temp_sensor(void)
> > > +{
> > > +	if (!cpu_is_omap446x())
> > > +		return 0;
> > > +
> > > +	return omap_hwmod_for_each_by_class("temperature_sensor",
> > > +			temp_sensor_dev_init, NULL);
> > > +}
> > > +
> > > +arch_initcall(omap_devinit_temp_sensor);
> > 
> > I really dislike people adding more and more *initcall() to their pieces
> > of code. But Tony is the final Judge.
> 
> Yes how about making this just a regular device driver and have it
> live under drivers/ somewhere?
> 
> Or is there some reason why this could not be a loadable module?

driver is loadable, this is just creating the platform_device, but still
I don't think it deserves its own arch_initcall(), it could very well be
something which is called after we know we're running at omap4, or
called by each board...

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-10 12:48         ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 12:48 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Felipe Balbi, Keerthy, lm-sensors, vishwanath.bs, linux-omap,
	b-cousson, rnayak


[-- Attachment #1.1: Type: text/plain, Size: 1058 bytes --]

Hi,

On Wed, Aug 10, 2011 at 05:41:02AM -0700, Tony Lindgren wrote:
> * Felipe Balbi <balbi@ti.com> [110810 05:31]:
> > 
> > On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
> > > +
> > > +int __init omap_devinit_temp_sensor(void)
> > > +{
> > > +	if (!cpu_is_omap446x())
> > > +		return 0;
> > > +
> > > +	return omap_hwmod_for_each_by_class("temperature_sensor",
> > > +			temp_sensor_dev_init, NULL);
> > > +}
> > > +
> > > +arch_initcall(omap_devinit_temp_sensor);
> > 
> > I really dislike people adding more and more *initcall() to their pieces
> > of code. But Tony is the final Judge.
> 
> Yes how about making this just a regular device driver and have it
> live under drivers/ somewhere?
> 
> Or is there some reason why this could not be a loadable module?

driver is loadable, this is just creating the platform_device, but still
I don't think it deserves its own arch_initcall(), it could very well be
something which is called after we know we're running at omap4, or
called by each board...

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-10 12:48         ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
@ 2011-08-10 14:17           ` Cousson, Benoit
  -1 siblings, 0 replies; 105+ messages in thread
From: Cousson, Benoit @ 2011-08-10 14:17 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: Tony Lindgren, J, KEERTHY, lm-sensors, Sripathy, Vishwanath,
	linux-omap, Nayak, Rajendra

On 8/10/2011 2:48 PM, Balbi, Felipe wrote:
> Hi,
>
> On Wed, Aug 10, 2011 at 05:41:02AM -0700, Tony Lindgren wrote:
>> * Felipe Balbi<balbi@ti.com>  [110810 05:31]:
>>>
>>> On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
>>>> +
>>>> +int __init omap_devinit_temp_sensor(void)
>>>> +{
>>>> +	if (!cpu_is_omap446x())
>>>> +		return 0;
>>>> +
>>>> +	return omap_hwmod_for_each_by_class("temperature_sensor",
>>>> +			temp_sensor_dev_init, NULL);
>>>> +}
>>>> +
>>>> +arch_initcall(omap_devinit_temp_sensor);
>>>
>>> I really dislike people adding more and more *initcall() to their pieces
>>> of code. But Tony is the final Judge.
>>
>> Yes how about making this just a regular device driver and have it
>> live under drivers/ somewhere?
>>
>> Or is there some reason why this could not be a loadable module?
>
> driver is loadable, this is just creating the platform_device, but still
> I don't think it deserves its own arch_initcall(), it could very well be
> something which is called after we know we're running at omap4, or
> called by each board...

Funny, because I thought we were trying to get rid of the ugly init 
devices from board file to use *initcall() from a dedicated device file.
The advantage is that you do not have anymore a central place that 
everybody will change and that is thus subject to merge conflicts.

The drawback is that you do not know where an when the devices are created.

That being said, device-tree will provide a nice way to build all this 
devices without any initcall or board hacks.
This is just a temporary issue :-)

Benoit

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-10 14:17           ` Cousson, Benoit
  0 siblings, 0 replies; 105+ messages in thread
From: Cousson, Benoit @ 2011-08-10 14:17 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: Tony Lindgren, J, KEERTHY, lm-sensors, Sripathy, Vishwanath,
	linux-omap, Nayak, Rajendra

On 8/10/2011 2:48 PM, Balbi, Felipe wrote:
> Hi,
>
> On Wed, Aug 10, 2011 at 05:41:02AM -0700, Tony Lindgren wrote:
>> * Felipe Balbi<balbi@ti.com>  [110810 05:31]:
>>>
>>> On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
>>>> +
>>>> +int __init omap_devinit_temp_sensor(void)
>>>> +{
>>>> +	if (!cpu_is_omap446x())
>>>> +		return 0;
>>>> +
>>>> +	return omap_hwmod_for_each_by_class("temperature_sensor",
>>>> +			temp_sensor_dev_init, NULL);
>>>> +}
>>>> +
>>>> +arch_initcall(omap_devinit_temp_sensor);
>>>
>>> I really dislike people adding more and more *initcall() to their pieces
>>> of code. But Tony is the final Judge.
>>
>> Yes how about making this just a regular device driver and have it
>> live under drivers/ somewhere?
>>
>> Or is there some reason why this could not be a loadable module?
>
> driver is loadable, this is just creating the platform_device, but still
> I don't think it deserves its own arch_initcall(), it could very well be
> something which is called after we know we're running at omap4, or
> called by each board...

Funny, because I thought we were trying to get rid of the ugly init 
devices from board file to use *initcall() from a dedicated device file.
The advantage is that you do not have anymore a central place that 
everybody will change and that is thus subject to merge conflicts.

The drawback is that you do not know where an when the devices are created.

That being said, device-tree will provide a nice way to build all this 
devices without any initcall or board hacks.
This is just a temporary issue :-)

Benoit

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 5/6] OMAP4460: Temperature sensor data
  2011-08-10 12:37     ` [lm-sensors] " Felipe Balbi
@ 2011-08-10 15:20       ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-10 15:08 UTC (permalink / raw)
  To: balbi; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, lm-sensors

On Wed, Aug 10, 2011 at 6:07 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Wed, Aug 10, 2011 at 05:55:21PM +0530, Keerthy wrote:
>> The register set and the
>> bit fields might vary across OMAP versions. Hence
>> creating a structure comprising of all the registers
>> and bit fields to make the driver uniform for all the
>> versions with different register sets. The data file
>> contains the structure populated with register offsets
>> and bit fields corresponding to OMAP4460 on die sensor.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>>  arch/arm/mach-omap2/temp_sensor4460_data.c |   63 ++++++++++++++++++++++++++++
>>  1 files changed, 63 insertions(+), 0 deletions(-)
>>  create mode 100644 arch/arm/mach-omap2/temp_sensor4460_data.c
>>
>> diff --git a/arch/arm/mach-omap2/temp_sensor4460_data.c b/arch/arm/mach-omap2/temp_sensor4460_data.c
>> new file mode 100644
>> index 0000000..294963d
>> --- /dev/null
>> +++ b/arch/arm/mach-omap2/temp_sensor4460_data.c
>> @@ -0,0 +1,63 @@
>> +/*
>> + * OMAP4460 on die Temperature sensor data file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@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/slab.h>
>> +#include "control.h"
>> +#include <plat/temperature_sensor.h>
>> +
>> +/*
>> + * OMAP4460 has one instance of thermal sensor for MPU
>> + * need to describe the individual bit fields
>> + */
>> +struct omap_temp_sensor_registers omap_mpu_temp_sensor_registers = {
>
> this is used on previous patch, so you have a compilation error.

I will reorder the patches.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 5/6] OMAP4460: Temperature sensor data
@ 2011-08-10 15:20       ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-10 15:20 UTC (permalink / raw)
  To: balbi; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak, lm-sensors

On Wed, Aug 10, 2011 at 6:07 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Wed, Aug 10, 2011 at 05:55:21PM +0530, Keerthy wrote:
>> The register set and the
>> bit fields might vary across OMAP versions. Hence
>> creating a structure comprising of all the registers
>> and bit fields to make the driver uniform for all the
>> versions with different register sets. The data file
>> contains the structure populated with register offsets
>> and bit fields corresponding to OMAP4460 on die sensor.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>>  arch/arm/mach-omap2/temp_sensor4460_data.c |   63 ++++++++++++++++++++++++++++
>>  1 files changed, 63 insertions(+), 0 deletions(-)
>>  create mode 100644 arch/arm/mach-omap2/temp_sensor4460_data.c
>>
>> diff --git a/arch/arm/mach-omap2/temp_sensor4460_data.c b/arch/arm/mach-omap2/temp_sensor4460_data.c
>> new file mode 100644
>> index 0000000..294963d
>> --- /dev/null
>> +++ b/arch/arm/mach-omap2/temp_sensor4460_data.c
>> @@ -0,0 +1,63 @@
>> +/*
>> + * OMAP4460 on die Temperature sensor data file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@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/slab.h>
>> +#include "control.h"
>> +#include <plat/temperature_sensor.h>
>> +
>> +/*
>> + * OMAP4460 has one instance of thermal sensor for MPU
>> + * need to describe the individual bit fields
>> + */
>> +struct omap_temp_sensor_registers omap_mpu_temp_sensor_registers = {
>
> this is used on previous patch, so you have a compilation error.

I will reorder the patches.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-10 12:37   ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Keerthy
@ 2011-08-10 16:47     ` R, Durgadoss
  -1 siblings, 0 replies; 105+ messages in thread
From: R, Durgadoss @ 2011-08-10 16:35 UTC (permalink / raw)
  To: Keerthy, lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak

Hi,

> -----Original Message-----
> From: lm-sensors-bounces@lm-sensors.org [mailto:lm-sensors-bounces@lm-
> sensors.org] On Behalf Of Keerthy
> Sent: Wednesday, August 10, 2011 5:55 PM
> To: lm-sensors@lm-sensors.org
> Cc: vishwanath.bs@ti.com; linux-omap@vger.kernel.org; b-cousson@ti.com;
> rnayak@ti.com
> Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor
> driver
>
> On chip temperature sensor driver. The driver monitors the temperature of
> the MPU subsystem of the OMAP4. It sends notifications to the user space if
> the temperature crosses user defined thresholds via kobject_uevent interface.
> The user is allowed to configure the temperature thresholds vis sysfs nodes
> exposed using hwmon interface.
>
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  drivers/hwmon/Kconfig            |   11 +
>  drivers/hwmon/Makefile           |    1 +
>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 962 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 5f888f7..9c9cd8b 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>         This driver can also be built as a module.  If so, the module
>         will be called f71805f.
>
> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
> +     bool "OMAP on-die temperature sensor hwmon driver"
> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
> +     help
> +       If you say yes here you get support for hardware
> +       monitoring features of the OMAP on die temperature
> +       sensor.
> +
> +       Continuous conversion programmable delay
> +       mode is used for temperature conversion.
> +
>  config SENSORS_F71882FG
>       tristate "Fintek F71882FG and compatibles"
>       help
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 28061cf..d0f89f5 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
> diff --git a/drivers/hwmon/omap_temp_sensor.c
> b/drivers/hwmon/omap_temp_sensor.c
> new file mode 100644
> index 0000000..15e2559
> --- /dev/null
> +++ b/drivers/hwmon/omap_temp_sensor.c
> @@ -0,0 +1,950 @@
> +/*
> + * OMAP4 Temperature sensor driver file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@ti.com>
> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/debugfs.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/init.h>
> +#include <plat/omap_device.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/jiffies.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/stddef.h>
> +#include <linux/sysfs.h>
> +#include <linux/err.h>
> +#include <linux/types.h>
> +#include <linux/mutex.h>
> +#include <linux/pm_runtime.h>
> +#include <plat/common.h>
> +#include <plat/temperature_sensor.h>
> +#include <mach/ctrl_module_core_44xx.h>
> +#include <mach/gpio.h>
> +
> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
> +#define OMAP_ADC_START_VALUE 530
> +#define OMAP_ADC_END_VALUE   923
> +
> +/*
> + * omap_temp_sensor structure
> + * @hwmon_dev - device pointer
> + * @clock - Clock pointer
> + * @registers - Pointer to structure with register offsets and bitfields
> + * @sensor_mutex - Mutex for sysfs, irq and PM
> + * @irq - MPU Irq number for thermal alert
> + * @phy_base - Physical base of the temp I/O
> + * @clk_rate - Holds current clock rate
> + * @temp_sensor_ctrl - temp sensor control register value
> + * @bg_ctrl - bandgap ctrl register value
> + * @bg_counter - bandgap counter value
> + * @bg_threshold - bandgap threshold register value
> + * @temp_sensor_tshut_threshold - bandgap tshut register value
> + * @is_efuse_valid - Flag to determine if efuse is valid or not
> + * @clk_on - Manages the current clock state
> + */
> +struct omap_temp_sensor {
> +     struct device           *hwmon_dev;
> +     struct clk              *clock;
> +     struct omap_temp_sensor_registers *registers;
> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
> +     unsigned int            irq;
> +     void __iomem            *phy_base;
> +     u32                     clk_rate;
> +     u32                     temp_sensor_ctrl;
> +     u32                     bg_ctrl;
> +     u32                     bg_counter;
> +     u32                     bg_threshold;
> +     u32                     temp_sensor_tshut_threshold;
> +     bool                    is_efuse_valid;
> +     bool                    clk_on;
> +};
> +
> +/*
> + * Temperature values in milli degree celsius
> + * ADC code values from 530 to 923
> + */
> +static int adc_to_temp[] = {
> +     -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
> +};
> +
> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
> +                                         *temp_sensor, u32 reg)
> +{
> +     return __raw_readl(temp_sensor->phy_base + reg);
> +}
> +
> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
> +                                 u32 val, u32 reg)
> +{
> +     __raw_writel(val, (temp_sensor->phy_base + reg));
> +}
> +
> +static int adc_to_temp_conversion(int adc_val)
> +{
> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
> +}
> +
> +static int temp_to_adc_conversion(long temp)
> +{
> +     int i;
> +
> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
> +             if (temp < adc_to_temp[i])
> +                     return OMAP_ADC_START_VALUE + i - 1;
> +
> +     return -EINVAL;
> +}
> +
> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
> +                                               *temp_sensor)
> +{
> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
> +
> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
> +
> +     /* Configure the TALERT thresholds */
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +             temp_sensor->registers->bgap_threshold);
> +
> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
> +
> +     /* Configure the TSHUT thresholds */
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->thsut_threshold);
> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +                     temp_sensor->registers->thsut_threshold);
> +}
> +
> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
> +                                            *temp_sensor, u32 counter)
> +{
> +     u32 val;
> +
> +     val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_counter);
> +     val &= ~(temp_sensor->registers->counter_mask);
> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
> +     omap_temp_sensor_writel(temp_sensor, val,
> +                     temp_sensor->registers->bgap_counter);
> +}
> +
> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
> +                                     bool enable)
> +{
> +     u32 val;
> +
> +     val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_mode_ctrl);
> +
> +     if (enable)
> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
> +     else
> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
> +
> +     omap_temp_sensor_writel(temp_sensor, val,
> +                     temp_sensor->registers->bgap_mode_ctrl);
> +}
> +
> +/* Sysfs hook functions */
> +
> +static ssize_t show_temp_max(struct device *dev,
> +                     struct device_attribute *devattr, char *buf)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     int temp;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +             dev_err(dev, "invalid value\n");
> +             goto out;
> +     }
> +     temp = adc_to_temp_conversion(temp);
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +     return snprintf(buf, 16, "%d\n", temp);

Even if it is invalid value, you are printing it.
May be you would have to do unlocking and returning -EINVAL inside the 'if' check.

Moreover, you are just doing a read.
So, do you really need a mutex_lock in this function.. ?

> +}
> +
> +static ssize_t set_temp_max(struct device *dev,
> +                         struct device_attribute *devattr,
> +                         const char *buf, size_t count)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     long                    val;
> +     u32                     reg_val, t_cold, t_hot, temp;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     if (strict_strtol(buf, 10, &val)) {
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     t_hot = temp_to_adc_conversion(val);
> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
> +             dev_err(dev, "invalid range\n");
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* obtain the T cold value */
> +     t_cold = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +     if (t_hot < t_cold) {
> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* write the new t_hot value */
> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
> +     reg_val |= (t_hot <<
> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> +                     temp_sensor->registers->bgap_threshold);
> +
> +     /* Read the current temperature */
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +     /*
> +      * If user sets the HIGH threshold(t_hot) greater than the current
> +      * temperature(temp) unmask the HOT interrupts
> +      */
> +     if (t_hot > temp) {
> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +     }
> +
> +     /*
> +      * If current temperature is in-between the hot and cold thresholds,
> +      * Enable both masks.
> +      */
> +     if (temp > t_cold && temp < t_hot) {
> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> +                             OMAP4460_BGAP_CTRL_OFFSET);
> +     }
> +     /*
> +      * else no need to do anything since HW will immediately compare
> +      * the new threshold and generate interrupt accordingly
> +      */
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     return count;
> +}
> +
> +static ssize_t show_temp_max_hyst(struct device *dev,
> +             struct device_attribute *devattr, char *buf)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     u32                     temp;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +             temp_sensor->registers->bgap_threshold);
> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +             dev_err(dev, "invalid value\n");
> +             goto out;

Same case here..
You can do ret = -EINVAL here..

> +     }
> +
> +     temp = adc_to_temp_conversion(temp);

...subsequently,
ret = snprintf(buf, 16, "%d\n", temp);

> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +     return snprintf(buf, 16, "%d\n", temp);

Return ret here..

> +}
> +
> +static ssize_t set_temp_max_hyst(struct device *dev,
> +                              struct device_attribute *devattr,
> +                              const char *buf, size_t count)
> +{
> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
> +     u32                             reg_val, t_hot, t_cold, temp;
> +     long                            val;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     if (strict_strtol(buf, 10, &val)) {
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     t_cold = temp_to_adc_conversion(val);
> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
> +             dev_err(dev, "invalid range");
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* obtain the T HOT value */
> +     t_hot = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +     if (t_cold > t_hot) {
> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* write the new t_cold value */
> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
> +     reg_val |= (t_cold <<
> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> +                     temp_sensor->registers->bgap_threshold);
> +
> +     /* Read the current temperature */
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +             temp_sensor->registers->temp_sensor_ctrl);
> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +     /*
> +      * If user sets the LOW threshold(t_cold) lower than the current
> +      * temperature(temp) unmask the COLD interrupts
> +      */
> +     if (t_cold < temp) {
> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> +                     temp_sensor->registers->bgap_mask_ctrl);
> +     }
> +
> +     /*
> +      * If current temperature is in-between the hot and cold thresholds,
> +      * Enable both masks.
> +      */
> +     if (temp < t_hot && temp > t_cold) {
> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +     }
> +
> +     /*
> +      * else no need to do anything since HW will immediately compare
> +      * the new threshold and generate interrupt accordingly
> +      */
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     return count;
> +}
> +
> +static ssize_t show_update_rate(struct device *dev,
> +                     struct device_attribute *devattr, char *buf)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     u32                     temp = 0, ret = 0;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     if (!temp_sensor->clk_rate) {
> +             dev_err(dev, "clk_rate is NULL\n");
> +             ret = -EINVAL;
> +             goto out;
> +     }
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_counter);
> +     temp = (temp & temp_sensor->registers->counter_mask) >>
> +                     __ffs(temp_sensor->registers->counter_mask);
> +     temp = temp * 1000 / (temp_sensor->clk_rate);
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     if (!ret)
> +             return sprintf(buf, "%d\n", temp);
> +     else

The 'else' is not necessary..

> +             return ret;
> +}
> +
> +static ssize_t set_update_rate(struct device *dev,
> +                            struct device_attribute *devattr,
> +                            const char *buf, size_t count)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     u32                     reg_val;
> +     long                    val;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     if (strict_strtol(buf, 10, &val)) {
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     val *= temp_sensor->clk_rate / 1000;
> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_counter);
> +
> +     reg_val &= ~(temp_sensor->registers->counter_mask);
> +     reg_val |= val;
> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> +                     temp_sensor->registers->bgap_counter);
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     return count;
> +}
> +
> +static int omap_temp_sensor_read_temp(struct device *dev,
> +                                   struct device_attribute *devattr,
> +                                   char *buf)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     int                     temp, ret = 0;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +             temp_sensor->registers->temp_sensor_ctrl);
> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
> +
> +     if (!temp_sensor->is_efuse_valid)
> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not
> accurate\n");
> +
> +     /* look up for temperature in the table and return the temperature */
> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +             dev_err(dev, "invalid adc code reported %d", temp);
> +             ret = -EINVAL;
> +             goto out;
> +     }
> +
> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     if (!ret)
> +             return sprintf(buf, "%d\n", temp);
> +     else

Same here..

> +             return ret;
> +}
> +
> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
> +                       NULL, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
> +                       set_temp_max, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
> show_temp_max_hyst,
> +                       set_temp_max_hyst, 0);
> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
> +                       set_update_rate, 0);
> +
> +static struct attribute *omap_temp_sensor_attributes[] = {
> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
> +     &sensor_dev_attr_update_rate.dev_attr.attr,
> +     NULL
> +};
> +
> +static const struct attribute_group omap_temp_sensor_group = {
> +     .attrs = omap_temp_sensor_attributes,
> +};
> +
> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
> +{
> +     u32 ret = 0, temp;
> +
> +     if (temp_sensor->clk_on) {
> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
> +             goto out;
> +     }
> +
> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
> +     if (ret < 0) {
> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
> +             ret = -EINVAL;

Please do not mask the return value.
Let it be whatever returned by the get_sync.
Anyway, you are returning 'ret' in the end...

> +             goto out;
> +     }
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
> +     /* BGAP_TEMPSOFF should be reset to 0 */
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +                             temp_sensor->registers->temp_sensor_ctrl);
> +     temp_sensor->clk_on = 1;
> +out:
> +     return ret;
> +}
> +
> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
> +{
> +     u32 temp, ret = 0;
> +     unsigned long timeout;
> +
> +     if (!temp_sensor->clk_on) {
> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
> +             goto out;
> +     }
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
> +
> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_status);
> +     timeout = jiffies + msecs_to_jiffies(5);
> +
> +     /* wait till the clean stop bit is set or till the timeout exppires */

s/expires/expires

> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
> +             !(time_after(jiffies, timeout))) {
> +             temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_status);
> +             usleep_range(500, 2000);
> +     }
> +
> +     if (time_after(jiffies, timeout))
> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
> +     /* Gate the clock */
> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
> +     if (ret < 0) {
> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
> +             ret = -EINVAL;

Same case as get_sync. Don't mask the return value.

> +             goto out;
> +     }
> +     temp_sensor->clk_on = 0;
> +out:
> +     return ret;
> +}
> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
> +{
> +     struct omap_temp_sensor         *temp_sensor;
> +     int                             t_hot, t_cold, temp;
> +
> +     temp_sensor = data;
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     /* Read the status of t_hot */
> +     t_hot = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_status)
> +                     & temp_sensor->registers->status_hot_mask;
> +
> +     /* Read the status of t_cold */
> +     t_cold = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_status)
> +                     & temp_sensor->registers->status_cold_mask;
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_mask_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) {
> +             temp &= ~(temp_sensor->registers->mask_hot_mask);
> +             temp |= temp_sensor->registers->mask_cold_mask;
> +     } else if (t_cold) {
> +             temp &= ~(temp_sensor->registers->mask_cold_mask);
> +             temp |= temp_sensor->registers->mask_hot_mask;
> +     }
> +
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +             temp_sensor->registers->bgap_mask_ctrl);
> +
> +     /* kobject_uvent to user space telling thermal threshold crossed */
> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
> +
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +     return IRQ_HANDLED;
> +}
> +
> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
> +{
> +     struct omap_temp_sensor_pdata   *pdata  = pdev->dev.platform_data;
> +     struct omap_temp_sensor         *temp_sensor;
> +     struct resource                 *mem;
> +     int                             ret = 0;
> +     int                             val, clk_rate;
> +
> +     if (!pdata) {
> +             dev_err(&pdev->dev, "platform data missing\n");
> +             return -EINVAL;
> +     }
> +
> +     temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
> +     if (!temp_sensor)
> +             return -ENOMEM;
> +
> +     mutex_init(&temp_sensor->sensor_mutex);
> +
> +     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +     if (!mem) {
> +             dev_err(&pdev->dev, "no mem resource\n");
> +             ret = -EINVAL;

You can do PTR_ERR(mem) to get the return error value as an integer.
Otherwise, it makes more sense to be -ENOMEM

> +             goto plat_res_err;
> +     }
> +
> +     temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
> +     if (temp_sensor->irq == -ENXIO) {
> +             dev_err(&pdev->dev, "get_irq_byname failed\n");
> +             ret = temp_sensor->irq;
> +             goto plat_res_err;
> +     }
> +

This flow can better be:
ret = platform_get_irq_byname(...)
if (ret < 0) //because it is an IRQ number
{ ... }

Then assign ret to temp_sensor->irq

> +     temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
> +     temp_sensor->clock = NULL;
> +     temp_sensor->registers = pdata->registers;
> +     temp_sensor->hwmon_dev = &pdev->dev;
> +
> +     pm_runtime_enable(&pdev->dev);
> +     pm_runtime_irq_safe(&pdev->dev);
> +
> +     /*
> +      * check if the efuse has a non-zero value if not
> +      * it is an untrimmed sample and the temperatures
> +      * may not be accurate
> +      */
> +
> +     if (omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_efuse))
> +             temp_sensor->is_efuse_valid = 1;
> +
> +     platform_set_drvdata(pdev, temp_sensor);
> +     dev_set_drvdata(&pdev->dev, temp_sensor);
> +     temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
> +     if (IS_ERR(temp_sensor->clock)) {
> +             ret = PTR_ERR(temp_sensor->clock);
> +             dev_err(temp_sensor->hwmon_dev,
> +                     "unable to get fclk: %d\n", ret);
> +             ret = -EINVAL;

Same case here. Do not assign -EINVAL to ret

> +             goto plat_res_err;
> +     }
> +
> +     ret = omap_temp_sensor_clk_enable(temp_sensor);
> +     if (ret) {
> +             dev_err(&pdev->dev, "Cannot enable temp sensor\n");
> +             goto clken_err;
> +     }
> +
> +     clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
> +     if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
> +             dev_err(&pdev->dev, "Error round rate\n");

You might want to assign something to 'ret' here.

> +             goto clken_err;
> +     }
> +
> +     ret = clk_set_rate(temp_sensor->clock, clk_rate);
> +     if (ret) {
> +             dev_err(&pdev->dev, "Cannot set clock rate\n");
> +             goto clken_err;
> +     }
> +
> +     temp_sensor->clk_rate = clk_rate;
> +     omap_enable_continuous_mode(temp_sensor, 1);
> +     omap_configure_temp_sensor_thresholds(temp_sensor);
> +     /* 1 ms */
> +     omap_configure_temp_sensor_counter(temp_sensor, 1);
> +
> +     /* Wait till the first conversion is done wait for at least 1ms */
> +     usleep_range(1000, 2000);
> +
> +     /* Read the temperature once due to hw issue*/
> +     omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +
> +     /* Set 2 seconds time as default counter */
> +     omap_configure_temp_sensor_counter(temp_sensor,
> +                                             temp_sensor->clk_rate * 2);
> +
> +     temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
> +     if (IS_ERR(temp_sensor->hwmon_dev)) {
> +             dev_err(&pdev->dev, "hwmon_device_register failed.\n");
> +             ret = PTR_ERR(temp_sensor->hwmon_dev);
> +             goto hwmon_reg_err;
> +     }
> +
> +     ret = sysfs_create_group(&pdev->dev.kobj,
> +                              &omap_temp_sensor_group);
> +     if (ret) {
> +             dev_err(&pdev->dev, "could not create sysfs files\n");
> +             goto sysfs_create_err;
> +     }
> +
> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
> +
> +     ret = request_threaded_irq(temp_sensor->irq, NULL,
> +             omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> +                     "temp_sensor", temp_sensor);
> +     if (ret) {
> +             dev_err(&pdev->dev, "Request threaded irq failed.\n");
> +             goto req_irq_err;
> +     }
> +
> +     /* unmask the T_COLD and unmask T_HOT at init */
> +     val = omap_temp_sensor_readl(temp_sensor,
> +             temp_sensor->registers->bgap_mask_ctrl);
> +     val |= temp_sensor->registers->mask_cold_mask
> +             | temp_sensor->registers->mask_hot_mask;
> +
> +     omap_temp_sensor_writel(temp_sensor, val,
> +             temp_sensor->registers->bgap_mask_ctrl);
> +
> +     return 0;
> +
> +req_irq_err:
> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
> +                             &omap_temp_sensor_group);
> +sysfs_create_err:
> +     hwmon_device_unregister(&pdev->dev);
> +hwmon_reg_err:
> +     omap_temp_sensor_clk_disable(temp_sensor);
> +clken_err:
> +     if (temp_sensor->clock)

Looking at the probe flow, this 'if' check seems unnecessary.

Thanks,
Durga


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die
@ 2011-08-10 16:47     ` R, Durgadoss
  0 siblings, 0 replies; 105+ messages in thread
From: R, Durgadoss @ 2011-08-10 16:47 UTC (permalink / raw)
  To: Keerthy, lm-sensors; +Cc: vishwanath.bs, linux-omap, b-cousson, rnayak

Hi,

> -----Original Message-----
> From: lm-sensors-bounces@lm-sensors.org [mailto:lm-sensors-bounces@lm-
> sensors.org] On Behalf Of Keerthy
> Sent: Wednesday, August 10, 2011 5:55 PM
> To: lm-sensors@lm-sensors.org
> Cc: vishwanath.bs@ti.com; linux-omap@vger.kernel.org; b-cousson@ti.com;
> rnayak@ti.com
> Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor
> driver
>
> On chip temperature sensor driver. The driver monitors the temperature of
> the MPU subsystem of the OMAP4. It sends notifications to the user space if
> the temperature crosses user defined thresholds via kobject_uevent interface.
> The user is allowed to configure the temperature thresholds vis sysfs nodes
> exposed using hwmon interface.
>
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  drivers/hwmon/Kconfig            |   11 +
>  drivers/hwmon/Makefile           |    1 +
>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 962 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 5f888f7..9c9cd8b 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>         This driver can also be built as a module.  If so, the module
>         will be called f71805f.
>
> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
> +     bool "OMAP on-die temperature sensor hwmon driver"
> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
> +     help
> +       If you say yes here you get support for hardware
> +       monitoring features of the OMAP on die temperature
> +       sensor.
> +
> +       Continuous conversion programmable delay
> +       mode is used for temperature conversion.
> +
>  config SENSORS_F71882FG
>       tristate "Fintek F71882FG and compatibles"
>       help
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 28061cf..d0f89f5 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
> diff --git a/drivers/hwmon/omap_temp_sensor.c
> b/drivers/hwmon/omap_temp_sensor.c
> new file mode 100644
> index 0000000..15e2559
> --- /dev/null
> +++ b/drivers/hwmon/omap_temp_sensor.c
> @@ -0,0 +1,950 @@
> +/*
> + * OMAP4 Temperature sensor driver file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy@ti.com>
> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/debugfs.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/init.h>
> +#include <plat/omap_device.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/jiffies.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/stddef.h>
> +#include <linux/sysfs.h>
> +#include <linux/err.h>
> +#include <linux/types.h>
> +#include <linux/mutex.h>
> +#include <linux/pm_runtime.h>
> +#include <plat/common.h>
> +#include <plat/temperature_sensor.h>
> +#include <mach/ctrl_module_core_44xx.h>
> +#include <mach/gpio.h>
> +
> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
> +#define OMAP_ADC_START_VALUE 530
> +#define OMAP_ADC_END_VALUE   923
> +
> +/*
> + * omap_temp_sensor structure
> + * @hwmon_dev - device pointer
> + * @clock - Clock pointer
> + * @registers - Pointer to structure with register offsets and bitfields
> + * @sensor_mutex - Mutex for sysfs, irq and PM
> + * @irq - MPU Irq number for thermal alert
> + * @phy_base - Physical base of the temp I/O
> + * @clk_rate - Holds current clock rate
> + * @temp_sensor_ctrl - temp sensor control register value
> + * @bg_ctrl - bandgap ctrl register value
> + * @bg_counter - bandgap counter value
> + * @bg_threshold - bandgap threshold register value
> + * @temp_sensor_tshut_threshold - bandgap tshut register value
> + * @is_efuse_valid - Flag to determine if efuse is valid or not
> + * @clk_on - Manages the current clock state
> + */
> +struct omap_temp_sensor {
> +     struct device           *hwmon_dev;
> +     struct clk              *clock;
> +     struct omap_temp_sensor_registers *registers;
> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
> +     unsigned int            irq;
> +     void __iomem            *phy_base;
> +     u32                     clk_rate;
> +     u32                     temp_sensor_ctrl;
> +     u32                     bg_ctrl;
> +     u32                     bg_counter;
> +     u32                     bg_threshold;
> +     u32                     temp_sensor_tshut_threshold;
> +     bool                    is_efuse_valid;
> +     bool                    clk_on;
> +};
> +
> +/*
> + * Temperature values in milli degree celsius
> + * ADC code values from 530 to 923
> + */
> +static int adc_to_temp[] = {
> +     -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
> +};
> +
> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
> +                                         *temp_sensor, u32 reg)
> +{
> +     return __raw_readl(temp_sensor->phy_base + reg);
> +}
> +
> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
> +                                 u32 val, u32 reg)
> +{
> +     __raw_writel(val, (temp_sensor->phy_base + reg));
> +}
> +
> +static int adc_to_temp_conversion(int adc_val)
> +{
> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
> +}
> +
> +static int temp_to_adc_conversion(long temp)
> +{
> +     int i;
> +
> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
> +             if (temp < adc_to_temp[i])
> +                     return OMAP_ADC_START_VALUE + i - 1;
> +
> +     return -EINVAL;
> +}
> +
> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
> +                                               *temp_sensor)
> +{
> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
> +
> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
> +
> +     /* Configure the TALERT thresholds */
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +             temp_sensor->registers->bgap_threshold);
> +
> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
> +
> +     /* Configure the TSHUT thresholds */
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->thsut_threshold);
> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +                     temp_sensor->registers->thsut_threshold);
> +}
> +
> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
> +                                            *temp_sensor, u32 counter)
> +{
> +     u32 val;
> +
> +     val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_counter);
> +     val &= ~(temp_sensor->registers->counter_mask);
> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
> +     omap_temp_sensor_writel(temp_sensor, val,
> +                     temp_sensor->registers->bgap_counter);
> +}
> +
> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
> +                                     bool enable)
> +{
> +     u32 val;
> +
> +     val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_mode_ctrl);
> +
> +     if (enable)
> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
> +     else
> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
> +
> +     omap_temp_sensor_writel(temp_sensor, val,
> +                     temp_sensor->registers->bgap_mode_ctrl);
> +}
> +
> +/* Sysfs hook functions */
> +
> +static ssize_t show_temp_max(struct device *dev,
> +                     struct device_attribute *devattr, char *buf)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     int temp;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +             dev_err(dev, "invalid value\n");
> +             goto out;
> +     }
> +     temp = adc_to_temp_conversion(temp);
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +     return snprintf(buf, 16, "%d\n", temp);

Even if it is invalid value, you are printing it.
May be you would have to do unlocking and returning -EINVAL inside the 'if' check.

Moreover, you are just doing a read.
So, do you really need a mutex_lock in this function.. ?

> +}
> +
> +static ssize_t set_temp_max(struct device *dev,
> +                         struct device_attribute *devattr,
> +                         const char *buf, size_t count)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     long                    val;
> +     u32                     reg_val, t_cold, t_hot, temp;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     if (strict_strtol(buf, 10, &val)) {
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     t_hot = temp_to_adc_conversion(val);
> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
> +             dev_err(dev, "invalid range\n");
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* obtain the T cold value */
> +     t_cold = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +     if (t_hot < t_cold) {
> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* write the new t_hot value */
> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
> +     reg_val |= (t_hot <<
> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> +                     temp_sensor->registers->bgap_threshold);
> +
> +     /* Read the current temperature */
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +     /*
> +      * If user sets the HIGH threshold(t_hot) greater than the current
> +      * temperature(temp) unmask the HOT interrupts
> +      */
> +     if (t_hot > temp) {
> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +     }
> +
> +     /*
> +      * If current temperature is in-between the hot and cold thresholds,
> +      * Enable both masks.
> +      */
> +     if (temp > t_cold && temp < t_hot) {
> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> +                             OMAP4460_BGAP_CTRL_OFFSET);
> +     }
> +     /*
> +      * else no need to do anything since HW will immediately compare
> +      * the new threshold and generate interrupt accordingly
> +      */
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     return count;
> +}
> +
> +static ssize_t show_temp_max_hyst(struct device *dev,
> +             struct device_attribute *devattr, char *buf)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     u32                     temp;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +             temp_sensor->registers->bgap_threshold);
> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
> +
> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +             dev_err(dev, "invalid value\n");
> +             goto out;

Same case here..
You can do ret = -EINVAL here..

> +     }
> +
> +     temp = adc_to_temp_conversion(temp);

...subsequently,
ret = snprintf(buf, 16, "%d\n", temp);

> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +     return snprintf(buf, 16, "%d\n", temp);

Return ret here..

> +}
> +
> +static ssize_t set_temp_max_hyst(struct device *dev,
> +                              struct device_attribute *devattr,
> +                              const char *buf, size_t count)
> +{
> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
> +     u32                             reg_val, t_hot, t_cold, temp;
> +     long                            val;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     if (strict_strtol(buf, 10, &val)) {
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     t_cold = temp_to_adc_conversion(val);
> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
> +             dev_err(dev, "invalid range");
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* obtain the T HOT value */
> +     t_hot = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
> +
> +     if (t_cold > t_hot) {
> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* write the new t_cold value */
> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_threshold);
> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
> +     reg_val |= (t_cold <<
> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> +                     temp_sensor->registers->bgap_threshold);
> +
> +     /* Read the current temperature */
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +             temp_sensor->registers->temp_sensor_ctrl);
> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
> +
> +     /*
> +      * If user sets the LOW threshold(t_cold) lower than the current
> +      * temperature(temp) unmask the COLD interrupts
> +      */
> +     if (t_cold < temp) {
> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> +                     temp_sensor->registers->bgap_mask_ctrl);
> +     }
> +
> +     /*
> +      * If current temperature is in-between the hot and cold thresholds,
> +      * Enable both masks.
> +      */
> +     if (temp < t_hot && temp > t_cold) {
> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> +                             temp_sensor->registers->bgap_mask_ctrl);
> +     }
> +
> +     /*
> +      * else no need to do anything since HW will immediately compare
> +      * the new threshold and generate interrupt accordingly
> +      */
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     return count;
> +}
> +
> +static ssize_t show_update_rate(struct device *dev,
> +                     struct device_attribute *devattr, char *buf)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     u32                     temp = 0, ret = 0;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     if (!temp_sensor->clk_rate) {
> +             dev_err(dev, "clk_rate is NULL\n");
> +             ret = -EINVAL;
> +             goto out;
> +     }
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_counter);
> +     temp = (temp & temp_sensor->registers->counter_mask) >>
> +                     __ffs(temp_sensor->registers->counter_mask);
> +     temp = temp * 1000 / (temp_sensor->clk_rate);
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     if (!ret)
> +             return sprintf(buf, "%d\n", temp);
> +     else

The 'else' is not necessary..

> +             return ret;
> +}
> +
> +static ssize_t set_update_rate(struct device *dev,
> +                            struct device_attribute *devattr,
> +                            const char *buf, size_t count)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     u32                     reg_val;
> +     long                    val;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     if (strict_strtol(buf, 10, &val)) {
> +             count = -EINVAL;
> +             goto out;
> +     }
> +
> +     val *= temp_sensor->clk_rate / 1000;
> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_counter);
> +
> +     reg_val &= ~(temp_sensor->registers->counter_mask);
> +     reg_val |= val;
> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> +                     temp_sensor->registers->bgap_counter);
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     return count;
> +}
> +
> +static int omap_temp_sensor_read_temp(struct device *dev,
> +                                   struct device_attribute *devattr,
> +                                   char *buf)
> +{
> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> +     int                     temp, ret = 0;
> +
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +             temp_sensor->registers->temp_sensor_ctrl);
> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
> +
> +     if (!temp_sensor->is_efuse_valid)
> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not
> accurate\n");
> +
> +     /* look up for temperature in the table and return the temperature */
> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> +             dev_err(dev, "invalid adc code reported %d", temp);
> +             ret = -EINVAL;
> +             goto out;
> +     }
> +
> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
> +
> +out:
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +     if (!ret)
> +             return sprintf(buf, "%d\n", temp);
> +     else

Same here..

> +             return ret;
> +}
> +
> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
> +                       NULL, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
> +                       set_temp_max, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
> show_temp_max_hyst,
> +                       set_temp_max_hyst, 0);
> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
> +                       set_update_rate, 0);
> +
> +static struct attribute *omap_temp_sensor_attributes[] = {
> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
> +     &sensor_dev_attr_update_rate.dev_attr.attr,
> +     NULL
> +};
> +
> +static const struct attribute_group omap_temp_sensor_group = {
> +     .attrs = omap_temp_sensor_attributes,
> +};
> +
> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
> +{
> +     u32 ret = 0, temp;
> +
> +     if (temp_sensor->clk_on) {
> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
> +             goto out;
> +     }
> +
> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
> +     if (ret < 0) {
> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
> +             ret = -EINVAL;

Please do not mask the return value.
Let it be whatever returned by the get_sync.
Anyway, you are returning 'ret' in the end...

> +             goto out;
> +     }
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
> +     /* BGAP_TEMPSOFF should be reset to 0 */
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +                             temp_sensor->registers->temp_sensor_ctrl);
> +     temp_sensor->clk_on = 1;
> +out:
> +     return ret;
> +}
> +
> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
> +{
> +     u32 temp, ret = 0;
> +     unsigned long timeout;
> +
> +     if (!temp_sensor->clk_on) {
> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
> +             goto out;
> +     }
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
> +
> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_status);
> +     timeout = jiffies + msecs_to_jiffies(5);
> +
> +     /* wait till the clean stop bit is set or till the timeout exppires */

s/expires/expires

> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
> +             !(time_after(jiffies, timeout))) {
> +             temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_status);
> +             usleep_range(500, 2000);
> +     }
> +
> +     if (time_after(jiffies, timeout))
> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
> +     /* Gate the clock */
> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
> +     if (ret < 0) {
> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
> +             ret = -EINVAL;

Same case as get_sync. Don't mask the return value.

> +             goto out;
> +     }
> +     temp_sensor->clk_on = 0;
> +out:
> +     return ret;
> +}
> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
> +{
> +     struct omap_temp_sensor         *temp_sensor;
> +     int                             t_hot, t_cold, temp;
> +
> +     temp_sensor = data;
> +     mutex_lock(&temp_sensor->sensor_mutex);
> +
> +     /* Read the status of t_hot */
> +     t_hot = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_status)
> +                     & temp_sensor->registers->status_hot_mask;
> +
> +     /* Read the status of t_cold */
> +     t_cold = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_status)
> +                     & temp_sensor->registers->status_cold_mask;
> +
> +     temp = omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_mask_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) {
> +             temp &= ~(temp_sensor->registers->mask_hot_mask);
> +             temp |= temp_sensor->registers->mask_cold_mask;
> +     } else if (t_cold) {
> +             temp &= ~(temp_sensor->registers->mask_cold_mask);
> +             temp |= temp_sensor->registers->mask_hot_mask;
> +     }
> +
> +     omap_temp_sensor_writel(temp_sensor, temp,
> +             temp_sensor->registers->bgap_mask_ctrl);
> +
> +     /* kobject_uvent to user space telling thermal threshold crossed */
> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
> +
> +     mutex_unlock(&temp_sensor->sensor_mutex);
> +
> +     return IRQ_HANDLED;
> +}
> +
> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
> +{
> +     struct omap_temp_sensor_pdata   *pdata  = pdev->dev.platform_data;
> +     struct omap_temp_sensor         *temp_sensor;
> +     struct resource                 *mem;
> +     int                             ret = 0;
> +     int                             val, clk_rate;
> +
> +     if (!pdata) {
> +             dev_err(&pdev->dev, "platform data missing\n");
> +             return -EINVAL;
> +     }
> +
> +     temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
> +     if (!temp_sensor)
> +             return -ENOMEM;
> +
> +     mutex_init(&temp_sensor->sensor_mutex);
> +
> +     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +     if (!mem) {
> +             dev_err(&pdev->dev, "no mem resource\n");
> +             ret = -EINVAL;

You can do PTR_ERR(mem) to get the return error value as an integer.
Otherwise, it makes more sense to be -ENOMEM

> +             goto plat_res_err;
> +     }
> +
> +     temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
> +     if (temp_sensor->irq = -ENXIO) {
> +             dev_err(&pdev->dev, "get_irq_byname failed\n");
> +             ret = temp_sensor->irq;
> +             goto plat_res_err;
> +     }
> +

This flow can better be:
ret = platform_get_irq_byname(...)
if (ret < 0) //because it is an IRQ number
{ ... }

Then assign ret to temp_sensor->irq

> +     temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
> +     temp_sensor->clock = NULL;
> +     temp_sensor->registers = pdata->registers;
> +     temp_sensor->hwmon_dev = &pdev->dev;
> +
> +     pm_runtime_enable(&pdev->dev);
> +     pm_runtime_irq_safe(&pdev->dev);
> +
> +     /*
> +      * check if the efuse has a non-zero value if not
> +      * it is an untrimmed sample and the temperatures
> +      * may not be accurate
> +      */
> +
> +     if (omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->bgap_efuse))
> +             temp_sensor->is_efuse_valid = 1;
> +
> +     platform_set_drvdata(pdev, temp_sensor);
> +     dev_set_drvdata(&pdev->dev, temp_sensor);
> +     temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
> +     if (IS_ERR(temp_sensor->clock)) {
> +             ret = PTR_ERR(temp_sensor->clock);
> +             dev_err(temp_sensor->hwmon_dev,
> +                     "unable to get fclk: %d\n", ret);
> +             ret = -EINVAL;

Same case here. Do not assign -EINVAL to ret

> +             goto plat_res_err;
> +     }
> +
> +     ret = omap_temp_sensor_clk_enable(temp_sensor);
> +     if (ret) {
> +             dev_err(&pdev->dev, "Cannot enable temp sensor\n");
> +             goto clken_err;
> +     }
> +
> +     clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
> +     if (clk_rate < 1000000 || clk_rate = 0xffffffff) {
> +             dev_err(&pdev->dev, "Error round rate\n");

You might want to assign something to 'ret' here.

> +             goto clken_err;
> +     }
> +
> +     ret = clk_set_rate(temp_sensor->clock, clk_rate);
> +     if (ret) {
> +             dev_err(&pdev->dev, "Cannot set clock rate\n");
> +             goto clken_err;
> +     }
> +
> +     temp_sensor->clk_rate = clk_rate;
> +     omap_enable_continuous_mode(temp_sensor, 1);
> +     omap_configure_temp_sensor_thresholds(temp_sensor);
> +     /* 1 ms */
> +     omap_configure_temp_sensor_counter(temp_sensor, 1);
> +
> +     /* Wait till the first conversion is done wait for at least 1ms */
> +     usleep_range(1000, 2000);
> +
> +     /* Read the temperature once due to hw issue*/
> +     omap_temp_sensor_readl(temp_sensor,
> +                     temp_sensor->registers->temp_sensor_ctrl);
> +
> +     /* Set 2 seconds time as default counter */
> +     omap_configure_temp_sensor_counter(temp_sensor,
> +                                             temp_sensor->clk_rate * 2);
> +
> +     temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
> +     if (IS_ERR(temp_sensor->hwmon_dev)) {
> +             dev_err(&pdev->dev, "hwmon_device_register failed.\n");
> +             ret = PTR_ERR(temp_sensor->hwmon_dev);
> +             goto hwmon_reg_err;
> +     }
> +
> +     ret = sysfs_create_group(&pdev->dev.kobj,
> +                              &omap_temp_sensor_group);
> +     if (ret) {
> +             dev_err(&pdev->dev, "could not create sysfs files\n");
> +             goto sysfs_create_err;
> +     }
> +
> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
> +
> +     ret = request_threaded_irq(temp_sensor->irq, NULL,
> +             omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> +                     "temp_sensor", temp_sensor);
> +     if (ret) {
> +             dev_err(&pdev->dev, "Request threaded irq failed.\n");
> +             goto req_irq_err;
> +     }
> +
> +     /* unmask the T_COLD and unmask T_HOT at init */
> +     val = omap_temp_sensor_readl(temp_sensor,
> +             temp_sensor->registers->bgap_mask_ctrl);
> +     val |= temp_sensor->registers->mask_cold_mask
> +             | temp_sensor->registers->mask_hot_mask;
> +
> +     omap_temp_sensor_writel(temp_sensor, val,
> +             temp_sensor->registers->bgap_mask_ctrl);
> +
> +     return 0;
> +
> +req_irq_err:
> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
> +                             &omap_temp_sensor_group);
> +sysfs_create_err:
> +     hwmon_device_unregister(&pdev->dev);
> +hwmon_reg_err:
> +     omap_temp_sensor_clk_disable(temp_sensor);
> +clken_err:
> +     if (temp_sensor->clock)

Looking at the probe flow, this 'if' check seems unnecessary.

Thanks,
Durga


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-10 14:17           ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Cousson, Benoit
@ 2011-08-10 21:37             ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 21:37 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Balbi, Felipe, Tony Lindgren, J, KEERTHY, lm-sensors, Sripathy,
	Vishwanath, linux-omap, Nayak, Rajendra

[-- Attachment #1: Type: text/plain, Size: 1950 bytes --]

Hi,

On Wed, Aug 10, 2011 at 04:17:05PM +0200, Cousson, Benoit wrote:
> On 8/10/2011 2:48 PM, Balbi, Felipe wrote:
> >Hi,
> >
> >On Wed, Aug 10, 2011 at 05:41:02AM -0700, Tony Lindgren wrote:
> >>* Felipe Balbi<balbi@ti.com>  [110810 05:31]:
> >>>
> >>>On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
> >>>>+
> >>>>+int __init omap_devinit_temp_sensor(void)
> >>>>+{
> >>>>+	if (!cpu_is_omap446x())
> >>>>+		return 0;
> >>>>+
> >>>>+	return omap_hwmod_for_each_by_class("temperature_sensor",
> >>>>+			temp_sensor_dev_init, NULL);
> >>>>+}
> >>>>+
> >>>>+arch_initcall(omap_devinit_temp_sensor);
> >>>
> >>>I really dislike people adding more and more *initcall() to their pieces
> >>>of code. But Tony is the final Judge.
> >>
> >>Yes how about making this just a regular device driver and have it
> >>live under drivers/ somewhere?
> >>
> >>Or is there some reason why this could not be a loadable module?
> >
> >driver is loadable, this is just creating the platform_device, but still
> >I don't think it deserves its own arch_initcall(), it could very well be
> >something which is called after we know we're running at omap4, or
> >called by each board...
> 
> Funny, because I thought we were trying to get rid of the ugly init
> devices from board file to use *initcall() from a dedicated device
> file.
> The advantage is that you do not have anymore a central place that
> everybody will change and that is thus subject to merge conflicts.
> 
> The drawback is that you do not know where an when the devices are created.
> 
> That being said, device-tree will provide a nice way to build all
> this devices without any initcall or board hacks.
> This is just a temporary issue :-)

Temporary or not, I would rather have this device created based on CPU
detection as it ought to be. But since we're moving to DT anyway, I
agree it might not be worth spending the time.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-10 21:37             ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-10 21:37 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Balbi, Felipe, Tony Lindgren, J, KEERTHY, lm-sensors, Sripathy,
	Vishwanath, linux-omap, Nayak, Rajendra


[-- Attachment #1.1: Type: text/plain, Size: 1950 bytes --]

Hi,

On Wed, Aug 10, 2011 at 04:17:05PM +0200, Cousson, Benoit wrote:
> On 8/10/2011 2:48 PM, Balbi, Felipe wrote:
> >Hi,
> >
> >On Wed, Aug 10, 2011 at 05:41:02AM -0700, Tony Lindgren wrote:
> >>* Felipe Balbi<balbi@ti.com>  [110810 05:31]:
> >>>
> >>>On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
> >>>>+
> >>>>+int __init omap_devinit_temp_sensor(void)
> >>>>+{
> >>>>+	if (!cpu_is_omap446x())
> >>>>+		return 0;
> >>>>+
> >>>>+	return omap_hwmod_for_each_by_class("temperature_sensor",
> >>>>+			temp_sensor_dev_init, NULL);
> >>>>+}
> >>>>+
> >>>>+arch_initcall(omap_devinit_temp_sensor);
> >>>
> >>>I really dislike people adding more and more *initcall() to their pieces
> >>>of code. But Tony is the final Judge.
> >>
> >>Yes how about making this just a regular device driver and have it
> >>live under drivers/ somewhere?
> >>
> >>Or is there some reason why this could not be a loadable module?
> >
> >driver is loadable, this is just creating the platform_device, but still
> >I don't think it deserves its own arch_initcall(), it could very well be
> >something which is called after we know we're running at omap4, or
> >called by each board...
> 
> Funny, because I thought we were trying to get rid of the ugly init
> devices from board file to use *initcall() from a dedicated device
> file.
> The advantage is that you do not have anymore a central place that
> everybody will change and that is thus subject to merge conflicts.
> 
> The drawback is that you do not know where an when the devices are created.
> 
> That being said, device-tree will provide a nice way to build all
> this devices without any initcall or board hacks.
> This is just a temporary issue :-)

Temporary or not, I would rather have this device created based on CPU
detection as it ought to be. But since we're moving to DT anyway, I
agree it might not be worth spending the time.

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-10 12:36     ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
@ 2011-08-11  2:52       ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11  2:40 UTC (permalink / raw)
  To: balbi; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

On Wed, Aug 10, 2011 at 6:06 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> (you should Cc Tony, as he's OMAP maintainer)
>
> On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
>> The device file adds the device support for OMAP4
>> on die temperature sensor.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>>  arch/arm/mach-omap2/Makefile                       |    3 +-
>>  arch/arm/mach-omap2/temp_sensor_device.c           |   85 +++++++++++++++++++
>>  arch/arm/plat-omap/Kconfig                         |   12 +++
>>  .../plat-omap/include/plat/temperature_sensor.h    |   87 ++++++++++++++++++++
>>  4 files changed, 186 insertions(+), 1 deletions(-)
>>  create mode 100644 arch/arm/mach-omap2/temp_sensor_device.c
>>  create mode 100644 arch/arm/plat-omap/include/plat/temperature_sensor.h
>>
>> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>> index fb02937..5812fb4 100644
>> --- a/arch/arm/mach-omap2/Makefile
>> +++ b/arch/arm/mach-omap2/Makefile
>> @@ -18,6 +18,7 @@ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
>>
>>  obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
>>
>> +obj-$(CONFIG_OMAP_TEMP_SENSOR)          += temp_sensor_device.o
>>  obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
>>
>>  # SMP support ONLY available for OMAP4
>> @@ -86,7 +87,7 @@ obj-$(CONFIG_ARCH_OMAP3)            += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
>>  obj-$(CONFIG_ARCH_OMAP4)             += prcm.o cm2xxx_3xxx.o cminst44xx.o \
>>                                          cm44xx.o prcm_mpu44xx.o \
>>                                          prminst44xx.o vc44xx_data.o \
>> -                                        vp44xx_data.o
>> +                                        vp44xx_data.o temp_sensor4460_data.o
>>
>>  # OMAP voltage domains
>>  ifeq ($(CONFIG_PM),y)
>> diff --git a/arch/arm/mach-omap2/temp_sensor_device.c b/arch/arm/mach-omap2/temp_sensor_device.c
>> new file mode 100644
>> index 0000000..5d5e92f
>> --- /dev/null
>> +++ b/arch/arm/mach-omap2/temp_sensor_device.c
>> @@ -0,0 +1,85 @@
>> +/*
>> + * OMAP on die Temperature sensor device file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@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/err.h>
>> +#include <linux/slab.h>
>> +#include <linux/io.h>
>> +#include <linux/pm_runtime.h>
>> +#include <plat/omap_device.h>
>> +#include "control.h"
>> +#include "pm.h"
>> +#include <plat/temperature_sensor.h>
>> +
>> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
>> +     {
>> +      .deactivate_func = omap_device_idle_hwmods,
>> +      .activate_func = omap_device_enable_hwmods,
>> +      .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
>> +     }
>
> wrong indentation.
>

Ok. I will correct this.

>> +};
>> +
>> +static int temp_sensor_dev_init(struct omap_hwmod *oh, void *user)
>> +{
>> +     struct  omap_temp_sensor_pdata          *temp_sensor_pdata;
>> +     struct  omap_device                     *od;
>> +     struct  omap_temp_sensor_dev_attr       *temp_sensor_dev_attr;
>> +     int                                     ret;
>> +     static int                              device_count;
>
> use an IDR here (see include/linux/idr.h)

Ok. I will check this.

>
>> +     ret = 0;
>
> initialize on the declarion and you can avoid this line.

Ok

>
>> +     temp_sensor_pdata =
>> +         kzalloc(sizeof(*temp_sensor_pdata), GFP_KERNEL);
>> +     if (!temp_sensor_pdata) {
>> +             dev_err(&oh->od->pdev.dev,
>> +                     "Unable to allocate memory for temp sensor pdata\n");
>> +             return -ENOMEM;
>> +     }
>> +
>> +     temp_sensor_dev_attr = oh->dev_attr;
>> +     if (!strcmp(temp_sensor_dev_attr->name, "mpu"))
>> +             temp_sensor_pdata->registers = &omap_mpu_temp_sensor_registers;
>> +
>> +     od = omap_device_build("omap_temp_sensor", device_count++,
>> +             oh, temp_sensor_pdata, sizeof(*temp_sensor_pdata),
>> +            omap_temp_sensor_latency,
>> +                     ARRAY_SIZE(omap_temp_sensor_latency), 0);
>> +     if (IS_ERR(od)) {
>> +             dev_warn(&oh->od->pdev.dev,
>> +                     "Could not build omap_device for %s\n", oh->name);
>> +             ret = PTR_ERR(od);
>> +     }
>> +
>> +     kfree(temp_sensor_pdata);
>> +
>> +     return ret;
>> +}
>> +
>> +int __init omap_devinit_temp_sensor(void)
>> +{
>> +     if (!cpu_is_omap446x())
>> +             return 0;
>> +
>> +     return omap_hwmod_for_each_by_class("temperature_sensor",
>> +                     temp_sensor_dev_init, NULL);
>> +}
>> +
>> +arch_initcall(omap_devinit_temp_sensor);
>
> I really dislike people adding more and more *initcall() to their pieces
> of code. But Tony is the final Judge.
>
>> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>> index 6e6735f..8fd8e80 100644
>> --- a/arch/arm/plat-omap/Kconfig
>> +++ b/arch/arm/plat-omap/Kconfig
>> @@ -115,6 +115,18 @@ config OMAP_MCBSP
>>         Say Y here if you want support for the OMAP Multichannel
>>         Buffered Serial Port.
>>
>> +config OMAP_TEMP_SENSOR
>> +     bool "OMAP Temp Sensor Support"
>> +     depends on ARCH_OMAP
>> +     default n
>> +     help
>> +       Say Y here if you want support for the temp sensor
>> +       on OMAP4460.
>> +
>> +       This provides the temperature of the MPU
>> +       subsystem. Only one instance of on die temperature
>> +       sensor is present.
>
> if there's only one instance, why do you use
> omap_hwmod_for_each_by_class() ??

In case of OMAP5 there are multiple instances. Hence using
omap_hwmod_for_each_by_class().

>
>> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> new file mode 100644
>> index 0000000..692ebdc
>> --- /dev/null
>> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> @@ -0,0 +1,87 @@
>> +/*
>> + * OMAP Temperature sensor header file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> +
>> +/* Offsets from the base of temperature sensor registers */
>> +
>> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
>> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
>> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
>> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
>> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
>> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
>> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
>> +
>> +struct omap_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     thsut_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;
>> +};
>
> I find it unnecessary to pass the register map to driver using
> platform_data.

With multiple instances the register map to individual instances will change.
So passing it via platform_data.

>
>> +/*
>> + * @name: Name of the domain of the temperature sensor
>> + */
>
> comment fits in one line.

Ok

>
>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-11  2:52       ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11  2:52 UTC (permalink / raw)
  To: balbi; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

On Wed, Aug 10, 2011 at 6:06 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> (you should Cc Tony, as he's OMAP maintainer)
>
> On Wed, Aug 10, 2011 at 05:55:20PM +0530, Keerthy wrote:
>> The device file adds the device support for OMAP4
>> on die temperature sensor.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>>  arch/arm/mach-omap2/Makefile                       |    3 +-
>>  arch/arm/mach-omap2/temp_sensor_device.c           |   85 +++++++++++++++++++
>>  arch/arm/plat-omap/Kconfig                         |   12 +++
>>  .../plat-omap/include/plat/temperature_sensor.h    |   87 ++++++++++++++++++++
>>  4 files changed, 186 insertions(+), 1 deletions(-)
>>  create mode 100644 arch/arm/mach-omap2/temp_sensor_device.c
>>  create mode 100644 arch/arm/plat-omap/include/plat/temperature_sensor.h
>>
>> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>> index fb02937..5812fb4 100644
>> --- a/arch/arm/mach-omap2/Makefile
>> +++ b/arch/arm/mach-omap2/Makefile
>> @@ -18,6 +18,7 @@ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
>>
>>  obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
>>
>> +obj-$(CONFIG_OMAP_TEMP_SENSOR)          += temp_sensor_device.o
>>  obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
>>
>>  # SMP support ONLY available for OMAP4
>> @@ -86,7 +87,7 @@ obj-$(CONFIG_ARCH_OMAP3)            += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
>>  obj-$(CONFIG_ARCH_OMAP4)             += prcm.o cm2xxx_3xxx.o cminst44xx.o \
>>                                          cm44xx.o prcm_mpu44xx.o \
>>                                          prminst44xx.o vc44xx_data.o \
>> -                                        vp44xx_data.o
>> +                                        vp44xx_data.o temp_sensor4460_data.o
>>
>>  # OMAP voltage domains
>>  ifeq ($(CONFIG_PM),y)
>> diff --git a/arch/arm/mach-omap2/temp_sensor_device.c b/arch/arm/mach-omap2/temp_sensor_device.c
>> new file mode 100644
>> index 0000000..5d5e92f
>> --- /dev/null
>> +++ b/arch/arm/mach-omap2/temp_sensor_device.c
>> @@ -0,0 +1,85 @@
>> +/*
>> + * OMAP on die Temperature sensor device file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@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/err.h>
>> +#include <linux/slab.h>
>> +#include <linux/io.h>
>> +#include <linux/pm_runtime.h>
>> +#include <plat/omap_device.h>
>> +#include "control.h"
>> +#include "pm.h"
>> +#include <plat/temperature_sensor.h>
>> +
>> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
>> +     {
>> +      .deactivate_func = omap_device_idle_hwmods,
>> +      .activate_func = omap_device_enable_hwmods,
>> +      .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
>> +     }
>
> wrong indentation.
>

Ok. I will correct this.

>> +};
>> +
>> +static int temp_sensor_dev_init(struct omap_hwmod *oh, void *user)
>> +{
>> +     struct  omap_temp_sensor_pdata          *temp_sensor_pdata;
>> +     struct  omap_device                     *od;
>> +     struct  omap_temp_sensor_dev_attr       *temp_sensor_dev_attr;
>> +     int                                     ret;
>> +     static int                              device_count;
>
> use an IDR here (see include/linux/idr.h)

Ok. I will check this.

>
>> +     ret = 0;
>
> initialize on the declarion and you can avoid this line.

Ok

>
>> +     temp_sensor_pdata >> +         kzalloc(sizeof(*temp_sensor_pdata), GFP_KERNEL);
>> +     if (!temp_sensor_pdata) {
>> +             dev_err(&oh->od->pdev.dev,
>> +                     "Unable to allocate memory for temp sensor pdata\n");
>> +             return -ENOMEM;
>> +     }
>> +
>> +     temp_sensor_dev_attr = oh->dev_attr;
>> +     if (!strcmp(temp_sensor_dev_attr->name, "mpu"))
>> +             temp_sensor_pdata->registers = &omap_mpu_temp_sensor_registers;
>> +
>> +     od = omap_device_build("omap_temp_sensor", device_count++,
>> +             oh, temp_sensor_pdata, sizeof(*temp_sensor_pdata),
>> +            omap_temp_sensor_latency,
>> +                     ARRAY_SIZE(omap_temp_sensor_latency), 0);
>> +     if (IS_ERR(od)) {
>> +             dev_warn(&oh->od->pdev.dev,
>> +                     "Could not build omap_device for %s\n", oh->name);
>> +             ret = PTR_ERR(od);
>> +     }
>> +
>> +     kfree(temp_sensor_pdata);
>> +
>> +     return ret;
>> +}
>> +
>> +int __init omap_devinit_temp_sensor(void)
>> +{
>> +     if (!cpu_is_omap446x())
>> +             return 0;
>> +
>> +     return omap_hwmod_for_each_by_class("temperature_sensor",
>> +                     temp_sensor_dev_init, NULL);
>> +}
>> +
>> +arch_initcall(omap_devinit_temp_sensor);
>
> I really dislike people adding more and more *initcall() to their pieces
> of code. But Tony is the final Judge.
>
>> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>> index 6e6735f..8fd8e80 100644
>> --- a/arch/arm/plat-omap/Kconfig
>> +++ b/arch/arm/plat-omap/Kconfig
>> @@ -115,6 +115,18 @@ config OMAP_MCBSP
>>         Say Y here if you want support for the OMAP Multichannel
>>         Buffered Serial Port.
>>
>> +config OMAP_TEMP_SENSOR
>> +     bool "OMAP Temp Sensor Support"
>> +     depends on ARCH_OMAP
>> +     default n
>> +     help
>> +       Say Y here if you want support for the temp sensor
>> +       on OMAP4460.
>> +
>> +       This provides the temperature of the MPU
>> +       subsystem. Only one instance of on die temperature
>> +       sensor is present.
>
> if there's only one instance, why do you use
> omap_hwmod_for_each_by_class() ??

In case of OMAP5 there are multiple instances. Hence using
omap_hwmod_for_each_by_class().

>
>> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> new file mode 100644
>> index 0000000..692ebdc
>> --- /dev/null
>> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> @@ -0,0 +1,87 @@
>> +/*
>> + * OMAP Temperature sensor header file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> +
>> +/* Offsets from the base of temperature sensor registers */
>> +
>> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
>> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
>> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
>> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
>> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
>> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
>> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
>> +
>> +struct omap_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     thsut_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;
>> +};
>
> I find it unnecessary to pass the register map to driver using
> platform_data.

With multiple instances the register map to individual instances will change.
So passing it via platform_data.

>
>> +/*
>> + * @name: Name of the domain of the temperature sensor
>> + */
>
> comment fits in one line.

Ok

>
>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-10 12:46     ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
  (?)
@ 2011-08-11  9:57       ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11  9:57 UTC (permalink / raw)
  To: balbi
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> (why aren't below in Cc ?

I will add them.

>
> HARDWARE MONITORING
> M:      Jean Delvare <khali@linux-fr.org>
> M:      Guenter Roeck <guenter.roeck@ericsson.com>
> L:      lm-sensors@lm-sensors.org
> W:      http://www.lm-sensors.org/
> T:      quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
> T:      git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
> S:      Maintained
> F:      Documentation/hwmon/
> F:      drivers/hwmon/
> F:      include/linux/hwmon*.h)
>
> On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
>> On chip temperature sensor driver. The driver monitors the temperature of
>> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>> the temperature crosses user defined thresholds via kobject_uevent interface.
>> The user is allowed to configure the temperature thresholds vis sysfs nodes
>> exposed using hwmon interface.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>>  drivers/hwmon/Kconfig            |   11 +
>>  drivers/hwmon/Makefile           |    1 +
>>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 962 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>>
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 5f888f7..9c9cd8b 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>>         This driver can also be built as a module.  If so, the module
>>         will be called f71805f.
>>
>> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>> +     bool "OMAP on-die temperature sensor hwmon driver"
>> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>> +     help
>> +       If you say yes here you get support for hardware
>> +       monitoring features of the OMAP on die temperature
>> +       sensor.
>> +
>> +       Continuous conversion programmable delay
>> +       mode is used for temperature conversion.
>> +
>>  config SENSORS_F71882FG
>>       tristate "Fintek F71882FG and compatibles"
>>       help
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index 28061cf..d0f89f5 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
>> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> new file mode 100644
>> index 0000000..15e2559
>> --- /dev/null
>> +++ b/drivers/hwmon/omap_temp_sensor.c
>> @@ -0,0 +1,950 @@
>> +/*
>> + * OMAP4 Temperature sensor driver file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@ti.com>
>> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> +#include <linux/clk.h>
>
> why ??

Clock rate setting functions.

>
>> +#include <linux/io.h>
>> +#include <linux/debugfs.h>
>
> why ??

It will be removed.

>
>> +#include <linux/delay.h>
>> +#include <linux/slab.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/init.h>
>> +#include <plat/omap_device.h>
>
> why ??
>

Context loss count

>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <linux/device.h>
>> +#include <linux/jiffies.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +#include <linux/stddef.h>
>> +#include <linux/sysfs.h>
>> +#include <linux/err.h>
>> +#include <linux/types.h>
>> +#include <linux/mutex.h>
>> +#include <linux/pm_runtime.h>
>> +#include <plat/common.h>
>
> why ?

usleep_range function.

>
>> +#include <plat/temperature_sensor.h>
>

It is the header file with the structure definitions
used in the driver.

> why ?
>
>> +#include <mach/ctrl_module_core_44xx.h>
>
> why ?

It will be removed

>
>> +#include <mach/gpio.h>
>
> linux/gpio.h for crying out loud... how many times Russell has to say
> the exact same thing ??????
>

It will be removed

>> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
>> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
>> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
>> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
>> +#define OMAP_ADC_START_VALUE 530
>> +#define OMAP_ADC_END_VALUE   923
>> +
>> +/*
>> + * omap_temp_sensor structure
>> + * @hwmon_dev - device pointer
>> + * @clock - Clock pointer
>> + * @registers - Pointer to structure with register offsets and bitfields
>> + * @sensor_mutex - Mutex for sysfs, irq and PM
>> + * @irq - MPU Irq number for thermal alert
>> + * @phy_base - Physical base of the temp I/O
>> + * @clk_rate - Holds current clock rate
>> + * @temp_sensor_ctrl - temp sensor control register value
>> + * @bg_ctrl - bandgap ctrl register value
>> + * @bg_counter - bandgap counter value
>> + * @bg_threshold - bandgap threshold register value
>> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>> + * @clk_on - Manages the current clock state
>> + */
>> +struct omap_temp_sensor {
>> +     struct device           *hwmon_dev;
>> +     struct clk              *clock;
>> +     struct omap_temp_sensor_registers *registers;
>> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
>> +     unsigned int            irq;
>> +     void __iomem            *phy_base;
>> +     u32                     clk_rate;
>> +     u32                     temp_sensor_ctrl;
>> +     u32                     bg_ctrl;
>> +     u32                     bg_counter;
>> +     u32                     bg_threshold;
>> +     u32                     temp_sensor_tshut_threshold;
>> +     bool                    is_efuse_valid;
>> +     bool                    clk_on;
>> +};
>> +
>> +/*
>> + * Temperature values in milli degree celsius
>> + * ADC code values from 530 to 923
>> + */
>> +static int adc_to_temp[] = {
>> +     -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
>> +};
>> +
>> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>> +                                         *temp_sensor, u32 reg)
>> +{
>> +     return __raw_readl(temp_sensor->phy_base + reg);
>> +}
>> +
>> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>> +                                 u32 val, u32 reg)
>> +{
>> +     __raw_writel(val, (temp_sensor->phy_base + reg));
>> +}
>> +
>> +static int adc_to_temp_conversion(int adc_val)
>> +{
>> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>> +}
>> +
>> +static int temp_to_adc_conversion(long temp)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>> +             if (temp < adc_to_temp[i])
>> +                     return OMAP_ADC_START_VALUE + i - 1;
>> +
>> +     return -EINVAL;
>> +}
>> +
>> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>> +                                               *temp_sensor)
>> +{
>> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>> +
>> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>> +
>> +     /* Configure the TALERT thresholds */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +             temp_sensor->registers->bgap_threshold);
>> +
>> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>> +
>> +     /* Configure the TSHUT thresholds */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->thsut_threshold);
>> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                     temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>> +                                            *temp_sensor, u32 counter)
>> +{
>> +     u32 val;
>> +
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +     val &= ~(temp_sensor->registers->counter_mask);
>> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +                     temp_sensor->registers->bgap_counter);
>> +}
>> +
>> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>> +                                     bool enable)
>> +{
>> +     u32 val;
>> +
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_mode_ctrl);
>> +
>> +     if (enable)
>> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>> +     else
>> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
>> +
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +                     temp_sensor->registers->bgap_mode_ctrl);
>> +}
>> +
>> +/* Sysfs hook functions */
>> +
>> +static ssize_t show_temp_max(struct device *dev,
>> +                     struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     int temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
>> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid value\n");
>> +             goto out;
>> +     }
>> +     temp = adc_to_temp_conversion(temp);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return snprintf(buf, 16, "%d\n", temp);
>> +}
>> +
>> +static ssize_t set_temp_max(struct device *dev,
>> +                         struct device_attribute *devattr,
>> +                         const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     long                    val;
>> +     u32                     reg_val, t_cold, t_hot, temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     t_hot = temp_to_adc_conversion(val);
>> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>> +             dev_err(dev, "invalid range\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* obtain the T cold value */
>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> +     if (t_hot < t_cold) {
>> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* write the new t_hot value */
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>> +     reg_val |= (t_hot <<
>> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_threshold);
>> +
>> +     /* Read the current temperature */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> +     /*
>> +      * If user sets the HIGH threshold(t_hot) greater than the current
>> +      * temperature(temp) unmask the HOT interrupts
>> +      */
>> +     if (t_hot > temp) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * If current temperature is in-between the hot and cold thresholds,
>> +      * Enable both masks.
>> +      */
>> +     if (temp > t_cold && temp < t_hot) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             OMAP4460_BGAP_CTRL_OFFSET);
>> +     }
>> +     /*
>> +      * else no need to do anything since HW will immediately compare
>> +      * the new threshold and generate interrupt accordingly
>> +      */
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static ssize_t show_temp_max_hyst(struct device *dev,
>> +             struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_threshold);
>> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid value\n");
>> +             goto out;
>> +     }
>> +
>> +     temp = adc_to_temp_conversion(temp);
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return snprintf(buf, 16, "%d\n", temp);
>> +}
>> +
>> +static ssize_t set_temp_max_hyst(struct device *dev,
>> +                              struct device_attribute *devattr,
>> +                              const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
>> +     u32                             reg_val, t_hot, t_cold, temp;
>> +     long                            val;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     t_cold = temp_to_adc_conversion(val);
>> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid range");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* obtain the T HOT value */
>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> +     if (t_cold > t_hot) {
>> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* write the new t_cold value */
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>> +     reg_val |= (t_cold <<
>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_threshold);
>> +
>> +     /* Read the current temperature */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> +     /*
>> +      * If user sets the LOW threshold(t_cold) lower than the current
>> +      * temperature(temp) unmask the COLD interrupts
>> +      */
>> +     if (t_cold < temp) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * If current temperature is in-between the hot and cold thresholds,
>> +      * Enable both masks.
>> +      */
>> +     if (temp < t_hot && temp > t_cold) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * else no need to do anything since HW will immediately compare
>> +      * the new threshold and generate interrupt accordingly
>> +      */
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static ssize_t show_update_rate(struct device *dev,
>> +                     struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     temp = 0, ret = 0;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (!temp_sensor->clk_rate) {
>> +             dev_err(dev, "clk_rate is NULL\n");
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +     temp = (temp & temp_sensor->registers->counter_mask) >>
>> +                     __ffs(temp_sensor->registers->counter_mask);
>
>        temp &= ??
>
>> +     temp = temp * 1000 / (temp_sensor->clk_rate);
>
>        temp *= ??

Need to multiply the temp with 1000 before dividing.
temp *= evaluates the RHS first and then multiplies LHS.

>
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     if (!ret)
>> +             return sprintf(buf, "%d\n", temp);
>> +     else
>> +             return ret;
>> +}
>> +
>> +static ssize_t set_update_rate(struct device *dev,
>> +                            struct device_attribute *devattr,
>> +                            const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     reg_val;
>> +     long                    val;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     val *= temp_sensor->clk_rate / 1000;
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +
>> +     reg_val &= ~(temp_sensor->registers->counter_mask);
>> +     reg_val |= val;
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_counter);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static int omap_temp_sensor_read_temp(struct device *dev,
>> +                                   struct device_attribute *devattr,
>> +                                   char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     int                     temp, ret = 0;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
>> +
>> +     if (!temp_sensor->is_efuse_valid)
>> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
>> +
>> +     /* look up for temperature in the table and return the temperature */
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid adc code reported %d", temp);
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     if (!ret)
>> +             return sprintf(buf, "%d\n", temp);
>> +     else
>> +             return ret;
>> +}
>> +
>> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>> +                       NULL, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>> +                       set_temp_max, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
>> +                       set_temp_max_hyst, 0);
>> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>> +                       set_update_rate, 0);
>> +
>> +static struct attribute *omap_temp_sensor_attributes[] = {
>> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
>> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
>> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>> +     &sensor_dev_attr_update_rate.dev_attr.attr,
>> +     NULL
>> +};
>> +
>> +static const struct attribute_group omap_temp_sensor_group = {
>> +     .attrs = omap_temp_sensor_attributes,
>> +};
>> +
>> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     u32 ret = 0, temp;
>> +
>> +     if (temp_sensor->clk_on) {
>> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>> +             goto out;
>> +     }
>> +
>> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>> +     if (ret < 0) {
>> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>> +     /* BGAP_TEMPSOFF should be reset to 0 */
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp_sensor->clk_on = 1;
>
> why isn't pm_runtime_get_sync() enough ??

This is the programming sequence indicated. BGAP_TEMPSOFF should be set
to 0 to enable the temperature sensor.

>
>> +out:
>> +     return ret;
>> +}
>> +
>> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     u32 temp, ret = 0;
>> +     unsigned long timeout;
>> +
>> +     if (!temp_sensor->clk_on) {
>> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>> +             goto out;
>> +     }
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
>> +
>> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status);
>> +     timeout = jiffies + msecs_to_jiffies(5);
>> +
>> +     /* wait till the clean stop bit is set or till the timeout exppires */
>> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>> +             !(time_after(jiffies, timeout))) {
>> +             temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status);
>> +             usleep_range(500, 2000);
>> +     }
>> +
>> +     if (time_after(jiffies, timeout))
>> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>> +     /* Gate the clock */
>> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>> +     if (ret < 0) {
>> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +     temp_sensor->clk_on = 0;
>> +out:
>> +     return ret;
>> +}
>> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
>> +{
>> +     struct omap_temp_sensor         *temp_sensor;
>> +     int                             t_hot, t_cold, temp;
>> +
>> +     temp_sensor = data;
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     /* Read the status of t_hot */
>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status)
>> +                     & temp_sensor->registers->status_hot_mask;
>> +
>> +     /* Read the status of t_cold */
>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status)
>> +                     & temp_sensor->registers->status_cold_mask;
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_mask_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) {
>> +             temp &= ~(temp_sensor->registers->mask_hot_mask);
>> +             temp |= temp_sensor->registers->mask_cold_mask;
>> +     } else if (t_cold) {
>> +             temp &= ~(temp_sensor->registers->mask_cold_mask);
>> +             temp |= temp_sensor->registers->mask_hot_mask;
>> +     }
>> +
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +
>> +     /* kobject_uvent to user space telling thermal threshold crossed */
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
>> +
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return IRQ_HANDLED;
>> +}
>> +
>> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
>> +{
>> +     struct omap_temp_sensor_pdata   *pdata  = pdev->dev.platform_data;
>> +     struct omap_temp_sensor         *temp_sensor;
>> +     struct resource                 *mem;
>> +     int                             ret = 0;
>> +     int                             val, clk_rate;
>> +
>> +     if (!pdata) {
>> +             dev_err(&pdev->dev, "platform data missing\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
>> +     if (!temp_sensor)
>> +             return -ENOMEM;
>> +
>> +     mutex_init(&temp_sensor->sensor_mutex);
>> +
>> +     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     if (!mem) {
>> +             dev_err(&pdev->dev, "no mem resource\n");
>> +             ret = -EINVAL;
>> +             goto plat_res_err;
>> +     }
>> +
>> +     temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
>> +     if (temp_sensor->irq == -ENXIO) {
>> +             dev_err(&pdev->dev, "get_irq_byname failed\n");
>> +             ret = temp_sensor->irq;
>> +             goto plat_res_err;
>> +     }
>> +
>> +     temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
>> +     temp_sensor->clock = NULL;
>> +     temp_sensor->registers = pdata->registers;
>> +     temp_sensor->hwmon_dev = &pdev->dev;
>> +
>> +     pm_runtime_enable(&pdev->dev);
>> +     pm_runtime_irq_safe(&pdev->dev);
>
> won't pm_runtime_irq_safe() keep the parent always running, thus
> preventing MPU from reaching lower power states ??
>

The function does a get_sync of the parent to add one
extra to the use count of the parent but then if we look
at the code snippet of cuntion rpm_resume() in rumtime.c

/*
                 * Increment the parent's usage counter and resume it if
                 * necessary.  Not needed if dev is irq-safe; then the
                 * parent is permanently resumed.
                 */
                parent = dev->parent;
                if (dev->power.irq_safe)
                        goto skip_parent;

So the extra use count increment is balanced here.
You can check these discussions:

http://www.mail-archive.com/linux-omap@vger.kernel.org/msg53115.html
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg52542.html




>> +     /*
>> +      * check if the efuse has a non-zero value if not
>> +      * it is an untrimmed sample and the temperatures
>> +      * may not be accurate
>> +      */
>> +
>> +     if (omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_efuse))
>> +             temp_sensor->is_efuse_valid = 1;
>> +
>> +     platform_set_drvdata(pdev, temp_sensor);
>> +     dev_set_drvdata(&pdev->dev, temp_sensor);
>
> why are you doing the same thing twice ???
>
>> +     temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
>
> why ?

get_sync enables the clock.
To set the clock rate recommended by the hardware team we need to
use clock APIs.

>
>> +     if (IS_ERR(temp_sensor->clock)) {
>> +             ret = PTR_ERR(temp_sensor->clock);
>> +             dev_err(temp_sensor->hwmon_dev,
>> +                     "unable to get fclk: %d\n", ret);
>> +             ret = -EINVAL;
>> +             goto plat_res_err;
>> +     }
>> +
>> +     ret = omap_temp_sensor_clk_enable(temp_sensor);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Cannot enable temp sensor\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
>
> why ?

Need to check the available dividers and the frequencies that can be
set for a particular functional clock and the set the closest matching
frequency.

>
>> +     if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
>> +             dev_err(&pdev->dev, "Error round rate\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     ret = clk_set_rate(temp_sensor->clock, clk_rate);
>
> why ??

frequency between 1-2MHz is recommended by hardware. Hence
setting the rate.

>
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Cannot set clock rate\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     temp_sensor->clk_rate = clk_rate;
>> +     omap_enable_continuous_mode(temp_sensor, 1);
>> +     omap_configure_temp_sensor_thresholds(temp_sensor);
>> +     /* 1 ms */
>> +     omap_configure_temp_sensor_counter(temp_sensor, 1);
>> +
>> +     /* Wait till the first conversion is done wait for at least 1ms */
>> +     usleep_range(1000, 2000);
>> +
>> +     /* Read the temperature once due to hw issue*/
>> +     omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +
>> +     /* Set 2 seconds time as default counter */
>> +     omap_configure_temp_sensor_counter(temp_sensor,
>> +                                             temp_sensor->clk_rate * 2);
>> +
>> +     temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
>> +     if (IS_ERR(temp_sensor->hwmon_dev)) {
>> +             dev_err(&pdev->dev, "hwmon_device_register failed.\n");
>> +             ret = PTR_ERR(temp_sensor->hwmon_dev);
>> +             goto hwmon_reg_err;
>> +     }
>> +
>> +     ret = sysfs_create_group(&pdev->dev.kobj,
>> +                              &omap_temp_sensor_group);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "could not create sysfs files\n");
>> +             goto sysfs_create_err;
>> +     }
>> +
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
>> +
>> +     ret = request_threaded_irq(temp_sensor->irq, NULL,
>> +             omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
>> +                     "temp_sensor", temp_sensor);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Request threaded irq failed.\n");
>> +             goto req_irq_err;
>> +     }
>> +
>> +     /* unmask the T_COLD and unmask T_HOT at init */
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +     val |= temp_sensor->registers->mask_cold_mask
>> +             | temp_sensor->registers->mask_hot_mask;
>> +
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +
>> +     return 0;
>> +
>> +req_irq_err:
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>> +                             &omap_temp_sensor_group);
>> +sysfs_create_err:
>> +     hwmon_device_unregister(&pdev->dev);
>> +hwmon_reg_err:
>> +     omap_temp_sensor_clk_disable(temp_sensor);
>> +clken_err:
>> +     if (temp_sensor->clock)
>> +             clk_put(temp_sensor->clock);
>> +plat_res_err:
>> +     mutex_destroy(&temp_sensor->sensor_mutex);
>> +     kfree(temp_sensor);
>> +     return ret;
>> +}
>> +
>> +static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
>> +
>> +     hwmon_device_unregister(&pdev->dev);
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>> +                     &omap_temp_sensor_group);
>> +     omap_temp_sensor_clk_disable(temp_sensor);
>> +     clk_put(temp_sensor->clock);
>> +     platform_set_drvdata(pdev, NULL);
>> +     free_irq(temp_sensor->irq, temp_sensor);
>> +     mutex_destroy(&temp_sensor->sensor_mutex);
>> +     kfree(temp_sensor);
>> +
>> +     return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     temp_sensor->temp_sensor_ctrl = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp_sensor->bg_ctrl = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +     temp_sensor->bg_counter = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_counter);
>> +     temp_sensor->bg_threshold = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_threshold);
>> +     temp_sensor->temp_sensor_tshut_threshold =
>> +             omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->temp_sensor_ctrl,
>> +                             temp_sensor->registers->temp_sensor_ctrl);
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->bg_ctrl,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->bg_counter,
>> +                             temp_sensor->registers->bgap_counter);
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->bg_threshold,
>> +                             temp_sensor->registers->bgap_threshold);
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->temp_sensor_tshut_threshold,
>> +                             temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static int omap_temp_sensor_suspend(struct device *dev)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> +     omap_temp_sensor_save_ctxt(temp_sensor);
>> +
>> +     return 0;
>> +}
>> +
>> +static int omap_temp_sensor_resume(struct device *dev)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> +     omap_temp_sensor_restore_ctxt(temp_sensor);
>> +
>> +     return 0;
>> +}
>> +
>> +static int omap_temp_sensor_runtime_suspend(struct device *dev)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> +     omap_temp_sensor_save_ctxt(temp_sensor);
>> +
>> +     return 0;
>> +}
>> +
>> +static int omap_temp_sensor_runtime_resume(struct device *dev)
>> +{
>> +     static int context_loss_count;
>> +     int temp;
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> +     temp = omap_device_get_context_loss_count(to_platform_device(dev));
>> +
>> +     if (temp != context_loss_count && context_loss_count != 0)
>> +             omap_temp_sensor_restore_ctxt(temp_sensor);
>> +
>> +     context_loss_count = temp;
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
>> +     .suspend = omap_temp_sensor_suspend,
>> +     .resume = omap_temp_sensor_resume,
>> +     .runtime_suspend = omap_temp_sensor_runtime_suspend,
>> +     .runtime_resume = omap_temp_sensor_runtime_resume,
>> +};
>> +
>> +#endif
>> +
>> +static struct platform_driver omap_temp_sensor_driver = {
>> +     .probe = omap_temp_sensor_probe,
>> +     .remove = omap_temp_sensor_remove,
>> +     .driver = {
>> +                     .name = "omap_temp_sensor",
>> +#ifdef CONFIG_PM
>> +                     .pm = &omap_temp_sensor_dev_pm_ops,
>> +#endif
>> +                },
>> +};
>> +
>> +int __init omap_temp_sensor_init(void)
>> +{
>> +     return platform_driver_register(&omap_temp_sensor_driver);
>> +}
>> +module_init(omap_temp_sensor_init);
>> +
>> +static void __exit omap_temp_sensor_exit(void)
>> +{
>> +     platform_driver_unregister(&omap_temp_sensor_driver);
>> +}
>> +module_exit(omap_temp_sensor_exit);
>> +
>> +MODULE_DESCRIPTION("OMAP446X temperature sensor Driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:" DRIVER_NAME);
>> +MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
>> --
>> 1.7.0.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11  9:57       ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11  9:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> (why aren't below in Cc ?

I will add them.

>
> HARDWARE MONITORING
> M: ? ? ?Jean Delvare <khali@linux-fr.org>
> M: ? ? ?Guenter Roeck <guenter.roeck@ericsson.com>
> L: ? ? ?lm-sensors at lm-sensors.org
> W: ? ? ?http://www.lm-sensors.org/
> T: ? ? ?quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
> T: ? ? ?git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
> S: ? ? ?Maintained
> F: ? ? ?Documentation/hwmon/
> F: ? ? ?drivers/hwmon/
> F: ? ? ?include/linux/hwmon*.h)
>
> On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
>> On chip temperature sensor driver. The driver monitors the temperature of
>> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>> the temperature crosses user defined thresholds via kobject_uevent interface.
>> The user is allowed to configure the temperature thresholds vis sysfs nodes
>> exposed using hwmon interface.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>> ?drivers/hwmon/Kconfig ? ? ? ? ? ?| ? 11 +
>> ?drivers/hwmon/Makefile ? ? ? ? ? | ? ?1 +
>> ?drivers/hwmon/omap_temp_sensor.c | ?950 ++++++++++++++++++++++++++++++++++++++
>> ?3 files changed, 962 insertions(+), 0 deletions(-)
>> ?create mode 100644 drivers/hwmon/omap_temp_sensor.c
>>
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 5f888f7..9c9cd8b 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>> ? ? ? ? This driver can also be built as a module. ?If so, the module
>> ? ? ? ? will be called f71805f.
>>
>> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>> + ? ? bool "OMAP on-die temperature sensor hwmon driver"
>> + ? ? depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>> + ? ? help
>> + ? ? ? If you say yes here you get support for hardware
>> + ? ? ? monitoring features of the OMAP on die temperature
>> + ? ? ? sensor.
>> +
>> + ? ? ? Continuous conversion programmable delay
>> + ? ? ? mode is used for temperature conversion.
>> +
>> ?config SENSORS_F71882FG
>> ? ? ? tristate "Fintek F71882FG and compatibles"
>> ? ? ? help
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index 28061cf..d0f89f5 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639) ? ? ? += max6639.o
>> ?obj-$(CONFIG_SENSORS_MAX6642) ? ? ? ?+= max6642.o
>> ?obj-$(CONFIG_SENSORS_MAX6650) ? ? ? ?+= max6650.o
>> ?obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR) ?+= omap_temp_sensor.o
>> ?obj-$(CONFIG_SENSORS_PC87360) ? ? ? ?+= pc87360.o
>> ?obj-$(CONFIG_SENSORS_PC87427) ? ? ? ?+= pc87427.o
>> ?obj-$(CONFIG_SENSORS_PCF8591) ? ? ? ?+= pcf8591.o
>> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> new file mode 100644
>> index 0000000..15e2559
>> --- /dev/null
>> +++ b/drivers/hwmon/omap_temp_sensor.c
>> @@ -0,0 +1,950 @@
>> +/*
>> + * OMAP4 Temperature sensor driver file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@ti.com>
>> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> +#include <linux/clk.h>
>
> why ??

Clock rate setting functions.

>
>> +#include <linux/io.h>
>> +#include <linux/debugfs.h>
>
> why ??

It will be removed.

>
>> +#include <linux/delay.h>
>> +#include <linux/slab.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/init.h>
>> +#include <plat/omap_device.h>
>
> why ??
>

Context loss count

>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <linux/device.h>
>> +#include <linux/jiffies.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +#include <linux/stddef.h>
>> +#include <linux/sysfs.h>
>> +#include <linux/err.h>
>> +#include <linux/types.h>
>> +#include <linux/mutex.h>
>> +#include <linux/pm_runtime.h>
>> +#include <plat/common.h>
>
> why ?

usleep_range function.

>
>> +#include <plat/temperature_sensor.h>
>

It is the header file with the structure definitions
used in the driver.

> why ?
>
>> +#include <mach/ctrl_module_core_44xx.h>
>
> why ?

It will be removed

>
>> +#include <mach/gpio.h>
>
> linux/gpio.h for crying out loud... how many times Russell has to say
> the exact same thing ??????
>

It will be removed

>> +#define TSHUT_THRESHOLD_HOT ?122000 ?/* 122 deg C */
>> +#define TSHUT_THRESHOLD_COLD 100000 ?/* 100 deg C */
>> +#define BGAP_THRESHOLD_T_HOT 73000 ? /* 73 deg C */
>> +#define BGAP_THRESHOLD_T_COLD ? ? ? ?71000 ? /* 71 deg C */
>> +#define OMAP_ADC_START_VALUE 530
>> +#define OMAP_ADC_END_VALUE ? 923
>> +
>> +/*
>> + * omap_temp_sensor structure
>> + * @hwmon_dev - device pointer
>> + * @clock - Clock pointer
>> + * @registers - Pointer to structure with register offsets and bitfields
>> + * @sensor_mutex - Mutex for sysfs, irq and PM
>> + * @irq - MPU Irq number for thermal alert
>> + * @phy_base - Physical base of the temp I/O
>> + * @clk_rate - Holds current clock rate
>> + * @temp_sensor_ctrl - temp sensor control register value
>> + * @bg_ctrl - bandgap ctrl register value
>> + * @bg_counter - bandgap counter value
>> + * @bg_threshold - bandgap threshold register value
>> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>> + * @clk_on - Manages the current clock state
>> + */
>> +struct omap_temp_sensor {
>> + ? ? struct device ? ? ? ? ? *hwmon_dev;
>> + ? ? struct clk ? ? ? ? ? ? ?*clock;
>> + ? ? struct omap_temp_sensor_registers *registers;
>> + ? ? struct mutex ? ? ? ? ? ?sensor_mutex; /* Mutex for sysfs, irq and PM */
>> + ? ? unsigned int ? ? ? ? ? ?irq;
>> + ? ? void __iomem ? ? ? ? ? ?*phy_base;
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? clk_rate;
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp_sensor_ctrl;
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_ctrl;
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_counter;
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_threshold;
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp_sensor_tshut_threshold;
>> + ? ? bool ? ? ? ? ? ? ? ? ? ?is_efuse_valid;
>> + ? ? bool ? ? ? ? ? ? ? ? ? ?clk_on;
>> +};
>> +
>> +/*
>> + * Temperature values in milli degree celsius
>> + * ADC code values from 530 to 923
>> + */
>> +static int adc_to_temp[] = {
>> + ? ? -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
>> +};
>> +
>> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *temp_sensor, u32 reg)
>> +{
>> + ? ? return __raw_readl(temp_sensor->phy_base + reg);
>> +}
>> +
>> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? u32 val, u32 reg)
>> +{
>> + ? ? __raw_writel(val, (temp_sensor->phy_base + reg));
>> +}
>> +
>> +static int adc_to_temp_conversion(int adc_val)
>> +{
>> + ? ? return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>> +}
>> +
>> +static int temp_to_adc_conversion(long temp)
>> +{
>> + ? ? int i;
>> +
>> + ? ? for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>> + ? ? ? ? ? ? if (temp < adc_to_temp[i])
>> + ? ? ? ? ? ? ? ? ? ? return OMAP_ADC_START_VALUE + i - 1;
>> +
>> + ? ? return -EINVAL;
>> +}
>> +
>> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *temp_sensor)
>> +{
>> + ? ? u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>> +
>> + ? ? t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>> + ? ? t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>> +
>> + ? ? /* Configure the TALERT thresholds */
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>> + ? ? ? ? ? ? (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> + ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> +
>> + ? ? tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>> + ? ? tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>> +
>> + ? ? /* Configure the TSHUT thresholds */
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->thsut_threshold);
>> + ? ? temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>> + ? ? ? ? | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*temp_sensor, u32 counter)
>> +{
>> + ? ? u32 val;
>> +
>> + ? ? val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> + ? ? val &= ~(temp_sensor->registers->counter_mask);
>> + ? ? val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>> + ? ? omap_temp_sensor_writel(temp_sensor, val,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> +}
>> +
>> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bool enable)
>> +{
>> + ? ? u32 val;
>> +
>> + ? ? val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mode_ctrl);
>> +
>> + ? ? if (enable)
>> + ? ? ? ? ? ? val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>> + ? ? else
>> + ? ? ? ? ? ? val &= ~(temp_sensor->registers->mode_ctrl_mask);
>> +
>> + ? ? omap_temp_sensor_writel(temp_sensor, val,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mode_ctrl);
>> +}
>> +
>> +/* Sysfs hook functions */
>> +
>> +static ssize_t show_temp_max(struct device *dev,
>> + ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> + ? ? int temp;
>> +
>> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? temp = (temp & temp_sensor->registers->threshold_thot_mask)
>> + ? ? ? ? ? ? ? ? ? ? >> __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> + ? ? ? ? ? ? dev_err(dev, "invalid value\n");
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> + ? ? temp = adc_to_temp_conversion(temp);
>> +
>> +out:
>> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? return snprintf(buf, 16, "%d\n", temp);
>> +}
>> +
>> +static ssize_t set_temp_max(struct device *dev,
>> + ? ? ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr,
>> + ? ? ? ? ? ? ? ? ? ? ? ? const char *buf, size_t count)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> + ? ? long ? ? ? ? ? ? ? ? ? ?val;
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? reg_val, t_cold, t_hot, temp;
>> +
>> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? if (strict_strtol(buf, 10, &val)) {
>> + ? ? ? ? ? ? count = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? t_hot = temp_to_adc_conversion(val);
>> + ? ? if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>> + ? ? ? ? ? ? dev_err(dev, "invalid range\n");
>> + ? ? ? ? ? ? count = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? /* obtain the T cold value */
>> + ? ? t_cold = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> + ? ? if (t_hot < t_cold) {
>> + ? ? ? ? ? ? dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>> + ? ? ? ? ? ? count = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? /* write the new t_hot value */
>> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>> + ? ? reg_val |= (t_hot <<
>> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_thot_mask));
>> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> +
>> + ? ? /* Read the current temperature */
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> + ? ? /*
>> + ? ? ?* If user sets the HIGH threshold(t_hot) greater than the current
>> + ? ? ?* temperature(temp) unmask the HOT interrupts
>> + ? ? ?*/
>> + ? ? if (t_hot > temp) {
>> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? ? ? ? ? reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
>> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? }
>> +
>> + ? ? /*
>> + ? ? ?* If current temperature is in-between the hot and cold thresholds,
>> + ? ? ?* Enable both masks.
>> + ? ? ?*/
>> + ? ? if (temp > t_cold && temp < t_hot) {
>> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
>> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
>> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4460_BGAP_CTRL_OFFSET);
>> + ? ? }
>> + ? ? /*
>> + ? ? ?* else no need to do anything since HW will immediately compare
>> + ? ? ?* the new threshold and generate interrupt accordingly
>> + ? ? ?*/
>> +out:
>> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> + ? ? return count;
>> +}
>> +
>> +static ssize_t show_temp_max_hyst(struct device *dev,
>> + ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp;
>> +
>> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>> + ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> + ? ? ? ? ? ? dev_err(dev, "invalid value\n");
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? temp = adc_to_temp_conversion(temp);
>> +out:
>> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? return snprintf(buf, 16, "%d\n", temp);
>> +}
>> +
>> +static ssize_t set_temp_max_hyst(struct device *dev,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct device_attribute *devattr,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *buf, size_t count)
>> +{
>> + ? ? struct omap_temp_sensor ? ? ? ? *temp_sensor = dev_get_drvdata(dev);
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? ? ? ? ? reg_val, t_hot, t_cold, temp;
>> + ? ? long ? ? ? ? ? ? ? ? ? ? ? ? ? ?val;
>> +
>> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? if (strict_strtol(buf, 10, &val)) {
>> + ? ? ? ? ? ? count = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? t_cold = temp_to_adc_conversion(val);
>> + ? ? if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>> + ? ? ? ? ? ? dev_err(dev, "invalid range");
>> + ? ? ? ? ? ? count = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? /* obtain the T HOT value */
>> + ? ? t_hot = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> + ? ? if (t_cold > t_hot) {
>> + ? ? ? ? ? ? dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>> + ? ? ? ? ? ? count = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? /* write the new t_cold value */
>> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>> + ? ? reg_val |= (t_cold <<
>> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask));
>> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> +
>> + ? ? /* Read the current temperature */
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> + ? ? /*
>> + ? ? ?* If user sets the LOW threshold(t_cold) lower than the current
>> + ? ? ?* temperature(temp) unmask the COLD interrupts
>> + ? ? ?*/
>> + ? ? if (t_cold < temp) {
>> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? ? ? ? ? reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
>> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? }
>> +
>> + ? ? /*
>> + ? ? ?* If current temperature is in-between the hot and cold thresholds,
>> + ? ? ?* Enable both masks.
>> + ? ? ?*/
>> + ? ? if (temp < t_hot && temp > t_cold) {
>> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
>> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
>> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? }
>> +
>> + ? ? /*
>> + ? ? ?* else no need to do anything since HW will immediately compare
>> + ? ? ?* the new threshold and generate interrupt accordingly
>> + ? ? ?*/
>> +
>> +out:
>> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> + ? ? return count;
>> +}
>> +
>> +static ssize_t show_update_rate(struct device *dev,
>> + ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp = 0, ret = 0;
>> +
>> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? if (!temp_sensor->clk_rate) {
>> + ? ? ? ? ? ? dev_err(dev, "clk_rate is NULL\n");
>> + ? ? ? ? ? ? ret = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> + ? ? temp = (temp & temp_sensor->registers->counter_mask) >>
>> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->counter_mask);
>
> ? ? ? ?temp &= ??
>
>> + ? ? temp = temp * 1000 / (temp_sensor->clk_rate);
>
> ? ? ? ?temp *= ??

Need to multiply the temp with 1000 before dividing.
temp *= evaluates the RHS first and then multiplies LHS.

>
>> +
>> +out:
>> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> + ? ? if (!ret)
>> + ? ? ? ? ? ? return sprintf(buf, "%d\n", temp);
>> + ? ? else
>> + ? ? ? ? ? ? return ret;
>> +}
>> +
>> +static ssize_t set_update_rate(struct device *dev,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct device_attribute *devattr,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *buf, size_t count)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> + ? ? u32 ? ? ? ? ? ? ? ? ? ? reg_val;
>> + ? ? long ? ? ? ? ? ? ? ? ? ?val;
>> +
>> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? if (strict_strtol(buf, 10, &val)) {
>> + ? ? ? ? ? ? count = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? val *= temp_sensor->clk_rate / 1000;
>> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> +
>> + ? ? reg_val &= ~(temp_sensor->registers->counter_mask);
>> + ? ? reg_val |= val;
>> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> +
>> +out:
>> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> + ? ? return count;
>> +}
>> +
>> +static int omap_temp_sensor_read_temp(struct device *dev,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? char *buf)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> + ? ? int ? ? ? ? ? ? ? ? ? ? temp, ret = 0;
>> +
>> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? temp &= temp_sensor->registers->bgap_dtemp_mask;
>> +
>> + ? ? if (!temp_sensor->is_efuse_valid)
>> + ? ? ? ? ? ? dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
>> +
>> + ? ? /* look up for temperature in the table and return the temperature */
>> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> + ? ? ? ? ? ? dev_err(dev, "invalid adc code reported %d", temp);
>> + ? ? ? ? ? ? ret = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>> +
>> +out:
>> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> + ? ? if (!ret)
>> + ? ? ? ? ? ? return sprintf(buf, "%d\n", temp);
>> + ? ? else
>> + ? ? ? ? ? ? return ret;
>> +}
>> +
>> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>> + ? ? ? ? ? ? ? ? ? ? ? NULL, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>> + ? ? ? ? ? ? ? ? ? ? ? set_temp_max, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
>> + ? ? ? ? ? ? ? ? ? ? ? set_temp_max_hyst, 0);
>> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>> + ? ? ? ? ? ? ? ? ? ? ? set_update_rate, 0);
>> +
>> +static struct attribute *omap_temp_sensor_attributes[] = {
>> + ? ? &sensor_dev_attr_temp1_input.dev_attr.attr,
>> + ? ? &sensor_dev_attr_temp1_max.dev_attr.attr,
>> + ? ? &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>> + ? ? &sensor_dev_attr_update_rate.dev_attr.attr,
>> + ? ? NULL
>> +};
>> +
>> +static const struct attribute_group omap_temp_sensor_group = {
>> + ? ? .attrs = omap_temp_sensor_attributes,
>> +};
>> +
>> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>> +{
>> + ? ? u32 ret = 0, temp;
>> +
>> + ? ? if (temp_sensor->clk_on) {
>> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>> + ? ? if (ret < 0) {
>> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>> + ? ? ? ? ? ? ret = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>> + ? ? /* BGAP_TEMPSOFF should be reset to 0 */
>> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? temp_sensor->clk_on = 1;
>
> why isn't pm_runtime_get_sync() enough ??

This is the programming sequence indicated. BGAP_TEMPSOFF should be set
to 0 to enable the temperature sensor.

>
>> +out:
>> + ? ? return ret;
>> +}
>> +
>> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>> +{
>> + ? ? u32 temp, ret = 0;
>> + ? ? unsigned long timeout;
>> +
>> + ? ? if (!temp_sensor->clk_on) {
>> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? temp |= temp_sensor->registers->bgap_tempsoff_mask;
>> +
>> + ? ? /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_status);
>> + ? ? timeout = jiffies + msecs_to_jiffies(5);
>> +
>> + ? ? /* wait till the clean stop bit is set or till the timeout exppires */
>> + ? ? while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>> + ? ? ? ? ? ? !(time_after(jiffies, timeout))) {
>> + ? ? ? ? ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_status);
>> + ? ? ? ? ? ? usleep_range(500, 2000);
>> + ? ? }
>> +
>> + ? ? if (time_after(jiffies, timeout))
>> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>> + ? ? /* Gate the clock */
>> + ? ? ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>> + ? ? if (ret < 0) {
>> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>> + ? ? ? ? ? ? ret = -EINVAL;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> + ? ? temp_sensor->clk_on = 0;
>> +out:
>> + ? ? return ret;
>> +}
>> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
>> +{
>> + ? ? struct omap_temp_sensor ? ? ? ? *temp_sensor;
>> + ? ? int ? ? ? ? ? ? ? ? ? ? ? ? ? ? t_hot, t_cold, temp;
>> +
>> + ? ? temp_sensor = data;
>> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? /* Read the status of t_hot */
>> + ? ? t_hot = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_status)
>> + ? ? ? ? ? ? ? ? ? ? & temp_sensor->registers->status_hot_mask;
>> +
>> + ? ? /* Read the status of t_cold */
>> + ? ? t_cold = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_status)
>> + ? ? ? ? ? ? ? ? ? ? & temp_sensor->registers->status_cold_mask;
>> +
>> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_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) {
>> + ? ? ? ? ? ? temp &= ~(temp_sensor->registers->mask_hot_mask);
>> + ? ? ? ? ? ? temp |= temp_sensor->registers->mask_cold_mask;
>> + ? ? } else if (t_cold) {
>> + ? ? ? ? ? ? temp &= ~(temp_sensor->registers->mask_cold_mask);
>> + ? ? ? ? ? ? temp |= temp_sensor->registers->mask_hot_mask;
>> + ? ? }
>> +
>> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> + ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> +
>> + ? ? /* kobject_uvent to user space telling thermal threshold crossed */
>> + ? ? kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
>> +
>> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> + ? ? return IRQ_HANDLED;
>> +}
>> +
>> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
>> +{
>> + ? ? struct omap_temp_sensor_pdata ? *pdata ?= pdev->dev.platform_data;
>> + ? ? struct omap_temp_sensor ? ? ? ? *temp_sensor;
>> + ? ? struct resource ? ? ? ? ? ? ? ? *mem;
>> + ? ? int ? ? ? ? ? ? ? ? ? ? ? ? ? ? ret = 0;
>> + ? ? int ? ? ? ? ? ? ? ? ? ? ? ? ? ? val, clk_rate;
>> +
>> + ? ? if (!pdata) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "platform data missing\n");
>> + ? ? ? ? ? ? return -EINVAL;
>> + ? ? }
>> +
>> + ? ? temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
>> + ? ? if (!temp_sensor)
>> + ? ? ? ? ? ? return -ENOMEM;
>> +
>> + ? ? mutex_init(&temp_sensor->sensor_mutex);
>> +
>> + ? ? mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + ? ? if (!mem) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "no mem resource\n");
>> + ? ? ? ? ? ? ret = -EINVAL;
>> + ? ? ? ? ? ? goto plat_res_err;
>> + ? ? }
>> +
>> + ? ? temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
>> + ? ? if (temp_sensor->irq == -ENXIO) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "get_irq_byname failed\n");
>> + ? ? ? ? ? ? ret = temp_sensor->irq;
>> + ? ? ? ? ? ? goto plat_res_err;
>> + ? ? }
>> +
>> + ? ? temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
>> + ? ? temp_sensor->clock = NULL;
>> + ? ? temp_sensor->registers = pdata->registers;
>> + ? ? temp_sensor->hwmon_dev = &pdev->dev;
>> +
>> + ? ? pm_runtime_enable(&pdev->dev);
>> + ? ? pm_runtime_irq_safe(&pdev->dev);
>
> won't pm_runtime_irq_safe() keep the parent always running, thus
> preventing MPU from reaching lower power states ??
>

The function does a get_sync of the parent to add one
extra to the use count of the parent but then if we look
at the code snippet of cuntion rpm_resume() in rumtime.c

/*
                 * Increment the parent's usage counter and resume it if
                 * necessary.  Not needed if dev is irq-safe; then the
                 * parent is permanently resumed.
                 */
                parent = dev->parent;
                if (dev->power.irq_safe)
                        goto skip_parent;

So the extra use count increment is balanced here.
You can check these discussions:

http://www.mail-archive.com/linux-omap at vger.kernel.org/msg53115.html
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg52542.html




>> + ? ? /*
>> + ? ? ?* check if the efuse has a non-zero value if not
>> + ? ? ?* it is an untrimmed sample and the temperatures
>> + ? ? ?* may not be accurate
>> + ? ? ?*/
>> +
>> + ? ? if (omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_efuse))
>> + ? ? ? ? ? ? temp_sensor->is_efuse_valid = 1;
>> +
>> + ? ? platform_set_drvdata(pdev, temp_sensor);
>> + ? ? dev_set_drvdata(&pdev->dev, temp_sensor);
>
> why are you doing the same thing twice ???
>
>> + ? ? temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
>
> why ?

get_sync enables the clock.
To set the clock rate recommended by the hardware team we need to
use clock APIs.

>
>> + ? ? if (IS_ERR(temp_sensor->clock)) {
>> + ? ? ? ? ? ? ret = PTR_ERR(temp_sensor->clock);
>> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev,
>> + ? ? ? ? ? ? ? ? ? ? "unable to get fclk: %d\n", ret);
>> + ? ? ? ? ? ? ret = -EINVAL;
>> + ? ? ? ? ? ? goto plat_res_err;
>> + ? ? }
>> +
>> + ? ? ret = omap_temp_sensor_clk_enable(temp_sensor);
>> + ? ? if (ret) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "Cannot enable temp sensor\n");
>> + ? ? ? ? ? ? goto clken_err;
>> + ? ? }
>> +
>> + ? ? clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
>
> why ?

Need to check the available dividers and the frequencies that can be
set for a particular functional clock and the set the closest matching
frequency.

>
>> + ? ? if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "Error round rate\n");
>> + ? ? ? ? ? ? goto clken_err;
>> + ? ? }
>> +
>> + ? ? ret = clk_set_rate(temp_sensor->clock, clk_rate);
>
> why ??

frequency between 1-2MHz is recommended by hardware. Hence
setting the rate.

>
>> + ? ? if (ret) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "Cannot set clock rate\n");
>> + ? ? ? ? ? ? goto clken_err;
>> + ? ? }
>> +
>> + ? ? temp_sensor->clk_rate = clk_rate;
>> + ? ? omap_enable_continuous_mode(temp_sensor, 1);
>> + ? ? omap_configure_temp_sensor_thresholds(temp_sensor);
>> + ? ? /* 1 ms */
>> + ? ? omap_configure_temp_sensor_counter(temp_sensor, 1);
>> +
>> + ? ? /* Wait till the first conversion is done wait for at least 1ms */
>> + ? ? usleep_range(1000, 2000);
>> +
>> + ? ? /* Read the temperature once due to hw issue*/
>> + ? ? omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> +
>> + ? ? /* Set 2 seconds time as default counter */
>> + ? ? omap_configure_temp_sensor_counter(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->clk_rate * 2);
>> +
>> + ? ? temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
>> + ? ? if (IS_ERR(temp_sensor->hwmon_dev)) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "hwmon_device_register failed.\n");
>> + ? ? ? ? ? ? ret = PTR_ERR(temp_sensor->hwmon_dev);
>> + ? ? ? ? ? ? goto hwmon_reg_err;
>> + ? ? }
>> +
>> + ? ? ret = sysfs_create_group(&pdev->dev.kobj,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&omap_temp_sensor_group);
>> + ? ? if (ret) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "could not create sysfs files\n");
>> + ? ? ? ? ? ? goto sysfs_create_err;
>> + ? ? }
>> +
>> + ? ? kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
>> +
>> + ? ? ret = request_threaded_irq(temp_sensor->irq, NULL,
>> + ? ? ? ? ? ? omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
>> + ? ? ? ? ? ? ? ? ? ? "temp_sensor", temp_sensor);
>> + ? ? if (ret) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "Request threaded irq failed.\n");
>> + ? ? ? ? ? ? goto req_irq_err;
>> + ? ? }
>> +
>> + ? ? /* unmask the T_COLD and unmask T_HOT at init */
>> + ? ? val = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? val |= temp_sensor->registers->mask_cold_mask
>> + ? ? ? ? ? ? | temp_sensor->registers->mask_hot_mask;
>> +
>> + ? ? omap_temp_sensor_writel(temp_sensor, val,
>> + ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> +
>> + ? ? return 0;
>> +
>> +req_irq_err:
>> + ? ? kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>> + ? ? sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? &omap_temp_sensor_group);
>> +sysfs_create_err:
>> + ? ? hwmon_device_unregister(&pdev->dev);
>> +hwmon_reg_err:
>> + ? ? omap_temp_sensor_clk_disable(temp_sensor);
>> +clken_err:
>> + ? ? if (temp_sensor->clock)
>> + ? ? ? ? ? ? clk_put(temp_sensor->clock);
>> +plat_res_err:
>> + ? ? mutex_destroy(&temp_sensor->sensor_mutex);
>> + ? ? kfree(temp_sensor);
>> + ? ? return ret;
>> +}
>> +
>> +static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
>> +
>> + ? ? hwmon_device_unregister(&pdev->dev);
>> + ? ? kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>> + ? ? sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>> + ? ? ? ? ? ? ? ? ? ? &omap_temp_sensor_group);
>> + ? ? omap_temp_sensor_clk_disable(temp_sensor);
>> + ? ? clk_put(temp_sensor->clock);
>> + ? ? platform_set_drvdata(pdev, NULL);
>> + ? ? free_irq(temp_sensor->irq, temp_sensor);
>> + ? ? mutex_destroy(&temp_sensor->sensor_mutex);
>> + ? ? kfree(temp_sensor);
>> +
>> + ? ? return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
>> +{
>> + ? ? temp_sensor->temp_sensor_ctrl = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? temp_sensor->bg_ctrl = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? temp_sensor->bg_counter = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> + ? ? temp_sensor->bg_threshold = omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? temp_sensor->temp_sensor_tshut_threshold =
>> + ? ? ? ? ? ? omap_temp_sensor_readl(temp_sensor,
>> + ? ? ? ? ? ? temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
>> +{
>> + ? ? omap_temp_sensor_writel(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->temp_sensor_ctrl,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> + ? ? omap_temp_sensor_writel(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->bg_ctrl,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> + ? ? omap_temp_sensor_writel(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->bg_counter,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> + ? ? omap_temp_sensor_writel(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->bg_threshold,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> + ? ? omap_temp_sensor_writel(temp_sensor,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->temp_sensor_tshut_threshold,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static int omap_temp_sensor_suspend(struct device *dev)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> + ? ? omap_temp_sensor_save_ctxt(temp_sensor);
>> +
>> + ? ? return 0;
>> +}
>> +
>> +static int omap_temp_sensor_resume(struct device *dev)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> + ? ? omap_temp_sensor_restore_ctxt(temp_sensor);
>> +
>> + ? ? return 0;
>> +}
>> +
>> +static int omap_temp_sensor_runtime_suspend(struct device *dev)
>> +{
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> + ? ? omap_temp_sensor_save_ctxt(temp_sensor);
>> +
>> + ? ? return 0;
>> +}
>> +
>> +static int omap_temp_sensor_runtime_resume(struct device *dev)
>> +{
>> + ? ? static int context_loss_count;
>> + ? ? int temp;
>> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> + ? ? temp = omap_device_get_context_loss_count(to_platform_device(dev));
>> +
>> + ? ? if (temp != context_loss_count && context_loss_count != 0)
>> + ? ? ? ? ? ? omap_temp_sensor_restore_ctxt(temp_sensor);
>> +
>> + ? ? context_loss_count = temp;
>> +
>> + ? ? return 0;
>> +}
>> +
>> +static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
>> + ? ? .suspend = omap_temp_sensor_suspend,
>> + ? ? .resume = omap_temp_sensor_resume,
>> + ? ? .runtime_suspend = omap_temp_sensor_runtime_suspend,
>> + ? ? .runtime_resume = omap_temp_sensor_runtime_resume,
>> +};
>> +
>> +#endif
>> +
>> +static struct platform_driver omap_temp_sensor_driver = {
>> + ? ? .probe = omap_temp_sensor_probe,
>> + ? ? .remove = omap_temp_sensor_remove,
>> + ? ? .driver = {
>> + ? ? ? ? ? ? ? ? ? ? .name = "omap_temp_sensor",
>> +#ifdef CONFIG_PM
>> + ? ? ? ? ? ? ? ? ? ? .pm = &omap_temp_sensor_dev_pm_ops,
>> +#endif
>> + ? ? ? ? ? ? ? ?},
>> +};
>> +
>> +int __init omap_temp_sensor_init(void)
>> +{
>> + ? ? return platform_driver_register(&omap_temp_sensor_driver);
>> +}
>> +module_init(omap_temp_sensor_init);
>> +
>> +static void __exit omap_temp_sensor_exit(void)
>> +{
>> + ? ? platform_driver_unregister(&omap_temp_sensor_driver);
>> +}
>> +module_exit(omap_temp_sensor_exit);
>> +
>> +MODULE_DESCRIPTION("OMAP446X temperature sensor Driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:" DRIVER_NAME);
>> +MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
>> --
>> 1.7.0.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11  9:57       ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 10:09 UTC (permalink / raw)
  To: balbi
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> (why aren't below in Cc ?

I will add them.

>
> HARDWARE MONITORING
> M:      Jean Delvare <khali@linux-fr.org>
> M:      Guenter Roeck <guenter.roeck@ericsson.com>
> L:      lm-sensors@lm-sensors.org
> W:      http://www.lm-sensors.org/
> T:      quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
> T:      git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
> S:      Maintained
> F:      Documentation/hwmon/
> F:      drivers/hwmon/
> F:      include/linux/hwmon*.h)
>
> On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
>> On chip temperature sensor driver. The driver monitors the temperature of
>> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>> the temperature crosses user defined thresholds via kobject_uevent interface.
>> The user is allowed to configure the temperature thresholds vis sysfs nodes
>> exposed using hwmon interface.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>>  drivers/hwmon/Kconfig            |   11 +
>>  drivers/hwmon/Makefile           |    1 +
>>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 962 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>>
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 5f888f7..9c9cd8b 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>>         This driver can also be built as a module.  If so, the module
>>         will be called f71805f.
>>
>> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>> +     bool "OMAP on-die temperature sensor hwmon driver"
>> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>> +     help
>> +       If you say yes here you get support for hardware
>> +       monitoring features of the OMAP on die temperature
>> +       sensor.
>> +
>> +       Continuous conversion programmable delay
>> +       mode is used for temperature conversion.
>> +
>>  config SENSORS_F71882FG
>>       tristate "Fintek F71882FG and compatibles"
>>       help
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index 28061cf..d0f89f5 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
>> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> new file mode 100644
>> index 0000000..15e2559
>> --- /dev/null
>> +++ b/drivers/hwmon/omap_temp_sensor.c
>> @@ -0,0 +1,950 @@
>> +/*
>> + * OMAP4 Temperature sensor driver file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@ti.com>
>> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> +#include <linux/clk.h>
>
> why ??

Clock rate setting functions.

>
>> +#include <linux/io.h>
>> +#include <linux/debugfs.h>
>
> why ??

It will be removed.

>
>> +#include <linux/delay.h>
>> +#include <linux/slab.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/init.h>
>> +#include <plat/omap_device.h>
>
> why ??
>

Context loss count

>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <linux/device.h>
>> +#include <linux/jiffies.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +#include <linux/stddef.h>
>> +#include <linux/sysfs.h>
>> +#include <linux/err.h>
>> +#include <linux/types.h>
>> +#include <linux/mutex.h>
>> +#include <linux/pm_runtime.h>
>> +#include <plat/common.h>
>
> why ?

usleep_range function.

>
>> +#include <plat/temperature_sensor.h>
>

It is the header file with the structure definitions
used in the driver.

> why ?
>
>> +#include <mach/ctrl_module_core_44xx.h>
>
> why ?

It will be removed

>
>> +#include <mach/gpio.h>
>
> linux/gpio.h for crying out loud... how many times Russell has to say
> the exact same thing ??????
>

It will be removed

>> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
>> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
>> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
>> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
>> +#define OMAP_ADC_START_VALUE 530
>> +#define OMAP_ADC_END_VALUE   923
>> +
>> +/*
>> + * omap_temp_sensor structure
>> + * @hwmon_dev - device pointer
>> + * @clock - Clock pointer
>> + * @registers - Pointer to structure with register offsets and bitfields
>> + * @sensor_mutex - Mutex for sysfs, irq and PM
>> + * @irq - MPU Irq number for thermal alert
>> + * @phy_base - Physical base of the temp I/O
>> + * @clk_rate - Holds current clock rate
>> + * @temp_sensor_ctrl - temp sensor control register value
>> + * @bg_ctrl - bandgap ctrl register value
>> + * @bg_counter - bandgap counter value
>> + * @bg_threshold - bandgap threshold register value
>> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>> + * @clk_on - Manages the current clock state
>> + */
>> +struct omap_temp_sensor {
>> +     struct device           *hwmon_dev;
>> +     struct clk              *clock;
>> +     struct omap_temp_sensor_registers *registers;
>> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
>> +     unsigned int            irq;
>> +     void __iomem            *phy_base;
>> +     u32                     clk_rate;
>> +     u32                     temp_sensor_ctrl;
>> +     u32                     bg_ctrl;
>> +     u32                     bg_counter;
>> +     u32                     bg_threshold;
>> +     u32                     temp_sensor_tshut_threshold;
>> +     bool                    is_efuse_valid;
>> +     bool                    clk_on;
>> +};
>> +
>> +/*
>> + * Temperature values in milli degree celsius
>> + * ADC code values from 530 to 923
>> + */
>> +static int adc_to_temp[] = {
>> +     -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
>> +};
>> +
>> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>> +                                         *temp_sensor, u32 reg)
>> +{
>> +     return __raw_readl(temp_sensor->phy_base + reg);
>> +}
>> +
>> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>> +                                 u32 val, u32 reg)
>> +{
>> +     __raw_writel(val, (temp_sensor->phy_base + reg));
>> +}
>> +
>> +static int adc_to_temp_conversion(int adc_val)
>> +{
>> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>> +}
>> +
>> +static int temp_to_adc_conversion(long temp)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>> +             if (temp < adc_to_temp[i])
>> +                     return OMAP_ADC_START_VALUE + i - 1;
>> +
>> +     return -EINVAL;
>> +}
>> +
>> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>> +                                               *temp_sensor)
>> +{
>> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>> +
>> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>> +
>> +     /* Configure the TALERT thresholds */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +             temp_sensor->registers->bgap_threshold);
>> +
>> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>> +
>> +     /* Configure the TSHUT thresholds */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->thsut_threshold);
>> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                     temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>> +                                            *temp_sensor, u32 counter)
>> +{
>> +     u32 val;
>> +
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +     val &= ~(temp_sensor->registers->counter_mask);
>> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +                     temp_sensor->registers->bgap_counter);
>> +}
>> +
>> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>> +                                     bool enable)
>> +{
>> +     u32 val;
>> +
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_mode_ctrl);
>> +
>> +     if (enable)
>> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>> +     else
>> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
>> +
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +                     temp_sensor->registers->bgap_mode_ctrl);
>> +}
>> +
>> +/* Sysfs hook functions */
>> +
>> +static ssize_t show_temp_max(struct device *dev,
>> +                     struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     int temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
>> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid value\n");
>> +             goto out;
>> +     }
>> +     temp = adc_to_temp_conversion(temp);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return snprintf(buf, 16, "%d\n", temp);
>> +}
>> +
>> +static ssize_t set_temp_max(struct device *dev,
>> +                         struct device_attribute *devattr,
>> +                         const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     long                    val;
>> +     u32                     reg_val, t_cold, t_hot, temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     t_hot = temp_to_adc_conversion(val);
>> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>> +             dev_err(dev, "invalid range\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* obtain the T cold value */
>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> +     if (t_hot < t_cold) {
>> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* write the new t_hot value */
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>> +     reg_val |= (t_hot <<
>> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_threshold);
>> +
>> +     /* Read the current temperature */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> +     /*
>> +      * If user sets the HIGH threshold(t_hot) greater than the current
>> +      * temperature(temp) unmask the HOT interrupts
>> +      */
>> +     if (t_hot > temp) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * If current temperature is in-between the hot and cold thresholds,
>> +      * Enable both masks.
>> +      */
>> +     if (temp > t_cold && temp < t_hot) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             OMAP4460_BGAP_CTRL_OFFSET);
>> +     }
>> +     /*
>> +      * else no need to do anything since HW will immediately compare
>> +      * the new threshold and generate interrupt accordingly
>> +      */
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static ssize_t show_temp_max_hyst(struct device *dev,
>> +             struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_threshold);
>> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid value\n");
>> +             goto out;
>> +     }
>> +
>> +     temp = adc_to_temp_conversion(temp);
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return snprintf(buf, 16, "%d\n", temp);
>> +}
>> +
>> +static ssize_t set_temp_max_hyst(struct device *dev,
>> +                              struct device_attribute *devattr,
>> +                              const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
>> +     u32                             reg_val, t_hot, t_cold, temp;
>> +     long                            val;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     t_cold = temp_to_adc_conversion(val);
>> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid range");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* obtain the T HOT value */
>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> +     if (t_cold > t_hot) {
>> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* write the new t_cold value */
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>> +     reg_val |= (t_cold <<
>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_threshold);
>> +
>> +     /* Read the current temperature */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> +     /*
>> +      * If user sets the LOW threshold(t_cold) lower than the current
>> +      * temperature(temp) unmask the COLD interrupts
>> +      */
>> +     if (t_cold < temp) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * If current temperature is in-between the hot and cold thresholds,
>> +      * Enable both masks.
>> +      */
>> +     if (temp < t_hot && temp > t_cold) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * else no need to do anything since HW will immediately compare
>> +      * the new threshold and generate interrupt accordingly
>> +      */
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static ssize_t show_update_rate(struct device *dev,
>> +                     struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     temp = 0, ret = 0;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (!temp_sensor->clk_rate) {
>> +             dev_err(dev, "clk_rate is NULL\n");
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +     temp = (temp & temp_sensor->registers->counter_mask) >>
>> +                     __ffs(temp_sensor->registers->counter_mask);
>
>        temp &= ??
>
>> +     temp = temp * 1000 / (temp_sensor->clk_rate);
>
>        temp *= ??

Need to multiply the temp with 1000 before dividing.
temp *= evaluates the RHS first and then multiplies LHS.

>
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     if (!ret)
>> +             return sprintf(buf, "%d\n", temp);
>> +     else
>> +             return ret;
>> +}
>> +
>> +static ssize_t set_update_rate(struct device *dev,
>> +                            struct device_attribute *devattr,
>> +                            const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     reg_val;
>> +     long                    val;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     val *= temp_sensor->clk_rate / 1000;
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +
>> +     reg_val &= ~(temp_sensor->registers->counter_mask);
>> +     reg_val |= val;
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_counter);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static int omap_temp_sensor_read_temp(struct device *dev,
>> +                                   struct device_attribute *devattr,
>> +                                   char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     int                     temp, ret = 0;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
>> +
>> +     if (!temp_sensor->is_efuse_valid)
>> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
>> +
>> +     /* look up for temperature in the table and return the temperature */
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid adc code reported %d", temp);
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     if (!ret)
>> +             return sprintf(buf, "%d\n", temp);
>> +     else
>> +             return ret;
>> +}
>> +
>> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>> +                       NULL, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>> +                       set_temp_max, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
>> +                       set_temp_max_hyst, 0);
>> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>> +                       set_update_rate, 0);
>> +
>> +static struct attribute *omap_temp_sensor_attributes[] = {
>> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
>> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
>> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>> +     &sensor_dev_attr_update_rate.dev_attr.attr,
>> +     NULL
>> +};
>> +
>> +static const struct attribute_group omap_temp_sensor_group = {
>> +     .attrs = omap_temp_sensor_attributes,
>> +};
>> +
>> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     u32 ret = 0, temp;
>> +
>> +     if (temp_sensor->clk_on) {
>> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>> +             goto out;
>> +     }
>> +
>> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>> +     if (ret < 0) {
>> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>> +     /* BGAP_TEMPSOFF should be reset to 0 */
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp_sensor->clk_on = 1;
>
> why isn't pm_runtime_get_sync() enough ??

This is the programming sequence indicated. BGAP_TEMPSOFF should be set
to 0 to enable the temperature sensor.

>
>> +out:
>> +     return ret;
>> +}
>> +
>> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     u32 temp, ret = 0;
>> +     unsigned long timeout;
>> +
>> +     if (!temp_sensor->clk_on) {
>> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>> +             goto out;
>> +     }
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
>> +
>> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status);
>> +     timeout = jiffies + msecs_to_jiffies(5);
>> +
>> +     /* wait till the clean stop bit is set or till the timeout exppires */
>> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>> +             !(time_after(jiffies, timeout))) {
>> +             temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status);
>> +             usleep_range(500, 2000);
>> +     }
>> +
>> +     if (time_after(jiffies, timeout))
>> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>> +     /* Gate the clock */
>> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>> +     if (ret < 0) {
>> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +     temp_sensor->clk_on = 0;
>> +out:
>> +     return ret;
>> +}
>> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
>> +{
>> +     struct omap_temp_sensor         *temp_sensor;
>> +     int                             t_hot, t_cold, temp;
>> +
>> +     temp_sensor = data;
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     /* Read the status of t_hot */
>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status)
>> +                     & temp_sensor->registers->status_hot_mask;
>> +
>> +     /* Read the status of t_cold */
>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status)
>> +                     & temp_sensor->registers->status_cold_mask;
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_mask_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) {
>> +             temp &= ~(temp_sensor->registers->mask_hot_mask);
>> +             temp |= temp_sensor->registers->mask_cold_mask;
>> +     } else if (t_cold) {
>> +             temp &= ~(temp_sensor->registers->mask_cold_mask);
>> +             temp |= temp_sensor->registers->mask_hot_mask;
>> +     }
>> +
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +
>> +     /* kobject_uvent to user space telling thermal threshold crossed */
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
>> +
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return IRQ_HANDLED;
>> +}
>> +
>> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
>> +{
>> +     struct omap_temp_sensor_pdata   *pdata  = pdev->dev.platform_data;
>> +     struct omap_temp_sensor         *temp_sensor;
>> +     struct resource                 *mem;
>> +     int                             ret = 0;
>> +     int                             val, clk_rate;
>> +
>> +     if (!pdata) {
>> +             dev_err(&pdev->dev, "platform data missing\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
>> +     if (!temp_sensor)
>> +             return -ENOMEM;
>> +
>> +     mutex_init(&temp_sensor->sensor_mutex);
>> +
>> +     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     if (!mem) {
>> +             dev_err(&pdev->dev, "no mem resource\n");
>> +             ret = -EINVAL;
>> +             goto plat_res_err;
>> +     }
>> +
>> +     temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
>> +     if (temp_sensor->irq = -ENXIO) {
>> +             dev_err(&pdev->dev, "get_irq_byname failed\n");
>> +             ret = temp_sensor->irq;
>> +             goto plat_res_err;
>> +     }
>> +
>> +     temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
>> +     temp_sensor->clock = NULL;
>> +     temp_sensor->registers = pdata->registers;
>> +     temp_sensor->hwmon_dev = &pdev->dev;
>> +
>> +     pm_runtime_enable(&pdev->dev);
>> +     pm_runtime_irq_safe(&pdev->dev);
>
> won't pm_runtime_irq_safe() keep the parent always running, thus
> preventing MPU from reaching lower power states ??
>

The function does a get_sync of the parent to add one
extra to the use count of the parent but then if we look
at the code snippet of cuntion rpm_resume() in rumtime.c

/*
                 * Increment the parent's usage counter and resume it if
                 * necessary.  Not needed if dev is irq-safe; then the
                 * parent is permanently resumed.
                 */
                parent = dev->parent;
                if (dev->power.irq_safe)
                        goto skip_parent;

So the extra use count increment is balanced here.
You can check these discussions:

http://www.mail-archive.com/linux-omap@vger.kernel.org/msg53115.html
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg52542.html




>> +     /*
>> +      * check if the efuse has a non-zero value if not
>> +      * it is an untrimmed sample and the temperatures
>> +      * may not be accurate
>> +      */
>> +
>> +     if (omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_efuse))
>> +             temp_sensor->is_efuse_valid = 1;
>> +
>> +     platform_set_drvdata(pdev, temp_sensor);
>> +     dev_set_drvdata(&pdev->dev, temp_sensor);
>
> why are you doing the same thing twice ???
>
>> +     temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
>
> why ?

get_sync enables the clock.
To set the clock rate recommended by the hardware team we need to
use clock APIs.

>
>> +     if (IS_ERR(temp_sensor->clock)) {
>> +             ret = PTR_ERR(temp_sensor->clock);
>> +             dev_err(temp_sensor->hwmon_dev,
>> +                     "unable to get fclk: %d\n", ret);
>> +             ret = -EINVAL;
>> +             goto plat_res_err;
>> +     }
>> +
>> +     ret = omap_temp_sensor_clk_enable(temp_sensor);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Cannot enable temp sensor\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
>
> why ?

Need to check the available dividers and the frequencies that can be
set for a particular functional clock and the set the closest matching
frequency.

>
>> +     if (clk_rate < 1000000 || clk_rate = 0xffffffff) {
>> +             dev_err(&pdev->dev, "Error round rate\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     ret = clk_set_rate(temp_sensor->clock, clk_rate);
>
> why ??

frequency between 1-2MHz is recommended by hardware. Hence
setting the rate.

>
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Cannot set clock rate\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     temp_sensor->clk_rate = clk_rate;
>> +     omap_enable_continuous_mode(temp_sensor, 1);
>> +     omap_configure_temp_sensor_thresholds(temp_sensor);
>> +     /* 1 ms */
>> +     omap_configure_temp_sensor_counter(temp_sensor, 1);
>> +
>> +     /* Wait till the first conversion is done wait for at least 1ms */
>> +     usleep_range(1000, 2000);
>> +
>> +     /* Read the temperature once due to hw issue*/
>> +     omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +
>> +     /* Set 2 seconds time as default counter */
>> +     omap_configure_temp_sensor_counter(temp_sensor,
>> +                                             temp_sensor->clk_rate * 2);
>> +
>> +     temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
>> +     if (IS_ERR(temp_sensor->hwmon_dev)) {
>> +             dev_err(&pdev->dev, "hwmon_device_register failed.\n");
>> +             ret = PTR_ERR(temp_sensor->hwmon_dev);
>> +             goto hwmon_reg_err;
>> +     }
>> +
>> +     ret = sysfs_create_group(&pdev->dev.kobj,
>> +                              &omap_temp_sensor_group);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "could not create sysfs files\n");
>> +             goto sysfs_create_err;
>> +     }
>> +
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
>> +
>> +     ret = request_threaded_irq(temp_sensor->irq, NULL,
>> +             omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
>> +                     "temp_sensor", temp_sensor);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Request threaded irq failed.\n");
>> +             goto req_irq_err;
>> +     }
>> +
>> +     /* unmask the T_COLD and unmask T_HOT at init */
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +     val |= temp_sensor->registers->mask_cold_mask
>> +             | temp_sensor->registers->mask_hot_mask;
>> +
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +
>> +     return 0;
>> +
>> +req_irq_err:
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>> +                             &omap_temp_sensor_group);
>> +sysfs_create_err:
>> +     hwmon_device_unregister(&pdev->dev);
>> +hwmon_reg_err:
>> +     omap_temp_sensor_clk_disable(temp_sensor);
>> +clken_err:
>> +     if (temp_sensor->clock)
>> +             clk_put(temp_sensor->clock);
>> +plat_res_err:
>> +     mutex_destroy(&temp_sensor->sensor_mutex);
>> +     kfree(temp_sensor);
>> +     return ret;
>> +}
>> +
>> +static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
>> +
>> +     hwmon_device_unregister(&pdev->dev);
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>> +                     &omap_temp_sensor_group);
>> +     omap_temp_sensor_clk_disable(temp_sensor);
>> +     clk_put(temp_sensor->clock);
>> +     platform_set_drvdata(pdev, NULL);
>> +     free_irq(temp_sensor->irq, temp_sensor);
>> +     mutex_destroy(&temp_sensor->sensor_mutex);
>> +     kfree(temp_sensor);
>> +
>> +     return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     temp_sensor->temp_sensor_ctrl = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp_sensor->bg_ctrl = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +     temp_sensor->bg_counter = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_counter);
>> +     temp_sensor->bg_threshold = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_threshold);
>> +     temp_sensor->temp_sensor_tshut_threshold >> +             omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->temp_sensor_ctrl,
>> +                             temp_sensor->registers->temp_sensor_ctrl);
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->bg_ctrl,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->bg_counter,
>> +                             temp_sensor->registers->bgap_counter);
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->bg_threshold,
>> +                             temp_sensor->registers->bgap_threshold);
>> +     omap_temp_sensor_writel(temp_sensor,
>> +                             temp_sensor->temp_sensor_tshut_threshold,
>> +                             temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static int omap_temp_sensor_suspend(struct device *dev)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> +     omap_temp_sensor_save_ctxt(temp_sensor);
>> +
>> +     return 0;
>> +}
>> +
>> +static int omap_temp_sensor_resume(struct device *dev)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> +     omap_temp_sensor_restore_ctxt(temp_sensor);
>> +
>> +     return 0;
>> +}
>> +
>> +static int omap_temp_sensor_runtime_suspend(struct device *dev)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> +     omap_temp_sensor_save_ctxt(temp_sensor);
>> +
>> +     return 0;
>> +}
>> +
>> +static int omap_temp_sensor_runtime_resume(struct device *dev)
>> +{
>> +     static int context_loss_count;
>> +     int temp;
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +
>> +     temp = omap_device_get_context_loss_count(to_platform_device(dev));
>> +
>> +     if (temp != context_loss_count && context_loss_count != 0)
>> +             omap_temp_sensor_restore_ctxt(temp_sensor);
>> +
>> +     context_loss_count = temp;
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
>> +     .suspend = omap_temp_sensor_suspend,
>> +     .resume = omap_temp_sensor_resume,
>> +     .runtime_suspend = omap_temp_sensor_runtime_suspend,
>> +     .runtime_resume = omap_temp_sensor_runtime_resume,
>> +};
>> +
>> +#endif
>> +
>> +static struct platform_driver omap_temp_sensor_driver = {
>> +     .probe = omap_temp_sensor_probe,
>> +     .remove = omap_temp_sensor_remove,
>> +     .driver = {
>> +                     .name = "omap_temp_sensor",
>> +#ifdef CONFIG_PM
>> +                     .pm = &omap_temp_sensor_dev_pm_ops,
>> +#endif
>> +                },
>> +};
>> +
>> +int __init omap_temp_sensor_init(void)
>> +{
>> +     return platform_driver_register(&omap_temp_sensor_driver);
>> +}
>> +module_init(omap_temp_sensor_init);
>> +
>> +static void __exit omap_temp_sensor_exit(void)
>> +{
>> +     platform_driver_unregister(&omap_temp_sensor_driver);
>> +}
>> +module_exit(omap_temp_sensor_exit);
>> +
>> +MODULE_DESCRIPTION("OMAP446X temperature sensor Driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:" DRIVER_NAME);
>> +MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
>> --
>> 1.7.0.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-11  2:52       ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device J, KEERTHY
@ 2011-08-11 10:30         ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 10:30 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: balbi, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

[-- Attachment #1: Type: text/plain, Size: 4312 bytes --]

Hi,

On Thu, Aug 11, 2011 at 08:10:07AM +0530, J, KEERTHY wrote:
> >> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> >> index 6e6735f..8fd8e80 100644
> >> --- a/arch/arm/plat-omap/Kconfig
> >> +++ b/arch/arm/plat-omap/Kconfig
> >> @@ -115,6 +115,18 @@ config OMAP_MCBSP
> >>         Say Y here if you want support for the OMAP Multichannel
> >>         Buffered Serial Port.
> >>
> >> +config OMAP_TEMP_SENSOR
> >> +     bool "OMAP Temp Sensor Support"
> >> +     depends on ARCH_OMAP
> >> +     default n
> >> +     help
> >> +       Say Y here if you want support for the temp sensor
> >> +       on OMAP4460.
> >> +
> >> +       This provides the temperature of the MPU
> >> +       subsystem. Only one instance of on die temperature
> >> +       sensor is present.
> >
> > if there's only one instance, why do you use
> > omap_hwmod_for_each_by_class() ??
> 
> In case of OMAP5 there are multiple instances. Hence using
> omap_hwmod_for_each_by_class().

that's not a reality yet, so why don't you leave it for when OMAP5 is
around ?

> >> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> >> new file mode 100644
> >> index 0000000..692ebdc
> >> --- /dev/null
> >> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> >> @@ -0,0 +1,87 @@
> >> +/*
> >> + * OMAP Temperature sensor header file
> >> + *
> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> >> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> >> +
> >> +/* Offsets from the base of temperature sensor registers */
> >> +
> >> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
> >> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
> >> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
> >> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
> >> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
> >> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
> >> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
> >> +
> >> +struct omap_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     thsut_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;
> >> +};
> >
> > I find it unnecessary to pass the register map to driver using
> > platform_data.
> 
> With multiple instances the register map to individual instances will change.
> So passing it via platform_data.

what will change is the base address, the offsets should remain the
same.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-11 10:30         ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 10:30 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: balbi, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak


[-- Attachment #1.1: Type: text/plain, Size: 4312 bytes --]

Hi,

On Thu, Aug 11, 2011 at 08:10:07AM +0530, J, KEERTHY wrote:
> >> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> >> index 6e6735f..8fd8e80 100644
> >> --- a/arch/arm/plat-omap/Kconfig
> >> +++ b/arch/arm/plat-omap/Kconfig
> >> @@ -115,6 +115,18 @@ config OMAP_MCBSP
> >>         Say Y here if you want support for the OMAP Multichannel
> >>         Buffered Serial Port.
> >>
> >> +config OMAP_TEMP_SENSOR
> >> +     bool "OMAP Temp Sensor Support"
> >> +     depends on ARCH_OMAP
> >> +     default n
> >> +     help
> >> +       Say Y here if you want support for the temp sensor
> >> +       on OMAP4460.
> >> +
> >> +       This provides the temperature of the MPU
> >> +       subsystem. Only one instance of on die temperature
> >> +       sensor is present.
> >
> > if there's only one instance, why do you use
> > omap_hwmod_for_each_by_class() ??
> 
> In case of OMAP5 there are multiple instances. Hence using
> omap_hwmod_for_each_by_class().

that's not a reality yet, so why don't you leave it for when OMAP5 is
around ?

> >> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> >> new file mode 100644
> >> index 0000000..692ebdc
> >> --- /dev/null
> >> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> >> @@ -0,0 +1,87 @@
> >> +/*
> >> + * OMAP Temperature sensor header file
> >> + *
> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> >> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> >> +
> >> +/* Offsets from the base of temperature sensor registers */
> >> +
> >> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
> >> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
> >> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
> >> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
> >> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
> >> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
> >> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
> >> +
> >> +struct omap_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     thsut_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;
> >> +};
> >
> > I find it unnecessary to pass the register map to driver using
> > platform_data.
> 
> With multiple instances the register map to individual instances will change.
> So passing it via platform_data.

what will change is the base address, the offsets should remain the
same.

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11  9:57       ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
  (?)
@ 2011-08-11 10:36         ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 10:36 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: balbi, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

[-- Attachment #1: Type: text/plain, Size: 32301 bytes --]

Hi,

On Thu, Aug 11, 2011 at 03:27:26PM +0530, J, KEERTHY wrote:
> On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > (why aren't below in Cc ?
> 
> I will add them.
> 
> >
> > HARDWARE MONITORING
> > M:      Jean Delvare <khali@linux-fr.org>
> > M:      Guenter Roeck <guenter.roeck@ericsson.com>
> > L:      lm-sensors@lm-sensors.org
> > W:      http://www.lm-sensors.org/
> > T:      quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
> > T:      git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
> > S:      Maintained
> > F:      Documentation/hwmon/
> > F:      drivers/hwmon/
> > F:      include/linux/hwmon*.h)
> >
> > On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
> >> On chip temperature sensor driver. The driver monitors the temperature of
> >> the MPU subsystem of the OMAP4. It sends notifications to the user space if
> >> the temperature crosses user defined thresholds via kobject_uevent interface.
> >> The user is allowed to configure the temperature thresholds vis sysfs nodes
> >> exposed using hwmon interface.
> >>
> >> Signed-off-by: Keerthy <j-keerthy@ti.com>
> >> ---
> >>  drivers/hwmon/Kconfig            |   11 +
> >>  drivers/hwmon/Makefile           |    1 +
> >>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
> >>  3 files changed, 962 insertions(+), 0 deletions(-)
> >>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
> >>
> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> >> index 5f888f7..9c9cd8b 100644
> >> --- a/drivers/hwmon/Kconfig
> >> +++ b/drivers/hwmon/Kconfig
> >> @@ -323,6 +323,17 @@ config SENSORS_F71805F
> >>         This driver can also be built as a module.  If so, the module
> >>         will be called f71805f.
> >>
> >> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
> >> +     bool "OMAP on-die temperature sensor hwmon driver"
> >> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
> >> +     help
> >> +       If you say yes here you get support for hardware
> >> +       monitoring features of the OMAP on die temperature
> >> +       sensor.
> >> +
> >> +       Continuous conversion programmable delay
> >> +       mode is used for temperature conversion.
> >> +
> >>  config SENSORS_F71882FG
> >>       tristate "Fintek F71882FG and compatibles"
> >>       help
> >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> >> index 28061cf..d0f89f5 100644
> >> --- a/drivers/hwmon/Makefile
> >> +++ b/drivers/hwmon/Makefile
> >> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
> >>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
> >>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
> >>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
> >> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
> >>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
> >>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
> >>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> new file mode 100644
> >> index 0000000..15e2559
> >> --- /dev/null
> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> @@ -0,0 +1,950 @@
> >> +/*
> >> + * OMAP4 Temperature sensor driver file
> >> + *
> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> +#include <linux/clk.h>
> >
> > why ??
> 
> Clock rate setting functions.

you shouldn't need in drivers.

> >> +#include <linux/io.h>
> >> +#include <linux/debugfs.h>
> >
> > why ??
> 
> It will be removed.
> 
> >
> >> +#include <linux/delay.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/init.h>
> >> +#include <plat/omap_device.h>
> >
> > why ??
> >
> 
> Context loss count

shouldn't use in drivers.

> >> +#include <linux/module.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/device.h>
> >> +#include <linux/jiffies.h>
> >> +#include <linux/hwmon.h>
> >> +#include <linux/hwmon-sysfs.h>
> >> +#include <linux/stddef.h>
> >> +#include <linux/sysfs.h>
> >> +#include <linux/err.h>
> >> +#include <linux/types.h>
> >> +#include <linux/mutex.h>
> >> +#include <linux/pm_runtime.h>
> >> +#include <plat/common.h>
> >
> > why ?
> 
> usleep_range function.

plat/common for usleep_range ?? usleep_range is defined in
<linux/delay.h>

> >> +#include <plat/temperature_sensor.h>
> >
> 
> It is the header file with the structure definitions
> used in the driver.

why don't you put in <linux/platform_data/....> ??

> >> +#include <mach/ctrl_module_core_44xx.h>
> >
> > why ?
> 
> It will be removed
> 
> >
> >> +#include <mach/gpio.h>
> >
> > linux/gpio.h for crying out loud... how many times Russell has to say
> > the exact same thing ??????
> >
> 
> It will be removed

oh, you don't even use any gpio ? Why do you blindly add so many headers
if you don't need them ???

> >> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
> >> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
> >> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
> >> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
> >> +#define OMAP_ADC_START_VALUE 530
> >> +#define OMAP_ADC_END_VALUE   923
> >> +
> >> +/*
> >> + * omap_temp_sensor structure
> >> + * @hwmon_dev - device pointer
> >> + * @clock - Clock pointer
> >> + * @registers - Pointer to structure with register offsets and bitfields
> >> + * @sensor_mutex - Mutex for sysfs, irq and PM
> >> + * @irq - MPU Irq number for thermal alert
> >> + * @phy_base - Physical base of the temp I/O
> >> + * @clk_rate - Holds current clock rate
> >> + * @temp_sensor_ctrl - temp sensor control register value
> >> + * @bg_ctrl - bandgap ctrl register value
> >> + * @bg_counter - bandgap counter value
> >> + * @bg_threshold - bandgap threshold register value
> >> + * @temp_sensor_tshut_threshold - bandgap tshut register value
> >> + * @is_efuse_valid - Flag to determine if efuse is valid or not
> >> + * @clk_on - Manages the current clock state
> >> + */
> >> +struct omap_temp_sensor {
> >> +     struct device           *hwmon_dev;
> >> +     struct clk              *clock;
> >> +     struct omap_temp_sensor_registers *registers;
> >> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
> >> +     unsigned int            irq;
> >> +     void __iomem            *phy_base;
> >> +     u32                     clk_rate;
> >> +     u32                     temp_sensor_ctrl;
> >> +     u32                     bg_ctrl;
> >> +     u32                     bg_counter;
> >> +     u32                     bg_threshold;
> >> +     u32                     temp_sensor_tshut_threshold;
> >> +     bool                    is_efuse_valid;
> >> +     bool                    clk_on;
> >> +};
> >> +
> >> +/*
> >> + * Temperature values in milli degree celsius
> >> + * ADC code values from 530 to 923
> >> + */
> >> +static int adc_to_temp[] = {
> >> +     -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
> >> +};
> >> +
> >> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
> >> +                                         *temp_sensor, u32 reg)
> >> +{
> >> +     return __raw_readl(temp_sensor->phy_base + reg);
> >> +}
> >> +
> >> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
> >> +                                 u32 val, u32 reg)
> >> +{
> >> +     __raw_writel(val, (temp_sensor->phy_base + reg));
> >> +}
> >> +
> >> +static int adc_to_temp_conversion(int adc_val)
> >> +{
> >> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
> >> +}
> >> +
> >> +static int temp_to_adc_conversion(long temp)
> >> +{
> >> +     int i;
> >> +
> >> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
> >> +             if (temp < adc_to_temp[i])
> >> +                     return OMAP_ADC_START_VALUE + i - 1;
> >> +
> >> +     return -EINVAL;
> >> +}
> >> +
> >> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
> >> +                                               *temp_sensor)
> >> +{
> >> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
> >> +
> >> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
> >> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
> >> +
> >> +     /* Configure the TALERT thresholds */
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
> >> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, temp,
> >> +             temp_sensor->registers->bgap_threshold);
> >> +
> >> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
> >> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
> >> +
> >> +     /* Configure the TSHUT thresholds */
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->thsut_threshold);
> >> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
> >> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, temp,
> >> +                     temp_sensor->registers->thsut_threshold);
> >> +}
> >> +
> >> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
> >> +                                            *temp_sensor, u32 counter)
> >> +{
> >> +     u32 val;
> >> +
> >> +     val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +     val &= ~(temp_sensor->registers->counter_mask);
> >> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, val,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +}
> >> +
> >> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
> >> +                                     bool enable)
> >> +{
> >> +     u32 val;
> >> +
> >> +     val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_mode_ctrl);
> >> +
> >> +     if (enable)
> >> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
> >> +     else
> >> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
> >> +
> >> +     omap_temp_sensor_writel(temp_sensor, val,
> >> +                     temp_sensor->registers->bgap_mode_ctrl);
> >> +}
> >> +
> >> +/* Sysfs hook functions */
> >> +
> >> +static ssize_t show_temp_max(struct device *dev,
> >> +                     struct device_attribute *devattr, char *buf)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     int temp;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
> >> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
> >> +
> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> +             dev_err(dev, "invalid value\n");
> >> +             goto out;
> >> +     }
> >> +     temp = adc_to_temp_conversion(temp);
> >> +
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +
> >> +     return snprintf(buf, 16, "%d\n", temp);
> >> +}
> >> +
> >> +static ssize_t set_temp_max(struct device *dev,
> >> +                         struct device_attribute *devattr,
> >> +                         const char *buf, size_t count)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     long                    val;
> >> +     u32                     reg_val, t_cold, t_hot, temp;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     if (strict_strtol(buf, 10, &val)) {
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     t_hot = temp_to_adc_conversion(val);
> >> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
> >> +             dev_err(dev, "invalid range\n");
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* obtain the T cold value */
> >> +     t_cold = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
> >> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
> >> +
> >> +     if (t_hot < t_cold) {
> >> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* write the new t_hot value */
> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
> >> +     reg_val |= (t_hot <<
> >> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +
> >> +     /* Read the current temperature */
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
> >> +
> >> +     /*
> >> +      * If user sets the HIGH threshold(t_hot) greater than the current
> >> +      * temperature(temp) unmask the HOT interrupts
> >> +      */
> >> +     if (t_hot > temp) {
> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +     }
> >> +
> >> +     /*
> >> +      * If current temperature is in-between the hot and cold thresholds,
> >> +      * Enable both masks.
> >> +      */
> >> +     if (temp > t_cold && temp < t_hot) {
> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                             OMAP4460_BGAP_CTRL_OFFSET);
> >> +     }
> >> +     /*
> >> +      * else no need to do anything since HW will immediately compare
> >> +      * the new threshold and generate interrupt accordingly
> >> +      */
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     return count;
> >> +}
> >> +
> >> +static ssize_t show_temp_max_hyst(struct device *dev,
> >> +             struct device_attribute *devattr, char *buf)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     u32                     temp;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +             temp_sensor->registers->bgap_threshold);
> >> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
> >> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
> >> +
> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> +             dev_err(dev, "invalid value\n");
> >> +             goto out;
> >> +     }
> >> +
> >> +     temp = adc_to_temp_conversion(temp);
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +
> >> +     return snprintf(buf, 16, "%d\n", temp);
> >> +}
> >> +
> >> +static ssize_t set_temp_max_hyst(struct device *dev,
> >> +                              struct device_attribute *devattr,
> >> +                              const char *buf, size_t count)
> >> +{
> >> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
> >> +     u32                             reg_val, t_hot, t_cold, temp;
> >> +     long                            val;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     if (strict_strtol(buf, 10, &val)) {
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     t_cold = temp_to_adc_conversion(val);
> >> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
> >> +             dev_err(dev, "invalid range");
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* obtain the T HOT value */
> >> +     t_hot = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
> >> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
> >> +
> >> +     if (t_cold > t_hot) {
> >> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* write the new t_cold value */
> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
> >> +     reg_val |= (t_cold <<
> >> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +
> >> +     /* Read the current temperature */
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +             temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
> >> +
> >> +     /*
> >> +      * If user sets the LOW threshold(t_cold) lower than the current
> >> +      * temperature(temp) unmask the COLD interrupts
> >> +      */
> >> +     if (t_cold < temp) {
> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                     temp_sensor->registers->bgap_mask_ctrl);
> >> +     }
> >> +
> >> +     /*
> >> +      * If current temperature is in-between the hot and cold thresholds,
> >> +      * Enable both masks.
> >> +      */
> >> +     if (temp < t_hot && temp > t_cold) {
> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +     }
> >> +
> >> +     /*
> >> +      * else no need to do anything since HW will immediately compare
> >> +      * the new threshold and generate interrupt accordingly
> >> +      */
> >> +
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     return count;
> >> +}
> >> +
> >> +static ssize_t show_update_rate(struct device *dev,
> >> +                     struct device_attribute *devattr, char *buf)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     u32                     temp = 0, ret = 0;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     if (!temp_sensor->clk_rate) {
> >> +             dev_err(dev, "clk_rate is NULL\n");
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +     temp = (temp & temp_sensor->registers->counter_mask) >>
> >> +                     __ffs(temp_sensor->registers->counter_mask);
> >
> >        temp &= ??
> >
> >> +     temp = temp * 1000 / (temp_sensor->clk_rate);
> >
> >        temp *= ??
> 
> Need to multiply the temp with 1000 before dividing.
> temp *= evaluates the RHS first and then multiplies LHS.

temp *= 1000;
temp /= clk_rate;

> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     if (!ret)
> >> +             return sprintf(buf, "%d\n", temp);
> >> +     else
> >> +             return ret;
> >> +}
> >> +
> >> +static ssize_t set_update_rate(struct device *dev,
> >> +                            struct device_attribute *devattr,
> >> +                            const char *buf, size_t count)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     u32                     reg_val;
> >> +     long                    val;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     if (strict_strtol(buf, 10, &val)) {
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     val *= temp_sensor->clk_rate / 1000;
> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +
> >> +     reg_val &= ~(temp_sensor->registers->counter_mask);
> >> +     reg_val |= val;
> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     return count;
> >> +}
> >> +
> >> +static int omap_temp_sensor_read_temp(struct device *dev,
> >> +                                   struct device_attribute *devattr,
> >> +                                   char *buf)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     int                     temp, ret = 0;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +             temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
> >> +
> >> +     if (!temp_sensor->is_efuse_valid)
> >> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
> >> +
> >> +     /* look up for temperature in the table and return the temperature */
> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> +             dev_err(dev, "invalid adc code reported %d", temp);
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
> >> +
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     if (!ret)
> >> +             return sprintf(buf, "%d\n", temp);
> >> +     else
> >> +             return ret;
> >> +}
> >> +
> >> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
> >> +                       NULL, 0);
> >> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
> >> +                       set_temp_max, 0);
> >> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
> >> +                       set_temp_max_hyst, 0);
> >> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
> >> +                       set_update_rate, 0);
> >> +
> >> +static struct attribute *omap_temp_sensor_attributes[] = {
> >> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
> >> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
> >> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
> >> +     &sensor_dev_attr_update_rate.dev_attr.attr,
> >> +     NULL
> >> +};
> >> +
> >> +static const struct attribute_group omap_temp_sensor_group = {
> >> +     .attrs = omap_temp_sensor_attributes,
> >> +};
> >> +
> >> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
> >> +{
> >> +     u32 ret = 0, temp;
> >> +
> >> +     if (temp_sensor->clk_on) {
> >> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
> >> +             goto out;
> >> +     }
> >> +
> >> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
> >> +     if (ret < 0) {
> >> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
> >> +     /* BGAP_TEMPSOFF should be reset to 0 */
> >> +     omap_temp_sensor_writel(temp_sensor, temp,
> >> +                             temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp_sensor->clk_on = 1;
> >
> > why isn't pm_runtime_get_sync() enough ??
> 
> This is the programming sequence indicated. BGAP_TEMPSOFF should be set
> to 0 to enable the temperature sensor.

why isn't this done as part of your runtime_resume() function ??

> >> +out:
> >> +     return ret;
> >> +}
> >> +
> >> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
> >> +{
> >> +     u32 temp, ret = 0;
> >> +     unsigned long timeout;
> >> +
> >> +     if (!temp_sensor->clk_on) {
> >> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
> >> +             goto out;
> >> +     }
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
> >> +
> >> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
> >> +     omap_temp_sensor_writel(temp_sensor, temp,
> >> +                     temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_status);
> >> +     timeout = jiffies + msecs_to_jiffies(5);
> >> +
> >> +     /* wait till the clean stop bit is set or till the timeout exppires */
> >> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
> >> +             !(time_after(jiffies, timeout))) {
> >> +             temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_status);
> >> +             usleep_range(500, 2000);
> >> +     }
> >> +
> >> +     if (time_after(jiffies, timeout))
> >> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
> >> +     /* Gate the clock */
> >> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
> >> +     if (ret < 0) {
> >> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +     temp_sensor->clk_on = 0;
> >> +out:
> >> +     return ret;
> >> +}

add a blank line here.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 10:36         ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 10:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, Aug 11, 2011 at 03:27:26PM +0530, J, KEERTHY wrote:
> On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > (why aren't below in Cc ?
> 
> I will add them.
> 
> >
> > HARDWARE MONITORING
> > M: ? ? ?Jean Delvare <khali@linux-fr.org>
> > M: ? ? ?Guenter Roeck <guenter.roeck@ericsson.com>
> > L: ? ? ?lm-sensors at lm-sensors.org
> > W: ? ? ?http://www.lm-sensors.org/
> > T: ? ? ?quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
> > T: ? ? ?git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
> > S: ? ? ?Maintained
> > F: ? ? ?Documentation/hwmon/
> > F: ? ? ?drivers/hwmon/
> > F: ? ? ?include/linux/hwmon*.h)
> >
> > On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
> >> On chip temperature sensor driver. The driver monitors the temperature of
> >> the MPU subsystem of the OMAP4. It sends notifications to the user space if
> >> the temperature crosses user defined thresholds via kobject_uevent interface.
> >> The user is allowed to configure the temperature thresholds vis sysfs nodes
> >> exposed using hwmon interface.
> >>
> >> Signed-off-by: Keerthy <j-keerthy@ti.com>
> >> ---
> >> ?drivers/hwmon/Kconfig ? ? ? ? ? ?| ? 11 +
> >> ?drivers/hwmon/Makefile ? ? ? ? ? | ? ?1 +
> >> ?drivers/hwmon/omap_temp_sensor.c | ?950 ++++++++++++++++++++++++++++++++++++++
> >> ?3 files changed, 962 insertions(+), 0 deletions(-)
> >> ?create mode 100644 drivers/hwmon/omap_temp_sensor.c
> >>
> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> >> index 5f888f7..9c9cd8b 100644
> >> --- a/drivers/hwmon/Kconfig
> >> +++ b/drivers/hwmon/Kconfig
> >> @@ -323,6 +323,17 @@ config SENSORS_F71805F
> >> ? ? ? ? This driver can also be built as a module. ?If so, the module
> >> ? ? ? ? will be called f71805f.
> >>
> >> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
> >> + ? ? bool "OMAP on-die temperature sensor hwmon driver"
> >> + ? ? depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
> >> + ? ? help
> >> + ? ? ? If you say yes here you get support for hardware
> >> + ? ? ? monitoring features of the OMAP on die temperature
> >> + ? ? ? sensor.
> >> +
> >> + ? ? ? Continuous conversion programmable delay
> >> + ? ? ? mode is used for temperature conversion.
> >> +
> >> ?config SENSORS_F71882FG
> >> ? ? ? tristate "Fintek F71882FG and compatibles"
> >> ? ? ? help
> >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> >> index 28061cf..d0f89f5 100644
> >> --- a/drivers/hwmon/Makefile
> >> +++ b/drivers/hwmon/Makefile
> >> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639) ? ? ? += max6639.o
> >> ?obj-$(CONFIG_SENSORS_MAX6642) ? ? ? ?+= max6642.o
> >> ?obj-$(CONFIG_SENSORS_MAX6650) ? ? ? ?+= max6650.o
> >> ?obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
> >> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR) ?+= omap_temp_sensor.o
> >> ?obj-$(CONFIG_SENSORS_PC87360) ? ? ? ?+= pc87360.o
> >> ?obj-$(CONFIG_SENSORS_PC87427) ? ? ? ?+= pc87427.o
> >> ?obj-$(CONFIG_SENSORS_PCF8591) ? ? ? ?+= pcf8591.o
> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> new file mode 100644
> >> index 0000000..15e2559
> >> --- /dev/null
> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> @@ -0,0 +1,950 @@
> >> +/*
> >> + * OMAP4 Temperature sensor driver file
> >> + *
> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> +#include <linux/clk.h>
> >
> > why ??
> 
> Clock rate setting functions.

you shouldn't need in drivers.

> >> +#include <linux/io.h>
> >> +#include <linux/debugfs.h>
> >
> > why ??
> 
> It will be removed.
> 
> >
> >> +#include <linux/delay.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/init.h>
> >> +#include <plat/omap_device.h>
> >
> > why ??
> >
> 
> Context loss count

shouldn't use in drivers.

> >> +#include <linux/module.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/device.h>
> >> +#include <linux/jiffies.h>
> >> +#include <linux/hwmon.h>
> >> +#include <linux/hwmon-sysfs.h>
> >> +#include <linux/stddef.h>
> >> +#include <linux/sysfs.h>
> >> +#include <linux/err.h>
> >> +#include <linux/types.h>
> >> +#include <linux/mutex.h>
> >> +#include <linux/pm_runtime.h>
> >> +#include <plat/common.h>
> >
> > why ?
> 
> usleep_range function.

plat/common for usleep_range ?? usleep_range is defined in
<linux/delay.h>

> >> +#include <plat/temperature_sensor.h>
> >
> 
> It is the header file with the structure definitions
> used in the driver.

why don't you put in <linux/platform_data/....> ??

> >> +#include <mach/ctrl_module_core_44xx.h>
> >
> > why ?
> 
> It will be removed
> 
> >
> >> +#include <mach/gpio.h>
> >
> > linux/gpio.h for crying out loud... how many times Russell has to say
> > the exact same thing ??????
> >
> 
> It will be removed

oh, you don't even use any gpio ? Why do you blindly add so many headers
if you don't need them ???

> >> +#define TSHUT_THRESHOLD_HOT ?122000 ?/* 122 deg C */
> >> +#define TSHUT_THRESHOLD_COLD 100000 ?/* 100 deg C */
> >> +#define BGAP_THRESHOLD_T_HOT 73000 ? /* 73 deg C */
> >> +#define BGAP_THRESHOLD_T_COLD ? ? ? ?71000 ? /* 71 deg C */
> >> +#define OMAP_ADC_START_VALUE 530
> >> +#define OMAP_ADC_END_VALUE ? 923
> >> +
> >> +/*
> >> + * omap_temp_sensor structure
> >> + * @hwmon_dev - device pointer
> >> + * @clock - Clock pointer
> >> + * @registers - Pointer to structure with register offsets and bitfields
> >> + * @sensor_mutex - Mutex for sysfs, irq and PM
> >> + * @irq - MPU Irq number for thermal alert
> >> + * @phy_base - Physical base of the temp I/O
> >> + * @clk_rate - Holds current clock rate
> >> + * @temp_sensor_ctrl - temp sensor control register value
> >> + * @bg_ctrl - bandgap ctrl register value
> >> + * @bg_counter - bandgap counter value
> >> + * @bg_threshold - bandgap threshold register value
> >> + * @temp_sensor_tshut_threshold - bandgap tshut register value
> >> + * @is_efuse_valid - Flag to determine if efuse is valid or not
> >> + * @clk_on - Manages the current clock state
> >> + */
> >> +struct omap_temp_sensor {
> >> + ? ? struct device ? ? ? ? ? *hwmon_dev;
> >> + ? ? struct clk ? ? ? ? ? ? ?*clock;
> >> + ? ? struct omap_temp_sensor_registers *registers;
> >> + ? ? struct mutex ? ? ? ? ? ?sensor_mutex; /* Mutex for sysfs, irq and PM */
> >> + ? ? unsigned int ? ? ? ? ? ?irq;
> >> + ? ? void __iomem ? ? ? ? ? ?*phy_base;
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? clk_rate;
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp_sensor_ctrl;
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_ctrl;
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_counter;
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_threshold;
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp_sensor_tshut_threshold;
> >> + ? ? bool ? ? ? ? ? ? ? ? ? ?is_efuse_valid;
> >> + ? ? bool ? ? ? ? ? ? ? ? ? ?clk_on;
> >> +};
> >> +
> >> +/*
> >> + * Temperature values in milli degree celsius
> >> + * ADC code values from 530 to 923
> >> + */
> >> +static int adc_to_temp[] = {
> >> + ? ? -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
> >> +};
> >> +
> >> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *temp_sensor, u32 reg)
> >> +{
> >> + ? ? return __raw_readl(temp_sensor->phy_base + reg);
> >> +}
> >> +
> >> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? u32 val, u32 reg)
> >> +{
> >> + ? ? __raw_writel(val, (temp_sensor->phy_base + reg));
> >> +}
> >> +
> >> +static int adc_to_temp_conversion(int adc_val)
> >> +{
> >> + ? ? return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
> >> +}
> >> +
> >> +static int temp_to_adc_conversion(long temp)
> >> +{
> >> + ? ? int i;
> >> +
> >> + ? ? for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
> >> + ? ? ? ? ? ? if (temp < adc_to_temp[i])
> >> + ? ? ? ? ? ? ? ? ? ? return OMAP_ADC_START_VALUE + i - 1;
> >> +
> >> + ? ? return -EINVAL;
> >> +}
> >> +
> >> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *temp_sensor)
> >> +{
> >> + ? ? u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
> >> +
> >> + ? ? t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
> >> + ? ? t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
> >> +
> >> + ? ? /* Configure the TALERT thresholds */
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> + ? ? temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
> >> + ? ? ? ? ? ? (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
> >> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
> >> + ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> +
> >> + ? ? tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
> >> + ? ? tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
> >> +
> >> + ? ? /* Configure the TSHUT thresholds */
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->thsut_threshold);
> >> + ? ? temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
> >> + ? ? ? ? | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
> >> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->thsut_threshold);
> >> +}
> >> +
> >> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*temp_sensor, u32 counter)
> >> +{
> >> + ? ? u32 val;
> >> +
> >> + ? ? val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
> >> + ? ? val &= ~(temp_sensor->registers->counter_mask);
> >> + ? ? val |= (counter << __ffs(temp_sensor->registers->counter_mask));
> >> + ? ? omap_temp_sensor_writel(temp_sensor, val,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
> >> +}
> >> +
> >> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bool enable)
> >> +{
> >> + ? ? u32 val;
> >> +
> >> + ? ? val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mode_ctrl);
> >> +
> >> + ? ? if (enable)
> >> + ? ? ? ? ? ? val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
> >> + ? ? else
> >> + ? ? ? ? ? ? val &= ~(temp_sensor->registers->mode_ctrl_mask);
> >> +
> >> + ? ? omap_temp_sensor_writel(temp_sensor, val,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mode_ctrl);
> >> +}
> >> +
> >> +/* Sysfs hook functions */
> >> +
> >> +static ssize_t show_temp_max(struct device *dev,
> >> + ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
> >> +{
> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> + ? ? int temp;
> >> +
> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> + ? ? temp = (temp & temp_sensor->registers->threshold_thot_mask)
> >> + ? ? ? ? ? ? ? ? ? ? >> __ffs(temp_sensor->registers->threshold_thot_mask);
> >> +
> >> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> + ? ? ? ? ? ? dev_err(dev, "invalid value\n");
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> + ? ? temp = adc_to_temp_conversion(temp);
> >> +
> >> +out:
> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? return snprintf(buf, 16, "%d\n", temp);
> >> +}
> >> +
> >> +static ssize_t set_temp_max(struct device *dev,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? const char *buf, size_t count)
> >> +{
> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> + ? ? long ? ? ? ? ? ? ? ? ? ?val;
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? reg_val, t_cold, t_hot, temp;
> >> +
> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? if (strict_strtol(buf, 10, &val)) {
> >> + ? ? ? ? ? ? count = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? t_hot = temp_to_adc_conversion(val);
> >> + ? ? if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
> >> + ? ? ? ? ? ? dev_err(dev, "invalid range\n");
> >> + ? ? ? ? ? ? count = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? /* obtain the T cold value */
> >> + ? ? t_cold = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> + ? ? t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask);
> >> +
> >> + ? ? if (t_hot < t_cold) {
> >> + ? ? ? ? ? ? dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
> >> + ? ? ? ? ? ? count = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? /* write the new t_hot value */
> >> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> + ? ? reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
> >> + ? ? reg_val |= (t_hot <<
> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_thot_mask));
> >> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> +
> >> + ? ? /* Read the current temperature */
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
> >> + ? ? temp &= (temp_sensor->registers->bgap_dtemp_mask);
> >> +
> >> + ? ? /*
> >> + ? ? ?* If user sets the HIGH threshold(t_hot) greater than the current
> >> + ? ? ?* temperature(temp) unmask the HOT interrupts
> >> + ? ? ?*/
> >> + ? ? if (t_hot > temp) {
> >> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
> >> + ? ? ? ? ? ? reg_val &= ~(temp_sensor->registers->mask_cold_mask);
> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
> >> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
> >> + ? ? }
> >> +
> >> + ? ? /*
> >> + ? ? ?* If current temperature is in-between the hot and cold thresholds,
> >> + ? ? ?* Enable both masks.
> >> + ? ? ?*/
> >> + ? ? if (temp > t_cold && temp < t_hot) {
> >> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
> >> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4460_BGAP_CTRL_OFFSET);
> >> + ? ? }
> >> + ? ? /*
> >> + ? ? ?* else no need to do anything since HW will immediately compare
> >> + ? ? ?* the new threshold and generate interrupt accordingly
> >> + ? ? ?*/
> >> +out:
> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
> >> + ? ? return count;
> >> +}
> >> +
> >> +static ssize_t show_temp_max_hyst(struct device *dev,
> >> + ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
> >> +{
> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp;
> >> +
> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> + ? ? temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
> >> + ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask);
> >> +
> >> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> + ? ? ? ? ? ? dev_err(dev, "invalid value\n");
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? temp = adc_to_temp_conversion(temp);
> >> +out:
> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? return snprintf(buf, 16, "%d\n", temp);
> >> +}
> >> +
> >> +static ssize_t set_temp_max_hyst(struct device *dev,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct device_attribute *devattr,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *buf, size_t count)
> >> +{
> >> + ? ? struct omap_temp_sensor ? ? ? ? *temp_sensor = dev_get_drvdata(dev);
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? ? ? ? ? reg_val, t_hot, t_cold, temp;
> >> + ? ? long ? ? ? ? ? ? ? ? ? ? ? ? ? ?val;
> >> +
> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? if (strict_strtol(buf, 10, &val)) {
> >> + ? ? ? ? ? ? count = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? t_cold = temp_to_adc_conversion(val);
> >> + ? ? if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
> >> + ? ? ? ? ? ? dev_err(dev, "invalid range");
> >> + ? ? ? ? ? ? count = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? /* obtain the T HOT value */
> >> + ? ? t_hot = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> + ? ? t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_thot_mask);
> >> +
> >> + ? ? if (t_cold > t_hot) {
> >> + ? ? ? ? ? ? dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
> >> + ? ? ? ? ? ? count = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? /* write the new t_cold value */
> >> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> + ? ? reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
> >> + ? ? reg_val |= (t_cold <<
> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask));
> >> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
> >> +
> >> + ? ? /* Read the current temperature */
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
> >> + ? ? temp &= (temp_sensor->registers->bgap_dtemp_mask);
> >> +
> >> + ? ? /*
> >> + ? ? ?* If user sets the LOW threshold(t_cold) lower than the current
> >> + ? ? ?* temperature(temp) unmask the COLD interrupts
> >> + ? ? ?*/
> >> + ? ? if (t_cold < temp) {
> >> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
> >> + ? ? ? ? ? ? reg_val &= ~(temp_sensor->registers->mask_hot_mask);
> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
> >> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
> >> + ? ? }
> >> +
> >> + ? ? /*
> >> + ? ? ?* If current temperature is in-between the hot and cold thresholds,
> >> + ? ? ?* Enable both masks.
> >> + ? ? ?*/
> >> + ? ? if (temp < t_hot && temp > t_cold) {
> >> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
> >> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
> >> + ? ? }
> >> +
> >> + ? ? /*
> >> + ? ? ?* else no need to do anything since HW will immediately compare
> >> + ? ? ?* the new threshold and generate interrupt accordingly
> >> + ? ? ?*/
> >> +
> >> +out:
> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
> >> + ? ? return count;
> >> +}
> >> +
> >> +static ssize_t show_update_rate(struct device *dev,
> >> + ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
> >> +{
> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp = 0, ret = 0;
> >> +
> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? if (!temp_sensor->clk_rate) {
> >> + ? ? ? ? ? ? dev_err(dev, "clk_rate is NULL\n");
> >> + ? ? ? ? ? ? ret = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
> >> + ? ? temp = (temp & temp_sensor->registers->counter_mask) >>
> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->counter_mask);
> >
> > ? ? ? ?temp &= ??
> >
> >> + ? ? temp = temp * 1000 / (temp_sensor->clk_rate);
> >
> > ? ? ? ?temp *= ??
> 
> Need to multiply the temp with 1000 before dividing.
> temp *= evaluates the RHS first and then multiplies LHS.

temp *= 1000;
temp /= clk_rate;

> >> +out:
> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
> >> + ? ? if (!ret)
> >> + ? ? ? ? ? ? return sprintf(buf, "%d\n", temp);
> >> + ? ? else
> >> + ? ? ? ? ? ? return ret;
> >> +}
> >> +
> >> +static ssize_t set_update_rate(struct device *dev,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct device_attribute *devattr,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *buf, size_t count)
> >> +{
> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? reg_val;
> >> + ? ? long ? ? ? ? ? ? ? ? ? ?val;
> >> +
> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? if (strict_strtol(buf, 10, &val)) {
> >> + ? ? ? ? ? ? count = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? val *= temp_sensor->clk_rate / 1000;
> >> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
> >> +
> >> + ? ? reg_val &= ~(temp_sensor->registers->counter_mask);
> >> + ? ? reg_val |= val;
> >> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
> >> +
> >> +out:
> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
> >> + ? ? return count;
> >> +}
> >> +
> >> +static int omap_temp_sensor_read_temp(struct device *dev,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? char *buf)
> >> +{
> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> + ? ? int ? ? ? ? ? ? ? ? ? ? temp, ret = 0;
> >> +
> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
> >> + ? ? temp &= temp_sensor->registers->bgap_dtemp_mask;
> >> +
> >> + ? ? if (!temp_sensor->is_efuse_valid)
> >> + ? ? ? ? ? ? dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
> >> +
> >> + ? ? /* look up for temperature in the table and return the temperature */
> >> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> + ? ? ? ? ? ? dev_err(dev, "invalid adc code reported %d", temp);
> >> + ? ? ? ? ? ? ret = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
> >> +
> >> +out:
> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
> >> + ? ? if (!ret)
> >> + ? ? ? ? ? ? return sprintf(buf, "%d\n", temp);
> >> + ? ? else
> >> + ? ? ? ? ? ? return ret;
> >> +}
> >> +
> >> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
> >> + ? ? ? ? ? ? ? ? ? ? ? NULL, 0);
> >> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
> >> + ? ? ? ? ? ? ? ? ? ? ? set_temp_max, 0);
> >> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
> >> + ? ? ? ? ? ? ? ? ? ? ? set_temp_max_hyst, 0);
> >> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
> >> + ? ? ? ? ? ? ? ? ? ? ? set_update_rate, 0);
> >> +
> >> +static struct attribute *omap_temp_sensor_attributes[] = {
> >> + ? ? &sensor_dev_attr_temp1_input.dev_attr.attr,
> >> + ? ? &sensor_dev_attr_temp1_max.dev_attr.attr,
> >> + ? ? &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
> >> + ? ? &sensor_dev_attr_update_rate.dev_attr.attr,
> >> + ? ? NULL
> >> +};
> >> +
> >> +static const struct attribute_group omap_temp_sensor_group = {
> >> + ? ? .attrs = omap_temp_sensor_attributes,
> >> +};
> >> +
> >> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
> >> +{
> >> + ? ? u32 ret = 0, temp;
> >> +
> >> + ? ? if (temp_sensor->clk_on) {
> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "clock already on\n");
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
> >> + ? ? if (ret < 0) {
> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
> >> + ? ? ? ? ? ? ret = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> +
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
> >> + ? ? temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
> >> + ? ? /* BGAP_TEMPSOFF should be reset to 0 */
> >> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
> >> + ? ? temp_sensor->clk_on = 1;
> >
> > why isn't pm_runtime_get_sync() enough ??
> 
> This is the programming sequence indicated. BGAP_TEMPSOFF should be set
> to 0 to enable the temperature sensor.

why isn't this done as part of your runtime_resume() function ??

> >> +out:
> >> + ? ? return ret;
> >> +}
> >> +
> >> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
> >> +{
> >> + ? ? u32 temp, ret = 0;
> >> + ? ? unsigned long timeout;
> >> +
> >> + ? ? if (!temp_sensor->clk_on) {
> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "clock already off\n");
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
> >> + ? ? temp |= temp_sensor->registers->bgap_tempsoff_mask;
> >> +
> >> + ? ? /* BGAP_TEMPSOFF should be set to 1 before gating clock */
> >> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_status);
> >> + ? ? timeout = jiffies + msecs_to_jiffies(5);
> >> +
> >> + ? ? /* wait till the clean stop bit is set or till the timeout exppires */
> >> + ? ? while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
> >> + ? ? ? ? ? ? !(time_after(jiffies, timeout))) {
> >> + ? ? ? ? ? ? temp = omap_temp_sensor_readl(temp_sensor,
> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_status);
> >> + ? ? ? ? ? ? usleep_range(500, 2000);
> >> + ? ? }
> >> +
> >> + ? ? if (time_after(jiffies, timeout))
> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
> >> + ? ? /* Gate the clock */
> >> + ? ? ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
> >> + ? ? if (ret < 0) {
> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
> >> + ? ? ? ? ? ? ret = -EINVAL;
> >> + ? ? ? ? ? ? goto out;
> >> + ? ? }
> >> + ? ? temp_sensor->clk_on = 0;
> >> +out:
> >> + ? ? return ret;
> >> +}

add a blank line here.

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110811/e8da2fe0/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 10:36         ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 10:36 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: balbi, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck


[-- Attachment #1.1: Type: text/plain, Size: 32301 bytes --]

Hi,

On Thu, Aug 11, 2011 at 03:27:26PM +0530, J, KEERTHY wrote:
> On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > (why aren't below in Cc ?
> 
> I will add them.
> 
> >
> > HARDWARE MONITORING
> > M:      Jean Delvare <khali@linux-fr.org>
> > M:      Guenter Roeck <guenter.roeck@ericsson.com>
> > L:      lm-sensors@lm-sensors.org
> > W:      http://www.lm-sensors.org/
> > T:      quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
> > T:      git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
> > S:      Maintained
> > F:      Documentation/hwmon/
> > F:      drivers/hwmon/
> > F:      include/linux/hwmon*.h)
> >
> > On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
> >> On chip temperature sensor driver. The driver monitors the temperature of
> >> the MPU subsystem of the OMAP4. It sends notifications to the user space if
> >> the temperature crosses user defined thresholds via kobject_uevent interface.
> >> The user is allowed to configure the temperature thresholds vis sysfs nodes
> >> exposed using hwmon interface.
> >>
> >> Signed-off-by: Keerthy <j-keerthy@ti.com>
> >> ---
> >>  drivers/hwmon/Kconfig            |   11 +
> >>  drivers/hwmon/Makefile           |    1 +
> >>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
> >>  3 files changed, 962 insertions(+), 0 deletions(-)
> >>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
> >>
> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> >> index 5f888f7..9c9cd8b 100644
> >> --- a/drivers/hwmon/Kconfig
> >> +++ b/drivers/hwmon/Kconfig
> >> @@ -323,6 +323,17 @@ config SENSORS_F71805F
> >>         This driver can also be built as a module.  If so, the module
> >>         will be called f71805f.
> >>
> >> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
> >> +     bool "OMAP on-die temperature sensor hwmon driver"
> >> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
> >> +     help
> >> +       If you say yes here you get support for hardware
> >> +       monitoring features of the OMAP on die temperature
> >> +       sensor.
> >> +
> >> +       Continuous conversion programmable delay
> >> +       mode is used for temperature conversion.
> >> +
> >>  config SENSORS_F71882FG
> >>       tristate "Fintek F71882FG and compatibles"
> >>       help
> >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> >> index 28061cf..d0f89f5 100644
> >> --- a/drivers/hwmon/Makefile
> >> +++ b/drivers/hwmon/Makefile
> >> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
> >>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
> >>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
> >>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
> >> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
> >>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
> >>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
> >>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> new file mode 100644
> >> index 0000000..15e2559
> >> --- /dev/null
> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> @@ -0,0 +1,950 @@
> >> +/*
> >> + * OMAP4 Temperature sensor driver file
> >> + *
> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> +#include <linux/clk.h>
> >
> > why ??
> 
> Clock rate setting functions.

you shouldn't need in drivers.

> >> +#include <linux/io.h>
> >> +#include <linux/debugfs.h>
> >
> > why ??
> 
> It will be removed.
> 
> >
> >> +#include <linux/delay.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/init.h>
> >> +#include <plat/omap_device.h>
> >
> > why ??
> >
> 
> Context loss count

shouldn't use in drivers.

> >> +#include <linux/module.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/device.h>
> >> +#include <linux/jiffies.h>
> >> +#include <linux/hwmon.h>
> >> +#include <linux/hwmon-sysfs.h>
> >> +#include <linux/stddef.h>
> >> +#include <linux/sysfs.h>
> >> +#include <linux/err.h>
> >> +#include <linux/types.h>
> >> +#include <linux/mutex.h>
> >> +#include <linux/pm_runtime.h>
> >> +#include <plat/common.h>
> >
> > why ?
> 
> usleep_range function.

plat/common for usleep_range ?? usleep_range is defined in
<linux/delay.h>

> >> +#include <plat/temperature_sensor.h>
> >
> 
> It is the header file with the structure definitions
> used in the driver.

why don't you put in <linux/platform_data/....> ??

> >> +#include <mach/ctrl_module_core_44xx.h>
> >
> > why ?
> 
> It will be removed
> 
> >
> >> +#include <mach/gpio.h>
> >
> > linux/gpio.h for crying out loud... how many times Russell has to say
> > the exact same thing ??????
> >
> 
> It will be removed

oh, you don't even use any gpio ? Why do you blindly add so many headers
if you don't need them ???

> >> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
> >> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
> >> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
> >> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
> >> +#define OMAP_ADC_START_VALUE 530
> >> +#define OMAP_ADC_END_VALUE   923
> >> +
> >> +/*
> >> + * omap_temp_sensor structure
> >> + * @hwmon_dev - device pointer
> >> + * @clock - Clock pointer
> >> + * @registers - Pointer to structure with register offsets and bitfields
> >> + * @sensor_mutex - Mutex for sysfs, irq and PM
> >> + * @irq - MPU Irq number for thermal alert
> >> + * @phy_base - Physical base of the temp I/O
> >> + * @clk_rate - Holds current clock rate
> >> + * @temp_sensor_ctrl - temp sensor control register value
> >> + * @bg_ctrl - bandgap ctrl register value
> >> + * @bg_counter - bandgap counter value
> >> + * @bg_threshold - bandgap threshold register value
> >> + * @temp_sensor_tshut_threshold - bandgap tshut register value
> >> + * @is_efuse_valid - Flag to determine if efuse is valid or not
> >> + * @clk_on - Manages the current clock state
> >> + */
> >> +struct omap_temp_sensor {
> >> +     struct device           *hwmon_dev;
> >> +     struct clk              *clock;
> >> +     struct omap_temp_sensor_registers *registers;
> >> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
> >> +     unsigned int            irq;
> >> +     void __iomem            *phy_base;
> >> +     u32                     clk_rate;
> >> +     u32                     temp_sensor_ctrl;
> >> +     u32                     bg_ctrl;
> >> +     u32                     bg_counter;
> >> +     u32                     bg_threshold;
> >> +     u32                     temp_sensor_tshut_threshold;
> >> +     bool                    is_efuse_valid;
> >> +     bool                    clk_on;
> >> +};
> >> +
> >> +/*
> >> + * Temperature values in milli degree celsius
> >> + * ADC code values from 530 to 923
> >> + */
> >> +static int adc_to_temp[] = {
> >> +     -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
> >> +};
> >> +
> >> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
> >> +                                         *temp_sensor, u32 reg)
> >> +{
> >> +     return __raw_readl(temp_sensor->phy_base + reg);
> >> +}
> >> +
> >> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
> >> +                                 u32 val, u32 reg)
> >> +{
> >> +     __raw_writel(val, (temp_sensor->phy_base + reg));
> >> +}
> >> +
> >> +static int adc_to_temp_conversion(int adc_val)
> >> +{
> >> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
> >> +}
> >> +
> >> +static int temp_to_adc_conversion(long temp)
> >> +{
> >> +     int i;
> >> +
> >> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
> >> +             if (temp < adc_to_temp[i])
> >> +                     return OMAP_ADC_START_VALUE + i - 1;
> >> +
> >> +     return -EINVAL;
> >> +}
> >> +
> >> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
> >> +                                               *temp_sensor)
> >> +{
> >> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
> >> +
> >> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
> >> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
> >> +
> >> +     /* Configure the TALERT thresholds */
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
> >> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, temp,
> >> +             temp_sensor->registers->bgap_threshold);
> >> +
> >> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
> >> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
> >> +
> >> +     /* Configure the TSHUT thresholds */
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->thsut_threshold);
> >> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
> >> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, temp,
> >> +                     temp_sensor->registers->thsut_threshold);
> >> +}
> >> +
> >> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
> >> +                                            *temp_sensor, u32 counter)
> >> +{
> >> +     u32 val;
> >> +
> >> +     val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +     val &= ~(temp_sensor->registers->counter_mask);
> >> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, val,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +}
> >> +
> >> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
> >> +                                     bool enable)
> >> +{
> >> +     u32 val;
> >> +
> >> +     val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_mode_ctrl);
> >> +
> >> +     if (enable)
> >> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
> >> +     else
> >> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
> >> +
> >> +     omap_temp_sensor_writel(temp_sensor, val,
> >> +                     temp_sensor->registers->bgap_mode_ctrl);
> >> +}
> >> +
> >> +/* Sysfs hook functions */
> >> +
> >> +static ssize_t show_temp_max(struct device *dev,
> >> +                     struct device_attribute *devattr, char *buf)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     int temp;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
> >> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
> >> +
> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> +             dev_err(dev, "invalid value\n");
> >> +             goto out;
> >> +     }
> >> +     temp = adc_to_temp_conversion(temp);
> >> +
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +
> >> +     return snprintf(buf, 16, "%d\n", temp);
> >> +}
> >> +
> >> +static ssize_t set_temp_max(struct device *dev,
> >> +                         struct device_attribute *devattr,
> >> +                         const char *buf, size_t count)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     long                    val;
> >> +     u32                     reg_val, t_cold, t_hot, temp;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     if (strict_strtol(buf, 10, &val)) {
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     t_hot = temp_to_adc_conversion(val);
> >> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
> >> +             dev_err(dev, "invalid range\n");
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* obtain the T cold value */
> >> +     t_cold = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
> >> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
> >> +
> >> +     if (t_hot < t_cold) {
> >> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* write the new t_hot value */
> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
> >> +     reg_val |= (t_hot <<
> >> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +
> >> +     /* Read the current temperature */
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
> >> +
> >> +     /*
> >> +      * If user sets the HIGH threshold(t_hot) greater than the current
> >> +      * temperature(temp) unmask the HOT interrupts
> >> +      */
> >> +     if (t_hot > temp) {
> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +     }
> >> +
> >> +     /*
> >> +      * If current temperature is in-between the hot and cold thresholds,
> >> +      * Enable both masks.
> >> +      */
> >> +     if (temp > t_cold && temp < t_hot) {
> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                             OMAP4460_BGAP_CTRL_OFFSET);
> >> +     }
> >> +     /*
> >> +      * else no need to do anything since HW will immediately compare
> >> +      * the new threshold and generate interrupt accordingly
> >> +      */
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     return count;
> >> +}
> >> +
> >> +static ssize_t show_temp_max_hyst(struct device *dev,
> >> +             struct device_attribute *devattr, char *buf)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     u32                     temp;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +             temp_sensor->registers->bgap_threshold);
> >> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
> >> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
> >> +
> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> +             dev_err(dev, "invalid value\n");
> >> +             goto out;
> >> +     }
> >> +
> >> +     temp = adc_to_temp_conversion(temp);
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +
> >> +     return snprintf(buf, 16, "%d\n", temp);
> >> +}
> >> +
> >> +static ssize_t set_temp_max_hyst(struct device *dev,
> >> +                              struct device_attribute *devattr,
> >> +                              const char *buf, size_t count)
> >> +{
> >> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
> >> +     u32                             reg_val, t_hot, t_cold, temp;
> >> +     long                            val;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     if (strict_strtol(buf, 10, &val)) {
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     t_cold = temp_to_adc_conversion(val);
> >> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
> >> +             dev_err(dev, "invalid range");
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* obtain the T HOT value */
> >> +     t_hot = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
> >> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
> >> +
> >> +     if (t_cold > t_hot) {
> >> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* write the new t_cold value */
> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
> >> +     reg_val |= (t_cold <<
> >> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                     temp_sensor->registers->bgap_threshold);
> >> +
> >> +     /* Read the current temperature */
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +             temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
> >> +
> >> +     /*
> >> +      * If user sets the LOW threshold(t_cold) lower than the current
> >> +      * temperature(temp) unmask the COLD interrupts
> >> +      */
> >> +     if (t_cold < temp) {
> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                     temp_sensor->registers->bgap_mask_ctrl);
> >> +     }
> >> +
> >> +     /*
> >> +      * If current temperature is in-between the hot and cold thresholds,
> >> +      * Enable both masks.
> >> +      */
> >> +     if (temp < t_hot && temp > t_cold) {
> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                             temp_sensor->registers->bgap_mask_ctrl);
> >> +     }
> >> +
> >> +     /*
> >> +      * else no need to do anything since HW will immediately compare
> >> +      * the new threshold and generate interrupt accordingly
> >> +      */
> >> +
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     return count;
> >> +}
> >> +
> >> +static ssize_t show_update_rate(struct device *dev,
> >> +                     struct device_attribute *devattr, char *buf)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     u32                     temp = 0, ret = 0;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     if (!temp_sensor->clk_rate) {
> >> +             dev_err(dev, "clk_rate is NULL\n");
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +     temp = (temp & temp_sensor->registers->counter_mask) >>
> >> +                     __ffs(temp_sensor->registers->counter_mask);
> >
> >        temp &= ??
> >
> >> +     temp = temp * 1000 / (temp_sensor->clk_rate);
> >
> >        temp *= ??
> 
> Need to multiply the temp with 1000 before dividing.
> temp *= evaluates the RHS first and then multiplies LHS.

temp *= 1000;
temp /= clk_rate;

> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     if (!ret)
> >> +             return sprintf(buf, "%d\n", temp);
> >> +     else
> >> +             return ret;
> >> +}
> >> +
> >> +static ssize_t set_update_rate(struct device *dev,
> >> +                            struct device_attribute *devattr,
> >> +                            const char *buf, size_t count)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     u32                     reg_val;
> >> +     long                    val;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     if (strict_strtol(buf, 10, &val)) {
> >> +             count = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     val *= temp_sensor->clk_rate / 1000;
> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +
> >> +     reg_val &= ~(temp_sensor->registers->counter_mask);
> >> +     reg_val |= val;
> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
> >> +                     temp_sensor->registers->bgap_counter);
> >> +
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     return count;
> >> +}
> >> +
> >> +static int omap_temp_sensor_read_temp(struct device *dev,
> >> +                                   struct device_attribute *devattr,
> >> +                                   char *buf)
> >> +{
> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
> >> +     int                     temp, ret = 0;
> >> +
> >> +     mutex_lock(&temp_sensor->sensor_mutex);
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +             temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
> >> +
> >> +     if (!temp_sensor->is_efuse_valid)
> >> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
> >> +
> >> +     /* look up for temperature in the table and return the temperature */
> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
> >> +             dev_err(dev, "invalid adc code reported %d", temp);
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
> >> +
> >> +out:
> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
> >> +     if (!ret)
> >> +             return sprintf(buf, "%d\n", temp);
> >> +     else
> >> +             return ret;
> >> +}
> >> +
> >> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
> >> +                       NULL, 0);
> >> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
> >> +                       set_temp_max, 0);
> >> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
> >> +                       set_temp_max_hyst, 0);
> >> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
> >> +                       set_update_rate, 0);
> >> +
> >> +static struct attribute *omap_temp_sensor_attributes[] = {
> >> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
> >> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
> >> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
> >> +     &sensor_dev_attr_update_rate.dev_attr.attr,
> >> +     NULL
> >> +};
> >> +
> >> +static const struct attribute_group omap_temp_sensor_group = {
> >> +     .attrs = omap_temp_sensor_attributes,
> >> +};
> >> +
> >> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
> >> +{
> >> +     u32 ret = 0, temp;
> >> +
> >> +     if (temp_sensor->clk_on) {
> >> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
> >> +             goto out;
> >> +     }
> >> +
> >> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
> >> +     if (ret < 0) {
> >> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
> >> +     /* BGAP_TEMPSOFF should be reset to 0 */
> >> +     omap_temp_sensor_writel(temp_sensor, temp,
> >> +                             temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp_sensor->clk_on = 1;
> >
> > why isn't pm_runtime_get_sync() enough ??
> 
> This is the programming sequence indicated. BGAP_TEMPSOFF should be set
> to 0 to enable the temperature sensor.

why isn't this done as part of your runtime_resume() function ??

> >> +out:
> >> +     return ret;
> >> +}
> >> +
> >> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
> >> +{
> >> +     u32 temp, ret = 0;
> >> +     unsigned long timeout;
> >> +
> >> +     if (!temp_sensor->clk_on) {
> >> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
> >> +             goto out;
> >> +     }
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
> >> +
> >> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
> >> +     omap_temp_sensor_writel(temp_sensor, temp,
> >> +                     temp_sensor->registers->temp_sensor_ctrl);
> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_status);
> >> +     timeout = jiffies + msecs_to_jiffies(5);
> >> +
> >> +     /* wait till the clean stop bit is set or till the timeout exppires */
> >> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
> >> +             !(time_after(jiffies, timeout))) {
> >> +             temp = omap_temp_sensor_readl(temp_sensor,
> >> +                     temp_sensor->registers->bgap_status);
> >> +             usleep_range(500, 2000);
> >> +     }
> >> +
> >> +     if (time_after(jiffies, timeout))
> >> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
> >> +     /* Gate the clock */
> >> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
> >> +     if (ret < 0) {
> >> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +     temp_sensor->clk_on = 0;
> >> +out:
> >> +     return ret;
> >> +}

add a blank line here.

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-11 10:30         ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
@ 2011-08-11 11:13           ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 11:01 UTC (permalink / raw)
  To: balbi; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

On Thu, Aug 11, 2011 at 4:00 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 08:10:07AM +0530, J, KEERTHY wrote:
>> >> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>> >> index 6e6735f..8fd8e80 100644
>> >> --- a/arch/arm/plat-omap/Kconfig
>> >> +++ b/arch/arm/plat-omap/Kconfig
>> >> @@ -115,6 +115,18 @@ config OMAP_MCBSP
>> >>         Say Y here if you want support for the OMAP Multichannel
>> >>         Buffered Serial Port.
>> >>
>> >> +config OMAP_TEMP_SENSOR
>> >> +     bool "OMAP Temp Sensor Support"
>> >> +     depends on ARCH_OMAP
>> >> +     default n
>> >> +     help
>> >> +       Say Y here if you want support for the temp sensor
>> >> +       on OMAP4460.
>> >> +
>> >> +       This provides the temperature of the MPU
>> >> +       subsystem. Only one instance of on die temperature
>> >> +       sensor is present.
>> >
>> > if there's only one instance, why do you use
>> > omap_hwmod_for_each_by_class() ??
>>
>> In case of OMAP5 there are multiple instances. Hence using
>> omap_hwmod_for_each_by_class().
>
> that's not a reality yet, so why don't you leave it for when OMAP5 is
> around ?

Keeping it generic so that we need not change again. We are pretty
close to reality i guess. Why not keep it generic? Any specific reason
for not keeping this loop?

>
>> >> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> >> new file mode 100644
>> >> index 0000000..692ebdc
>> >> --- /dev/null
>> >> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> >> @@ -0,0 +1,87 @@
>> >> +/*
>> >> + * OMAP Temperature sensor header file
>> >> + *
>> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> >> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> >> +
>> >> +/* Offsets from the base of temperature sensor registers */
>> >> +
>> >> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
>> >> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
>> >> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
>> >> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
>> >> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
>> >> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
>> >> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
>> >> +
>> >> +struct omap_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     thsut_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;
>> >> +};
>> >
>> > I find it unnecessary to pass the register map to driver using
>> > platform_data.
>>
>> With multiple instances the register map to individual instances will change.
>> So passing it via platform_data.
>
> what will change is the base address, the offsets should remain the
> same.

The base address offsets and even bit fields seem to be differing across
different OMAP versions.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-11 11:13           ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 11:13 UTC (permalink / raw)
  To: balbi; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

On Thu, Aug 11, 2011 at 4:00 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 08:10:07AM +0530, J, KEERTHY wrote:
>> >> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>> >> index 6e6735f..8fd8e80 100644
>> >> --- a/arch/arm/plat-omap/Kconfig
>> >> +++ b/arch/arm/plat-omap/Kconfig
>> >> @@ -115,6 +115,18 @@ config OMAP_MCBSP
>> >>         Say Y here if you want support for the OMAP Multichannel
>> >>         Buffered Serial Port.
>> >>
>> >> +config OMAP_TEMP_SENSOR
>> >> +     bool "OMAP Temp Sensor Support"
>> >> +     depends on ARCH_OMAP
>> >> +     default n
>> >> +     help
>> >> +       Say Y here if you want support for the temp sensor
>> >> +       on OMAP4460.
>> >> +
>> >> +       This provides the temperature of the MPU
>> >> +       subsystem. Only one instance of on die temperature
>> >> +       sensor is present.
>> >
>> > if there's only one instance, why do you use
>> > omap_hwmod_for_each_by_class() ??
>>
>> In case of OMAP5 there are multiple instances. Hence using
>> omap_hwmod_for_each_by_class().
>
> that's not a reality yet, so why don't you leave it for when OMAP5 is
> around ?

Keeping it generic so that we need not change again. We are pretty
close to reality i guess. Why not keep it generic? Any specific reason
for not keeping this loop?

>
>> >> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> >> new file mode 100644
>> >> index 0000000..692ebdc
>> >> --- /dev/null
>> >> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> >> @@ -0,0 +1,87 @@
>> >> +/*
>> >> + * OMAP Temperature sensor header file
>> >> + *
>> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> >> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> >> +
>> >> +/* Offsets from the base of temperature sensor registers */
>> >> +
>> >> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
>> >> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
>> >> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
>> >> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
>> >> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
>> >> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
>> >> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
>> >> +
>> >> +struct omap_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     thsut_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;
>> >> +};
>> >
>> > I find it unnecessary to pass the register map to driver using
>> > platform_data.
>>
>> With multiple instances the register map to individual instances will change.
>> So passing it via platform_data.
>
> what will change is the base address, the offsets should remain the
> same.

The base address offsets and even bit fields seem to be differing across
different OMAP versions.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 10:36         ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
  (?)
@ 2011-08-11 13:00           ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 13:00 UTC (permalink / raw)
  To: balbi
  Cc: Russell King, b-cousson, Tony Lindgren, rnayak, lm-sensors,
	khali, vishwanath.bs, linux-omap, Linux ARM Kernel Mailing List,
	guenter.roeck

On Thu, Aug 11, 2011 at 4:06 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 03:27:26PM +0530, J, KEERTHY wrote:
>> On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
>> > Hi,
>> >
>> > (why aren't below in Cc ?
>>
>> I will add them.
>>
>> >
>> > HARDWARE MONITORING
>> > M:      Jean Delvare <khali@linux-fr.org>
>> > M:      Guenter Roeck <guenter.roeck@ericsson.com>
>> > L:      lm-sensors@lm-sensors.org
>> > W:      http://www.lm-sensors.org/
>> > T:      quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
>> > T:      git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
>> > S:      Maintained
>> > F:      Documentation/hwmon/
>> > F:      drivers/hwmon/
>> > F:      include/linux/hwmon*.h)
>> >
>> > On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
>> >> On chip temperature sensor driver. The driver monitors the temperature of
>> >> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>> >> the temperature crosses user defined thresholds via kobject_uevent interface.
>> >> The user is allowed to configure the temperature thresholds vis sysfs nodes
>> >> exposed using hwmon interface.
>> >>
>> >> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> >> ---
>> >>  drivers/hwmon/Kconfig            |   11 +
>> >>  drivers/hwmon/Makefile           |    1 +
>> >>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>> >>  3 files changed, 962 insertions(+), 0 deletions(-)
>> >>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>> >>
>> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> >> index 5f888f7..9c9cd8b 100644
>> >> --- a/drivers/hwmon/Kconfig
>> >> +++ b/drivers/hwmon/Kconfig
>> >> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>> >>         This driver can also be built as a module.  If so, the module
>> >>         will be called f71805f.
>> >>
>> >> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>> >> +     bool "OMAP on-die temperature sensor hwmon driver"
>> >> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>> >> +     help
>> >> +       If you say yes here you get support for hardware
>> >> +       monitoring features of the OMAP on die temperature
>> >> +       sensor.
>> >> +
>> >> +       Continuous conversion programmable delay
>> >> +       mode is used for temperature conversion.
>> >> +
>> >>  config SENSORS_F71882FG
>> >>       tristate "Fintek F71882FG and compatibles"
>> >>       help
>> >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> >> index 28061cf..d0f89f5 100644
>> >> --- a/drivers/hwmon/Makefile
>> >> +++ b/drivers/hwmon/Makefile
>> >> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>> >>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>> >>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>> >>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>> >> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>> >>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>> >>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>> >>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
>> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> >> new file mode 100644
>> >> index 0000000..15e2559
>> >> --- /dev/null
>> >> +++ b/drivers/hwmon/omap_temp_sensor.c
>> >> @@ -0,0 +1,950 @@
>> >> +/*
>> >> + * OMAP4 Temperature sensor driver file
>> >> + *
>> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> + * Author: J Keerthy <j-keerthy@ti.com>
>> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> >> +#include <linux/clk.h>
>> >
>> > why ??
>>
>> Clock rate setting functions.
>
> you shouldn't need in drivers.

It is a one time setting of the rate so keeping it in drivers.

>
>> >> +#include <linux/io.h>
>> >> +#include <linux/debugfs.h>
>> >
>> > why ??
>>
>> It will be removed.
>>
>> >
>> >> +#include <linux/delay.h>
>> >> +#include <linux/slab.h>
>> >> +#include <linux/platform_device.h>
>> >> +#include <linux/init.h>
>> >> +#include <plat/omap_device.h>
>> >
>> > why ??
>> >
>>
>> Context loss count
>
> shouldn't use in drivers.

I guess already mmc and display are using
omap_pm_get_dev_context_loss_count but are
populating this function in pdata as a function pointer.
I will add that code.

>
>> >> +#include <linux/module.h>
>> >> +#include <linux/kernel.h>
>> >> +#include <linux/device.h>
>> >> +#include <linux/jiffies.h>
>> >> +#include <linux/hwmon.h>
>> >> +#include <linux/hwmon-sysfs.h>
>> >> +#include <linux/stddef.h>
>> >> +#include <linux/sysfs.h>
>> >> +#include <linux/err.h>
>> >> +#include <linux/types.h>
>> >> +#include <linux/mutex.h>
>> >> +#include <linux/pm_runtime.h>
>> >> +#include <plat/common.h>
>> >
>> > why ?
>>
>> usleep_range function.
>
> plat/common for usleep_range ?? usleep_range is defined in
> <linux/delay.h>

Ok it was indirect inclusion. I got it.
I will change this.

>
>> >> +#include <plat/temperature_sensor.h>
>> >
>>
>> It is the header file with the structure definitions
>> used in the driver.
>
> why don't you put in <linux/platform_data/....> ??

I saw many omap specific header files in plat-omap/include/plat.
Any specific reason behind placing the header in linux/platform_data?

>
>> >> +#include <mach/ctrl_module_core_44xx.h>
>> >
>> > why ?
>>
>> It will be removed
>>
>> >
>> >> +#include <mach/gpio.h>
>> >
>> > linux/gpio.h for crying out loud... how many times Russell has to say
>> > the exact same thing ??????
>> >
>>
>> It will be removed
>
> oh, you don't even use any gpio ? Why do you blindly add so many headers
> if you don't need them ???

It is not required.

>
>> >> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
>> >> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
>> >> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
>> >> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
>> >> +#define OMAP_ADC_START_VALUE 530
>> >> +#define OMAP_ADC_END_VALUE   923
>> >> +
>> >> +/*
>> >> + * omap_temp_sensor structure
>> >> + * @hwmon_dev - device pointer
>> >> + * @clock - Clock pointer
>> >> + * @registers - Pointer to structure with register offsets and bitfields
>> >> + * @sensor_mutex - Mutex for sysfs, irq and PM
>> >> + * @irq - MPU Irq number for thermal alert
>> >> + * @phy_base - Physical base of the temp I/O
>> >> + * @clk_rate - Holds current clock rate
>> >> + * @temp_sensor_ctrl - temp sensor control register value
>> >> + * @bg_ctrl - bandgap ctrl register value
>> >> + * @bg_counter - bandgap counter value
>> >> + * @bg_threshold - bandgap threshold register value
>> >> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>> >> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>> >> + * @clk_on - Manages the current clock state
>> >> + */
>> >> +struct omap_temp_sensor {
>> >> +     struct device           *hwmon_dev;
>> >> +     struct clk              *clock;
>> >> +     struct omap_temp_sensor_registers *registers;
>> >> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
>> >> +     unsigned int            irq;
>> >> +     void __iomem            *phy_base;
>> >> +     u32                     clk_rate;
>> >> +     u32                     temp_sensor_ctrl;
>> >> +     u32                     bg_ctrl;
>> >> +     u32                     bg_counter;
>> >> +     u32                     bg_threshold;
>> >> +     u32                     temp_sensor_tshut_threshold;
>> >> +     bool                    is_efuse_valid;
>> >> +     bool                    clk_on;
>> >> +};
>> >> +
>> >> +/*
>> >> + * Temperature values in milli degree celsius
>> >> + * ADC code values from 530 to 923
>> >> + */
>> >> +static int adc_to_temp[] = {
>> >> +     -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
>> >> +};
>> >> +
>> >> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>> >> +                                         *temp_sensor, u32 reg)
>> >> +{
>> >> +     return __raw_readl(temp_sensor->phy_base + reg);
>> >> +}
>> >> +
>> >> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>> >> +                                 u32 val, u32 reg)
>> >> +{
>> >> +     __raw_writel(val, (temp_sensor->phy_base + reg));
>> >> +}
>> >> +
>> >> +static int adc_to_temp_conversion(int adc_val)
>> >> +{
>> >> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>> >> +}
>> >> +
>> >> +static int temp_to_adc_conversion(long temp)
>> >> +{
>> >> +     int i;
>> >> +
>> >> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>> >> +             if (temp < adc_to_temp[i])
>> >> +                     return OMAP_ADC_START_VALUE + i - 1;
>> >> +
>> >> +     return -EINVAL;
>> >> +}
>> >> +
>> >> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>> >> +                                               *temp_sensor)
>> >> +{
>> >> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>> >> +
>> >> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>> >> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>> >> +
>> >> +     /* Configure the TALERT thresholds */
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>> >> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, temp,
>> >> +             temp_sensor->registers->bgap_threshold);
>> >> +
>> >> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>> >> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>> >> +
>> >> +     /* Configure the TSHUT thresholds */
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->thsut_threshold);
>> >> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>> >> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, temp,
>> >> +                     temp_sensor->registers->thsut_threshold);
>> >> +}
>> >> +
>> >> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>> >> +                                            *temp_sensor, u32 counter)
>> >> +{
>> >> +     u32 val;
>> >> +
>> >> +     val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +     val &= ~(temp_sensor->registers->counter_mask);
>> >> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, val,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +}
>> >> +
>> >> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>> >> +                                     bool enable)
>> >> +{
>> >> +     u32 val;
>> >> +
>> >> +     val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_mode_ctrl);
>> >> +
>> >> +     if (enable)
>> >> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>> >> +     else
>> >> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
>> >> +
>> >> +     omap_temp_sensor_writel(temp_sensor, val,
>> >> +                     temp_sensor->registers->bgap_mode_ctrl);
>> >> +}
>> >> +
>> >> +/* Sysfs hook functions */
>> >> +
>> >> +static ssize_t show_temp_max(struct device *dev,
>> >> +                     struct device_attribute *devattr, char *buf)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     int temp;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
>> >> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
>> >> +
>> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> +             dev_err(dev, "invalid value\n");
>> >> +             goto out;
>> >> +     }
>> >> +     temp = adc_to_temp_conversion(temp);
>> >> +
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     return snprintf(buf, 16, "%d\n", temp);
>> >> +}
>> >> +
>> >> +static ssize_t set_temp_max(struct device *dev,
>> >> +                         struct device_attribute *devattr,
>> >> +                         const char *buf, size_t count)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     long                    val;
>> >> +     u32                     reg_val, t_cold, t_hot, temp;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     if (strict_strtol(buf, 10, &val)) {
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     t_hot = temp_to_adc_conversion(val);
>> >> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>> >> +             dev_err(dev, "invalid range\n");
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* obtain the T cold value */
>> >> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>> >> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
>> >> +
>> >> +     if (t_hot < t_cold) {
>> >> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* write the new t_hot value */
>> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>> >> +     reg_val |= (t_hot <<
>> >> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +
>> >> +     /* Read the current temperature */
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> >> +
>> >> +     /*
>> >> +      * If user sets the HIGH threshold(t_hot) greater than the current
>> >> +      * temperature(temp) unmask the HOT interrupts
>> >> +      */
>> >> +     if (t_hot > temp) {
>> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +     }
>> >> +
>> >> +     /*
>> >> +      * If current temperature is in-between the hot and cold thresholds,
>> >> +      * Enable both masks.
>> >> +      */
>> >> +     if (temp > t_cold && temp < t_hot) {
>> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                             OMAP4460_BGAP_CTRL_OFFSET);
>> >> +     }
>> >> +     /*
>> >> +      * else no need to do anything since HW will immediately compare
>> >> +      * the new threshold and generate interrupt accordingly
>> >> +      */
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     return count;
>> >> +}
>> >> +
>> >> +static ssize_t show_temp_max_hyst(struct device *dev,
>> >> +             struct device_attribute *devattr, char *buf)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     u32                     temp;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +             temp_sensor->registers->bgap_threshold);
>> >> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>> >> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
>> >> +
>> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> +             dev_err(dev, "invalid value\n");
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     temp = adc_to_temp_conversion(temp);
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     return snprintf(buf, 16, "%d\n", temp);
>> >> +}
>> >> +
>> >> +static ssize_t set_temp_max_hyst(struct device *dev,
>> >> +                              struct device_attribute *devattr,
>> >> +                              const char *buf, size_t count)
>> >> +{
>> >> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
>> >> +     u32                             reg_val, t_hot, t_cold, temp;
>> >> +     long                            val;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     if (strict_strtol(buf, 10, &val)) {
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     t_cold = temp_to_adc_conversion(val);
>> >> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>> >> +             dev_err(dev, "invalid range");
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* obtain the T HOT value */
>> >> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>> >> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
>> >> +
>> >> +     if (t_cold > t_hot) {
>> >> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* write the new t_cold value */
>> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>> >> +     reg_val |= (t_cold <<
>> >> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +
>> >> +     /* Read the current temperature */
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +             temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> >> +
>> >> +     /*
>> >> +      * If user sets the LOW threshold(t_cold) lower than the current
>> >> +      * temperature(temp) unmask the COLD interrupts
>> >> +      */
>> >> +     if (t_cold < temp) {
>> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                     temp_sensor->registers->bgap_mask_ctrl);
>> >> +     }
>> >> +
>> >> +     /*
>> >> +      * If current temperature is in-between the hot and cold thresholds,
>> >> +      * Enable both masks.
>> >> +      */
>> >> +     if (temp < t_hot && temp > t_cold) {
>> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +     }
>> >> +
>> >> +     /*
>> >> +      * else no need to do anything since HW will immediately compare
>> >> +      * the new threshold and generate interrupt accordingly
>> >> +      */
>> >> +
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     return count;
>> >> +}
>> >> +
>> >> +static ssize_t show_update_rate(struct device *dev,
>> >> +                     struct device_attribute *devattr, char *buf)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     u32                     temp = 0, ret = 0;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     if (!temp_sensor->clk_rate) {
>> >> +             dev_err(dev, "clk_rate is NULL\n");
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +     temp = (temp & temp_sensor->registers->counter_mask) >>
>> >> +                     __ffs(temp_sensor->registers->counter_mask);
>> >
>> >        temp &= ??
>> >
>> >> +     temp = temp * 1000 / (temp_sensor->clk_rate);
>> >
>> >        temp *= ??
>>
>> Need to multiply the temp with 1000 before dividing.
>> temp *= evaluates the RHS first and then multiplies LHS.
>
> temp *= 1000;
> temp /= clk_rate;
>

Different coding style. I preferred to do it in a single line.

>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     if (!ret)
>> >> +             return sprintf(buf, "%d\n", temp);
>> >> +     else
>> >> +             return ret;
>> >> +}
>> >> +
>> >> +static ssize_t set_update_rate(struct device *dev,
>> >> +                            struct device_attribute *devattr,
>> >> +                            const char *buf, size_t count)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     u32                     reg_val;
>> >> +     long                    val;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     if (strict_strtol(buf, 10, &val)) {
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     val *= temp_sensor->clk_rate / 1000;
>> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +
>> >> +     reg_val &= ~(temp_sensor->registers->counter_mask);
>> >> +     reg_val |= val;
>> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     return count;
>> >> +}
>> >> +
>> >> +static int omap_temp_sensor_read_temp(struct device *dev,
>> >> +                                   struct device_attribute *devattr,
>> >> +                                   char *buf)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     int                     temp, ret = 0;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +             temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
>> >> +
>> >> +     if (!temp_sensor->is_efuse_valid)
>> >> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
>> >> +
>> >> +     /* look up for temperature in the table and return the temperature */
>> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> +             dev_err(dev, "invalid adc code reported %d", temp);
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>> >> +
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     if (!ret)
>> >> +             return sprintf(buf, "%d\n", temp);
>> >> +     else
>> >> +             return ret;
>> >> +}
>> >> +
>> >> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>> >> +                       NULL, 0);
>> >> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>> >> +                       set_temp_max, 0);
>> >> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
>> >> +                       set_temp_max_hyst, 0);
>> >> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>> >> +                       set_update_rate, 0);
>> >> +
>> >> +static struct attribute *omap_temp_sensor_attributes[] = {
>> >> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
>> >> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
>> >> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>> >> +     &sensor_dev_attr_update_rate.dev_attr.attr,
>> >> +     NULL
>> >> +};
>> >> +
>> >> +static const struct attribute_group omap_temp_sensor_group = {
>> >> +     .attrs = omap_temp_sensor_attributes,
>> >> +};
>> >> +
>> >> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>> >> +{
>> >> +     u32 ret = 0, temp;
>> >> +
>> >> +     if (temp_sensor->clk_on) {
>> >> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>> >> +     if (ret < 0) {
>> >> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>> >> +     /* BGAP_TEMPSOFF should be reset to 0 */
>> >> +     omap_temp_sensor_writel(temp_sensor, temp,
>> >> +                             temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp_sensor->clk_on = 1;
>> >
>> > why isn't pm_runtime_get_sync() enough ??
>>
>> This is the programming sequence indicated. BGAP_TEMPSOFF should be set
>> to 0 to enable the temperature sensor.
>
> why isn't this done as part of your runtime_resume() function ??

Ok seems the best place.

>
>> >> +out:
>> >> +     return ret;
>> >> +}
>> >> +
>> >> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>> >> +{
>> >> +     u32 temp, ret = 0;
>> >> +     unsigned long timeout;
>> >> +
>> >> +     if (!temp_sensor->clk_on) {
>> >> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>> >> +             goto out;
>> >> +     }
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
>> >> +
>> >> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>> >> +     omap_temp_sensor_writel(temp_sensor, temp,
>> >> +                     temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_status);
>> >> +     timeout = jiffies + msecs_to_jiffies(5);
>> >> +
>> >> +     /* wait till the clean stop bit is set or till the timeout exppires */
>> >> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>> >> +             !(time_after(jiffies, timeout))) {
>> >> +             temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_status);
>> >> +             usleep_range(500, 2000);
>> >> +     }
>> >> +
>> >> +     if (time_after(jiffies, timeout))
>> >> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>> >> +     /* Gate the clock */
>> >> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>> >> +     if (ret < 0) {
>> >> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +     temp_sensor->clk_on = 0;
>> >> +out:
>> >> +     return ret;
>> >> +}
>
> add a blank line here.

Ok

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 13:00           ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 13:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 11, 2011 at 4:06 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 03:27:26PM +0530, J, KEERTHY wrote:
>> On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
>> > Hi,
>> >
>> > (why aren't below in Cc ?
>>
>> I will add them.
>>
>> >
>> > HARDWARE MONITORING
>> > M: ? ? ?Jean Delvare <khali@linux-fr.org>
>> > M: ? ? ?Guenter Roeck <guenter.roeck@ericsson.com>
>> > L: ? ? ?lm-sensors at lm-sensors.org
>> > W: ? ? ?http://www.lm-sensors.org/
>> > T: ? ? ?quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
>> > T: ? ? ?git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
>> > S: ? ? ?Maintained
>> > F: ? ? ?Documentation/hwmon/
>> > F: ? ? ?drivers/hwmon/
>> > F: ? ? ?include/linux/hwmon*.h)
>> >
>> > On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
>> >> On chip temperature sensor driver. The driver monitors the temperature of
>> >> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>> >> the temperature crosses user defined thresholds via kobject_uevent interface.
>> >> The user is allowed to configure the temperature thresholds vis sysfs nodes
>> >> exposed using hwmon interface.
>> >>
>> >> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> >> ---
>> >> ?drivers/hwmon/Kconfig ? ? ? ? ? ?| ? 11 +
>> >> ?drivers/hwmon/Makefile ? ? ? ? ? | ? ?1 +
>> >> ?drivers/hwmon/omap_temp_sensor.c | ?950 ++++++++++++++++++++++++++++++++++++++
>> >> ?3 files changed, 962 insertions(+), 0 deletions(-)
>> >> ?create mode 100644 drivers/hwmon/omap_temp_sensor.c
>> >>
>> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> >> index 5f888f7..9c9cd8b 100644
>> >> --- a/drivers/hwmon/Kconfig
>> >> +++ b/drivers/hwmon/Kconfig
>> >> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>> >> ? ? ? ? This driver can also be built as a module. ?If so, the module
>> >> ? ? ? ? will be called f71805f.
>> >>
>> >> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>> >> + ? ? bool "OMAP on-die temperature sensor hwmon driver"
>> >> + ? ? depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>> >> + ? ? help
>> >> + ? ? ? If you say yes here you get support for hardware
>> >> + ? ? ? monitoring features of the OMAP on die temperature
>> >> + ? ? ? sensor.
>> >> +
>> >> + ? ? ? Continuous conversion programmable delay
>> >> + ? ? ? mode is used for temperature conversion.
>> >> +
>> >> ?config SENSORS_F71882FG
>> >> ? ? ? tristate "Fintek F71882FG and compatibles"
>> >> ? ? ? help
>> >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> >> index 28061cf..d0f89f5 100644
>> >> --- a/drivers/hwmon/Makefile
>> >> +++ b/drivers/hwmon/Makefile
>> >> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639) ? ? ? += max6639.o
>> >> ?obj-$(CONFIG_SENSORS_MAX6642) ? ? ? ?+= max6642.o
>> >> ?obj-$(CONFIG_SENSORS_MAX6650) ? ? ? ?+= max6650.o
>> >> ?obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>> >> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR) ?+= omap_temp_sensor.o
>> >> ?obj-$(CONFIG_SENSORS_PC87360) ? ? ? ?+= pc87360.o
>> >> ?obj-$(CONFIG_SENSORS_PC87427) ? ? ? ?+= pc87427.o
>> >> ?obj-$(CONFIG_SENSORS_PCF8591) ? ? ? ?+= pcf8591.o
>> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> >> new file mode 100644
>> >> index 0000000..15e2559
>> >> --- /dev/null
>> >> +++ b/drivers/hwmon/omap_temp_sensor.c
>> >> @@ -0,0 +1,950 @@
>> >> +/*
>> >> + * OMAP4 Temperature sensor driver file
>> >> + *
>> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> + * Author: J Keerthy <j-keerthy@ti.com>
>> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> >> +#include <linux/clk.h>
>> >
>> > why ??
>>
>> Clock rate setting functions.
>
> you shouldn't need in drivers.

It is a one time setting of the rate so keeping it in drivers.

>
>> >> +#include <linux/io.h>
>> >> +#include <linux/debugfs.h>
>> >
>> > why ??
>>
>> It will be removed.
>>
>> >
>> >> +#include <linux/delay.h>
>> >> +#include <linux/slab.h>
>> >> +#include <linux/platform_device.h>
>> >> +#include <linux/init.h>
>> >> +#include <plat/omap_device.h>
>> >
>> > why ??
>> >
>>
>> Context loss count
>
> shouldn't use in drivers.

I guess already mmc and display are using
omap_pm_get_dev_context_loss_count but are
populating this function in pdata as a function pointer.
I will add that code.

>
>> >> +#include <linux/module.h>
>> >> +#include <linux/kernel.h>
>> >> +#include <linux/device.h>
>> >> +#include <linux/jiffies.h>
>> >> +#include <linux/hwmon.h>
>> >> +#include <linux/hwmon-sysfs.h>
>> >> +#include <linux/stddef.h>
>> >> +#include <linux/sysfs.h>
>> >> +#include <linux/err.h>
>> >> +#include <linux/types.h>
>> >> +#include <linux/mutex.h>
>> >> +#include <linux/pm_runtime.h>
>> >> +#include <plat/common.h>
>> >
>> > why ?
>>
>> usleep_range function.
>
> plat/common for usleep_range ?? usleep_range is defined in
> <linux/delay.h>

Ok it was indirect inclusion. I got it.
I will change this.

>
>> >> +#include <plat/temperature_sensor.h>
>> >
>>
>> It is the header file with the structure definitions
>> used in the driver.
>
> why don't you put in <linux/platform_data/....> ??

I saw many omap specific header files in plat-omap/include/plat.
Any specific reason behind placing the header in linux/platform_data?

>
>> >> +#include <mach/ctrl_module_core_44xx.h>
>> >
>> > why ?
>>
>> It will be removed
>>
>> >
>> >> +#include <mach/gpio.h>
>> >
>> > linux/gpio.h for crying out loud... how many times Russell has to say
>> > the exact same thing ??????
>> >
>>
>> It will be removed
>
> oh, you don't even use any gpio ? Why do you blindly add so many headers
> if you don't need them ???

It is not required.

>
>> >> +#define TSHUT_THRESHOLD_HOT ?122000 ?/* 122 deg C */
>> >> +#define TSHUT_THRESHOLD_COLD 100000 ?/* 100 deg C */
>> >> +#define BGAP_THRESHOLD_T_HOT 73000 ? /* 73 deg C */
>> >> +#define BGAP_THRESHOLD_T_COLD ? ? ? ?71000 ? /* 71 deg C */
>> >> +#define OMAP_ADC_START_VALUE 530
>> >> +#define OMAP_ADC_END_VALUE ? 923
>> >> +
>> >> +/*
>> >> + * omap_temp_sensor structure
>> >> + * @hwmon_dev - device pointer
>> >> + * @clock - Clock pointer
>> >> + * @registers - Pointer to structure with register offsets and bitfields
>> >> + * @sensor_mutex - Mutex for sysfs, irq and PM
>> >> + * @irq - MPU Irq number for thermal alert
>> >> + * @phy_base - Physical base of the temp I/O
>> >> + * @clk_rate - Holds current clock rate
>> >> + * @temp_sensor_ctrl - temp sensor control register value
>> >> + * @bg_ctrl - bandgap ctrl register value
>> >> + * @bg_counter - bandgap counter value
>> >> + * @bg_threshold - bandgap threshold register value
>> >> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>> >> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>> >> + * @clk_on - Manages the current clock state
>> >> + */
>> >> +struct omap_temp_sensor {
>> >> + ? ? struct device ? ? ? ? ? *hwmon_dev;
>> >> + ? ? struct clk ? ? ? ? ? ? ?*clock;
>> >> + ? ? struct omap_temp_sensor_registers *registers;
>> >> + ? ? struct mutex ? ? ? ? ? ?sensor_mutex; /* Mutex for sysfs, irq and PM */
>> >> + ? ? unsigned int ? ? ? ? ? ?irq;
>> >> + ? ? void __iomem ? ? ? ? ? ?*phy_base;
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? clk_rate;
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp_sensor_ctrl;
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_ctrl;
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_counter;
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? bg_threshold;
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp_sensor_tshut_threshold;
>> >> + ? ? bool ? ? ? ? ? ? ? ? ? ?is_efuse_valid;
>> >> + ? ? bool ? ? ? ? ? ? ? ? ? ?clk_on;
>> >> +};
>> >> +
>> >> +/*
>> >> + * Temperature values in milli degree celsius
>> >> + * ADC code values from 530 to 923
>> >> + */
>> >> +static int adc_to_temp[] = {
>> >> + ? ? -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
>> >> +};
>> >> +
>> >> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *temp_sensor, u32 reg)
>> >> +{
>> >> + ? ? return __raw_readl(temp_sensor->phy_base + reg);
>> >> +}
>> >> +
>> >> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? u32 val, u32 reg)
>> >> +{
>> >> + ? ? __raw_writel(val, (temp_sensor->phy_base + reg));
>> >> +}
>> >> +
>> >> +static int adc_to_temp_conversion(int adc_val)
>> >> +{
>> >> + ? ? return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>> >> +}
>> >> +
>> >> +static int temp_to_adc_conversion(long temp)
>> >> +{
>> >> + ? ? int i;
>> >> +
>> >> + ? ? for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>> >> + ? ? ? ? ? ? if (temp < adc_to_temp[i])
>> >> + ? ? ? ? ? ? ? ? ? ? return OMAP_ADC_START_VALUE + i - 1;
>> >> +
>> >> + ? ? return -EINVAL;
>> >> +}
>> >> +
>> >> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *temp_sensor)
>> >> +{
>> >> + ? ? u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>> >> +
>> >> + ? ? t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>> >> + ? ? t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>> >> +
>> >> + ? ? /* Configure the TALERT thresholds */
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> + ? ? temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>> >> + ? ? ? ? ? ? (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> >> + ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> +
>> >> + ? ? tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>> >> + ? ? tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>> >> +
>> >> + ? ? /* Configure the TSHUT thresholds */
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->thsut_threshold);
>> >> + ? ? temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>> >> + ? ? ? ? | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->thsut_threshold);
>> >> +}
>> >> +
>> >> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*temp_sensor, u32 counter)
>> >> +{
>> >> + ? ? u32 val;
>> >> +
>> >> + ? ? val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> >> + ? ? val &= ~(temp_sensor->registers->counter_mask);
>> >> + ? ? val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, val,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> >> +}
>> >> +
>> >> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bool enable)
>> >> +{
>> >> + ? ? u32 val;
>> >> +
>> >> + ? ? val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mode_ctrl);
>> >> +
>> >> + ? ? if (enable)
>> >> + ? ? ? ? ? ? val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>> >> + ? ? else
>> >> + ? ? ? ? ? ? val &= ~(temp_sensor->registers->mode_ctrl_mask);
>> >> +
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, val,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mode_ctrl);
>> >> +}
>> >> +
>> >> +/* Sysfs hook functions */
>> >> +
>> >> +static ssize_t show_temp_max(struct device *dev,
>> >> + ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
>> >> +{
>> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> + ? ? int temp;
>> >> +
>> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> + ? ? temp = (temp & temp_sensor->registers->threshold_thot_mask)
>> >> + ? ? ? ? ? ? ? ? ? ? >> __ffs(temp_sensor->registers->threshold_thot_mask);
>> >> +
>> >> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> + ? ? ? ? ? ? dev_err(dev, "invalid value\n");
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> + ? ? temp = adc_to_temp_conversion(temp);
>> >> +
>> >> +out:
>> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? return snprintf(buf, 16, "%d\n", temp);
>> >> +}
>> >> +
>> >> +static ssize_t set_temp_max(struct device *dev,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? const char *buf, size_t count)
>> >> +{
>> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> + ? ? long ? ? ? ? ? ? ? ? ? ?val;
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? reg_val, t_cold, t_hot, temp;
>> >> +
>> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? if (strict_strtol(buf, 10, &val)) {
>> >> + ? ? ? ? ? ? count = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? t_hot = temp_to_adc_conversion(val);
>> >> + ? ? if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>> >> + ? ? ? ? ? ? dev_err(dev, "invalid range\n");
>> >> + ? ? ? ? ? ? count = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? /* obtain the T cold value */
>> >> + ? ? t_cold = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> + ? ? t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask);
>> >> +
>> >> + ? ? if (t_hot < t_cold) {
>> >> + ? ? ? ? ? ? dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>> >> + ? ? ? ? ? ? count = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? /* write the new t_hot value */
>> >> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> + ? ? reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>> >> + ? ? reg_val |= (t_hot <<
>> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_thot_mask));
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> +
>> >> + ? ? /* Read the current temperature */
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> >> + ? ? temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> >> +
>> >> + ? ? /*
>> >> + ? ? ?* If user sets the HIGH threshold(t_hot) greater than the current
>> >> + ? ? ?* temperature(temp) unmask the HOT interrupts
>> >> + ? ? ?*/
>> >> + ? ? if (t_hot > temp) {
>> >> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> >> + ? ? ? ? ? ? reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> >> + ? ? }
>> >> +
>> >> + ? ? /*
>> >> + ? ? ?* If current temperature is in-between the hot and cold thresholds,
>> >> + ? ? ?* Enable both masks.
>> >> + ? ? ?*/
>> >> + ? ? if (temp > t_cold && temp < t_hot) {
>> >> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4460_BGAP_CTRL_OFFSET);
>> >> + ? ? }
>> >> + ? ? /*
>> >> + ? ? ?* else no need to do anything since HW will immediately compare
>> >> + ? ? ?* the new threshold and generate interrupt accordingly
>> >> + ? ? ?*/
>> >> +out:
>> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> >> + ? ? return count;
>> >> +}
>> >> +
>> >> +static ssize_t show_temp_max_hyst(struct device *dev,
>> >> + ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
>> >> +{
>> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp;
>> >> +
>> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> + ? ? temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>> >> + ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask);
>> >> +
>> >> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> + ? ? ? ? ? ? dev_err(dev, "invalid value\n");
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? temp = adc_to_temp_conversion(temp);
>> >> +out:
>> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? return snprintf(buf, 16, "%d\n", temp);
>> >> +}
>> >> +
>> >> +static ssize_t set_temp_max_hyst(struct device *dev,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct device_attribute *devattr,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *buf, size_t count)
>> >> +{
>> >> + ? ? struct omap_temp_sensor ? ? ? ? *temp_sensor = dev_get_drvdata(dev);
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? ? ? ? ? reg_val, t_hot, t_cold, temp;
>> >> + ? ? long ? ? ? ? ? ? ? ? ? ? ? ? ? ?val;
>> >> +
>> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? if (strict_strtol(buf, 10, &val)) {
>> >> + ? ? ? ? ? ? count = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? t_cold = temp_to_adc_conversion(val);
>> >> + ? ? if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>> >> + ? ? ? ? ? ? dev_err(dev, "invalid range");
>> >> + ? ? ? ? ? ? count = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? /* obtain the T HOT value */
>> >> + ? ? t_hot = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> + ? ? t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_thot_mask);
>> >> +
>> >> + ? ? if (t_cold > t_hot) {
>> >> + ? ? ? ? ? ? dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>> >> + ? ? ? ? ? ? count = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? /* write the new t_cold value */
>> >> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> + ? ? reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>> >> + ? ? reg_val |= (t_cold <<
>> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->threshold_tcold_mask));
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_threshold);
>> >> +
>> >> + ? ? /* Read the current temperature */
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> >> + ? ? temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> >> +
>> >> + ? ? /*
>> >> + ? ? ?* If user sets the LOW threshold(t_cold) lower than the current
>> >> + ? ? ?* temperature(temp) unmask the COLD interrupts
>> >> + ? ? ?*/
>> >> + ? ? if (t_cold < temp) {
>> >> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> >> + ? ? ? ? ? ? reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> >> + ? ? }
>> >> +
>> >> + ? ? /*
>> >> + ? ? ?* If current temperature is in-between the hot and cold thresholds,
>> >> + ? ? ?* Enable both masks.
>> >> + ? ? ?*/
>> >> + ? ? if (temp < t_hot && temp > t_cold) {
>> >> + ? ? ? ? ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> + ? ? ? ? ? ? reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> + ? ? ? ? ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_mask_ctrl);
>> >> + ? ? }
>> >> +
>> >> + ? ? /*
>> >> + ? ? ?* else no need to do anything since HW will immediately compare
>> >> + ? ? ?* the new threshold and generate interrupt accordingly
>> >> + ? ? ?*/
>> >> +
>> >> +out:
>> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> >> + ? ? return count;
>> >> +}
>> >> +
>> >> +static ssize_t show_update_rate(struct device *dev,
>> >> + ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr, char *buf)
>> >> +{
>> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? temp = 0, ret = 0;
>> >> +
>> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? if (!temp_sensor->clk_rate) {
>> >> + ? ? ? ? ? ? dev_err(dev, "clk_rate is NULL\n");
>> >> + ? ? ? ? ? ? ret = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> >> + ? ? temp = (temp & temp_sensor->registers->counter_mask) >>
>> >> + ? ? ? ? ? ? ? ? ? ? __ffs(temp_sensor->registers->counter_mask);
>> >
>> > ? ? ? ?temp &= ??
>> >
>> >> + ? ? temp = temp * 1000 / (temp_sensor->clk_rate);
>> >
>> > ? ? ? ?temp *= ??
>>
>> Need to multiply the temp with 1000 before dividing.
>> temp *= evaluates the RHS first and then multiplies LHS.
>
> temp *= 1000;
> temp /= clk_rate;
>

Different coding style. I preferred to do it in a single line.

>> >> +out:
>> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> >> + ? ? if (!ret)
>> >> + ? ? ? ? ? ? return sprintf(buf, "%d\n", temp);
>> >> + ? ? else
>> >> + ? ? ? ? ? ? return ret;
>> >> +}
>> >> +
>> >> +static ssize_t set_update_rate(struct device *dev,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct device_attribute *devattr,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *buf, size_t count)
>> >> +{
>> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> + ? ? u32 ? ? ? ? ? ? ? ? ? ? reg_val;
>> >> + ? ? long ? ? ? ? ? ? ? ? ? ?val;
>> >> +
>> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? if (strict_strtol(buf, 10, &val)) {
>> >> + ? ? ? ? ? ? count = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? val *= temp_sensor->clk_rate / 1000;
>> >> + ? ? reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> >> +
>> >> + ? ? reg_val &= ~(temp_sensor->registers->counter_mask);
>> >> + ? ? reg_val |= val;
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_counter);
>> >> +
>> >> +out:
>> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> >> + ? ? return count;
>> >> +}
>> >> +
>> >> +static int omap_temp_sensor_read_temp(struct device *dev,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct device_attribute *devattr,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? char *buf)
>> >> +{
>> >> + ? ? struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> + ? ? int ? ? ? ? ? ? ? ? ? ? temp, ret = 0;
>> >> +
>> >> + ? ? mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> >> + ? ? temp &= temp_sensor->registers->bgap_dtemp_mask;
>> >> +
>> >> + ? ? if (!temp_sensor->is_efuse_valid)
>> >> + ? ? ? ? ? ? dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
>> >> +
>> >> + ? ? /* look up for temperature in the table and return the temperature */
>> >> + ? ? if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> + ? ? ? ? ? ? dev_err(dev, "invalid adc code reported %d", temp);
>> >> + ? ? ? ? ? ? ret = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>> >> +
>> >> +out:
>> >> + ? ? mutex_unlock(&temp_sensor->sensor_mutex);
>> >> + ? ? if (!ret)
>> >> + ? ? ? ? ? ? return sprintf(buf, "%d\n", temp);
>> >> + ? ? else
>> >> + ? ? ? ? ? ? return ret;
>> >> +}
>> >> +
>> >> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>> >> + ? ? ? ? ? ? ? ? ? ? ? NULL, 0);
>> >> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>> >> + ? ? ? ? ? ? ? ? ? ? ? set_temp_max, 0);
>> >> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
>> >> + ? ? ? ? ? ? ? ? ? ? ? set_temp_max_hyst, 0);
>> >> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>> >> + ? ? ? ? ? ? ? ? ? ? ? set_update_rate, 0);
>> >> +
>> >> +static struct attribute *omap_temp_sensor_attributes[] = {
>> >> + ? ? &sensor_dev_attr_temp1_input.dev_attr.attr,
>> >> + ? ? &sensor_dev_attr_temp1_max.dev_attr.attr,
>> >> + ? ? &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>> >> + ? ? &sensor_dev_attr_update_rate.dev_attr.attr,
>> >> + ? ? NULL
>> >> +};
>> >> +
>> >> +static const struct attribute_group omap_temp_sensor_group = {
>> >> + ? ? .attrs = omap_temp_sensor_attributes,
>> >> +};
>> >> +
>> >> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>> >> +{
>> >> + ? ? u32 ret = 0, temp;
>> >> +
>> >> + ? ? if (temp_sensor->clk_on) {
>> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>> >> + ? ? if (ret < 0) {
>> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>> >> + ? ? ? ? ? ? ret = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> +
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> >> + ? ? temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>> >> + ? ? /* BGAP_TEMPSOFF should be reset to 0 */
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> >> + ? ? temp_sensor->clk_on = 1;
>> >
>> > why isn't pm_runtime_get_sync() enough ??
>>
>> This is the programming sequence indicated. BGAP_TEMPSOFF should be set
>> to 0 to enable the temperature sensor.
>
> why isn't this done as part of your runtime_resume() function ??

Ok seems the best place.

>
>> >> +out:
>> >> + ? ? return ret;
>> >> +}
>> >> +
>> >> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>> >> +{
>> >> + ? ? u32 temp, ret = 0;
>> >> + ? ? unsigned long timeout;
>> >> +
>> >> + ? ? if (!temp_sensor->clk_on) {
>> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> >> + ? ? temp |= temp_sensor->registers->bgap_tempsoff_mask;
>> >> +
>> >> + ? ? /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>> >> + ? ? omap_temp_sensor_writel(temp_sensor, temp,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->temp_sensor_ctrl);
>> >> + ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_status);
>> >> + ? ? timeout = jiffies + msecs_to_jiffies(5);
>> >> +
>> >> + ? ? /* wait till the clean stop bit is set or till the timeout exppires */
>> >> + ? ? while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>> >> + ? ? ? ? ? ? !(time_after(jiffies, timeout))) {
>> >> + ? ? ? ? ? ? temp = omap_temp_sensor_readl(temp_sensor,
>> >> + ? ? ? ? ? ? ? ? ? ? temp_sensor->registers->bgap_status);
>> >> + ? ? ? ? ? ? usleep_range(500, 2000);
>> >> + ? ? }
>> >> +
>> >> + ? ? if (time_after(jiffies, timeout))
>> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>> >> + ? ? /* Gate the clock */
>> >> + ? ? ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>> >> + ? ? if (ret < 0) {
>> >> + ? ? ? ? ? ? dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>> >> + ? ? ? ? ? ? ret = -EINVAL;
>> >> + ? ? ? ? ? ? goto out;
>> >> + ? ? }
>> >> + ? ? temp_sensor->clk_on = 0;
>> >> +out:
>> >> + ? ? return ret;
>> >> +}
>
> add a blank line here.

Ok

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 13:00           ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 13:12 UTC (permalink / raw)
  To: balbi
  Cc: Russell King, b-cousson, Tony Lindgren, rnayak, lm-sensors,
	khali, vishwanath.bs, linux-omap, Linux ARM Kernel Mailing List,
	guenter.roeck

On Thu, Aug 11, 2011 at 4:06 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 03:27:26PM +0530, J, KEERTHY wrote:
>> On Wed, Aug 10, 2011 at 6:16 PM, Felipe Balbi <balbi@ti.com> wrote:
>> > Hi,
>> >
>> > (why aren't below in Cc ?
>>
>> I will add them.
>>
>> >
>> > HARDWARE MONITORING
>> > M:      Jean Delvare <khali@linux-fr.org>
>> > M:      Guenter Roeck <guenter.roeck@ericsson.com>
>> > L:      lm-sensors@lm-sensors.org
>> > W:      http://www.lm-sensors.org/
>> > T:      quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
>> > T:      git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
>> > S:      Maintained
>> > F:      Documentation/hwmon/
>> > F:      drivers/hwmon/
>> > F:      include/linux/hwmon*.h)
>> >
>> > On Wed, Aug 10, 2011 at 05:55:22PM +0530, Keerthy wrote:
>> >> On chip temperature sensor driver. The driver monitors the temperature of
>> >> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>> >> the temperature crosses user defined thresholds via kobject_uevent interface.
>> >> The user is allowed to configure the temperature thresholds vis sysfs nodes
>> >> exposed using hwmon interface.
>> >>
>> >> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> >> ---
>> >>  drivers/hwmon/Kconfig            |   11 +
>> >>  drivers/hwmon/Makefile           |    1 +
>> >>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>> >>  3 files changed, 962 insertions(+), 0 deletions(-)
>> >>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>> >>
>> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> >> index 5f888f7..9c9cd8b 100644
>> >> --- a/drivers/hwmon/Kconfig
>> >> +++ b/drivers/hwmon/Kconfig
>> >> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>> >>         This driver can also be built as a module.  If so, the module
>> >>         will be called f71805f.
>> >>
>> >> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>> >> +     bool "OMAP on-die temperature sensor hwmon driver"
>> >> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>> >> +     help
>> >> +       If you say yes here you get support for hardware
>> >> +       monitoring features of the OMAP on die temperature
>> >> +       sensor.
>> >> +
>> >> +       Continuous conversion programmable delay
>> >> +       mode is used for temperature conversion.
>> >> +
>> >>  config SENSORS_F71882FG
>> >>       tristate "Fintek F71882FG and compatibles"
>> >>       help
>> >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> >> index 28061cf..d0f89f5 100644
>> >> --- a/drivers/hwmon/Makefile
>> >> +++ b/drivers/hwmon/Makefile
>> >> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>> >>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>> >>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>> >>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>> >> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>> >>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>> >>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>> >>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
>> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> >> new file mode 100644
>> >> index 0000000..15e2559
>> >> --- /dev/null
>> >> +++ b/drivers/hwmon/omap_temp_sensor.c
>> >> @@ -0,0 +1,950 @@
>> >> +/*
>> >> + * OMAP4 Temperature sensor driver file
>> >> + *
>> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> + * Author: J Keerthy <j-keerthy@ti.com>
>> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> >> +#include <linux/clk.h>
>> >
>> > why ??
>>
>> Clock rate setting functions.
>
> you shouldn't need in drivers.

It is a one time setting of the rate so keeping it in drivers.

>
>> >> +#include <linux/io.h>
>> >> +#include <linux/debugfs.h>
>> >
>> > why ??
>>
>> It will be removed.
>>
>> >
>> >> +#include <linux/delay.h>
>> >> +#include <linux/slab.h>
>> >> +#include <linux/platform_device.h>
>> >> +#include <linux/init.h>
>> >> +#include <plat/omap_device.h>
>> >
>> > why ??
>> >
>>
>> Context loss count
>
> shouldn't use in drivers.

I guess already mmc and display are using
omap_pm_get_dev_context_loss_count but are
populating this function in pdata as a function pointer.
I will add that code.

>
>> >> +#include <linux/module.h>
>> >> +#include <linux/kernel.h>
>> >> +#include <linux/device.h>
>> >> +#include <linux/jiffies.h>
>> >> +#include <linux/hwmon.h>
>> >> +#include <linux/hwmon-sysfs.h>
>> >> +#include <linux/stddef.h>
>> >> +#include <linux/sysfs.h>
>> >> +#include <linux/err.h>
>> >> +#include <linux/types.h>
>> >> +#include <linux/mutex.h>
>> >> +#include <linux/pm_runtime.h>
>> >> +#include <plat/common.h>
>> >
>> > why ?
>>
>> usleep_range function.
>
> plat/common for usleep_range ?? usleep_range is defined in
> <linux/delay.h>

Ok it was indirect inclusion. I got it.
I will change this.

>
>> >> +#include <plat/temperature_sensor.h>
>> >
>>
>> It is the header file with the structure definitions
>> used in the driver.
>
> why don't you put in <linux/platform_data/....> ??

I saw many omap specific header files in plat-omap/include/plat.
Any specific reason behind placing the header in linux/platform_data?

>
>> >> +#include <mach/ctrl_module_core_44xx.h>
>> >
>> > why ?
>>
>> It will be removed
>>
>> >
>> >> +#include <mach/gpio.h>
>> >
>> > linux/gpio.h for crying out loud... how many times Russell has to say
>> > the exact same thing ??????
>> >
>>
>> It will be removed
>
> oh, you don't even use any gpio ? Why do you blindly add so many headers
> if you don't need them ???

It is not required.

>
>> >> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
>> >> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
>> >> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
>> >> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
>> >> +#define OMAP_ADC_START_VALUE 530
>> >> +#define OMAP_ADC_END_VALUE   923
>> >> +
>> >> +/*
>> >> + * omap_temp_sensor structure
>> >> + * @hwmon_dev - device pointer
>> >> + * @clock - Clock pointer
>> >> + * @registers - Pointer to structure with register offsets and bitfields
>> >> + * @sensor_mutex - Mutex for sysfs, irq and PM
>> >> + * @irq - MPU Irq number for thermal alert
>> >> + * @phy_base - Physical base of the temp I/O
>> >> + * @clk_rate - Holds current clock rate
>> >> + * @temp_sensor_ctrl - temp sensor control register value
>> >> + * @bg_ctrl - bandgap ctrl register value
>> >> + * @bg_counter - bandgap counter value
>> >> + * @bg_threshold - bandgap threshold register value
>> >> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>> >> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>> >> + * @clk_on - Manages the current clock state
>> >> + */
>> >> +struct omap_temp_sensor {
>> >> +     struct device           *hwmon_dev;
>> >> +     struct clk              *clock;
>> >> +     struct omap_temp_sensor_registers *registers;
>> >> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
>> >> +     unsigned int            irq;
>> >> +     void __iomem            *phy_base;
>> >> +     u32                     clk_rate;
>> >> +     u32                     temp_sensor_ctrl;
>> >> +     u32                     bg_ctrl;
>> >> +     u32                     bg_counter;
>> >> +     u32                     bg_threshold;
>> >> +     u32                     temp_sensor_tshut_threshold;
>> >> +     bool                    is_efuse_valid;
>> >> +     bool                    clk_on;
>> >> +};
>> >> +
>> >> +/*
>> >> + * Temperature values in milli degree celsius
>> >> + * ADC code values from 530 to 923
>> >> + */
>> >> +static int adc_to_temp[] = {
>> >> +     -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
>> >> +};
>> >> +
>> >> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>> >> +                                         *temp_sensor, u32 reg)
>> >> +{
>> >> +     return __raw_readl(temp_sensor->phy_base + reg);
>> >> +}
>> >> +
>> >> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>> >> +                                 u32 val, u32 reg)
>> >> +{
>> >> +     __raw_writel(val, (temp_sensor->phy_base + reg));
>> >> +}
>> >> +
>> >> +static int adc_to_temp_conversion(int adc_val)
>> >> +{
>> >> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>> >> +}
>> >> +
>> >> +static int temp_to_adc_conversion(long temp)
>> >> +{
>> >> +     int i;
>> >> +
>> >> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>> >> +             if (temp < adc_to_temp[i])
>> >> +                     return OMAP_ADC_START_VALUE + i - 1;
>> >> +
>> >> +     return -EINVAL;
>> >> +}
>> >> +
>> >> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>> >> +                                               *temp_sensor)
>> >> +{
>> >> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>> >> +
>> >> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>> >> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>> >> +
>> >> +     /* Configure the TALERT thresholds */
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>> >> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, temp,
>> >> +             temp_sensor->registers->bgap_threshold);
>> >> +
>> >> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>> >> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>> >> +
>> >> +     /* Configure the TSHUT thresholds */
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->thsut_threshold);
>> >> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>> >> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, temp,
>> >> +                     temp_sensor->registers->thsut_threshold);
>> >> +}
>> >> +
>> >> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>> >> +                                            *temp_sensor, u32 counter)
>> >> +{
>> >> +     u32 val;
>> >> +
>> >> +     val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +     val &= ~(temp_sensor->registers->counter_mask);
>> >> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, val,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +}
>> >> +
>> >> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>> >> +                                     bool enable)
>> >> +{
>> >> +     u32 val;
>> >> +
>> >> +     val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_mode_ctrl);
>> >> +
>> >> +     if (enable)
>> >> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>> >> +     else
>> >> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
>> >> +
>> >> +     omap_temp_sensor_writel(temp_sensor, val,
>> >> +                     temp_sensor->registers->bgap_mode_ctrl);
>> >> +}
>> >> +
>> >> +/* Sysfs hook functions */
>> >> +
>> >> +static ssize_t show_temp_max(struct device *dev,
>> >> +                     struct device_attribute *devattr, char *buf)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     int temp;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
>> >> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
>> >> +
>> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> +             dev_err(dev, "invalid value\n");
>> >> +             goto out;
>> >> +     }
>> >> +     temp = adc_to_temp_conversion(temp);
>> >> +
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     return snprintf(buf, 16, "%d\n", temp);
>> >> +}
>> >> +
>> >> +static ssize_t set_temp_max(struct device *dev,
>> >> +                         struct device_attribute *devattr,
>> >> +                         const char *buf, size_t count)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     long                    val;
>> >> +     u32                     reg_val, t_cold, t_hot, temp;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     if (strict_strtol(buf, 10, &val)) {
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     t_hot = temp_to_adc_conversion(val);
>> >> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>> >> +             dev_err(dev, "invalid range\n");
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* obtain the T cold value */
>> >> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>> >> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
>> >> +
>> >> +     if (t_hot < t_cold) {
>> >> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* write the new t_hot value */
>> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>> >> +     reg_val |= (t_hot <<
>> >> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +
>> >> +     /* Read the current temperature */
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> >> +
>> >> +     /*
>> >> +      * If user sets the HIGH threshold(t_hot) greater than the current
>> >> +      * temperature(temp) unmask the HOT interrupts
>> >> +      */
>> >> +     if (t_hot > temp) {
>> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +     }
>> >> +
>> >> +     /*
>> >> +      * If current temperature is in-between the hot and cold thresholds,
>> >> +      * Enable both masks.
>> >> +      */
>> >> +     if (temp > t_cold && temp < t_hot) {
>> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                             OMAP4460_BGAP_CTRL_OFFSET);
>> >> +     }
>> >> +     /*
>> >> +      * else no need to do anything since HW will immediately compare
>> >> +      * the new threshold and generate interrupt accordingly
>> >> +      */
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     return count;
>> >> +}
>> >> +
>> >> +static ssize_t show_temp_max_hyst(struct device *dev,
>> >> +             struct device_attribute *devattr, char *buf)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     u32                     temp;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +             temp_sensor->registers->bgap_threshold);
>> >> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>> >> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
>> >> +
>> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> +             dev_err(dev, "invalid value\n");
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     temp = adc_to_temp_conversion(temp);
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     return snprintf(buf, 16, "%d\n", temp);
>> >> +}
>> >> +
>> >> +static ssize_t set_temp_max_hyst(struct device *dev,
>> >> +                              struct device_attribute *devattr,
>> >> +                              const char *buf, size_t count)
>> >> +{
>> >> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
>> >> +     u32                             reg_val, t_hot, t_cold, temp;
>> >> +     long                            val;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     if (strict_strtol(buf, 10, &val)) {
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     t_cold = temp_to_adc_conversion(val);
>> >> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>> >> +             dev_err(dev, "invalid range");
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* obtain the T HOT value */
>> >> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>> >> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
>> >> +
>> >> +     if (t_cold > t_hot) {
>> >> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* write the new t_cold value */
>> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>> >> +     reg_val |= (t_cold <<
>> >> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
>> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                     temp_sensor->registers->bgap_threshold);
>> >> +
>> >> +     /* Read the current temperature */
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +             temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> >> +
>> >> +     /*
>> >> +      * If user sets the LOW threshold(t_cold) lower than the current
>> >> +      * temperature(temp) unmask the COLD interrupts
>> >> +      */
>> >> +     if (t_cold < temp) {
>> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                     temp_sensor->registers->bgap_mask_ctrl);
>> >> +     }
>> >> +
>> >> +     /*
>> >> +      * If current temperature is in-between the hot and cold thresholds,
>> >> +      * Enable both masks.
>> >> +      */
>> >> +     if (temp < t_hot && temp > t_cold) {
>> >> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> >> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> >> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                             temp_sensor->registers->bgap_mask_ctrl);
>> >> +     }
>> >> +
>> >> +     /*
>> >> +      * else no need to do anything since HW will immediately compare
>> >> +      * the new threshold and generate interrupt accordingly
>> >> +      */
>> >> +
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     return count;
>> >> +}
>> >> +
>> >> +static ssize_t show_update_rate(struct device *dev,
>> >> +                     struct device_attribute *devattr, char *buf)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     u32                     temp = 0, ret = 0;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     if (!temp_sensor->clk_rate) {
>> >> +             dev_err(dev, "clk_rate is NULL\n");
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +     temp = (temp & temp_sensor->registers->counter_mask) >>
>> >> +                     __ffs(temp_sensor->registers->counter_mask);
>> >
>> >        temp &= ??
>> >
>> >> +     temp = temp * 1000 / (temp_sensor->clk_rate);
>> >
>> >        temp *= ??
>>
>> Need to multiply the temp with 1000 before dividing.
>> temp *= evaluates the RHS first and then multiplies LHS.
>
> temp *= 1000;
> temp /= clk_rate;
>

Different coding style. I preferred to do it in a single line.

>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     if (!ret)
>> >> +             return sprintf(buf, "%d\n", temp);
>> >> +     else
>> >> +             return ret;
>> >> +}
>> >> +
>> >> +static ssize_t set_update_rate(struct device *dev,
>> >> +                            struct device_attribute *devattr,
>> >> +                            const char *buf, size_t count)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     u32                     reg_val;
>> >> +     long                    val;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     if (strict_strtol(buf, 10, &val)) {
>> >> +             count = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     val *= temp_sensor->clk_rate / 1000;
>> >> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +
>> >> +     reg_val &= ~(temp_sensor->registers->counter_mask);
>> >> +     reg_val |= val;
>> >> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> >> +                     temp_sensor->registers->bgap_counter);
>> >> +
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     return count;
>> >> +}
>> >> +
>> >> +static int omap_temp_sensor_read_temp(struct device *dev,
>> >> +                                   struct device_attribute *devattr,
>> >> +                                   char *buf)
>> >> +{
>> >> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> >> +     int                     temp, ret = 0;
>> >> +
>> >> +     mutex_lock(&temp_sensor->sensor_mutex);
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +             temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
>> >> +
>> >> +     if (!temp_sensor->is_efuse_valid)
>> >> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not accurate\n");
>> >> +
>> >> +     /* look up for temperature in the table and return the temperature */
>> >> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> >> +             dev_err(dev, "invalid adc code reported %d", temp);
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>> >> +
>> >> +out:
>> >> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> >> +     if (!ret)
>> >> +             return sprintf(buf, "%d\n", temp);
>> >> +     else
>> >> +             return ret;
>> >> +}
>> >> +
>> >> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>> >> +                       NULL, 0);
>> >> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>> >> +                       set_temp_max, 0);
>> >> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
>> >> +                       set_temp_max_hyst, 0);
>> >> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>> >> +                       set_update_rate, 0);
>> >> +
>> >> +static struct attribute *omap_temp_sensor_attributes[] = {
>> >> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
>> >> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
>> >> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>> >> +     &sensor_dev_attr_update_rate.dev_attr.attr,
>> >> +     NULL
>> >> +};
>> >> +
>> >> +static const struct attribute_group omap_temp_sensor_group = {
>> >> +     .attrs = omap_temp_sensor_attributes,
>> >> +};
>> >> +
>> >> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>> >> +{
>> >> +     u32 ret = 0, temp;
>> >> +
>> >> +     if (temp_sensor->clk_on) {
>> >> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>> >> +     if (ret < 0) {
>> >> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>> >> +     /* BGAP_TEMPSOFF should be reset to 0 */
>> >> +     omap_temp_sensor_writel(temp_sensor, temp,
>> >> +                             temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp_sensor->clk_on = 1;
>> >
>> > why isn't pm_runtime_get_sync() enough ??
>>
>> This is the programming sequence indicated. BGAP_TEMPSOFF should be set
>> to 0 to enable the temperature sensor.
>
> why isn't this done as part of your runtime_resume() function ??

Ok seems the best place.

>
>> >> +out:
>> >> +     return ret;
>> >> +}
>> >> +
>> >> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>> >> +{
>> >> +     u32 temp, ret = 0;
>> >> +     unsigned long timeout;
>> >> +
>> >> +     if (!temp_sensor->clk_on) {
>> >> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>> >> +             goto out;
>> >> +     }
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
>> >> +
>> >> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>> >> +     omap_temp_sensor_writel(temp_sensor, temp,
>> >> +                     temp_sensor->registers->temp_sensor_ctrl);
>> >> +     temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_status);
>> >> +     timeout = jiffies + msecs_to_jiffies(5);
>> >> +
>> >> +     /* wait till the clean stop bit is set or till the timeout exppires */
>> >> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>> >> +             !(time_after(jiffies, timeout))) {
>> >> +             temp = omap_temp_sensor_readl(temp_sensor,
>> >> +                     temp_sensor->registers->bgap_status);
>> >> +             usleep_range(500, 2000);
>> >> +     }
>> >> +
>> >> +     if (time_after(jiffies, timeout))
>> >> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>> >> +     /* Gate the clock */
>> >> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>> >> +     if (ret < 0) {
>> >> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +     temp_sensor->clk_on = 0;
>> >> +out:
>> >> +     return ret;
>> >> +}
>
> add a blank line here.

Ok

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-11 11:13           ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device J, KEERTHY
@ 2011-08-11 14:05             ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 14:05 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: balbi, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

[-- Attachment #1: Type: text/plain, Size: 5373 bytes --]

Hi,

On Thu, Aug 11, 2011 at 04:31:50PM +0530, J, KEERTHY wrote:
> On Thu, Aug 11, 2011 at 4:00 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > On Thu, Aug 11, 2011 at 08:10:07AM +0530, J, KEERTHY wrote:
> >> >> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> >> >> index 6e6735f..8fd8e80 100644
> >> >> --- a/arch/arm/plat-omap/Kconfig
> >> >> +++ b/arch/arm/plat-omap/Kconfig
> >> >> @@ -115,6 +115,18 @@ config OMAP_MCBSP
> >> >>         Say Y here if you want support for the OMAP Multichannel
> >> >>         Buffered Serial Port.
> >> >>
> >> >> +config OMAP_TEMP_SENSOR
> >> >> +     bool "OMAP Temp Sensor Support"
> >> >> +     depends on ARCH_OMAP
> >> >> +     default n
> >> >> +     help
> >> >> +       Say Y here if you want support for the temp sensor
> >> >> +       on OMAP4460.
> >> >> +
> >> >> +       This provides the temperature of the MPU
> >> >> +       subsystem. Only one instance of on die temperature
> >> >> +       sensor is present.
> >> >
> >> > if there's only one instance, why do you use
> >> > omap_hwmod_for_each_by_class() ??
> >>
> >> In case of OMAP5 there are multiple instances. Hence using
> >> omap_hwmod_for_each_by_class().
> >
> > that's not a reality yet, so why don't you leave it for when OMAP5 is
> > around ?
> 
> Keeping it generic so that we need not change again. We are pretty
> close to reality i guess. Why not keep it generic? Any specific reason
> for not keeping this loop?

Other than the loop being completely unnecessary on the only OMAP
version you're supporting ? no... not really.

> >> >> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> >> >> new file mode 100644
> >> >> index 0000000..692ebdc
> >> >> --- /dev/null
> >> >> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> >> >> @@ -0,0 +1,87 @@
> >> >> +/*
> >> >> + * OMAP Temperature sensor header file
> >> >> + *
> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> >> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> >> >> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> >> >> +
> >> >> +/* Offsets from the base of temperature sensor registers */
> >> >> +
> >> >> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
> >> >> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
> >> >> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
> >> >> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
> >> >> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
> >> >> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
> >> >> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
> >> >> +
> >> >> +struct omap_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     thsut_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;
> >> >> +};
> >> >
> >> > I find it unnecessary to pass the register map to driver using
> >> > platform_data.
> >>
> >> With multiple instances the register map to individual instances will change.
> >> So passing it via platform_data.
> >
> > what will change is the base address, the offsets should remain the
> > same.
> 
> The base address offsets and even bit fields seem to be differing across
> different OMAP versions.

then a comment making that clear is necessary. But as of today, you
support only one OMAP version, so I'm sure it's worth the trouble for a
first version of the driver.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-11 14:05             ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 14:05 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: balbi, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak


[-- Attachment #1.1: Type: text/plain, Size: 5373 bytes --]

Hi,

On Thu, Aug 11, 2011 at 04:31:50PM +0530, J, KEERTHY wrote:
> On Thu, Aug 11, 2011 at 4:00 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > On Thu, Aug 11, 2011 at 08:10:07AM +0530, J, KEERTHY wrote:
> >> >> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> >> >> index 6e6735f..8fd8e80 100644
> >> >> --- a/arch/arm/plat-omap/Kconfig
> >> >> +++ b/arch/arm/plat-omap/Kconfig
> >> >> @@ -115,6 +115,18 @@ config OMAP_MCBSP
> >> >>         Say Y here if you want support for the OMAP Multichannel
> >> >>         Buffered Serial Port.
> >> >>
> >> >> +config OMAP_TEMP_SENSOR
> >> >> +     bool "OMAP Temp Sensor Support"
> >> >> +     depends on ARCH_OMAP
> >> >> +     default n
> >> >> +     help
> >> >> +       Say Y here if you want support for the temp sensor
> >> >> +       on OMAP4460.
> >> >> +
> >> >> +       This provides the temperature of the MPU
> >> >> +       subsystem. Only one instance of on die temperature
> >> >> +       sensor is present.
> >> >
> >> > if there's only one instance, why do you use
> >> > omap_hwmod_for_each_by_class() ??
> >>
> >> In case of OMAP5 there are multiple instances. Hence using
> >> omap_hwmod_for_each_by_class().
> >
> > that's not a reality yet, so why don't you leave it for when OMAP5 is
> > around ?
> 
> Keeping it generic so that we need not change again. We are pretty
> close to reality i guess. Why not keep it generic? Any specific reason
> for not keeping this loop?

Other than the loop being completely unnecessary on the only OMAP
version you're supporting ? no... not really.

> >> >> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> >> >> new file mode 100644
> >> >> index 0000000..692ebdc
> >> >> --- /dev/null
> >> >> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
> >> >> @@ -0,0 +1,87 @@
> >> >> +/*
> >> >> + * OMAP Temperature sensor header file
> >> >> + *
> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> >> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> >> >> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
> >> >> +
> >> >> +/* Offsets from the base of temperature sensor registers */
> >> >> +
> >> >> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
> >> >> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
> >> >> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
> >> >> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
> >> >> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
> >> >> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
> >> >> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
> >> >> +
> >> >> +struct omap_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     thsut_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;
> >> >> +};
> >> >
> >> > I find it unnecessary to pass the register map to driver using
> >> > platform_data.
> >>
> >> With multiple instances the register map to individual instances will change.
> >> So passing it via platform_data.
> >
> > what will change is the base address, the offsets should remain the
> > same.
> 
> The base address offsets and even bit fields seem to be differing across
> different OMAP versions.

then a comment making that clear is necessary. But as of today, you
support only one OMAP version, so I'm sure it's worth the trouble for a
first version of the driver.

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 13:00           ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
  (?)
@ 2011-08-11 14:12             ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 14:12 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: balbi, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

[-- Attachment #1: Type: text/plain, Size: 3916 bytes --]

Hi,

On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> >> new file mode 100644
> >> >> index 0000000..15e2559
> >> >> --- /dev/null
> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> >> @@ -0,0 +1,950 @@
> >> >> +/*
> >> >> + * OMAP4 Temperature sensor driver file
> >> >> + *
> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> >> +#include <linux/clk.h>
> >> >
> >> > why ??
> >>
> >> Clock rate setting functions.
> >
> > you shouldn't need in drivers.
> 
> It is a one time setting of the rate so keeping it in drivers.

you need some other way to handle this. Why do you need to manually set
the rate rather than having hwmod handle this for you ?

your argument that "it's a one time setting" is not enough to have this
in the driver. Drivers should not care about clocks anymore, this should
have been done on another layer.

> >> >> +#include <linux/delay.h>
> >> >> +#include <linux/slab.h>
> >> >> +#include <linux/platform_device.h>
> >> >> +#include <linux/init.h>
> >> >> +#include <plat/omap_device.h>
> >> >
> >> > why ??
> >> >
> >>
> >> Context loss count
> >
> > shouldn't use in drivers.
> 
> I guess already mmc and display are using
> omap_pm_get_dev_context_loss_count but are
> populating this function in pdata as a function pointer.
> I will add that code.

at least ;-) better than accessing that function directly. But think
carefully how you will make this work when we move to DT.

> >> >> +#include <plat/temperature_sensor.h>
> >> >
> >>
> >> It is the header file with the structure definitions
> >> used in the driver.
> >
> > why don't you put in <linux/platform_data/....> ??
> 
> I saw many omap specific header files in plat-omap/include/plat.
> Any specific reason behind placing the header in linux/platform_data?

because it's not a good idea to perpetuate the failure.

> >> >> +#include <mach/ctrl_module_core_44xx.h>
> >> >
> >> > why ?
> >>
> >> It will be removed
> >>
> >> >
> >> >> +#include <mach/gpio.h>
> >> >
> >> > linux/gpio.h for crying out loud... how many times Russell has to say
> >> > the exact same thing ??????
> >> >
> >>
> >> It will be removed
> >
> > oh, you don't even use any gpio ? Why do you blindly add so many headers
> > if you don't need them ???
> 
> It is not required.

this is my point, be careful when adding new drivers... You're consuming
"review bandwidth" when you send code/patch/new-drivers and reviewers
are part of an endangered species. If you keep on making such silly
mistakes, you consume time from reviewers to let you know about things
which are obvious, to say the least. So be careful when sending code,
nobody is perfect, for sure, but by being careful you can help your code
being accepted earlier.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 14:12             ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 14:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> >> new file mode 100644
> >> >> index 0000000..15e2559
> >> >> --- /dev/null
> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> >> @@ -0,0 +1,950 @@
> >> >> +/*
> >> >> + * OMAP4 Temperature sensor driver file
> >> >> + *
> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> >> +#include <linux/clk.h>
> >> >
> >> > why ??
> >>
> >> Clock rate setting functions.
> >
> > you shouldn't need in drivers.
> 
> It is a one time setting of the rate so keeping it in drivers.

you need some other way to handle this. Why do you need to manually set
the rate rather than having hwmod handle this for you ?

your argument that "it's a one time setting" is not enough to have this
in the driver. Drivers should not care about clocks anymore, this should
have been done on another layer.

> >> >> +#include <linux/delay.h>
> >> >> +#include <linux/slab.h>
> >> >> +#include <linux/platform_device.h>
> >> >> +#include <linux/init.h>
> >> >> +#include <plat/omap_device.h>
> >> >
> >> > why ??
> >> >
> >>
> >> Context loss count
> >
> > shouldn't use in drivers.
> 
> I guess already mmc and display are using
> omap_pm_get_dev_context_loss_count but are
> populating this function in pdata as a function pointer.
> I will add that code.

at least ;-) better than accessing that function directly. But think
carefully how you will make this work when we move to DT.

> >> >> +#include <plat/temperature_sensor.h>
> >> >
> >>
> >> It is the header file with the structure definitions
> >> used in the driver.
> >
> > why don't you put in <linux/platform_data/....> ??
> 
> I saw many omap specific header files in plat-omap/include/plat.
> Any specific reason behind placing the header in linux/platform_data?

because it's not a good idea to perpetuate the failure.

> >> >> +#include <mach/ctrl_module_core_44xx.h>
> >> >
> >> > why ?
> >>
> >> It will be removed
> >>
> >> >
> >> >> +#include <mach/gpio.h>
> >> >
> >> > linux/gpio.h for crying out loud... how many times Russell has to say
> >> > the exact same thing ??????
> >> >
> >>
> >> It will be removed
> >
> > oh, you don't even use any gpio ? Why do you blindly add so many headers
> > if you don't need them ???
> 
> It is not required.

this is my point, be careful when adding new drivers... You're consuming
"review bandwidth" when you send code/patch/new-drivers and reviewers
are part of an endangered species. If you keep on making such silly
mistakes, you consume time from reviewers to let you know about things
which are obvious, to say the least. So be careful when sending code,
nobody is perfect, for sure, but by being careful you can help your code
being accepted earlier.

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110811/b2744ba5/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 14:12             ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 14:12 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: balbi, lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck


[-- Attachment #1.1: Type: text/plain, Size: 3916 bytes --]

Hi,

On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> >> new file mode 100644
> >> >> index 0000000..15e2559
> >> >> --- /dev/null
> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> >> @@ -0,0 +1,950 @@
> >> >> +/*
> >> >> + * OMAP4 Temperature sensor driver file
> >> >> + *
> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> >> +#include <linux/clk.h>
> >> >
> >> > why ??
> >>
> >> Clock rate setting functions.
> >
> > you shouldn't need in drivers.
> 
> It is a one time setting of the rate so keeping it in drivers.

you need some other way to handle this. Why do you need to manually set
the rate rather than having hwmod handle this for you ?

your argument that "it's a one time setting" is not enough to have this
in the driver. Drivers should not care about clocks anymore, this should
have been done on another layer.

> >> >> +#include <linux/delay.h>
> >> >> +#include <linux/slab.h>
> >> >> +#include <linux/platform_device.h>
> >> >> +#include <linux/init.h>
> >> >> +#include <plat/omap_device.h>
> >> >
> >> > why ??
> >> >
> >>
> >> Context loss count
> >
> > shouldn't use in drivers.
> 
> I guess already mmc and display are using
> omap_pm_get_dev_context_loss_count but are
> populating this function in pdata as a function pointer.
> I will add that code.

at least ;-) better than accessing that function directly. But think
carefully how you will make this work when we move to DT.

> >> >> +#include <plat/temperature_sensor.h>
> >> >
> >>
> >> It is the header file with the structure definitions
> >> used in the driver.
> >
> > why don't you put in <linux/platform_data/....> ??
> 
> I saw many omap specific header files in plat-omap/include/plat.
> Any specific reason behind placing the header in linux/platform_data?

because it's not a good idea to perpetuate the failure.

> >> >> +#include <mach/ctrl_module_core_44xx.h>
> >> >
> >> > why ?
> >>
> >> It will be removed
> >>
> >> >
> >> >> +#include <mach/gpio.h>
> >> >
> >> > linux/gpio.h for crying out loud... how many times Russell has to say
> >> > the exact same thing ??????
> >> >
> >>
> >> It will be removed
> >
> > oh, you don't even use any gpio ? Why do you blindly add so many headers
> > if you don't need them ???
> 
> It is not required.

this is my point, be careful when adding new drivers... You're consuming
"review bandwidth" when you send code/patch/new-drivers and reviewers
are part of an endangered species. If you keep on making such silly
mistakes, you consume time from reviewers to let you know about things
which are obvious, to say the least. So be careful when sending code,
nobody is perfect, for sure, but by being careful you can help your code
being accepted earlier.

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
  2011-08-11 14:05             ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
@ 2011-08-11 14:27               ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 14:15 UTC (permalink / raw)
  To: balbi; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

On Thu, Aug 11, 2011 at 7:35 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 04:31:50PM +0530, J, KEERTHY wrote:
>> On Thu, Aug 11, 2011 at 4:00 PM, Felipe Balbi <balbi@ti.com> wrote:
>> > Hi,
>> >
>> > On Thu, Aug 11, 2011 at 08:10:07AM +0530, J, KEERTHY wrote:
>> >> >> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>> >> >> index 6e6735f..8fd8e80 100644
>> >> >> --- a/arch/arm/plat-omap/Kconfig
>> >> >> +++ b/arch/arm/plat-omap/Kconfig
>> >> >> @@ -115,6 +115,18 @@ config OMAP_MCBSP
>> >> >>         Say Y here if you want support for the OMAP Multichannel
>> >> >>         Buffered Serial Port.
>> >> >>
>> >> >> +config OMAP_TEMP_SENSOR
>> >> >> +     bool "OMAP Temp Sensor Support"
>> >> >> +     depends on ARCH_OMAP
>> >> >> +     default n
>> >> >> +     help
>> >> >> +       Say Y here if you want support for the temp sensor
>> >> >> +       on OMAP4460.
>> >> >> +
>> >> >> +       This provides the temperature of the MPU
>> >> >> +       subsystem. Only one instance of on die temperature
>> >> >> +       sensor is present.
>> >> >
>> >> > if there's only one instance, why do you use
>> >> > omap_hwmod_for_each_by_class() ??
>> >>
>> >> In case of OMAP5 there are multiple instances. Hence using
>> >> omap_hwmod_for_each_by_class().
>> >
>> > that's not a reality yet, so why don't you leave it for when OMAP5 is
>> > around ?
>>
>> Keeping it generic so that we need not change again. We are pretty
>> close to reality i guess. Why not keep it generic? Any specific reason
>> for not keeping this loop?
>
> Other than the loop being completely unnecessary on the only OMAP
> version you're supporting ? no... not really.
>
>> >> >> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> >> >> new file mode 100644
>> >> >> index 0000000..692ebdc
>> >> >> --- /dev/null
>> >> >> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> >> >> @@ -0,0 +1,87 @@
>> >> >> +/*
>> >> >> + * OMAP Temperature sensor header file
>> >> >> + *
>> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> >> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> >> >> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> >> >> +
>> >> >> +/* Offsets from the base of temperature sensor registers */
>> >> >> +
>> >> >> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
>> >> >> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
>> >> >> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
>> >> >> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
>> >> >> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
>> >> >> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
>> >> >> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
>> >> >> +
>> >> >> +struct omap_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     thsut_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;
>> >> >> +};
>> >> >
>> >> > I find it unnecessary to pass the register map to driver using
>> >> > platform_data.
>> >>
>> >> With multiple instances the register map to individual instances will change.
>> >> So passing it via platform_data.
>> >
>> > what will change is the base address, the offsets should remain the
>> > same.
>>
>> The base address offsets and even bit fields seem to be differing across
>> different OMAP versions.
>
> then a comment making that clear is necessary. But as of today, you
> support only one OMAP version, so I'm sure it's worth the trouble for a
> first version of the driver.

I will add a comment.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 14:12             ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
  (?)
@ 2011-08-11 14:25               ` Rajendra Nayak
  -1 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-11 14:25 UTC (permalink / raw)
  To: balbi
  Cc: J, KEERTHY, lm-sensors, vishwanath.bs, linux-omap, b-cousson,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

On 8/11/2011 7:42 PM, Felipe Balbi wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
>>>>>> >  >>  >>  diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>>>>>> >  >>  >>  new file mode 100644
>>>>>> >  >>  >>  index 0000000..15e2559
>>>>>> >  >>  >>  --- /dev/null
>>>>>> >  >>  >>  +++ b/drivers/hwmon/omap_temp_sensor.c
>>>>>> >  >>  >>  @@ -0,0 +1,950 @@
>>>>>> >  >>  >>  +/*
>>>>>> >  >>  >>  + * OMAP4 Temperature sensor driver file
>>>>>> >  >>  >>  + *
>>>>>> >  >>  >>  + * Copyright (C) 2011 Texas Instruments Incorporated -http://www.ti.com/
>>>>>> >  >>  >>  + * Author: J Keerthy<j-keerthy@ti.com>
>>>>>> >  >>  >>  + * Author: Moiz Sonasath<m-sonasath@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/interrupt.h>
>>>>>> >  >>  >>  +#include<linux/clk.h>
>>>>> >  >>  >
>>>>> >  >>  >  why ??
>>>> >  >>
>>>> >  >>  Clock rate setting functions.
>>> >  >
>>> >  >  you shouldn't need in drivers.
>> >
>> >  It is a one time setting of the rate so keeping it in drivers.
> you need some other way to handle this. Why do you need to manually set
> the rate rather than having hwmod handle this for you ?

Because hwmod has not idea about what rate a device needs to operate
in any point.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 14:25               ` Rajendra Nayak
  0 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-11 14:25 UTC (permalink / raw)
  To: linux-arm-kernel

On 8/11/2011 7:42 PM, Felipe Balbi wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
>>>>>> >  >>  >>  diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>>>>>> >  >>  >>  new file mode 100644
>>>>>> >  >>  >>  index 0000000..15e2559
>>>>>> >  >>  >>  --- /dev/null
>>>>>> >  >>  >>  +++ b/drivers/hwmon/omap_temp_sensor.c
>>>>>> >  >>  >>  @@ -0,0 +1,950 @@
>>>>>> >  >>  >>  +/*
>>>>>> >  >>  >>  + * OMAP4 Temperature sensor driver file
>>>>>> >  >>  >>  + *
>>>>>> >  >>  >>  + * Copyright (C) 2011 Texas Instruments Incorporated -http://www.ti.com/
>>>>>> >  >>  >>  + * Author: J Keerthy<j-keerthy@ti.com>
>>>>>> >  >>  >>  + * Author: Moiz Sonasath<m-sonasath@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/interrupt.h>
>>>>>> >  >>  >>  +#include<linux/clk.h>
>>>>> >  >>  >
>>>>> >  >>  >  why ??
>>>> >  >>
>>>> >  >>  Clock rate setting functions.
>>> >  >
>>> >  >  you shouldn't need in drivers.
>> >
>> >  It is a one time setting of the rate so keeping it in drivers.
> you need some other way to handle this. Why do you need to manually set
> the rate rather than having hwmod handle this for you ?

Because hwmod has not idea about what rate a device needs to operate
in any point.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device
@ 2011-08-11 14:27               ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 14:27 UTC (permalink / raw)
  To: balbi; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

On Thu, Aug 11, 2011 at 7:35 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 04:31:50PM +0530, J, KEERTHY wrote:
>> On Thu, Aug 11, 2011 at 4:00 PM, Felipe Balbi <balbi@ti.com> wrote:
>> > Hi,
>> >
>> > On Thu, Aug 11, 2011 at 08:10:07AM +0530, J, KEERTHY wrote:
>> >> >> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>> >> >> index 6e6735f..8fd8e80 100644
>> >> >> --- a/arch/arm/plat-omap/Kconfig
>> >> >> +++ b/arch/arm/plat-omap/Kconfig
>> >> >> @@ -115,6 +115,18 @@ config OMAP_MCBSP
>> >> >>         Say Y here if you want support for the OMAP Multichannel
>> >> >>         Buffered Serial Port.
>> >> >>
>> >> >> +config OMAP_TEMP_SENSOR
>> >> >> +     bool "OMAP Temp Sensor Support"
>> >> >> +     depends on ARCH_OMAP
>> >> >> +     default n
>> >> >> +     help
>> >> >> +       Say Y here if you want support for the temp sensor
>> >> >> +       on OMAP4460.
>> >> >> +
>> >> >> +       This provides the temperature of the MPU
>> >> >> +       subsystem. Only one instance of on die temperature
>> >> >> +       sensor is present.
>> >> >
>> >> > if there's only one instance, why do you use
>> >> > omap_hwmod_for_each_by_class() ??
>> >>
>> >> In case of OMAP5 there are multiple instances. Hence using
>> >> omap_hwmod_for_each_by_class().
>> >
>> > that's not a reality yet, so why don't you leave it for when OMAP5 is
>> > around ?
>>
>> Keeping it generic so that we need not change again. We are pretty
>> close to reality i guess. Why not keep it generic? Any specific reason
>> for not keeping this loop?
>
> Other than the loop being completely unnecessary on the only OMAP
> version you're supporting ? no... not really.
>
>> >> >> diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> >> >> new file mode 100644
>> >> >> index 0000000..692ebdc
>> >> >> --- /dev/null
>> >> >> +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h
>> >> >> @@ -0,0 +1,87 @@
>> >> >> +/*
>> >> >> + * OMAP Temperature sensor header file
>> >> >> + *
>> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> >> + * Author: J Keerthy <j-keerthy@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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> >> >> +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H
>> >> >> +
>> >> >> +/* Offsets from the base of temperature sensor registers */
>> >> >> +
>> >> >> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET     0x00
>> >> >> +#define OMAP4460_BGAP_CTRL_OFFSET            0x4c
>> >> >> +#define OMAP4460_BGAP_COUNTER_OFFSET         0x50
>> >> >> +#define OMAP4460_BGAP_THRESHOLD_OFFSET               0x54
>> >> >> +#define OMAP4460_BGAP_TSHUT_OFFSET           0x58
>> >> >> +#define OMAP4460_BGAP_STATUS_OFFSET          0x5c
>> >> >> +#define OMAP4460_FUSE_OPP_BGAP                       -0xcc
>> >> >> +
>> >> >> +struct omap_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     thsut_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;
>> >> >> +};
>> >> >
>> >> > I find it unnecessary to pass the register map to driver using
>> >> > platform_data.
>> >>
>> >> With multiple instances the register map to individual instances will change.
>> >> So passing it via platform_data.
>> >
>> > what will change is the base address, the offsets should remain the
>> > same.
>>
>> The base address offsets and even bit fields seem to be differing across
>> different OMAP versions.
>
> then a comment making that clear is necessary. But as of today, you
> support only one OMAP version, so I'm sure it's worth the trouble for a
> first version of the driver.

I will add a comment.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 14:12             ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
  (?)
@ 2011-08-11 14:32               ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 14:32 UTC (permalink / raw)
  To: balbi, Tony Lindgren
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Russell King, Linux ARM Kernel Mailing List, khali,
	guenter.roeck

On Thu, Aug 11, 2011 at 7:42 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
>> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> >> >> new file mode 100644
>> >> >> index 0000000..15e2559
>> >> >> --- /dev/null
>> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
>> >> >> @@ -0,0 +1,950 @@
>> >> >> +/*
>> >> >> + * OMAP4 Temperature sensor driver file
>> >> >> + *
>> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
>> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> >> >> +#include <linux/clk.h>
>> >> >
>> >> > why ??
>> >>
>> >> Clock rate setting functions.
>> >
>> > you shouldn't need in drivers.
>>
>> It is a one time setting of the rate so keeping it in drivers.
>
> you need some other way to handle this. Why do you need to manually set
> the rate rather than having hwmod handle this for you ?
>
> your argument that "it's a one time setting" is not enough to have this
> in the driver. Drivers should not care about clocks anymore, this should
> have been done on another layer.

Hwmod will have no idea on the rate required.

>
>> >> >> +#include <linux/delay.h>
>> >> >> +#include <linux/slab.h>
>> >> >> +#include <linux/platform_device.h>
>> >> >> +#include <linux/init.h>
>> >> >> +#include <plat/omap_device.h>
>> >> >
>> >> > why ??
>> >> >
>> >>
>> >> Context loss count
>> >
>> > shouldn't use in drivers.
>>
>> I guess already mmc and display are using
>> omap_pm_get_dev_context_loss_count but are
>> populating this function in pdata as a function pointer.
>> I will add that code.
>
> at least ;-) better than accessing that function directly. But think
> carefully how you will make this work when we move to DT.

Ok

>
>> >> >> +#include <plat/temperature_sensor.h>
>> >> >
>> >>
>> >> It is the header file with the structure definitions
>> >> used in the driver.
>> >
>> > why don't you put in <linux/platform_data/....> ??
>>
>> I saw many omap specific header files in plat-omap/include/plat.
>> Any specific reason behind placing the header in linux/platform_data?
>
> because it's not a good idea to perpetuate the failure.

May be Tony can give some inputs on where the OMAP specific header
should be placed.

>
>> >> >> +#include <mach/ctrl_module_core_44xx.h>
>> >> >
>> >> > why ?
>> >>
>> >> It will be removed
>> >>
>> >> >
>> >> >> +#include <mach/gpio.h>
>> >> >
>> >> > linux/gpio.h for crying out loud... how many times Russell has to say
>> >> > the exact same thing ??????
>> >> >
>> >>
>> >> It will be removed
>> >
>> > oh, you don't even use any gpio ? Why do you blindly add so many headers
>> > if you don't need them ???
>>
>> It is not required.
>
> this is my point, be careful when adding new drivers... You're consuming
> "review bandwidth" when you send code/patch/new-drivers and reviewers
> are part of an endangered species. If you keep on making such silly
> mistakes, you consume time from reviewers to let you know about things
> which are obvious, to say the least. So be careful when sending code,
> nobody is perfect, for sure, but by being careful you can help your code
> being accepted earlier.

My Bad. I will take care of this.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 14:32               ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 14:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 11, 2011 at 7:42 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
>> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> >> >> new file mode 100644
>> >> >> index 0000000..15e2559
>> >> >> --- /dev/null
>> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
>> >> >> @@ -0,0 +1,950 @@
>> >> >> +/*
>> >> >> + * OMAP4 Temperature sensor driver file
>> >> >> + *
>> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
>> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> >> >> +#include <linux/clk.h>
>> >> >
>> >> > why ??
>> >>
>> >> Clock rate setting functions.
>> >
>> > you shouldn't need in drivers.
>>
>> It is a one time setting of the rate so keeping it in drivers.
>
> you need some other way to handle this. Why do you need to manually set
> the rate rather than having hwmod handle this for you ?
>
> your argument that "it's a one time setting" is not enough to have this
> in the driver. Drivers should not care about clocks anymore, this should
> have been done on another layer.

Hwmod will have no idea on the rate required.

>
>> >> >> +#include <linux/delay.h>
>> >> >> +#include <linux/slab.h>
>> >> >> +#include <linux/platform_device.h>
>> >> >> +#include <linux/init.h>
>> >> >> +#include <plat/omap_device.h>
>> >> >
>> >> > why ??
>> >> >
>> >>
>> >> Context loss count
>> >
>> > shouldn't use in drivers.
>>
>> I guess already mmc and display are using
>> omap_pm_get_dev_context_loss_count but are
>> populating this function in pdata as a function pointer.
>> I will add that code.
>
> at least ;-) better than accessing that function directly. But think
> carefully how you will make this work when we move to DT.

Ok

>
>> >> >> +#include <plat/temperature_sensor.h>
>> >> >
>> >>
>> >> It is the header file with the structure definitions
>> >> used in the driver.
>> >
>> > why don't you put in <linux/platform_data/....> ??
>>
>> I saw many omap specific header files in plat-omap/include/plat.
>> Any specific reason behind placing the header in linux/platform_data?
>
> because it's not a good idea to perpetuate the failure.

May be Tony can give some inputs on where the OMAP specific header
should be placed.

>
>> >> >> +#include <mach/ctrl_module_core_44xx.h>
>> >> >
>> >> > why ?
>> >>
>> >> It will be removed
>> >>
>> >> >
>> >> >> +#include <mach/gpio.h>
>> >> >
>> >> > linux/gpio.h for crying out loud... how many times Russell has to say
>> >> > the exact same thing ??????
>> >> >
>> >>
>> >> It will be removed
>> >
>> > oh, you don't even use any gpio ? Why do you blindly add so many headers
>> > if you don't need them ???
>>
>> It is not required.
>
> this is my point, be careful when adding new drivers... You're consuming
> "review bandwidth" when you send code/patch/new-drivers and reviewers
> are part of an endangered species. If you keep on making such silly
> mistakes, you consume time from reviewers to let you know about things
> which are obvious, to say the least. So be careful when sending code,
> nobody is perfect, for sure, but by being careful you can help your code
> being accepted earlier.

My Bad. I will take care of this.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 14:25               ` Rajendra Nayak
  0 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-11 14:37 UTC (permalink / raw)
  To: balbi
  Cc: J, KEERTHY, lm-sensors, vishwanath.bs, linux-omap, b-cousson,
	Tony Lindgren, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

On 8/11/2011 7:42 PM, Felipe Balbi wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
>>>>>> >  >>  >>  diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>>>>>> >  >>  >>  new file mode 100644
>>>>>> >  >>  >>  index 0000000..15e2559
>>>>>> >  >>  >>  --- /dev/null
>>>>>> >  >>  >>  +++ b/drivers/hwmon/omap_temp_sensor.c
>>>>>> >  >>  >>  @@ -0,0 +1,950 @@
>>>>>> >  >>  >>  +/*
>>>>>> >  >>  >>  + * OMAP4 Temperature sensor driver file
>>>>>> >  >>  >>  + *
>>>>>> >  >>  >>  + * Copyright (C) 2011 Texas Instruments Incorporated -http://www.ti.com/
>>>>>> >  >>  >>  + * Author: J Keerthy<j-keerthy@ti.com>
>>>>>> >  >>  >>  + * Author: Moiz Sonasath<m-sonasath@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/interrupt.h>
>>>>>> >  >>  >>  +#include<linux/clk.h>
>>>>> >  >>  >
>>>>> >  >>  >  why ??
>>>> >  >>
>>>> >  >>  Clock rate setting functions.
>>> >  >
>>> >  >  you shouldn't need in drivers.
>> >
>> >  It is a one time setting of the rate so keeping it in drivers.
> you need some other way to handle this. Why do you need to manually set
> the rate rather than having hwmod handle this for you ?

Because hwmod has not idea about what rate a device needs to operate
in any point.

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 14:32               ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-11 14:44 UTC (permalink / raw)
  To: balbi, Tony Lindgren
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak,
	Russell King, Linux ARM Kernel Mailing List, khali,
	guenter.roeck

On Thu, Aug 11, 2011 at 7:42 PM, Felipe Balbi <balbi@ti.com> wrote:
> Hi,
>
> On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
>> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
>> >> >> new file mode 100644
>> >> >> index 0000000..15e2559
>> >> >> --- /dev/null
>> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
>> >> >> @@ -0,0 +1,950 @@
>> >> >> +/*
>> >> >> + * OMAP4 Temperature sensor driver file
>> >> >> + *
>> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
>> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> >> >> +#include <linux/clk.h>
>> >> >
>> >> > why ??
>> >>
>> >> Clock rate setting functions.
>> >
>> > you shouldn't need in drivers.
>>
>> It is a one time setting of the rate so keeping it in drivers.
>
> you need some other way to handle this. Why do you need to manually set
> the rate rather than having hwmod handle this for you ?
>
> your argument that "it's a one time setting" is not enough to have this
> in the driver. Drivers should not care about clocks anymore, this should
> have been done on another layer.

Hwmod will have no idea on the rate required.

>
>> >> >> +#include <linux/delay.h>
>> >> >> +#include <linux/slab.h>
>> >> >> +#include <linux/platform_device.h>
>> >> >> +#include <linux/init.h>
>> >> >> +#include <plat/omap_device.h>
>> >> >
>> >> > why ??
>> >> >
>> >>
>> >> Context loss count
>> >
>> > shouldn't use in drivers.
>>
>> I guess already mmc and display are using
>> omap_pm_get_dev_context_loss_count but are
>> populating this function in pdata as a function pointer.
>> I will add that code.
>
> at least ;-) better than accessing that function directly. But think
> carefully how you will make this work when we move to DT.

Ok

>
>> >> >> +#include <plat/temperature_sensor.h>
>> >> >
>> >>
>> >> It is the header file with the structure definitions
>> >> used in the driver.
>> >
>> > why don't you put in <linux/platform_data/....> ??
>>
>> I saw many omap specific header files in plat-omap/include/plat.
>> Any specific reason behind placing the header in linux/platform_data?
>
> because it's not a good idea to perpetuate the failure.

May be Tony can give some inputs on where the OMAP specific header
should be placed.

>
>> >> >> +#include <mach/ctrl_module_core_44xx.h>
>> >> >
>> >> > why ?
>> >>
>> >> It will be removed
>> >>
>> >> >
>> >> >> +#include <mach/gpio.h>
>> >> >
>> >> > linux/gpio.h for crying out loud... how many times Russell has to say
>> >> > the exact same thing ??????
>> >> >
>> >>
>> >> It will be removed
>> >
>> > oh, you don't even use any gpio ? Why do you blindly add so many headers
>> > if you don't need them ???
>>
>> It is not required.
>
> this is my point, be careful when adding new drivers... You're consuming
> "review bandwidth" when you send code/patch/new-drivers and reviewers
> are part of an endangered species. If you keep on making such silly
> mistakes, you consume time from reviewers to let you know about things
> which are obvious, to say the least. So be careful when sending code,
> nobody is perfect, for sure, but by being careful you can help your code
> being accepted earlier.

My Bad. I will take care of this.

>
> --
> balbi
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 13:00           ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
  (?)
@ 2011-08-11 16:38             ` Guenter Roeck
  -1 siblings, 0 replies; 105+ messages in thread
From: Guenter Roeck @ 2011-08-11 16:38 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: Russell King, b-cousson, Tony Lindgren, rnayak, balbi,
	lm-sensors, khali, vishwanath.bs, linux-omap,
	Linux ARM Kernel Mailing List

On Thu, 2011-08-11 at 09:00 -0400, J, KEERTHY wrote:
> On Thu, Aug 11, 2011 at 4:06 PM, Felipe Balbi <balbi@ti.com> wrote:

[ ... ]

> >> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> >> +                     temp_sensor->registers->bgap_counter);
> >> >> +     temp = (temp & temp_sensor->registers->counter_mask) >>
> >> >> +                     __ffs(temp_sensor->registers->counter_mask);
> >> >
> >> >        temp &= ??
> >> >
> >> >> +     temp = temp * 1000 / (temp_sensor->clk_rate);
> >> >
> >> >        temp *= ??
> >>
> >> Need to multiply the temp with 1000 before dividing.
> >> temp *= evaluates the RHS first and then multiplies LHS.
> >
> > temp *= 1000;
> > temp /= clk_rate;
> >
> 
> Different coding style. I preferred to do it in a single line.
> 
Me too.

Guenter

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 16:38             ` Guenter Roeck
  0 siblings, 0 replies; 105+ messages in thread
From: Guenter Roeck @ 2011-08-11 16:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-08-11 at 09:00 -0400, J, KEERTHY wrote:
> On Thu, Aug 11, 2011 at 4:06 PM, Felipe Balbi <balbi@ti.com> wrote:

[ ... ]

> >> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> >> +                     temp_sensor->registers->bgap_counter);
> >> >> +     temp = (temp & temp_sensor->registers->counter_mask) >>
> >> >> +                     __ffs(temp_sensor->registers->counter_mask);
> >> >
> >> >        temp &= ??
> >> >
> >> >> +     temp = temp * 1000 / (temp_sensor->clk_rate);
> >> >
> >> >        temp *= ??
> >>
> >> Need to multiply the temp with 1000 before dividing.
> >> temp *= evaluates the RHS first and then multiplies LHS.
> >
> > temp *= 1000;
> > temp /= clk_rate;
> >
> 
> Different coding style. I preferred to do it in a single line.
> 
Me too.

Guenter

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 16:38             ` Guenter Roeck
  0 siblings, 0 replies; 105+ messages in thread
From: Guenter Roeck @ 2011-08-11 16:38 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: Russell King, b-cousson, Tony Lindgren, rnayak, balbi,
	lm-sensors, khali, vishwanath.bs, linux-omap,
	Linux ARM Kernel Mailing List

On Thu, 2011-08-11 at 09:00 -0400, J, KEERTHY wrote:
> On Thu, Aug 11, 2011 at 4:06 PM, Felipe Balbi <balbi@ti.com> wrote:

[ ... ]

> >> >> +     temp = omap_temp_sensor_readl(temp_sensor,
> >> >> +                     temp_sensor->registers->bgap_counter);
> >> >> +     temp = (temp & temp_sensor->registers->counter_mask) >>
> >> >> +                     __ffs(temp_sensor->registers->counter_mask);
> >> >
> >> >        temp &= ??
> >> >
> >> >> +     temp = temp * 1000 / (temp_sensor->clk_rate);
> >> >
> >> >        temp *= ??
> >>
> >> Need to multiply the temp with 1000 before dividing.
> >> temp *= evaluates the RHS first and then multiplies LHS.
> >
> > temp *= 1000;
> > temp /= clk_rate;
> >
> 
> Different coding style. I preferred to do it in a single line.
> 
Me too.

Guenter



_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 14:32               ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
  (?)
@ 2011-08-11 18:54                 ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 18:54 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: Russell King, b-cousson, Tony Lindgren, rnayak, balbi,
	lm-sensors, khali, vishwanath.bs, linux-omap,
	Linux ARM Kernel Mailing List, guenter.roeck


[-- Attachment #1.1: Type: text/plain, Size: 3442 bytes --]

Hi,

On Thu, Aug 11, 2011 at 08:02:55PM +0530, J, KEERTHY wrote:
> On Thu, Aug 11, 2011 at 7:42 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
> >> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> >> >> new file mode 100644
> >> >> >> index 0000000..15e2559
> >> >> >> --- /dev/null
> >> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> >> >> @@ -0,0 +1,950 @@
> >> >> >> +/*
> >> >> >> + * OMAP4 Temperature sensor driver file
> >> >> >> + *
> >> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> >> >> +#include <linux/clk.h>
> >> >> >
> >> >> > why ??
> >> >>
> >> >> Clock rate setting functions.
> >> >
> >> > you shouldn't need in drivers.
> >>
> >> It is a one time setting of the rate so keeping it in drivers.
> >
> > you need some other way to handle this. Why do you need to manually set
> > the rate rather than having hwmod handle this for you ?
> >
> > your argument that "it's a one time setting" is not enough to have this
> > in the driver. Drivers should not care about clocks anymore, this should
> > have been done on another layer.
> 
> Hwmod will have no idea on the rate required.

does the rate need to change ? Also, I have not mentioned hwmod anytime
simply because I'm not sure where this should be placed, but hopefully
not in the driver.

If the clock doesn't need to change after you set the correct rate, then
there's really no point in adding complexity to the driver.

Tony, would you have any comment here ?

> >> >> >> +#include <plat/temperature_sensor.h>
> >> >> >
> >> >>
> >> >> It is the header file with the structure definitions
> >> >> used in the driver.
> >> >
> >> > why don't you put in <linux/platform_data/....> ??
> >>
> >> I saw many omap specific header files in plat-omap/include/plat.
> >> Any specific reason behind placing the header in linux/platform_data?
> >
> > because it's not a good idea to perpetuate the failure.
> 
> May be Tony can give some inputs on where the OMAP specific header
> should be placed.

it's not omap-specific. It's specific to your driver and considering
it's platform_data, it should sit under include/linux/platform_data.h.
That directory was created (fairly recently) to hold platform_data...

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 18:54                 ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 18:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, Aug 11, 2011 at 08:02:55PM +0530, J, KEERTHY wrote:
> On Thu, Aug 11, 2011 at 7:42 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
> >> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> >> >> new file mode 100644
> >> >> >> index 0000000..15e2559
> >> >> >> --- /dev/null
> >> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> >> >> @@ -0,0 +1,950 @@
> >> >> >> +/*
> >> >> >> + * OMAP4 Temperature sensor driver file
> >> >> >> + *
> >> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> >> >> +#include <linux/clk.h>
> >> >> >
> >> >> > why ??
> >> >>
> >> >> Clock rate setting functions.
> >> >
> >> > you shouldn't need in drivers.
> >>
> >> It is a one time setting of the rate so keeping it in drivers.
> >
> > you need some other way to handle this. Why do you need to manually set
> > the rate rather than having hwmod handle this for you ?
> >
> > your argument that "it's a one time setting" is not enough to have this
> > in the driver. Drivers should not care about clocks anymore, this should
> > have been done on another layer.
> 
> Hwmod will have no idea on the rate required.

does the rate need to change ? Also, I have not mentioned hwmod anytime
simply because I'm not sure where this should be placed, but hopefully
not in the driver.

If the clock doesn't need to change after you set the correct rate, then
there's really no point in adding complexity to the driver.

Tony, would you have any comment here ?

> >> >> >> +#include <plat/temperature_sensor.h>
> >> >> >
> >> >>
> >> >> It is the header file with the structure definitions
> >> >> used in the driver.
> >> >
> >> > why don't you put in <linux/platform_data/....> ??
> >>
> >> I saw many omap specific header files in plat-omap/include/plat.
> >> Any specific reason behind placing the header in linux/platform_data?
> >
> > because it's not a good idea to perpetuate the failure.
> 
> May be Tony can give some inputs on where the OMAP specific header
> should be placed.

it's not omap-specific. It's specific to your driver and considering
it's platform_data, it should sit under include/linux/platform_data.h.
That directory was created (fairly recently) to hold platform_data...

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110811/af6058f5/attachment.sig>

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 18:54                 ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 18:54 UTC (permalink / raw)
  To: J, KEERTHY
  Cc: Russell King, b-cousson, Tony Lindgren, rnayak, balbi,
	lm-sensors, khali, vishwanath.bs, linux-omap,
	Linux ARM Kernel Mailing List, guenter.roeck


[-- Attachment #1.1: Type: text/plain, Size: 3442 bytes --]

Hi,

On Thu, Aug 11, 2011 at 08:02:55PM +0530, J, KEERTHY wrote:
> On Thu, Aug 11, 2011 at 7:42 PM, Felipe Balbi <balbi@ti.com> wrote:
> > Hi,
> >
> > On Thu, Aug 11, 2011 at 06:30:04PM +0530, J, KEERTHY wrote:
> >> >> >> diff --git a/drivers/hwmon/omap_temp_sensor.c b/drivers/hwmon/omap_temp_sensor.c
> >> >> >> new file mode 100644
> >> >> >> index 0000000..15e2559
> >> >> >> --- /dev/null
> >> >> >> +++ b/drivers/hwmon/omap_temp_sensor.c
> >> >> >> @@ -0,0 +1,950 @@
> >> >> >> +/*
> >> >> >> + * OMAP4 Temperature sensor driver file
> >> >> >> + *
> >> >> >> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> >> >> >> + * Author: J Keerthy <j-keerthy@ti.com>
> >> >> >> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
> >> >> >> +#include <linux/clk.h>
> >> >> >
> >> >> > why ??
> >> >>
> >> >> Clock rate setting functions.
> >> >
> >> > you shouldn't need in drivers.
> >>
> >> It is a one time setting of the rate so keeping it in drivers.
> >
> > you need some other way to handle this. Why do you need to manually set
> > the rate rather than having hwmod handle this for you ?
> >
> > your argument that "it's a one time setting" is not enough to have this
> > in the driver. Drivers should not care about clocks anymore, this should
> > have been done on another layer.
> 
> Hwmod will have no idea on the rate required.

does the rate need to change ? Also, I have not mentioned hwmod anytime
simply because I'm not sure where this should be placed, but hopefully
not in the driver.

If the clock doesn't need to change after you set the correct rate, then
there's really no point in adding complexity to the driver.

Tony, would you have any comment here ?

> >> >> >> +#include <plat/temperature_sensor.h>
> >> >> >
> >> >>
> >> >> It is the header file with the structure definitions
> >> >> used in the driver.
> >> >
> >> > why don't you put in <linux/platform_data/....> ??
> >>
> >> I saw many omap specific header files in plat-omap/include/plat.
> >> Any specific reason behind placing the header in linux/platform_data?
> >
> > because it's not a good idea to perpetuate the failure.
> 
> May be Tony can give some inputs on where the OMAP specific header
> should be placed.

it's not omap-specific. It's specific to your driver and considering
it's platform_data, it should sit under include/linux/platform_data.h.
That directory was created (fairly recently) to hold platform_data...

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 18:54                 ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
  (?)
@ 2011-08-11 18:55                   ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 18:55 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: J, KEERTHY, Tony Lindgren, lm-sensors, vishwanath.bs, linux-omap,
	b-cousson, rnayak, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

[-- Attachment #1: Type: text/plain, Size: 674 bytes --]

Hi,

On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
> > > you need some other way to handle this. Why do you need to manually set
> > > the rate rather than having hwmod handle this for you ?
> > >
> > > your argument that "it's a one time setting" is not enough to have this
> > > in the driver. Drivers should not care about clocks anymore, this should
> > > have been done on another layer.
> > 
> > Hwmod will have no idea on the rate required.
> 
> does the rate need to change ? Also, I have not mentioned hwmod anytime

i did mention hwmod, nevermind that part. Still I'm not sure where is
the right place to handle this.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 18:55                   ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 18:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
> > > you need some other way to handle this. Why do you need to manually set
> > > the rate rather than having hwmod handle this for you ?
> > >
> > > your argument that "it's a one time setting" is not enough to have this
> > > in the driver. Drivers should not care about clocks anymore, this should
> > > have been done on another layer.
> > 
> > Hwmod will have no idea on the rate required.
> 
> does the rate need to change ? Also, I have not mentioned hwmod anytime

i did mention hwmod, nevermind that part. Still I'm not sure where is
the right place to handle this.

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110811/c455d781/attachment.sig>

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 18:55                   ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-11 18:55 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: J, KEERTHY, Tony Lindgren, lm-sensors, vishwanath.bs, linux-omap,
	b-cousson, rnayak, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck


[-- Attachment #1.1: Type: text/plain, Size: 674 bytes --]

Hi,

On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
> > > you need some other way to handle this. Why do you need to manually set
> > > the rate rather than having hwmod handle this for you ?
> > >
> > > your argument that "it's a one time setting" is not enough to have this
> > > in the driver. Drivers should not care about clocks anymore, this should
> > > have been done on another layer.
> > 
> > Hwmod will have no idea on the rate required.
> 
> does the rate need to change ? Also, I have not mentioned hwmod anytime

i did mention hwmod, nevermind that part. Still I'm not sure where is
the right place to handle this.

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 18:55                   ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
  (?)
@ 2011-08-11 21:37                     ` Roger Quadros
  -1 siblings, 0 replies; 105+ messages in thread
From: Roger Quadros @ 2011-08-11 21:37 UTC (permalink / raw)
  To: balbi
  Cc: Russell King, b-cousson, Tony Lindgren, J, KEERTHY, rnayak,
	lm-sensors, khali, vishwanath.bs, linux-omap,
	Linux ARM Kernel Mailing List, guenter.roeck

On 08/11/2011 01:55 PM, Felipe Balbi wrote:
> Hi,
> 
> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>> you need some other way to handle this. Why do you need to manually set
>>>> the rate rather than having hwmod handle this for you ?
>>>>
>>>> your argument that "it's a one time setting" is not enough to have this
>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>> have been done on another layer.
>>>
>>> Hwmod will have no idea on the rate required.
>>
>> does the rate need to change ? Also, I have not mentioned hwmod anytime
> 
> i did mention hwmod, nevermind that part. Still I'm not sure where is
> the right place to handle this.
> 

Aren't the omap_device_pm_latency callbacks the right place to do it?

e.g. in the following snippet from mach-omap2/temp_sensor_device.c

+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
+	{
+	 .deactivate_func = omap_device_idle_hwmods,
+	 .activate_func = omap_device_enable_hwmods,
+	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};

instead of directly pointing activate_func to omap_device_enable_hwmods,
it could point to a function that sets the required clock rate and then
enables the hwmod.


regards,
-roger

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-11 21:37                     ` Roger Quadros
  0 siblings, 0 replies; 105+ messages in thread
From: Roger Quadros @ 2011-08-11 21:37 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/11/2011 01:55 PM, Felipe Balbi wrote:
> Hi,
> 
> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>> you need some other way to handle this. Why do you need to manually set
>>>> the rate rather than having hwmod handle this for you ?
>>>>
>>>> your argument that "it's a one time setting" is not enough to have this
>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>> have been done on another layer.
>>>
>>> Hwmod will have no idea on the rate required.
>>
>> does the rate need to change ? Also, I have not mentioned hwmod anytime
> 
> i did mention hwmod, nevermind that part. Still I'm not sure where is
> the right place to handle this.
> 

Aren't the omap_device_pm_latency callbacks the right place to do it?

e.g. in the following snippet from mach-omap2/temp_sensor_device.c

+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
+	{
+	 .deactivate_func = omap_device_idle_hwmods,
+	 .activate_func = omap_device_enable_hwmods,
+	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};

instead of directly pointing activate_func to omap_device_enable_hwmods,
it could point to a function that sets the required clock rate and then
enables the hwmod.


regards,
-roger

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-11 21:37                     ` Roger Quadros
  0 siblings, 0 replies; 105+ messages in thread
From: Roger Quadros @ 2011-08-11 21:37 UTC (permalink / raw)
  To: balbi
  Cc: Russell King, b-cousson, Tony Lindgren, J, KEERTHY, rnayak,
	lm-sensors, khali, vishwanath.bs, linux-omap,
	Linux ARM Kernel Mailing List, guenter.roeck

On 08/11/2011 01:55 PM, Felipe Balbi wrote:
> Hi,
> 
> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>> you need some other way to handle this. Why do you need to manually set
>>>> the rate rather than having hwmod handle this for you ?
>>>>
>>>> your argument that "it's a one time setting" is not enough to have this
>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>> have been done on another layer.
>>>
>>> Hwmod will have no idea on the rate required.
>>
>> does the rate need to change ? Also, I have not mentioned hwmod anytime
> 
> i did mention hwmod, nevermind that part. Still I'm not sure where is
> the right place to handle this.
> 

Aren't the omap_device_pm_latency callbacks the right place to do it?

e.g. in the following snippet from mach-omap2/temp_sensor_device.c

+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
+	{
+	 .deactivate_func = omap_device_idle_hwmods,
+	 .activate_func = omap_device_enable_hwmods,
+	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};

instead of directly pointing activate_func to omap_device_enable_hwmods,
it could point to a function that sets the required clock rate and then
enables the hwmod.


regards,
-roger

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 21:37                     ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Roger Quadros
  (?)
@ 2011-08-12  1:02                       ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-12  1:02 UTC (permalink / raw)
  To: Roger Quadros
  Cc: balbi, Tony Lindgren, lm-sensors, vishwanath.bs, linux-omap,
	b-cousson, rnayak, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

On Fri, Aug 12, 2011 at 3:07 AM, Roger Quadros <rogerq@ti.com> wrote:
> On 08/11/2011 01:55 PM, Felipe Balbi wrote:
>> Hi,
>>
>> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>>> you need some other way to handle this. Why do you need to manually set
>>>>> the rate rather than having hwmod handle this for you ?
>>>>>
>>>>> your argument that "it's a one time setting" is not enough to have this
>>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>>> have been done on another layer.
>>>>
>>>> Hwmod will have no idea on the rate required.
>>>
>>> does the rate need to change ? Also, I have not mentioned hwmod anytime
>>
>> i did mention hwmod, nevermind that part. Still I'm not sure where is
>> the right place to handle this.
>>
>
> Aren't the omap_device_pm_latency callbacks the right place to do it?

It is a one time setting. These callbacks get called everytime
pm_runtime_get_sync and pm_runtime_put_sync are called.
IMHO this is not the right place.

>
> e.g. in the following snippet from mach-omap2/temp_sensor_device.c
>
> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> +       {
> +        .deactivate_func = omap_device_idle_hwmods,
> +        .activate_func = omap_device_enable_hwmods,
> +        .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> +       }
> +};
>
> instead of directly pointing activate_func to omap_device_enable_hwmods,
> it could point to a function that sets the required clock rate and then
> enables the hwmod.
>
>
> regards,
> -roger
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-12  1:02                       ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-12  1:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Aug 12, 2011 at 3:07 AM, Roger Quadros <rogerq@ti.com> wrote:
> On 08/11/2011 01:55 PM, Felipe Balbi wrote:
>> Hi,
>>
>> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>>> you need some other way to handle this. Why do you need to manually set
>>>>> the rate rather than having hwmod handle this for you ?
>>>>>
>>>>> your argument that "it's a one time setting" is not enough to have this
>>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>>> have been done on another layer.
>>>>
>>>> Hwmod will have no idea on the rate required.
>>>
>>> does the rate need to change ? Also, I have not mentioned hwmod anytime
>>
>> i did mention hwmod, nevermind that part. Still I'm not sure where is
>> the right place to handle this.
>>
>
> Aren't the omap_device_pm_latency callbacks the right place to do it?

It is a one time setting. These callbacks get called everytime
pm_runtime_get_sync and pm_runtime_put_sync are called.
IMHO this is not the right place.

>
> e.g. in the following snippet from mach-omap2/temp_sensor_device.c
>
> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> + ? ? ? {
> + ? ? ? ?.deactivate_func = omap_device_idle_hwmods,
> + ? ? ? ?.activate_func = omap_device_enable_hwmods,
> + ? ? ? ?.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> + ? ? ? }
> +};
>
> instead of directly pointing activate_func to omap_device_enable_hwmods,
> it could point to a function that sets the required clock rate and then
> enables the hwmod.
>
>
> regards,
> -roger
>



-- 
Regards and Thanks,
Keerthy

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-12  1:02                       ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-12  1:14 UTC (permalink / raw)
  To: Roger Quadros
  Cc: balbi, Tony Lindgren, lm-sensors, vishwanath.bs, linux-omap,
	b-cousson, rnayak, Russell King, Linux ARM Kernel Mailing List,
	khali, guenter.roeck

On Fri, Aug 12, 2011 at 3:07 AM, Roger Quadros <rogerq@ti.com> wrote:
> On 08/11/2011 01:55 PM, Felipe Balbi wrote:
>> Hi,
>>
>> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>>> you need some other way to handle this. Why do you need to manually set
>>>>> the rate rather than having hwmod handle this for you ?
>>>>>
>>>>> your argument that "it's a one time setting" is not enough to have this
>>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>>> have been done on another layer.
>>>>
>>>> Hwmod will have no idea on the rate required.
>>>
>>> does the rate need to change ? Also, I have not mentioned hwmod anytime
>>
>> i did mention hwmod, nevermind that part. Still I'm not sure where is
>> the right place to handle this.
>>
>
> Aren't the omap_device_pm_latency callbacks the right place to do it?

It is a one time setting. These callbacks get called everytime
pm_runtime_get_sync and pm_runtime_put_sync are called.
IMHO this is not the right place.

>
> e.g. in the following snippet from mach-omap2/temp_sensor_device.c
>
> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> +       {
> +        .deactivate_func = omap_device_idle_hwmods,
> +        .activate_func = omap_device_enable_hwmods,
> +        .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> +       }
> +};
>
> instead of directly pointing activate_func to omap_device_enable_hwmods,
> it could point to a function that sets the required clock rate and then
> enables the hwmod.
>
>
> regards,
> -roger
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-11 21:37                     ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Roger Quadros
  (?)
@ 2011-08-12  3:26                       ` Rajendra Nayak
  -1 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-12  3:26 UTC (permalink / raw)
  To: Roger Quadros
  Cc: balbi, J, KEERTHY, Tony Lindgren, lm-sensors, vishwanath.bs,
	linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

On 8/12/2011 3:07 AM, Roger Quadros wrote:
> On 08/11/2011 01:55 PM, Felipe Balbi wrote:
>> Hi,
>>
>> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>>> you need some other way to handle this. Why do you need to manually set
>>>>> the rate rather than having hwmod handle this for you ?
>>>>>
>>>>> your argument that "it's a one time setting" is not enough to have this
>>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>>> have been done on another layer.
>>>>
>>>> Hwmod will have no idea on the rate required.
>>>
>>> does the rate need to change ? Also, I have not mentioned hwmod anytime
>>
>> i did mention hwmod, nevermind that part. Still I'm not sure where is
>> the right place to handle this.
>>
>
> Aren't the omap_device_pm_latency callbacks the right place to do it?
>
> e.g. in the following snippet from mach-omap2/temp_sensor_device.c
>
> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> +	{
> +	 .deactivate_func = omap_device_idle_hwmods,
> +	 .activate_func = omap_device_enable_hwmods,
> +	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> +	}
> +};
>
> instead of directly pointing activate_func to omap_device_enable_hwmods,
> it could point to a function that sets the required clock rate and then
> enables the hwmod.

FWIK, its a one time requirement to set the clock rate to the
right rate the device can operate in based on what a platform
supports. What you are suggesting would add the overhead of doing
this every time the device is runtime enabled/idled.

>
>
> regards,
> -roger


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-12  3:26                       ` Rajendra Nayak
  0 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-12  3:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 8/12/2011 3:07 AM, Roger Quadros wrote:
> On 08/11/2011 01:55 PM, Felipe Balbi wrote:
>> Hi,
>>
>> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>>> you need some other way to handle this. Why do you need to manually set
>>>>> the rate rather than having hwmod handle this for you ?
>>>>>
>>>>> your argument that "it's a one time setting" is not enough to have this
>>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>>> have been done on another layer.
>>>>
>>>> Hwmod will have no idea on the rate required.
>>>
>>> does the rate need to change ? Also, I have not mentioned hwmod anytime
>>
>> i did mention hwmod, nevermind that part. Still I'm not sure where is
>> the right place to handle this.
>>
>
> Aren't the omap_device_pm_latency callbacks the right place to do it?
>
> e.g. in the following snippet from mach-omap2/temp_sensor_device.c
>
> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> +	{
> +	 .deactivate_func = omap_device_idle_hwmods,
> +	 .activate_func = omap_device_enable_hwmods,
> +	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> +	}
> +};
>
> instead of directly pointing activate_func to omap_device_enable_hwmods,
> it could point to a function that sets the required clock rate and then
> enables the hwmod.

FWIK, its a one time requirement to set the clock rate to the
right rate the device can operate in based on what a platform
supports. What you are suggesting would add the overhead of doing
this every time the device is runtime enabled/idled.

>
>
> regards,
> -roger

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-12  3:26                       ` Rajendra Nayak
  0 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-12  3:38 UTC (permalink / raw)
  To: Roger Quadros
  Cc: balbi, J, KEERTHY, Tony Lindgren, lm-sensors, vishwanath.bs,
	linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

On 8/12/2011 3:07 AM, Roger Quadros wrote:
> On 08/11/2011 01:55 PM, Felipe Balbi wrote:
>> Hi,
>>
>> On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
>>>>> you need some other way to handle this. Why do you need to manually set
>>>>> the rate rather than having hwmod handle this for you ?
>>>>>
>>>>> your argument that "it's a one time setting" is not enough to have this
>>>>> in the driver. Drivers should not care about clocks anymore, this should
>>>>> have been done on another layer.
>>>>
>>>> Hwmod will have no idea on the rate required.
>>>
>>> does the rate need to change ? Also, I have not mentioned hwmod anytime
>>
>> i did mention hwmod, nevermind that part. Still I'm not sure where is
>> the right place to handle this.
>>
>
> Aren't the omap_device_pm_latency callbacks the right place to do it?
>
> e.g. in the following snippet from mach-omap2/temp_sensor_device.c
>
> +static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> +	{
> +	 .deactivate_func = omap_device_idle_hwmods,
> +	 .activate_func = omap_device_enable_hwmods,
> +	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> +	}
> +};
>
> instead of directly pointing activate_func to omap_device_enable_hwmods,
> it could point to a function that sets the required clock rate and then
> enables the hwmod.

FWIK, its a one time requirement to set the clock rate to the
right rate the device can operate in based on what a platform
supports. What you are suggesting would add the overhead of doing
this every time the device is runtime enabled/idled.

>
>
> regards,
> -roger


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-12  3:26                       ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Rajendra Nayak
  (?)
@ 2011-08-12  8:44                         ` Felipe Balbi
  -1 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-12  8:44 UTC (permalink / raw)
  To: Rajendra Nayak
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

[-- Attachment #1: Type: text/plain, Size: 2193 bytes --]

Hi,

On Fri, Aug 12, 2011 at 08:56:29AM +0530, Rajendra Nayak wrote:
> On 8/12/2011 3:07 AM, Roger Quadros wrote:
> >On 08/11/2011 01:55 PM, Felipe Balbi wrote:
> >>Hi,
> >>
> >>On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
> >>>>>you need some other way to handle this. Why do you need to manually set
> >>>>>the rate rather than having hwmod handle this for you ?
> >>>>>
> >>>>>your argument that "it's a one time setting" is not enough to have this
> >>>>>in the driver. Drivers should not care about clocks anymore, this should
> >>>>>have been done on another layer.
> >>>>
> >>>>Hwmod will have no idea on the rate required.
> >>>
> >>>does the rate need to change ? Also, I have not mentioned hwmod anytime
> >>
> >>i did mention hwmod, nevermind that part. Still I'm not sure where is
> >>the right place to handle this.
> >>
> >
> >Aren't the omap_device_pm_latency callbacks the right place to do it?
> >
> >e.g. in the following snippet from mach-omap2/temp_sensor_device.c
> >
> >+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> >+	{
> >+	 .deactivate_func = omap_device_idle_hwmods,
> >+	 .activate_func = omap_device_enable_hwmods,
> >+	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> >+	}
> >+};
> >
> >instead of directly pointing activate_func to omap_device_enable_hwmods,
> >it could point to a function that sets the required clock rate and then
> >enables the hwmod.
> 
> FWIK, its a one time requirement to set the clock rate to the
> right rate the device can operate in based on what a platform
> supports. What you are suggesting would add the overhead of doing
> this every time the device is runtime enabled/idled.

if it's a one time setting, why don't you just change the clock fwk to
handle this nicely ? Maybe provide a different ->enable() function which
would already set the correct rate ?

Russell, what would be the best way here ? driver needs clock to be at a
particular rate for the device to work, but it's a one time setting and
I don't think driver should be doing clk_get() - clk_enable() -
clk_set_rate(), where should that functionality be put ?

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-12  8:44                         ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-12  8:44 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Fri, Aug 12, 2011 at 08:56:29AM +0530, Rajendra Nayak wrote:
> On 8/12/2011 3:07 AM, Roger Quadros wrote:
> >On 08/11/2011 01:55 PM, Felipe Balbi wrote:
> >>Hi,
> >>
> >>On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
> >>>>>you need some other way to handle this. Why do you need to manually set
> >>>>>the rate rather than having hwmod handle this for you ?
> >>>>>
> >>>>>your argument that "it's a one time setting" is not enough to have this
> >>>>>in the driver. Drivers should not care about clocks anymore, this should
> >>>>>have been done on another layer.
> >>>>
> >>>>Hwmod will have no idea on the rate required.
> >>>
> >>>does the rate need to change ? Also, I have not mentioned hwmod anytime
> >>
> >>i did mention hwmod, nevermind that part. Still I'm not sure where is
> >>the right place to handle this.
> >>
> >
> >Aren't the omap_device_pm_latency callbacks the right place to do it?
> >
> >e.g. in the following snippet from mach-omap2/temp_sensor_device.c
> >
> >+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> >+	{
> >+	 .deactivate_func = omap_device_idle_hwmods,
> >+	 .activate_func = omap_device_enable_hwmods,
> >+	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> >+	}
> >+};
> >
> >instead of directly pointing activate_func to omap_device_enable_hwmods,
> >it could point to a function that sets the required clock rate and then
> >enables the hwmod.
> 
> FWIK, its a one time requirement to set the clock rate to the
> right rate the device can operate in based on what a platform
> supports. What you are suggesting would add the overhead of doing
> this every time the device is runtime enabled/idled.

if it's a one time setting, why don't you just change the clock fwk to
handle this nicely ? Maybe provide a different ->enable() function which
would already set the correct rate ?

Russell, what would be the best way here ? driver needs clock to be at a
particular rate for the device to work, but it's a one time setting and
I don't think driver should be doing clk_get() - clk_enable() -
clk_set_rate(), where should that functionality be put ?

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110812/e7038205/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-12  8:44                         ` Felipe Balbi
  0 siblings, 0 replies; 105+ messages in thread
From: Felipe Balbi @ 2011-08-12  8:44 UTC (permalink / raw)
  To: Rajendra Nayak
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck


[-- Attachment #1.1: Type: text/plain, Size: 2193 bytes --]

Hi,

On Fri, Aug 12, 2011 at 08:56:29AM +0530, Rajendra Nayak wrote:
> On 8/12/2011 3:07 AM, Roger Quadros wrote:
> >On 08/11/2011 01:55 PM, Felipe Balbi wrote:
> >>Hi,
> >>
> >>On Thu, Aug 11, 2011 at 09:54:09PM +0300, Felipe Balbi wrote:
> >>>>>you need some other way to handle this. Why do you need to manually set
> >>>>>the rate rather than having hwmod handle this for you ?
> >>>>>
> >>>>>your argument that "it's a one time setting" is not enough to have this
> >>>>>in the driver. Drivers should not care about clocks anymore, this should
> >>>>>have been done on another layer.
> >>>>
> >>>>Hwmod will have no idea on the rate required.
> >>>
> >>>does the rate need to change ? Also, I have not mentioned hwmod anytime
> >>
> >>i did mention hwmod, nevermind that part. Still I'm not sure where is
> >>the right place to handle this.
> >>
> >
> >Aren't the omap_device_pm_latency callbacks the right place to do it?
> >
> >e.g. in the following snippet from mach-omap2/temp_sensor_device.c
> >
> >+static struct omap_device_pm_latency omap_temp_sensor_latency[] = {
> >+	{
> >+	 .deactivate_func = omap_device_idle_hwmods,
> >+	 .activate_func = omap_device_enable_hwmods,
> >+	 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> >+	}
> >+};
> >
> >instead of directly pointing activate_func to omap_device_enable_hwmods,
> >it could point to a function that sets the required clock rate and then
> >enables the hwmod.
> 
> FWIK, its a one time requirement to set the clock rate to the
> right rate the device can operate in based on what a platform
> supports. What you are suggesting would add the overhead of doing
> this every time the device is runtime enabled/idled.

if it's a one time setting, why don't you just change the clock fwk to
handle this nicely ? Maybe provide a different ->enable() function which
would already set the correct rate ?

Russell, what would be the best way here ? driver needs clock to be at a
particular rate for the device to work, but it's a one time setting and
I don't think driver should be doing clk_get() - clk_enable() -
clk_set_rate(), where should that functionality be put ?

-- 
balbi

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-10 16:47     ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die R, Durgadoss
@ 2011-08-15  6:34       ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-15  6:22 UTC (permalink / raw)
  To: R, Durgadoss; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

Hi,

Thanks for the Review Durga.

On Wed, Aug 10, 2011 at 10:05 PM, R, Durgadoss <durgadoss.r@intel.com> wrote:
> Hi,
>
>> -----Original Message-----
>> From: lm-sensors-bounces@lm-sensors.org [mailto:lm-sensors-bounces@lm-
>> sensors.org] On Behalf Of Keerthy
>> Sent: Wednesday, August 10, 2011 5:55 PM
>> To: lm-sensors@lm-sensors.org
>> Cc: vishwanath.bs@ti.com; linux-omap@vger.kernel.org; b-cousson@ti.com;
>> rnayak@ti.com
>> Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor
>> driver
>>
>> On chip temperature sensor driver. The driver monitors the temperature of
>> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>> the temperature crosses user defined thresholds via kobject_uevent interface.
>> The user is allowed to configure the temperature thresholds vis sysfs nodes
>> exposed using hwmon interface.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>>  drivers/hwmon/Kconfig            |   11 +
>>  drivers/hwmon/Makefile           |    1 +
>>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 962 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>>
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 5f888f7..9c9cd8b 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>>         This driver can also be built as a module.  If so, the module
>>         will be called f71805f.
>>
>> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>> +     bool "OMAP on-die temperature sensor hwmon driver"
>> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>> +     help
>> +       If you say yes here you get support for hardware
>> +       monitoring features of the OMAP on die temperature
>> +       sensor.
>> +
>> +       Continuous conversion programmable delay
>> +       mode is used for temperature conversion.
>> +
>>  config SENSORS_F71882FG
>>       tristate "Fintek F71882FG and compatibles"
>>       help
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index 28061cf..d0f89f5 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
>> diff --git a/drivers/hwmon/omap_temp_sensor.c
>> b/drivers/hwmon/omap_temp_sensor.c
>> new file mode 100644
>> index 0000000..15e2559
>> --- /dev/null
>> +++ b/drivers/hwmon/omap_temp_sensor.c
>> @@ -0,0 +1,950 @@
>> +/*
>> + * OMAP4 Temperature sensor driver file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@ti.com>
>> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> +#include <linux/clk.h>
>> +#include <linux/io.h>
>> +#include <linux/debugfs.h>
>> +#include <linux/delay.h>
>> +#include <linux/slab.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/init.h>
>> +#include <plat/omap_device.h>
>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <linux/device.h>
>> +#include <linux/jiffies.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +#include <linux/stddef.h>
>> +#include <linux/sysfs.h>
>> +#include <linux/err.h>
>> +#include <linux/types.h>
>> +#include <linux/mutex.h>
>> +#include <linux/pm_runtime.h>
>> +#include <plat/common.h>
>> +#include <plat/temperature_sensor.h>
>> +#include <mach/ctrl_module_core_44xx.h>
>> +#include <mach/gpio.h>
>> +
>> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
>> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
>> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
>> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
>> +#define OMAP_ADC_START_VALUE 530
>> +#define OMAP_ADC_END_VALUE   923
>> +
>> +/*
>> + * omap_temp_sensor structure
>> + * @hwmon_dev - device pointer
>> + * @clock - Clock pointer
>> + * @registers - Pointer to structure with register offsets and bitfields
>> + * @sensor_mutex - Mutex for sysfs, irq and PM
>> + * @irq - MPU Irq number for thermal alert
>> + * @phy_base - Physical base of the temp I/O
>> + * @clk_rate - Holds current clock rate
>> + * @temp_sensor_ctrl - temp sensor control register value
>> + * @bg_ctrl - bandgap ctrl register value
>> + * @bg_counter - bandgap counter value
>> + * @bg_threshold - bandgap threshold register value
>> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>> + * @clk_on - Manages the current clock state
>> + */
>> +struct omap_temp_sensor {
>> +     struct device           *hwmon_dev;
>> +     struct clk              *clock;
>> +     struct omap_temp_sensor_registers *registers;
>> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
>> +     unsigned int            irq;
>> +     void __iomem            *phy_base;
>> +     u32                     clk_rate;
>> +     u32                     temp_sensor_ctrl;
>> +     u32                     bg_ctrl;
>> +     u32                     bg_counter;
>> +     u32                     bg_threshold;
>> +     u32                     temp_sensor_tshut_threshold;
>> +     bool                    is_efuse_valid;
>> +     bool                    clk_on;
>> +};
>> +
>> +/*
>> + * Temperature values in milli degree celsius
>> + * ADC code values from 530 to 923
>> + */
>> +static int adc_to_temp[] = {
>> +     -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
>> +};
>> +
>> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>> +                                         *temp_sensor, u32 reg)
>> +{
>> +     return __raw_readl(temp_sensor->phy_base + reg);
>> +}
>> +
>> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>> +                                 u32 val, u32 reg)
>> +{
>> +     __raw_writel(val, (temp_sensor->phy_base + reg));
>> +}
>> +
>> +static int adc_to_temp_conversion(int adc_val)
>> +{
>> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>> +}
>> +
>> +static int temp_to_adc_conversion(long temp)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>> +             if (temp < adc_to_temp[i])
>> +                     return OMAP_ADC_START_VALUE + i - 1;
>> +
>> +     return -EINVAL;
>> +}
>> +
>> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>> +                                               *temp_sensor)
>> +{
>> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>> +
>> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>> +
>> +     /* Configure the TALERT thresholds */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +             temp_sensor->registers->bgap_threshold);
>> +
>> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>> +
>> +     /* Configure the TSHUT thresholds */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->thsut_threshold);
>> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                     temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>> +                                            *temp_sensor, u32 counter)
>> +{
>> +     u32 val;
>> +
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +     val &= ~(temp_sensor->registers->counter_mask);
>> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +                     temp_sensor->registers->bgap_counter);
>> +}
>> +
>> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>> +                                     bool enable)
>> +{
>> +     u32 val;
>> +
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_mode_ctrl);
>> +
>> +     if (enable)
>> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>> +     else
>> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
>> +
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +                     temp_sensor->registers->bgap_mode_ctrl);
>> +}
>> +
>> +/* Sysfs hook functions */
>> +
>> +static ssize_t show_temp_max(struct device *dev,
>> +                     struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     int temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
>> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid value\n");
>> +             goto out;
>> +     }
>> +     temp = adc_to_temp_conversion(temp);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return snprintf(buf, 16, "%d\n", temp);
>
> Even if it is invalid value, you are printing it.
> May be you would have to do unlocking and returning -EINVAL inside the 'if' check.

Ok

>
> Moreover, you are just doing a read.
> So, do you really need a mutex_lock in this function.. ?

These values are RW. So the user can write a new value
while you are reading. To be consistent mutex_lock is needed.

>
>> +}
>> +
>> +static ssize_t set_temp_max(struct device *dev,
>> +                         struct device_attribute *devattr,
>> +                         const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     long                    val;
>> +     u32                     reg_val, t_cold, t_hot, temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     t_hot = temp_to_adc_conversion(val);
>> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>> +             dev_err(dev, "invalid range\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* obtain the T cold value */
>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> +     if (t_hot < t_cold) {
>> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* write the new t_hot value */
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>> +     reg_val |= (t_hot <<
>> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_threshold);
>> +
>> +     /* Read the current temperature */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> +     /*
>> +      * If user sets the HIGH threshold(t_hot) greater than the current
>> +      * temperature(temp) unmask the HOT interrupts
>> +      */
>> +     if (t_hot > temp) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * If current temperature is in-between the hot and cold thresholds,
>> +      * Enable both masks.
>> +      */
>> +     if (temp > t_cold && temp < t_hot) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             OMAP4460_BGAP_CTRL_OFFSET);
>> +     }
>> +     /*
>> +      * else no need to do anything since HW will immediately compare
>> +      * the new threshold and generate interrupt accordingly
>> +      */
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static ssize_t show_temp_max_hyst(struct device *dev,
>> +             struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_threshold);
>> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid value\n");
>> +             goto out;
>
> Same case here..
> You can do ret = -EINVAL here..

Ok

>
>> +     }
>> +
>> +     temp = adc_to_temp_conversion(temp);
>
> ...subsequently,
> ret = snprintf(buf, 16, "%d\n", temp);
>
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return snprintf(buf, 16, "%d\n", temp);
>
> Return ret here..

Ok

>
>> +}
>> +
>> +static ssize_t set_temp_max_hyst(struct device *dev,
>> +                              struct device_attribute *devattr,
>> +                              const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
>> +     u32                             reg_val, t_hot, t_cold, temp;
>> +     long                            val;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     t_cold = temp_to_adc_conversion(val);
>> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid range");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* obtain the T HOT value */
>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> +     if (t_cold > t_hot) {
>> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* write the new t_cold value */
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>> +     reg_val |= (t_cold <<
>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_threshold);
>> +
>> +     /* Read the current temperature */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> +     /*
>> +      * If user sets the LOW threshold(t_cold) lower than the current
>> +      * temperature(temp) unmask the COLD interrupts
>> +      */
>> +     if (t_cold < temp) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * If current temperature is in-between the hot and cold thresholds,
>> +      * Enable both masks.
>> +      */
>> +     if (temp < t_hot && temp > t_cold) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * else no need to do anything since HW will immediately compare
>> +      * the new threshold and generate interrupt accordingly
>> +      */
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static ssize_t show_update_rate(struct device *dev,
>> +                     struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     temp = 0, ret = 0;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (!temp_sensor->clk_rate) {
>> +             dev_err(dev, "clk_rate is NULL\n");
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +     temp = (temp & temp_sensor->registers->counter_mask) >>
>> +                     __ffs(temp_sensor->registers->counter_mask);
>> +     temp = temp * 1000 / (temp_sensor->clk_rate);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     if (!ret)
>> +             return sprintf(buf, "%d\n", temp);
>> +     else
>
> The 'else' is not necessary..

Ok

>
>> +             return ret;
>> +}
>> +
>> +static ssize_t set_update_rate(struct device *dev,
>> +                            struct device_attribute *devattr,
>> +                            const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     reg_val;
>> +     long                    val;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     val *= temp_sensor->clk_rate / 1000;
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +
>> +     reg_val &= ~(temp_sensor->registers->counter_mask);
>> +     reg_val |= val;
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_counter);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static int omap_temp_sensor_read_temp(struct device *dev,
>> +                                   struct device_attribute *devattr,
>> +                                   char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     int                     temp, ret = 0;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
>> +
>> +     if (!temp_sensor->is_efuse_valid)
>> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not
>> accurate\n");
>> +
>> +     /* look up for temperature in the table and return the temperature */
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid adc code reported %d", temp);
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     if (!ret)
>> +             return sprintf(buf, "%d\n", temp);
>> +     else
>
> Same here..

Ok

>
>> +             return ret;
>> +}
>> +
>> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>> +                       NULL, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>> +                       set_temp_max, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
>> show_temp_max_hyst,
>> +                       set_temp_max_hyst, 0);
>> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>> +                       set_update_rate, 0);
>> +
>> +static struct attribute *omap_temp_sensor_attributes[] = {
>> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
>> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
>> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>> +     &sensor_dev_attr_update_rate.dev_attr.attr,
>> +     NULL
>> +};
>> +
>> +static const struct attribute_group omap_temp_sensor_group = {
>> +     .attrs = omap_temp_sensor_attributes,
>> +};
>> +
>> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     u32 ret = 0, temp;
>> +
>> +     if (temp_sensor->clk_on) {
>> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>> +             goto out;
>> +     }
>> +
>> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>> +     if (ret < 0) {
>> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>> +             ret = -EINVAL;
>
> Please do not mask the return value.
> Let it be whatever returned by the get_sync.
> Anyway, you are returning 'ret' in the end...
>
>> +             goto out;
>> +     }
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>> +     /* BGAP_TEMPSOFF should be reset to 0 */
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp_sensor->clk_on = 1;
>> +out:
>> +     return ret;
>> +}
>> +
>> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     u32 temp, ret = 0;
>> +     unsigned long timeout;
>> +
>> +     if (!temp_sensor->clk_on) {
>> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>> +             goto out;
>> +     }
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
>> +
>> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status);
>> +     timeout = jiffies + msecs_to_jiffies(5);
>> +
>> +     /* wait till the clean stop bit is set or till the timeout exppires */
>
> s/expires/expires

I will correct this.

>
>> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>> +             !(time_after(jiffies, timeout))) {
>> +             temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status);
>> +             usleep_range(500, 2000);
>> +     }
>> +
>> +     if (time_after(jiffies, timeout))
>> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>> +     /* Gate the clock */
>> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>> +     if (ret < 0) {
>> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>> +             ret = -EINVAL;
>
> Same case as get_sync. Don't mask the return value.

Ok

>
>> +             goto out;
>> +     }
>> +     temp_sensor->clk_on = 0;
>> +out:
>> +     return ret;
>> +}
>> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
>> +{
>> +     struct omap_temp_sensor         *temp_sensor;
>> +     int                             t_hot, t_cold, temp;
>> +
>> +     temp_sensor = data;
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     /* Read the status of t_hot */
>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status)
>> +                     & temp_sensor->registers->status_hot_mask;
>> +
>> +     /* Read the status of t_cold */
>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status)
>> +                     & temp_sensor->registers->status_cold_mask;
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_mask_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) {
>> +             temp &= ~(temp_sensor->registers->mask_hot_mask);
>> +             temp |= temp_sensor->registers->mask_cold_mask;
>> +     } else if (t_cold) {
>> +             temp &= ~(temp_sensor->registers->mask_cold_mask);
>> +             temp |= temp_sensor->registers->mask_hot_mask;
>> +     }
>> +
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +
>> +     /* kobject_uvent to user space telling thermal threshold crossed */
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
>> +
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return IRQ_HANDLED;
>> +}
>> +
>> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
>> +{
>> +     struct omap_temp_sensor_pdata   *pdata  = pdev->dev.platform_data;
>> +     struct omap_temp_sensor         *temp_sensor;
>> +     struct resource                 *mem;
>> +     int                             ret = 0;
>> +     int                             val, clk_rate;
>> +
>> +     if (!pdata) {
>> +             dev_err(&pdev->dev, "platform data missing\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
>> +     if (!temp_sensor)
>> +             return -ENOMEM;
>> +
>> +     mutex_init(&temp_sensor->sensor_mutex);
>> +
>> +     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     if (!mem) {
>> +             dev_err(&pdev->dev, "no mem resource\n");
>> +             ret = -EINVAL;
>
> You can do PTR_ERR(mem) to get the return error value as an integer.
> Otherwise, it makes more sense to be -ENOMEM

Ok

>
>> +             goto plat_res_err;
>> +     }
>> +
>> +     temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
>> +     if (temp_sensor->irq == -ENXIO) {
>> +             dev_err(&pdev->dev, "get_irq_byname failed\n");
>> +             ret = temp_sensor->irq;
>> +             goto plat_res_err;
>> +     }
>> +
>
> This flow can better be:
> ret = platform_get_irq_byname(...)
> if (ret < 0) //because it is an IRQ number
> { ... }
>

Ok


> Then assign ret to temp_sensor->irq

Ok

>
>> +     temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
>> +     temp_sensor->clock = NULL;
>> +     temp_sensor->registers = pdata->registers;
>> +     temp_sensor->hwmon_dev = &pdev->dev;
>> +
>> +     pm_runtime_enable(&pdev->dev);
>> +     pm_runtime_irq_safe(&pdev->dev);
>> +
>> +     /*
>> +      * check if the efuse has a non-zero value if not
>> +      * it is an untrimmed sample and the temperatures
>> +      * may not be accurate
>> +      */
>> +
>> +     if (omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_efuse))
>> +             temp_sensor->is_efuse_valid = 1;
>> +
>> +     platform_set_drvdata(pdev, temp_sensor);
>> +     dev_set_drvdata(&pdev->dev, temp_sensor);
>> +     temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
>> +     if (IS_ERR(temp_sensor->clock)) {
>> +             ret = PTR_ERR(temp_sensor->clock);
>> +             dev_err(temp_sensor->hwmon_dev,
>> +                     "unable to get fclk: %d\n", ret);
>> +             ret = -EINVAL;
>
> Same case here. Do not assign -EINVAL to ret

Ok

>
>> +             goto plat_res_err;
>> +     }
>> +
>> +     ret = omap_temp_sensor_clk_enable(temp_sensor);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Cannot enable temp sensor\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
>> +     if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
>> +             dev_err(&pdev->dev, "Error round rate\n");
>
> You might want to assign something to 'ret' here.

Ok

>
>> +             goto clken_err;
>> +     }
>> +
>> +     ret = clk_set_rate(temp_sensor->clock, clk_rate);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Cannot set clock rate\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     temp_sensor->clk_rate = clk_rate;
>> +     omap_enable_continuous_mode(temp_sensor, 1);
>> +     omap_configure_temp_sensor_thresholds(temp_sensor);
>> +     /* 1 ms */
>> +     omap_configure_temp_sensor_counter(temp_sensor, 1);
>> +
>> +     /* Wait till the first conversion is done wait for at least 1ms */
>> +     usleep_range(1000, 2000);
>> +
>> +     /* Read the temperature once due to hw issue*/
>> +     omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +
>> +     /* Set 2 seconds time as default counter */
>> +     omap_configure_temp_sensor_counter(temp_sensor,
>> +                                             temp_sensor->clk_rate * 2);
>> +
>> +     temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
>> +     if (IS_ERR(temp_sensor->hwmon_dev)) {
>> +             dev_err(&pdev->dev, "hwmon_device_register failed.\n");
>> +             ret = PTR_ERR(temp_sensor->hwmon_dev);
>> +             goto hwmon_reg_err;
>> +     }
>> +
>> +     ret = sysfs_create_group(&pdev->dev.kobj,
>> +                              &omap_temp_sensor_group);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "could not create sysfs files\n");
>> +             goto sysfs_create_err;
>> +     }
>> +
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
>> +
>> +     ret = request_threaded_irq(temp_sensor->irq, NULL,
>> +             omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
>> +                     "temp_sensor", temp_sensor);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Request threaded irq failed.\n");
>> +             goto req_irq_err;
>> +     }
>> +
>> +     /* unmask the T_COLD and unmask T_HOT at init */
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +     val |= temp_sensor->registers->mask_cold_mask
>> +             | temp_sensor->registers->mask_hot_mask;
>> +
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +
>> +     return 0;
>> +
>> +req_irq_err:
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>> +                             &omap_temp_sensor_group);
>> +sysfs_create_err:
>> +     hwmon_device_unregister(&pdev->dev);
>> +hwmon_reg_err:
>> +     omap_temp_sensor_clk_disable(temp_sensor);
>> +clken_err:
>> +     if (temp_sensor->clock)
>
> Looking at the probe flow, this 'if' check seems unnecessary.

Ok

>
> Thanks,
> Durga
>
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-15  6:34       ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-15  6:34 UTC (permalink / raw)
  To: R, Durgadoss; +Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak

Hi,

Thanks for the Review Durga.

On Wed, Aug 10, 2011 at 10:05 PM, R, Durgadoss <durgadoss.r@intel.com> wrote:
> Hi,
>
>> -----Original Message-----
>> From: lm-sensors-bounces@lm-sensors.org [mailto:lm-sensors-bounces@lm-
>> sensors.org] On Behalf Of Keerthy
>> Sent: Wednesday, August 10, 2011 5:55 PM
>> To: lm-sensors@lm-sensors.org
>> Cc: vishwanath.bs@ti.com; linux-omap@vger.kernel.org; b-cousson@ti.com;
>> rnayak@ti.com
>> Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor
>> driver
>>
>> On chip temperature sensor driver. The driver monitors the temperature of
>> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>> the temperature crosses user defined thresholds via kobject_uevent interface.
>> The user is allowed to configure the temperature thresholds vis sysfs nodes
>> exposed using hwmon interface.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> ---
>>  drivers/hwmon/Kconfig            |   11 +
>>  drivers/hwmon/Makefile           |    1 +
>>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 962 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>>
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 5f888f7..9c9cd8b 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>>         This driver can also be built as a module.  If so, the module
>>         will be called f71805f.
>>
>> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>> +     bool "OMAP on-die temperature sensor hwmon driver"
>> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>> +     help
>> +       If you say yes here you get support for hardware
>> +       monitoring features of the OMAP on die temperature
>> +       sensor.
>> +
>> +       Continuous conversion programmable delay
>> +       mode is used for temperature conversion.
>> +
>>  config SENSORS_F71882FG
>>       tristate "Fintek F71882FG and compatibles"
>>       help
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index 28061cf..d0f89f5 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
>> diff --git a/drivers/hwmon/omap_temp_sensor.c
>> b/drivers/hwmon/omap_temp_sensor.c
>> new file mode 100644
>> index 0000000..15e2559
>> --- /dev/null
>> +++ b/drivers/hwmon/omap_temp_sensor.c
>> @@ -0,0 +1,950 @@
>> +/*
>> + * OMAP4 Temperature sensor driver file
>> + *
>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>> + * Author: J Keerthy <j-keerthy@ti.com>
>> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>> +#include <linux/clk.h>
>> +#include <linux/io.h>
>> +#include <linux/debugfs.h>
>> +#include <linux/delay.h>
>> +#include <linux/slab.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/init.h>
>> +#include <plat/omap_device.h>
>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <linux/device.h>
>> +#include <linux/jiffies.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +#include <linux/stddef.h>
>> +#include <linux/sysfs.h>
>> +#include <linux/err.h>
>> +#include <linux/types.h>
>> +#include <linux/mutex.h>
>> +#include <linux/pm_runtime.h>
>> +#include <plat/common.h>
>> +#include <plat/temperature_sensor.h>
>> +#include <mach/ctrl_module_core_44xx.h>
>> +#include <mach/gpio.h>
>> +
>> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
>> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
>> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
>> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
>> +#define OMAP_ADC_START_VALUE 530
>> +#define OMAP_ADC_END_VALUE   923
>> +
>> +/*
>> + * omap_temp_sensor structure
>> + * @hwmon_dev - device pointer
>> + * @clock - Clock pointer
>> + * @registers - Pointer to structure with register offsets and bitfields
>> + * @sensor_mutex - Mutex for sysfs, irq and PM
>> + * @irq - MPU Irq number for thermal alert
>> + * @phy_base - Physical base of the temp I/O
>> + * @clk_rate - Holds current clock rate
>> + * @temp_sensor_ctrl - temp sensor control register value
>> + * @bg_ctrl - bandgap ctrl register value
>> + * @bg_counter - bandgap counter value
>> + * @bg_threshold - bandgap threshold register value
>> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>> + * @clk_on - Manages the current clock state
>> + */
>> +struct omap_temp_sensor {
>> +     struct device           *hwmon_dev;
>> +     struct clk              *clock;
>> +     struct omap_temp_sensor_registers *registers;
>> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
>> +     unsigned int            irq;
>> +     void __iomem            *phy_base;
>> +     u32                     clk_rate;
>> +     u32                     temp_sensor_ctrl;
>> +     u32                     bg_ctrl;
>> +     u32                     bg_counter;
>> +     u32                     bg_threshold;
>> +     u32                     temp_sensor_tshut_threshold;
>> +     bool                    is_efuse_valid;
>> +     bool                    clk_on;
>> +};
>> +
>> +/*
>> + * Temperature values in milli degree celsius
>> + * ADC code values from 530 to 923
>> + */
>> +static int adc_to_temp[] = {
>> +     -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
>> +};
>> +
>> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>> +                                         *temp_sensor, u32 reg)
>> +{
>> +     return __raw_readl(temp_sensor->phy_base + reg);
>> +}
>> +
>> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>> +                                 u32 val, u32 reg)
>> +{
>> +     __raw_writel(val, (temp_sensor->phy_base + reg));
>> +}
>> +
>> +static int adc_to_temp_conversion(int adc_val)
>> +{
>> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>> +}
>> +
>> +static int temp_to_adc_conversion(long temp)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>> +             if (temp < adc_to_temp[i])
>> +                     return OMAP_ADC_START_VALUE + i - 1;
>> +
>> +     return -EINVAL;
>> +}
>> +
>> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>> +                                               *temp_sensor)
>> +{
>> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>> +
>> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>> +
>> +     /* Configure the TALERT thresholds */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +             temp_sensor->registers->bgap_threshold);
>> +
>> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>> +
>> +     /* Configure the TSHUT thresholds */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->thsut_threshold);
>> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                     temp_sensor->registers->thsut_threshold);
>> +}
>> +
>> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>> +                                            *temp_sensor, u32 counter)
>> +{
>> +     u32 val;
>> +
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +     val &= ~(temp_sensor->registers->counter_mask);
>> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +                     temp_sensor->registers->bgap_counter);
>> +}
>> +
>> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>> +                                     bool enable)
>> +{
>> +     u32 val;
>> +
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_mode_ctrl);
>> +
>> +     if (enable)
>> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>> +     else
>> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
>> +
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +                     temp_sensor->registers->bgap_mode_ctrl);
>> +}
>> +
>> +/* Sysfs hook functions */
>> +
>> +static ssize_t show_temp_max(struct device *dev,
>> +                     struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     int temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
>> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid value\n");
>> +             goto out;
>> +     }
>> +     temp = adc_to_temp_conversion(temp);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return snprintf(buf, 16, "%d\n", temp);
>
> Even if it is invalid value, you are printing it.
> May be you would have to do unlocking and returning -EINVAL inside the 'if' check.

Ok

>
> Moreover, you are just doing a read.
> So, do you really need a mutex_lock in this function.. ?

These values are RW. So the user can write a new value
while you are reading. To be consistent mutex_lock is needed.

>
>> +}
>> +
>> +static ssize_t set_temp_max(struct device *dev,
>> +                         struct device_attribute *devattr,
>> +                         const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     long                    val;
>> +     u32                     reg_val, t_cold, t_hot, temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     t_hot = temp_to_adc_conversion(val);
>> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>> +             dev_err(dev, "invalid range\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* obtain the T cold value */
>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> +     if (t_hot < t_cold) {
>> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* write the new t_hot value */
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>> +     reg_val |= (t_hot <<
>> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_threshold);
>> +
>> +     /* Read the current temperature */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> +     /*
>> +      * If user sets the HIGH threshold(t_hot) greater than the current
>> +      * temperature(temp) unmask the HOT interrupts
>> +      */
>> +     if (t_hot > temp) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * If current temperature is in-between the hot and cold thresholds,
>> +      * Enable both masks.
>> +      */
>> +     if (temp > t_cold && temp < t_hot) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             OMAP4460_BGAP_CTRL_OFFSET);
>> +     }
>> +     /*
>> +      * else no need to do anything since HW will immediately compare
>> +      * the new threshold and generate interrupt accordingly
>> +      */
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static ssize_t show_temp_max_hyst(struct device *dev,
>> +             struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     temp;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_threshold);
>> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
>> +
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid value\n");
>> +             goto out;
>
> Same case here..
> You can do ret = -EINVAL here..

Ok

>
>> +     }
>> +
>> +     temp = adc_to_temp_conversion(temp);
>
> ...subsequently,
> ret = snprintf(buf, 16, "%d\n", temp);
>
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return snprintf(buf, 16, "%d\n", temp);
>
> Return ret here..

Ok

>
>> +}
>> +
>> +static ssize_t set_temp_max_hyst(struct device *dev,
>> +                              struct device_attribute *devattr,
>> +                              const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
>> +     u32                             reg_val, t_hot, t_cold, temp;
>> +     long                            val;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     t_cold = temp_to_adc_conversion(val);
>> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid range");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* obtain the T HOT value */
>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
>> +
>> +     if (t_cold > t_hot) {
>> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     /* write the new t_cold value */
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_threshold);
>> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>> +     reg_val |= (t_cold <<
>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_threshold);
>> +
>> +     /* Read the current temperature */
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>> +
>> +     /*
>> +      * If user sets the LOW threshold(t_cold) lower than the current
>> +      * temperature(temp) unmask the COLD interrupts
>> +      */
>> +     if (t_cold < temp) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * If current temperature is in-between the hot and cold thresholds,
>> +      * Enable both masks.
>> +      */
>> +     if (temp < t_hot && temp > t_cold) {
>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                             temp_sensor->registers->bgap_mask_ctrl);
>> +     }
>> +
>> +     /*
>> +      * else no need to do anything since HW will immediately compare
>> +      * the new threshold and generate interrupt accordingly
>> +      */
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static ssize_t show_update_rate(struct device *dev,
>> +                     struct device_attribute *devattr, char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     temp = 0, ret = 0;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (!temp_sensor->clk_rate) {
>> +             dev_err(dev, "clk_rate is NULL\n");
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +     temp = (temp & temp_sensor->registers->counter_mask) >>
>> +                     __ffs(temp_sensor->registers->counter_mask);
>> +     temp = temp * 1000 / (temp_sensor->clk_rate);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     if (!ret)
>> +             return sprintf(buf, "%d\n", temp);
>> +     else
>
> The 'else' is not necessary..

Ok

>
>> +             return ret;
>> +}
>> +
>> +static ssize_t set_update_rate(struct device *dev,
>> +                            struct device_attribute *devattr,
>> +                            const char *buf, size_t count)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     u32                     reg_val;
>> +     long                    val;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     if (strict_strtol(buf, 10, &val)) {
>> +             count = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     val *= temp_sensor->clk_rate / 1000;
>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_counter);
>> +
>> +     reg_val &= ~(temp_sensor->registers->counter_mask);
>> +     reg_val |= val;
>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>> +                     temp_sensor->registers->bgap_counter);
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     return count;
>> +}
>> +
>> +static int omap_temp_sensor_read_temp(struct device *dev,
>> +                                   struct device_attribute *devattr,
>> +                                   char *buf)
>> +{
>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>> +     int                     temp, ret = 0;
>> +
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
>> +
>> +     if (!temp_sensor->is_efuse_valid)
>> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not
>> accurate\n");
>> +
>> +     /* look up for temperature in the table and return the temperature */
>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>> +             dev_err(dev, "invalid adc code reported %d", temp);
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>> +
>> +out:
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +     if (!ret)
>> +             return sprintf(buf, "%d\n", temp);
>> +     else
>
> Same here..

Ok

>
>> +             return ret;
>> +}
>> +
>> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>> +                       NULL, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>> +                       set_temp_max, 0);
>> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
>> show_temp_max_hyst,
>> +                       set_temp_max_hyst, 0);
>> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>> +                       set_update_rate, 0);
>> +
>> +static struct attribute *omap_temp_sensor_attributes[] = {
>> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
>> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
>> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>> +     &sensor_dev_attr_update_rate.dev_attr.attr,
>> +     NULL
>> +};
>> +
>> +static const struct attribute_group omap_temp_sensor_group = {
>> +     .attrs = omap_temp_sensor_attributes,
>> +};
>> +
>> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     u32 ret = 0, temp;
>> +
>> +     if (temp_sensor->clk_on) {
>> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>> +             goto out;
>> +     }
>> +
>> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>> +     if (ret < 0) {
>> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>> +             ret = -EINVAL;
>
> Please do not mask the return value.
> Let it be whatever returned by the get_sync.
> Anyway, you are returning 'ret' in the end...
>
>> +             goto out;
>> +     }
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>> +     /* BGAP_TEMPSOFF should be reset to 0 */
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                             temp_sensor->registers->temp_sensor_ctrl);
>> +     temp_sensor->clk_on = 1;
>> +out:
>> +     return ret;
>> +}
>> +
>> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>> +{
>> +     u32 temp, ret = 0;
>> +     unsigned long timeout;
>> +
>> +     if (!temp_sensor->clk_on) {
>> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>> +             goto out;
>> +     }
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
>> +
>> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status);
>> +     timeout = jiffies + msecs_to_jiffies(5);
>> +
>> +     /* wait till the clean stop bit is set or till the timeout exppires */
>
> s/expires/expires

I will correct this.

>
>> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>> +             !(time_after(jiffies, timeout))) {
>> +             temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status);
>> +             usleep_range(500, 2000);
>> +     }
>> +
>> +     if (time_after(jiffies, timeout))
>> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>> +     /* Gate the clock */
>> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>> +     if (ret < 0) {
>> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>> +             ret = -EINVAL;
>
> Same case as get_sync. Don't mask the return value.

Ok

>
>> +             goto out;
>> +     }
>> +     temp_sensor->clk_on = 0;
>> +out:
>> +     return ret;
>> +}
>> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
>> +{
>> +     struct omap_temp_sensor         *temp_sensor;
>> +     int                             t_hot, t_cold, temp;
>> +
>> +     temp_sensor = data;
>> +     mutex_lock(&temp_sensor->sensor_mutex);
>> +
>> +     /* Read the status of t_hot */
>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status)
>> +                     & temp_sensor->registers->status_hot_mask;
>> +
>> +     /* Read the status of t_cold */
>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_status)
>> +                     & temp_sensor->registers->status_cold_mask;
>> +
>> +     temp = omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_mask_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) {
>> +             temp &= ~(temp_sensor->registers->mask_hot_mask);
>> +             temp |= temp_sensor->registers->mask_cold_mask;
>> +     } else if (t_cold) {
>> +             temp &= ~(temp_sensor->registers->mask_cold_mask);
>> +             temp |= temp_sensor->registers->mask_hot_mask;
>> +     }
>> +
>> +     omap_temp_sensor_writel(temp_sensor, temp,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +
>> +     /* kobject_uvent to user space telling thermal threshold crossed */
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
>> +
>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>> +
>> +     return IRQ_HANDLED;
>> +}
>> +
>> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
>> +{
>> +     struct omap_temp_sensor_pdata   *pdata  = pdev->dev.platform_data;
>> +     struct omap_temp_sensor         *temp_sensor;
>> +     struct resource                 *mem;
>> +     int                             ret = 0;
>> +     int                             val, clk_rate;
>> +
>> +     if (!pdata) {
>> +             dev_err(&pdev->dev, "platform data missing\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
>> +     if (!temp_sensor)
>> +             return -ENOMEM;
>> +
>> +     mutex_init(&temp_sensor->sensor_mutex);
>> +
>> +     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     if (!mem) {
>> +             dev_err(&pdev->dev, "no mem resource\n");
>> +             ret = -EINVAL;
>
> You can do PTR_ERR(mem) to get the return error value as an integer.
> Otherwise, it makes more sense to be -ENOMEM

Ok

>
>> +             goto plat_res_err;
>> +     }
>> +
>> +     temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
>> +     if (temp_sensor->irq = -ENXIO) {
>> +             dev_err(&pdev->dev, "get_irq_byname failed\n");
>> +             ret = temp_sensor->irq;
>> +             goto plat_res_err;
>> +     }
>> +
>
> This flow can better be:
> ret = platform_get_irq_byname(...)
> if (ret < 0) //because it is an IRQ number
> { ... }
>

Ok


> Then assign ret to temp_sensor->irq

Ok

>
>> +     temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
>> +     temp_sensor->clock = NULL;
>> +     temp_sensor->registers = pdata->registers;
>> +     temp_sensor->hwmon_dev = &pdev->dev;
>> +
>> +     pm_runtime_enable(&pdev->dev);
>> +     pm_runtime_irq_safe(&pdev->dev);
>> +
>> +     /*
>> +      * check if the efuse has a non-zero value if not
>> +      * it is an untrimmed sample and the temperatures
>> +      * may not be accurate
>> +      */
>> +
>> +     if (omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->bgap_efuse))
>> +             temp_sensor->is_efuse_valid = 1;
>> +
>> +     platform_set_drvdata(pdev, temp_sensor);
>> +     dev_set_drvdata(&pdev->dev, temp_sensor);
>> +     temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
>> +     if (IS_ERR(temp_sensor->clock)) {
>> +             ret = PTR_ERR(temp_sensor->clock);
>> +             dev_err(temp_sensor->hwmon_dev,
>> +                     "unable to get fclk: %d\n", ret);
>> +             ret = -EINVAL;
>
> Same case here. Do not assign -EINVAL to ret

Ok

>
>> +             goto plat_res_err;
>> +     }
>> +
>> +     ret = omap_temp_sensor_clk_enable(temp_sensor);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Cannot enable temp sensor\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
>> +     if (clk_rate < 1000000 || clk_rate = 0xffffffff) {
>> +             dev_err(&pdev->dev, "Error round rate\n");
>
> You might want to assign something to 'ret' here.

Ok

>
>> +             goto clken_err;
>> +     }
>> +
>> +     ret = clk_set_rate(temp_sensor->clock, clk_rate);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Cannot set clock rate\n");
>> +             goto clken_err;
>> +     }
>> +
>> +     temp_sensor->clk_rate = clk_rate;
>> +     omap_enable_continuous_mode(temp_sensor, 1);
>> +     omap_configure_temp_sensor_thresholds(temp_sensor);
>> +     /* 1 ms */
>> +     omap_configure_temp_sensor_counter(temp_sensor, 1);
>> +
>> +     /* Wait till the first conversion is done wait for at least 1ms */
>> +     usleep_range(1000, 2000);
>> +
>> +     /* Read the temperature once due to hw issue*/
>> +     omap_temp_sensor_readl(temp_sensor,
>> +                     temp_sensor->registers->temp_sensor_ctrl);
>> +
>> +     /* Set 2 seconds time as default counter */
>> +     omap_configure_temp_sensor_counter(temp_sensor,
>> +                                             temp_sensor->clk_rate * 2);
>> +
>> +     temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
>> +     if (IS_ERR(temp_sensor->hwmon_dev)) {
>> +             dev_err(&pdev->dev, "hwmon_device_register failed.\n");
>> +             ret = PTR_ERR(temp_sensor->hwmon_dev);
>> +             goto hwmon_reg_err;
>> +     }
>> +
>> +     ret = sysfs_create_group(&pdev->dev.kobj,
>> +                              &omap_temp_sensor_group);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "could not create sysfs files\n");
>> +             goto sysfs_create_err;
>> +     }
>> +
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
>> +
>> +     ret = request_threaded_irq(temp_sensor->irq, NULL,
>> +             omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
>> +                     "temp_sensor", temp_sensor);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Request threaded irq failed.\n");
>> +             goto req_irq_err;
>> +     }
>> +
>> +     /* unmask the T_COLD and unmask T_HOT at init */
>> +     val = omap_temp_sensor_readl(temp_sensor,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +     val |= temp_sensor->registers->mask_cold_mask
>> +             | temp_sensor->registers->mask_hot_mask;
>> +
>> +     omap_temp_sensor_writel(temp_sensor, val,
>> +             temp_sensor->registers->bgap_mask_ctrl);
>> +
>> +     return 0;
>> +
>> +req_irq_err:
>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>> +                             &omap_temp_sensor_group);
>> +sysfs_create_err:
>> +     hwmon_device_unregister(&pdev->dev);
>> +hwmon_reg_err:
>> +     omap_temp_sensor_clk_disable(temp_sensor);
>> +clken_err:
>> +     if (temp_sensor->clock)
>
> Looking at the probe flow, this 'if' check seems unnecessary.

Ok

>
> Thanks,
> Durga
>
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-15  6:34       ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
@ 2011-08-17 10:49         ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-17 10:37 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak, R, Durgadoss

On Mon, Aug 15, 2011 at 11:52 AM, J, KEERTHY <j-keerthy@ti.com> wrote:
> Hi,
>
> Thanks for the Review Durga.
>
> On Wed, Aug 10, 2011 at 10:05 PM, R, Durgadoss <durgadoss.r@intel.com> wrote:
>> Hi,
>>
>>> -----Original Message-----
>>> From: lm-sensors-bounces@lm-sensors.org [mailto:lm-sensors-bounces@lm-
>>> sensors.org] On Behalf Of Keerthy
>>> Sent: Wednesday, August 10, 2011 5:55 PM
>>> To: lm-sensors@lm-sensors.org
>>> Cc: vishwanath.bs@ti.com; linux-omap@vger.kernel.org; b-cousson@ti.com;
>>> rnayak@ti.com
>>> Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor
>>> driver
>>>
>>> On chip temperature sensor driver. The driver monitors the temperature of
>>> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>>> the temperature crosses user defined thresholds via kobject_uevent interface.
>>> The user is allowed to configure the temperature thresholds vis sysfs nodes
>>> exposed using hwmon interface.
>>>
>>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>>> ---
>>>  drivers/hwmon/Kconfig            |   11 +
>>>  drivers/hwmon/Makefile           |    1 +
>>>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 962 insertions(+), 0 deletions(-)
>>>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>>>
>>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>>> index 5f888f7..9c9cd8b 100644
>>> --- a/drivers/hwmon/Kconfig
>>> +++ b/drivers/hwmon/Kconfig
>>> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>>>         This driver can also be built as a module.  If so, the module
>>>         will be called f71805f.
>>>
>>> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>>> +     bool "OMAP on-die temperature sensor hwmon driver"
>>> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>>> +     help
>>> +       If you say yes here you get support for hardware
>>> +       monitoring features of the OMAP on die temperature
>>> +       sensor.
>>> +
>>> +       Continuous conversion programmable delay
>>> +       mode is used for temperature conversion.
>>> +
>>>  config SENSORS_F71882FG
>>>       tristate "Fintek F71882FG and compatibles"
>>>       help
>>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>>> index 28061cf..d0f89f5 100644
>>> --- a/drivers/hwmon/Makefile
>>> +++ b/drivers/hwmon/Makefile
>>> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>>>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>>>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>>>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>>> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>>>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>>>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>>>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
>>> diff --git a/drivers/hwmon/omap_temp_sensor.c
>>> b/drivers/hwmon/omap_temp_sensor.c
>>> new file mode 100644
>>> index 0000000..15e2559
>>> --- /dev/null
>>> +++ b/drivers/hwmon/omap_temp_sensor.c
>>> @@ -0,0 +1,950 @@
>>> +/*
>>> + * OMAP4 Temperature sensor driver file
>>> + *
>>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>>> + * Author: J Keerthy <j-keerthy@ti.com>
>>> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>>> +#include <linux/clk.h>
>>> +#include <linux/io.h>
>>> +#include <linux/debugfs.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/init.h>
>>> +#include <plat/omap_device.h>
>>> +#include <linux/module.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/device.h>
>>> +#include <linux/jiffies.h>
>>> +#include <linux/hwmon.h>
>>> +#include <linux/hwmon-sysfs.h>
>>> +#include <linux/stddef.h>
>>> +#include <linux/sysfs.h>
>>> +#include <linux/err.h>
>>> +#include <linux/types.h>
>>> +#include <linux/mutex.h>
>>> +#include <linux/pm_runtime.h>
>>> +#include <plat/common.h>
>>> +#include <plat/temperature_sensor.h>
>>> +#include <mach/ctrl_module_core_44xx.h>
>>> +#include <mach/gpio.h>
>>> +
>>> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
>>> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
>>> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
>>> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
>>> +#define OMAP_ADC_START_VALUE 530
>>> +#define OMAP_ADC_END_VALUE   923
>>> +
>>> +/*
>>> + * omap_temp_sensor structure
>>> + * @hwmon_dev - device pointer
>>> + * @clock - Clock pointer
>>> + * @registers - Pointer to structure with register offsets and bitfields
>>> + * @sensor_mutex - Mutex for sysfs, irq and PM
>>> + * @irq - MPU Irq number for thermal alert
>>> + * @phy_base - Physical base of the temp I/O
>>> + * @clk_rate - Holds current clock rate
>>> + * @temp_sensor_ctrl - temp sensor control register value
>>> + * @bg_ctrl - bandgap ctrl register value
>>> + * @bg_counter - bandgap counter value
>>> + * @bg_threshold - bandgap threshold register value
>>> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>>> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>>> + * @clk_on - Manages the current clock state
>>> + */
>>> +struct omap_temp_sensor {
>>> +     struct device           *hwmon_dev;
>>> +     struct clk              *clock;
>>> +     struct omap_temp_sensor_registers *registers;
>>> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
>>> +     unsigned int            irq;
>>> +     void __iomem            *phy_base;
>>> +     u32                     clk_rate;
>>> +     u32                     temp_sensor_ctrl;
>>> +     u32                     bg_ctrl;
>>> +     u32                     bg_counter;
>>> +     u32                     bg_threshold;
>>> +     u32                     temp_sensor_tshut_threshold;
>>> +     bool                    is_efuse_valid;
>>> +     bool                    clk_on;
>>> +};
>>> +
>>> +/*
>>> + * Temperature values in milli degree celsius
>>> + * ADC code values from 530 to 923
>>> + */
>>> +static int adc_to_temp[] = {
>>> +     -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
>>> +};
>>> +
>>> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>>> +                                         *temp_sensor, u32 reg)
>>> +{
>>> +     return __raw_readl(temp_sensor->phy_base + reg);
>>> +}
>>> +
>>> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>>> +                                 u32 val, u32 reg)
>>> +{
>>> +     __raw_writel(val, (temp_sensor->phy_base + reg));
>>> +}
>>> +
>>> +static int adc_to_temp_conversion(int adc_val)
>>> +{
>>> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>>> +}
>>> +
>>> +static int temp_to_adc_conversion(long temp)
>>> +{
>>> +     int i;
>>> +
>>> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>>> +             if (temp < adc_to_temp[i])
>>> +                     return OMAP_ADC_START_VALUE + i - 1;
>>> +
>>> +     return -EINVAL;
>>> +}
>>> +
>>> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>>> +                                               *temp_sensor)
>>> +{
>>> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>>> +
>>> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>>> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>>> +
>>> +     /* Configure the TALERT thresholds */
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>>> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +             temp_sensor->registers->bgap_threshold);
>>> +
>>> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>>> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>>> +
>>> +     /* Configure the TSHUT thresholds */
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->thsut_threshold);
>>> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>>> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +                     temp_sensor->registers->thsut_threshold);
>>> +}
>>> +
>>> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>>> +                                            *temp_sensor, u32 counter)
>>> +{
>>> +     u32 val;
>>> +
>>> +     val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +     val &= ~(temp_sensor->registers->counter_mask);
>>> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, val,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +}
>>> +
>>> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>>> +                                     bool enable)
>>> +{
>>> +     u32 val;
>>> +
>>> +     val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_mode_ctrl);
>>> +
>>> +     if (enable)
>>> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>>> +     else
>>> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
>>> +
>>> +     omap_temp_sensor_writel(temp_sensor, val,
>>> +                     temp_sensor->registers->bgap_mode_ctrl);
>>> +}
>>> +
>>> +/* Sysfs hook functions */
>>> +
>>> +static ssize_t show_temp_max(struct device *dev,
>>> +                     struct device_attribute *devattr, char *buf)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     int temp;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
>>> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
>>> +
>>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>>> +             dev_err(dev, "invalid value\n");
>>> +             goto out;
>>> +     }
>>> +     temp = adc_to_temp_conversion(temp);
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +
>>> +     return snprintf(buf, 16, "%d\n", temp);
>>
>> Even if it is invalid value, you are printing it.
>> May be you would have to do unlocking and returning -EINVAL inside the 'if' check.
>
> Ok
>
>>
>> Moreover, you are just doing a read.
>> So, do you really need a mutex_lock in this function.. ?
>
> These values are RW. So the user can write a new value
> while you are reading. To be consistent mutex_lock is needed.
>
>>
>>> +}
>>> +
>>> +static ssize_t set_temp_max(struct device *dev,
>>> +                         struct device_attribute *devattr,
>>> +                         const char *buf, size_t count)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     long                    val;
>>> +     u32                     reg_val, t_cold, t_hot, temp;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     if (strict_strtol(buf, 10, &val)) {
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     t_hot = temp_to_adc_conversion(val);
>>> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>>> +             dev_err(dev, "invalid range\n");
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* obtain the T cold value */
>>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
>>> +
>>> +     if (t_hot < t_cold) {
>>> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* write the new t_hot value */
>>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>>> +     reg_val |= (t_hot <<
>>> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +
>>> +     /* Read the current temperature */
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>>> +
>>> +     /*
>>> +      * If user sets the HIGH threshold(t_hot) greater than the current
>>> +      * temperature(temp) unmask the HOT interrupts
>>> +      */
>>> +     if (t_hot > temp) {
>>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +     }
>>> +
>>> +     /*
>>> +      * If current temperature is in-between the hot and cold thresholds,
>>> +      * Enable both masks.
>>> +      */
>>> +     if (temp > t_cold && temp < t_hot) {
>>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                             OMAP4460_BGAP_CTRL_OFFSET);
>>> +     }
>>> +     /*
>>> +      * else no need to do anything since HW will immediately compare
>>> +      * the new threshold and generate interrupt accordingly
>>> +      */
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     return count;
>>> +}
>>> +
>>> +static ssize_t show_temp_max_hyst(struct device *dev,
>>> +             struct device_attribute *devattr, char *buf)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     u32                     temp;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +             temp_sensor->registers->bgap_threshold);
>>> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>>> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
>>> +
>>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>>> +             dev_err(dev, "invalid value\n");
>>> +             goto out;
>>
>> Same case here..
>> You can do ret = -EINVAL here..
>
> Ok
>
>>
>>> +     }
>>> +
>>> +     temp = adc_to_temp_conversion(temp);
>>
>> ...subsequently,
>> ret = snprintf(buf, 16, "%d\n", temp);
>>
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +
>>> +     return snprintf(buf, 16, "%d\n", temp);
>>
>> Return ret here..
>
> Ok
>
>>
>>> +}
>>> +
>>> +static ssize_t set_temp_max_hyst(struct device *dev,
>>> +                              struct device_attribute *devattr,
>>> +                              const char *buf, size_t count)
>>> +{
>>> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
>>> +     u32                             reg_val, t_hot, t_cold, temp;
>>> +     long                            val;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     if (strict_strtol(buf, 10, &val)) {
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     t_cold = temp_to_adc_conversion(val);
>>> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>>> +             dev_err(dev, "invalid range");
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* obtain the T HOT value */
>>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>>> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
>>> +
>>> +     if (t_cold > t_hot) {
>>> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* write the new t_cold value */
>>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>>> +     reg_val |= (t_cold <<
>>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +
>>> +     /* Read the current temperature */
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +             temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>>> +
>>> +     /*
>>> +      * If user sets the LOW threshold(t_cold) lower than the current
>>> +      * temperature(temp) unmask the COLD interrupts
>>> +      */
>>> +     if (t_cold < temp) {
>>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                     temp_sensor->registers->bgap_mask_ctrl);
>>> +     }
>>> +
>>> +     /*
>>> +      * If current temperature is in-between the hot and cold thresholds,
>>> +      * Enable both masks.
>>> +      */
>>> +     if (temp < t_hot && temp > t_cold) {
>>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +     }
>>> +
>>> +     /*
>>> +      * else no need to do anything since HW will immediately compare
>>> +      * the new threshold and generate interrupt accordingly
>>> +      */
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     return count;
>>> +}
>>> +
>>> +static ssize_t show_update_rate(struct device *dev,
>>> +                     struct device_attribute *devattr, char *buf)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     u32                     temp = 0, ret = 0;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     if (!temp_sensor->clk_rate) {
>>> +             dev_err(dev, "clk_rate is NULL\n");
>>> +             ret = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +     temp = (temp & temp_sensor->registers->counter_mask) >>
>>> +                     __ffs(temp_sensor->registers->counter_mask);
>>> +     temp = temp * 1000 / (temp_sensor->clk_rate);
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     if (!ret)
>>> +             return sprintf(buf, "%d\n", temp);
>>> +     else
>>
>> The 'else' is not necessary..
>
> Ok
>
>>
>>> +             return ret;
>>> +}
>>> +
>>> +static ssize_t set_update_rate(struct device *dev,
>>> +                            struct device_attribute *devattr,
>>> +                            const char *buf, size_t count)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     u32                     reg_val;
>>> +     long                    val;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     if (strict_strtol(buf, 10, &val)) {
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     val *= temp_sensor->clk_rate / 1000;
>>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +
>>> +     reg_val &= ~(temp_sensor->registers->counter_mask);
>>> +     reg_val |= val;
>>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     return count;
>>> +}
>>> +
>>> +static int omap_temp_sensor_read_temp(struct device *dev,
>>> +                                   struct device_attribute *devattr,
>>> +                                   char *buf)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     int                     temp, ret = 0;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +             temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
>>> +
>>> +     if (!temp_sensor->is_efuse_valid)
>>> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not
>>> accurate\n");
>>> +
>>> +     /* look up for temperature in the table and return the temperature */
>>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>>> +             dev_err(dev, "invalid adc code reported %d", temp);
>>> +             ret = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     if (!ret)
>>> +             return sprintf(buf, "%d\n", temp);
>>> +     else
>>
>> Same here..
>
> Ok
>
>>
>>> +             return ret;
>>> +}
>>> +
>>> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>>> +                       NULL, 0);
>>> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>>> +                       set_temp_max, 0);
>>> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
>>> show_temp_max_hyst,
>>> +                       set_temp_max_hyst, 0);
>>> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>>> +                       set_update_rate, 0);
>>> +
>>> +static struct attribute *omap_temp_sensor_attributes[] = {
>>> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
>>> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
>>> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>>> +     &sensor_dev_attr_update_rate.dev_attr.attr,
>>> +     NULL
>>> +};
>>> +
>>> +static const struct attribute_group omap_temp_sensor_group = {
>>> +     .attrs = omap_temp_sensor_attributes,
>>> +};
>>> +
>>> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>>> +{
>>> +     u32 ret = 0, temp;
>>> +
>>> +     if (temp_sensor->clk_on) {
>>> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>>> +             goto out;
>>> +     }
>>> +
>>> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>>> +     if (ret < 0) {
>>> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>>> +             ret = -EINVAL;
>>
>> Please do not mask the return value.
>> Let it be whatever returned by the get_sync.
>> Anyway, you are returning 'ret' in the end...
>>
>>> +             goto out;
>>> +     }
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>>> +     /* BGAP_TEMPSOFF should be reset to 0 */
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +                             temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp_sensor->clk_on = 1;
>>> +out:
>>> +     return ret;
>>> +}
>>> +
>>> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>>> +{
>>> +     u32 temp, ret = 0;
>>> +     unsigned long timeout;
>>> +
>>> +     if (!temp_sensor->clk_on) {
>>> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>>> +             goto out;
>>> +     }
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
>>> +
>>> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_status);
>>> +     timeout = jiffies + msecs_to_jiffies(5);
>>> +
>>> +     /* wait till the clean stop bit is set or till the timeout exppires */
>>
>> s/expires/expires
>
> I will correct this.
>
>>
>>> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>>> +             !(time_after(jiffies, timeout))) {
>>> +             temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_status);
>>> +             usleep_range(500, 2000);
>>> +     }
>>> +
>>> +     if (time_after(jiffies, timeout))
>>> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>>> +     /* Gate the clock */
>>> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>>> +     if (ret < 0) {
>>> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>>> +             ret = -EINVAL;
>>
>> Same case as get_sync. Don't mask the return value.
>
> Ok
>
>>
>>> +             goto out;
>>> +     }
>>> +     temp_sensor->clk_on = 0;
>>> +out:
>>> +     return ret;
>>> +}
>>> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
>>> +{
>>> +     struct omap_temp_sensor         *temp_sensor;
>>> +     int                             t_hot, t_cold, temp;
>>> +
>>> +     temp_sensor = data;
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     /* Read the status of t_hot */
>>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_status)
>>> +                     & temp_sensor->registers->status_hot_mask;
>>> +
>>> +     /* Read the status of t_cold */
>>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_status)
>>> +                     & temp_sensor->registers->status_cold_mask;
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_mask_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) {
>>> +             temp &= ~(temp_sensor->registers->mask_hot_mask);
>>> +             temp |= temp_sensor->registers->mask_cold_mask;
>>> +     } else if (t_cold) {
>>> +             temp &= ~(temp_sensor->registers->mask_cold_mask);
>>> +             temp |= temp_sensor->registers->mask_hot_mask;
>>> +     }
>>> +
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +             temp_sensor->registers->bgap_mask_ctrl);
>>> +
>>> +     /* kobject_uvent to user space telling thermal threshold crossed */
>>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
>>> +
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +
>>> +     return IRQ_HANDLED;
>>> +}
>>> +
>>> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
>>> +{
>>> +     struct omap_temp_sensor_pdata   *pdata  = pdev->dev.platform_data;
>>> +     struct omap_temp_sensor         *temp_sensor;
>>> +     struct resource                 *mem;
>>> +     int                             ret = 0;
>>> +     int                             val, clk_rate;
>>> +
>>> +     if (!pdata) {
>>> +             dev_err(&pdev->dev, "platform data missing\n");
>>> +             return -EINVAL;
>>> +     }
>>> +
>>> +     temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
>>> +     if (!temp_sensor)
>>> +             return -ENOMEM;
>>> +
>>> +     mutex_init(&temp_sensor->sensor_mutex);
>>> +
>>> +     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +     if (!mem) {
>>> +             dev_err(&pdev->dev, "no mem resource\n");
>>> +             ret = -EINVAL;
>>
>> You can do PTR_ERR(mem) to get the return error value as an integer.
>> Otherwise, it makes more sense to be -ENOMEM
>
> Ok
>
>>
>>> +             goto plat_res_err;
>>> +     }
>>> +
>>> +     temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
>>> +     if (temp_sensor->irq == -ENXIO) {
>>> +             dev_err(&pdev->dev, "get_irq_byname failed\n");
>>> +             ret = temp_sensor->irq;
>>> +             goto plat_res_err;
>>> +     }
>>> +
>>
>> This flow can better be:
>> ret = platform_get_irq_byname(...)
>> if (ret < 0) //because it is an IRQ number
>> { ... }
>>
>
> Ok
>
>
>> Then assign ret to temp_sensor->irq
>
> Ok
>
>>
>>> +     temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
>>> +     temp_sensor->clock = NULL;
>>> +     temp_sensor->registers = pdata->registers;
>>> +     temp_sensor->hwmon_dev = &pdev->dev;
>>> +
>>> +     pm_runtime_enable(&pdev->dev);
>>> +     pm_runtime_irq_safe(&pdev->dev);
>>> +
>>> +     /*
>>> +      * check if the efuse has a non-zero value if not
>>> +      * it is an untrimmed sample and the temperatures
>>> +      * may not be accurate
>>> +      */
>>> +
>>> +     if (omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_efuse))
>>> +             temp_sensor->is_efuse_valid = 1;
>>> +
>>> +     platform_set_drvdata(pdev, temp_sensor);
>>> +     dev_set_drvdata(&pdev->dev, temp_sensor);
>>> +     temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
>>> +     if (IS_ERR(temp_sensor->clock)) {
>>> +             ret = PTR_ERR(temp_sensor->clock);
>>> +             dev_err(temp_sensor->hwmon_dev,
>>> +                     "unable to get fclk: %d\n", ret);
>>> +             ret = -EINVAL;
>>
>> Same case here. Do not assign -EINVAL to ret
>
> Ok
>
>>
>>> +             goto plat_res_err;
>>> +     }
>>> +
>>> +     ret = omap_temp_sensor_clk_enable(temp_sensor);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev, "Cannot enable temp sensor\n");
>>> +             goto clken_err;
>>> +     }
>>> +
>>> +     clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
>>> +     if (clk_rate < 1000000 || clk_rate == 0xffffffff) {
>>> +             dev_err(&pdev->dev, "Error round rate\n");
>>
>> You might want to assign something to 'ret' here.
>
> Ok
>
>>
>>> +             goto clken_err;
>>> +     }
>>> +
>>> +     ret = clk_set_rate(temp_sensor->clock, clk_rate);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev, "Cannot set clock rate\n");
>>> +             goto clken_err;
>>> +     }
>>> +
>>> +     temp_sensor->clk_rate = clk_rate;
>>> +     omap_enable_continuous_mode(temp_sensor, 1);
>>> +     omap_configure_temp_sensor_thresholds(temp_sensor);
>>> +     /* 1 ms */
>>> +     omap_configure_temp_sensor_counter(temp_sensor, 1);
>>> +
>>> +     /* Wait till the first conversion is done wait for at least 1ms */
>>> +     usleep_range(1000, 2000);
>>> +
>>> +     /* Read the temperature once due to hw issue*/
>>> +     omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +
>>> +     /* Set 2 seconds time as default counter */
>>> +     omap_configure_temp_sensor_counter(temp_sensor,
>>> +                                             temp_sensor->clk_rate * 2);
>>> +
>>> +     temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
>>> +     if (IS_ERR(temp_sensor->hwmon_dev)) {
>>> +             dev_err(&pdev->dev, "hwmon_device_register failed.\n");
>>> +             ret = PTR_ERR(temp_sensor->hwmon_dev);
>>> +             goto hwmon_reg_err;
>>> +     }
>>> +
>>> +     ret = sysfs_create_group(&pdev->dev.kobj,
>>> +                              &omap_temp_sensor_group);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev, "could not create sysfs files\n");
>>> +             goto sysfs_create_err;
>>> +     }
>>> +
>>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
>>> +
>>> +     ret = request_threaded_irq(temp_sensor->irq, NULL,
>>> +             omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
>>> +                     "temp_sensor", temp_sensor);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev, "Request threaded irq failed.\n");
>>> +             goto req_irq_err;
>>> +     }
>>> +
>>> +     /* unmask the T_COLD and unmask T_HOT at init */
>>> +     val = omap_temp_sensor_readl(temp_sensor,
>>> +             temp_sensor->registers->bgap_mask_ctrl);
>>> +     val |= temp_sensor->registers->mask_cold_mask
>>> +             | temp_sensor->registers->mask_hot_mask;
>>> +
>>> +     omap_temp_sensor_writel(temp_sensor, val,
>>> +             temp_sensor->registers->bgap_mask_ctrl);
>>> +
>>> +     return 0;
>>> +
>>> +req_irq_err:
>>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>>> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>>> +                             &omap_temp_sensor_group);
>>> +sysfs_create_err:
>>> +     hwmon_device_unregister(&pdev->dev);
>>> +hwmon_reg_err:
>>> +     omap_temp_sensor_clk_disable(temp_sensor);
>>> +clken_err:
>>> +     if (temp_sensor->clock)
>>
>> Looking at the probe flow, this 'if' check seems unnecessary.
>
> Ok
>
>>
>> Thanks,
>> Durga
>>
>>
>
>

Hi Guenter,

Any inputs on the driver?

>
> --
> Regards and Thanks,
> Keerthy
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-17 10:49         ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-17 10:49 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak, R, Durgadoss

On Mon, Aug 15, 2011 at 11:52 AM, J, KEERTHY <j-keerthy@ti.com> wrote:
> Hi,
>
> Thanks for the Review Durga.
>
> On Wed, Aug 10, 2011 at 10:05 PM, R, Durgadoss <durgadoss.r@intel.com> wrote:
>> Hi,
>>
>>> -----Original Message-----
>>> From: lm-sensors-bounces@lm-sensors.org [mailto:lm-sensors-bounces@lm-
>>> sensors.org] On Behalf Of Keerthy
>>> Sent: Wednesday, August 10, 2011 5:55 PM
>>> To: lm-sensors@lm-sensors.org
>>> Cc: vishwanath.bs@ti.com; linux-omap@vger.kernel.org; b-cousson@ti.com;
>>> rnayak@ti.com
>>> Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor
>>> driver
>>>
>>> On chip temperature sensor driver. The driver monitors the temperature of
>>> the MPU subsystem of the OMAP4. It sends notifications to the user space if
>>> the temperature crosses user defined thresholds via kobject_uevent interface.
>>> The user is allowed to configure the temperature thresholds vis sysfs nodes
>>> exposed using hwmon interface.
>>>
>>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>>> ---
>>>  drivers/hwmon/Kconfig            |   11 +
>>>  drivers/hwmon/Makefile           |    1 +
>>>  drivers/hwmon/omap_temp_sensor.c |  950 ++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 962 insertions(+), 0 deletions(-)
>>>  create mode 100644 drivers/hwmon/omap_temp_sensor.c
>>>
>>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>>> index 5f888f7..9c9cd8b 100644
>>> --- a/drivers/hwmon/Kconfig
>>> +++ b/drivers/hwmon/Kconfig
>>> @@ -323,6 +323,17 @@ config SENSORS_F71805F
>>>         This driver can also be built as a module.  If so, the module
>>>         will be called f71805f.
>>>
>>> +config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
>>> +     bool "OMAP on-die temperature sensor hwmon driver"
>>> +     depends on HWMON && ARCH_OMAP && OMAP_TEMP_SENSOR
>>> +     help
>>> +       If you say yes here you get support for hardware
>>> +       monitoring features of the OMAP on die temperature
>>> +       sensor.
>>> +
>>> +       Continuous conversion programmable delay
>>> +       mode is used for temperature conversion.
>>> +
>>>  config SENSORS_F71882FG
>>>       tristate "Fintek F71882FG and compatibles"
>>>       help
>>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>>> index 28061cf..d0f89f5 100644
>>> --- a/drivers/hwmon/Makefile
>>> +++ b/drivers/hwmon/Makefile
>>> @@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639)       += max6639.o
>>>  obj-$(CONFIG_SENSORS_MAX6642)        += max6642.o
>>>  obj-$(CONFIG_SENSORS_MAX6650)        += max6650.o
>>>  obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
>>> +obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap_temp_sensor.o
>>>  obj-$(CONFIG_SENSORS_PC87360)        += pc87360.o
>>>  obj-$(CONFIG_SENSORS_PC87427)        += pc87427.o
>>>  obj-$(CONFIG_SENSORS_PCF8591)        += pcf8591.o
>>> diff --git a/drivers/hwmon/omap_temp_sensor.c
>>> b/drivers/hwmon/omap_temp_sensor.c
>>> new file mode 100644
>>> index 0000000..15e2559
>>> --- /dev/null
>>> +++ b/drivers/hwmon/omap_temp_sensor.c
>>> @@ -0,0 +1,950 @@
>>> +/*
>>> + * OMAP4 Temperature sensor driver file
>>> + *
>>> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
>>> + * Author: J Keerthy <j-keerthy@ti.com>
>>> + * Author: Moiz Sonasath <m-sonasath@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/interrupt.h>
>>> +#include <linux/clk.h>
>>> +#include <linux/io.h>
>>> +#include <linux/debugfs.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/init.h>
>>> +#include <plat/omap_device.h>
>>> +#include <linux/module.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/device.h>
>>> +#include <linux/jiffies.h>
>>> +#include <linux/hwmon.h>
>>> +#include <linux/hwmon-sysfs.h>
>>> +#include <linux/stddef.h>
>>> +#include <linux/sysfs.h>
>>> +#include <linux/err.h>
>>> +#include <linux/types.h>
>>> +#include <linux/mutex.h>
>>> +#include <linux/pm_runtime.h>
>>> +#include <plat/common.h>
>>> +#include <plat/temperature_sensor.h>
>>> +#include <mach/ctrl_module_core_44xx.h>
>>> +#include <mach/gpio.h>
>>> +
>>> +#define TSHUT_THRESHOLD_HOT  122000  /* 122 deg C */
>>> +#define TSHUT_THRESHOLD_COLD 100000  /* 100 deg C */
>>> +#define BGAP_THRESHOLD_T_HOT 73000   /* 73 deg C */
>>> +#define BGAP_THRESHOLD_T_COLD        71000   /* 71 deg C */
>>> +#define OMAP_ADC_START_VALUE 530
>>> +#define OMAP_ADC_END_VALUE   923
>>> +
>>> +/*
>>> + * omap_temp_sensor structure
>>> + * @hwmon_dev - device pointer
>>> + * @clock - Clock pointer
>>> + * @registers - Pointer to structure with register offsets and bitfields
>>> + * @sensor_mutex - Mutex for sysfs, irq and PM
>>> + * @irq - MPU Irq number for thermal alert
>>> + * @phy_base - Physical base of the temp I/O
>>> + * @clk_rate - Holds current clock rate
>>> + * @temp_sensor_ctrl - temp sensor control register value
>>> + * @bg_ctrl - bandgap ctrl register value
>>> + * @bg_counter - bandgap counter value
>>> + * @bg_threshold - bandgap threshold register value
>>> + * @temp_sensor_tshut_threshold - bandgap tshut register value
>>> + * @is_efuse_valid - Flag to determine if efuse is valid or not
>>> + * @clk_on - Manages the current clock state
>>> + */
>>> +struct omap_temp_sensor {
>>> +     struct device           *hwmon_dev;
>>> +     struct clk              *clock;
>>> +     struct omap_temp_sensor_registers *registers;
>>> +     struct mutex            sensor_mutex; /* Mutex for sysfs, irq and PM */
>>> +     unsigned int            irq;
>>> +     void __iomem            *phy_base;
>>> +     u32                     clk_rate;
>>> +     u32                     temp_sensor_ctrl;
>>> +     u32                     bg_ctrl;
>>> +     u32                     bg_counter;
>>> +     u32                     bg_threshold;
>>> +     u32                     temp_sensor_tshut_threshold;
>>> +     bool                    is_efuse_valid;
>>> +     bool                    clk_on;
>>> +};
>>> +
>>> +/*
>>> + * Temperature values in milli degree celsius
>>> + * ADC code values from 530 to 923
>>> + */
>>> +static int adc_to_temp[] = {
>>> +     -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
>>> +};
>>> +
>>> +static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
>>> +                                         *temp_sensor, u32 reg)
>>> +{
>>> +     return __raw_readl(temp_sensor->phy_base + reg);
>>> +}
>>> +
>>> +static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
>>> +                                 u32 val, u32 reg)
>>> +{
>>> +     __raw_writel(val, (temp_sensor->phy_base + reg));
>>> +}
>>> +
>>> +static int adc_to_temp_conversion(int adc_val)
>>> +{
>>> +     return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
>>> +}
>>> +
>>> +static int temp_to_adc_conversion(long temp)
>>> +{
>>> +     int i;
>>> +
>>> +     for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
>>> +             if (temp < adc_to_temp[i])
>>> +                     return OMAP_ADC_START_VALUE + i - 1;
>>> +
>>> +     return -EINVAL;
>>> +}
>>> +
>>> +static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
>>> +                                               *temp_sensor)
>>> +{
>>> +     u32 temp, t_hot, t_cold, tshut_hot, tshut_cold;
>>> +
>>> +     t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
>>> +     t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
>>> +
>>> +     /* Configure the TALERT thresholds */
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     temp |= (t_hot << __ffs(temp_sensor->registers->threshold_thot_mask)) |
>>> +             (t_cold << __ffs(temp_sensor->registers->threshold_tcold_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +             temp_sensor->registers->bgap_threshold);
>>> +
>>> +     tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_HOT);
>>> +     tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_COLD);
>>> +
>>> +     /* Configure the TSHUT thresholds */
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->thsut_threshold);
>>> +     temp |= (tshut_hot << __ffs(temp_sensor->registers->tshut_hot_mask))
>>> +         | (tshut_cold << __ffs(temp_sensor->registers->tshut_hot_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +                     temp_sensor->registers->thsut_threshold);
>>> +}
>>> +
>>> +static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
>>> +                                            *temp_sensor, u32 counter)
>>> +{
>>> +     u32 val;
>>> +
>>> +     val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +     val &= ~(temp_sensor->registers->counter_mask);
>>> +     val |= (counter << __ffs(temp_sensor->registers->counter_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, val,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +}
>>> +
>>> +static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor,
>>> +                                     bool enable)
>>> +{
>>> +     u32 val;
>>> +
>>> +     val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_mode_ctrl);
>>> +
>>> +     if (enable)
>>> +             val |= (1 << __ffs(temp_sensor->registers->mode_ctrl_mask));
>>> +     else
>>> +             val &= ~(temp_sensor->registers->mode_ctrl_mask);
>>> +
>>> +     omap_temp_sensor_writel(temp_sensor, val,
>>> +                     temp_sensor->registers->bgap_mode_ctrl);
>>> +}
>>> +
>>> +/* Sysfs hook functions */
>>> +
>>> +static ssize_t show_temp_max(struct device *dev,
>>> +                     struct device_attribute *devattr, char *buf)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     int temp;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     temp = (temp & temp_sensor->registers->threshold_thot_mask)
>>> +                     >> __ffs(temp_sensor->registers->threshold_thot_mask);
>>> +
>>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>>> +             dev_err(dev, "invalid value\n");
>>> +             goto out;
>>> +     }
>>> +     temp = adc_to_temp_conversion(temp);
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +
>>> +     return snprintf(buf, 16, "%d\n", temp);
>>
>> Even if it is invalid value, you are printing it.
>> May be you would have to do unlocking and returning -EINVAL inside the 'if' check.
>
> Ok
>
>>
>> Moreover, you are just doing a read.
>> So, do you really need a mutex_lock in this function.. ?
>
> These values are RW. So the user can write a new value
> while you are reading. To be consistent mutex_lock is needed.
>
>>
>>> +}
>>> +
>>> +static ssize_t set_temp_max(struct device *dev,
>>> +                         struct device_attribute *devattr,
>>> +                         const char *buf, size_t count)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     long                    val;
>>> +     u32                     reg_val, t_cold, t_hot, temp;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     if (strict_strtol(buf, 10, &val)) {
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     t_hot = temp_to_adc_conversion(val);
>>> +     if ((t_hot < OMAP_ADC_START_VALUE || t_hot > OMAP_ADC_END_VALUE)) {
>>> +             dev_err(dev, "invalid range\n");
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* obtain the T cold value */
>>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     t_cold = (t_cold & temp_sensor->registers->threshold_tcold_mask) >>
>>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask);
>>> +
>>> +     if (t_hot < t_cold) {
>>> +             dev_err(dev, "Error! T_HOT value lesser than T_COLD\n");
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* write the new t_hot value */
>>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     reg_val &= ~(temp_sensor->registers->threshold_thot_mask);
>>> +     reg_val |= (t_hot <<
>>> +                     __ffs(temp_sensor->registers->threshold_thot_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +
>>> +     /* Read the current temperature */
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>>> +
>>> +     /*
>>> +      * If user sets the HIGH threshold(t_hot) greater than the current
>>> +      * temperature(temp) unmask the HOT interrupts
>>> +      */
>>> +     if (t_hot > temp) {
>>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +             reg_val &= ~(temp_sensor->registers->mask_cold_mask);
>>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +     }
>>> +
>>> +     /*
>>> +      * If current temperature is in-between the hot and cold thresholds,
>>> +      * Enable both masks.
>>> +      */
>>> +     if (temp > t_cold && temp < t_hot) {
>>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                             OMAP4460_BGAP_CTRL_OFFSET);
>>> +     }
>>> +     /*
>>> +      * else no need to do anything since HW will immediately compare
>>> +      * the new threshold and generate interrupt accordingly
>>> +      */
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     return count;
>>> +}
>>> +
>>> +static ssize_t show_temp_max_hyst(struct device *dev,
>>> +             struct device_attribute *devattr, char *buf)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     u32                     temp;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +             temp_sensor->registers->bgap_threshold);
>>> +     temp = (temp & temp_sensor->registers->threshold_tcold_mask) >>
>>> +             __ffs(temp_sensor->registers->threshold_tcold_mask);
>>> +
>>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>>> +             dev_err(dev, "invalid value\n");
>>> +             goto out;
>>
>> Same case here..
>> You can do ret = -EINVAL here..
>
> Ok
>
>>
>>> +     }
>>> +
>>> +     temp = adc_to_temp_conversion(temp);
>>
>> ...subsequently,
>> ret = snprintf(buf, 16, "%d\n", temp);
>>
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +
>>> +     return snprintf(buf, 16, "%d\n", temp);
>>
>> Return ret here..
>
> Ok
>
>>
>>> +}
>>> +
>>> +static ssize_t set_temp_max_hyst(struct device *dev,
>>> +                              struct device_attribute *devattr,
>>> +                              const char *buf, size_t count)
>>> +{
>>> +     struct omap_temp_sensor         *temp_sensor = dev_get_drvdata(dev);
>>> +     u32                             reg_val, t_hot, t_cold, temp;
>>> +     long                            val;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     if (strict_strtol(buf, 10, &val)) {
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     t_cold = temp_to_adc_conversion(val);
>>> +     if (t_cold < OMAP_ADC_START_VALUE || t_cold > OMAP_ADC_END_VALUE) {
>>> +             dev_err(dev, "invalid range");
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* obtain the T HOT value */
>>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     t_hot = (t_hot & temp_sensor->registers->threshold_thot_mask) >>
>>> +                     __ffs(temp_sensor->registers->threshold_thot_mask);
>>> +
>>> +     if (t_cold > t_hot) {
>>> +             dev_err(dev, "Error! T_COLD value greater than T_HOT\n");
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* write the new t_cold value */
>>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +     reg_val &= ~(temp_sensor->registers->threshold_tcold_mask);
>>> +     reg_val |= (t_cold <<
>>> +                     __ffs(temp_sensor->registers->threshold_tcold_mask));
>>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                     temp_sensor->registers->bgap_threshold);
>>> +
>>> +     /* Read the current temperature */
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +             temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp &= (temp_sensor->registers->bgap_dtemp_mask);
>>> +
>>> +     /*
>>> +      * If user sets the LOW threshold(t_cold) lower than the current
>>> +      * temperature(temp) unmask the COLD interrupts
>>> +      */
>>> +     if (t_cold < temp) {
>>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +             reg_val &= ~(temp_sensor->registers->mask_hot_mask);
>>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                     temp_sensor->registers->bgap_mask_ctrl);
>>> +     }
>>> +
>>> +     /*
>>> +      * If current temperature is in-between the hot and cold thresholds,
>>> +      * Enable both masks.
>>> +      */
>>> +     if (temp < t_hot && temp > t_cold) {
>>> +             reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +             reg_val |= temp_sensor->registers->mask_cold_mask;
>>> +             reg_val |= temp_sensor->registers->mask_hot_mask;
>>> +             omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                             temp_sensor->registers->bgap_mask_ctrl);
>>> +     }
>>> +
>>> +     /*
>>> +      * else no need to do anything since HW will immediately compare
>>> +      * the new threshold and generate interrupt accordingly
>>> +      */
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     return count;
>>> +}
>>> +
>>> +static ssize_t show_update_rate(struct device *dev,
>>> +                     struct device_attribute *devattr, char *buf)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     u32                     temp = 0, ret = 0;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     if (!temp_sensor->clk_rate) {
>>> +             dev_err(dev, "clk_rate is NULL\n");
>>> +             ret = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +     temp = (temp & temp_sensor->registers->counter_mask) >>
>>> +                     __ffs(temp_sensor->registers->counter_mask);
>>> +     temp = temp * 1000 / (temp_sensor->clk_rate);
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     if (!ret)
>>> +             return sprintf(buf, "%d\n", temp);
>>> +     else
>>
>> The 'else' is not necessary..
>
> Ok
>
>>
>>> +             return ret;
>>> +}
>>> +
>>> +static ssize_t set_update_rate(struct device *dev,
>>> +                            struct device_attribute *devattr,
>>> +                            const char *buf, size_t count)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     u32                     reg_val;
>>> +     long                    val;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     if (strict_strtol(buf, 10, &val)) {
>>> +             count = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     val *= temp_sensor->clk_rate / 1000;
>>> +     reg_val = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +
>>> +     reg_val &= ~(temp_sensor->registers->counter_mask);
>>> +     reg_val |= val;
>>> +     omap_temp_sensor_writel(temp_sensor, reg_val,
>>> +                     temp_sensor->registers->bgap_counter);
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     return count;
>>> +}
>>> +
>>> +static int omap_temp_sensor_read_temp(struct device *dev,
>>> +                                   struct device_attribute *devattr,
>>> +                                   char *buf)
>>> +{
>>> +     struct omap_temp_sensor *temp_sensor = dev_get_drvdata(dev);
>>> +     int                     temp, ret = 0;
>>> +
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +             temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp &= temp_sensor->registers->bgap_dtemp_mask;
>>> +
>>> +     if (!temp_sensor->is_efuse_valid)
>>> +             dev_err(dev, "Invalid EFUSE, Non-trimmed BGAP, Temp not
>>> accurate\n");
>>> +
>>> +     /* look up for temperature in the table and return the temperature */
>>> +     if (temp < OMAP_ADC_START_VALUE || temp > OMAP_ADC_END_VALUE) {
>>> +             dev_err(dev, "invalid adc code reported %d", temp);
>>> +             ret = -EINVAL;
>>> +             goto out;
>>> +     }
>>> +
>>> +     temp = adc_to_temp[temp - OMAP_ADC_START_VALUE];
>>> +
>>> +out:
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +     if (!ret)
>>> +             return sprintf(buf, "%d\n", temp);
>>> +     else
>>
>> Same here..
>
> Ok
>
>>
>>> +             return ret;
>>> +}
>>> +
>>> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, omap_temp_sensor_read_temp,
>>> +                       NULL, 0);
>>> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
>>> +                       set_temp_max, 0);
>>> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
>>> show_temp_max_hyst,
>>> +                       set_temp_max_hyst, 0);
>>> +static SENSOR_DEVICE_ATTR(update_rate, S_IWUSR | S_IRUGO, show_update_rate,
>>> +                       set_update_rate, 0);
>>> +
>>> +static struct attribute *omap_temp_sensor_attributes[] = {
>>> +     &sensor_dev_attr_temp1_input.dev_attr.attr,
>>> +     &sensor_dev_attr_temp1_max.dev_attr.attr,
>>> +     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
>>> +     &sensor_dev_attr_update_rate.dev_attr.attr,
>>> +     NULL
>>> +};
>>> +
>>> +static const struct attribute_group omap_temp_sensor_group = {
>>> +     .attrs = omap_temp_sensor_attributes,
>>> +};
>>> +
>>> +static int omap_temp_sensor_clk_enable(struct omap_temp_sensor *temp_sensor)
>>> +{
>>> +     u32 ret = 0, temp;
>>> +
>>> +     if (temp_sensor->clk_on) {
>>> +             dev_err(temp_sensor->hwmon_dev, "clock already on\n");
>>> +             goto out;
>>> +     }
>>> +
>>> +     ret = pm_runtime_get_sync(temp_sensor->hwmon_dev);
>>> +     if (ret < 0) {
>>> +             dev_err(temp_sensor->hwmon_dev, "get sync failed\n");
>>> +             ret = -EINVAL;
>>
>> Please do not mask the return value.
>> Let it be whatever returned by the get_sync.
>> Anyway, you are returning 'ret' in the end...
>>
>>> +             goto out;
>>> +     }
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp &= ~(temp_sensor->registers->bgap_tempsoff_mask);
>>> +     /* BGAP_TEMPSOFF should be reset to 0 */
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +                             temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp_sensor->clk_on = 1;
>>> +out:
>>> +     return ret;
>>> +}
>>> +
>>> +static int omap_temp_sensor_clk_disable(struct omap_temp_sensor *temp_sensor)
>>> +{
>>> +     u32 temp, ret = 0;
>>> +     unsigned long timeout;
>>> +
>>> +     if (!temp_sensor->clk_on) {
>>> +             dev_err(temp_sensor->hwmon_dev, "clock already off\n");
>>> +             goto out;
>>> +     }
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp |= temp_sensor->registers->bgap_tempsoff_mask;
>>> +
>>> +     /* BGAP_TEMPSOFF should be set to 1 before gating clock */
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_status);
>>> +     timeout = jiffies + msecs_to_jiffies(5);
>>> +
>>> +     /* wait till the clean stop bit is set or till the timeout exppires */
>>
>> s/expires/expires
>
> I will correct this.
>
>>
>>> +     while (!(temp | temp_sensor->registers->status_clean_stop_mask) &&
>>> +             !(time_after(jiffies, timeout))) {
>>> +             temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_status);
>>> +             usleep_range(500, 2000);
>>> +     }
>>> +
>>> +     if (time_after(jiffies, timeout))
>>> +             dev_err(temp_sensor->hwmon_dev, "Clean stop bit not set\n");
>>> +     /* Gate the clock */
>>> +     ret = pm_runtime_put_sync(temp_sensor->hwmon_dev);
>>> +     if (ret < 0) {
>>> +             dev_err(temp_sensor->hwmon_dev, "put sync failed\n");
>>> +             ret = -EINVAL;
>>
>> Same case as get_sync. Don't mask the return value.
>
> Ok
>
>>
>>> +             goto out;
>>> +     }
>>> +     temp_sensor->clk_on = 0;
>>> +out:
>>> +     return ret;
>>> +}
>>> +static irqreturn_t omap_talert_irq_handler(int irq, void *data)
>>> +{
>>> +     struct omap_temp_sensor         *temp_sensor;
>>> +     int                             t_hot, t_cold, temp;
>>> +
>>> +     temp_sensor = data;
>>> +     mutex_lock(&temp_sensor->sensor_mutex);
>>> +
>>> +     /* Read the status of t_hot */
>>> +     t_hot = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_status)
>>> +                     & temp_sensor->registers->status_hot_mask;
>>> +
>>> +     /* Read the status of t_cold */
>>> +     t_cold = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_status)
>>> +                     & temp_sensor->registers->status_cold_mask;
>>> +
>>> +     temp = omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_mask_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) {
>>> +             temp &= ~(temp_sensor->registers->mask_hot_mask);
>>> +             temp |= temp_sensor->registers->mask_cold_mask;
>>> +     } else if (t_cold) {
>>> +             temp &= ~(temp_sensor->registers->mask_cold_mask);
>>> +             temp |= temp_sensor->registers->mask_hot_mask;
>>> +     }
>>> +
>>> +     omap_temp_sensor_writel(temp_sensor, temp,
>>> +             temp_sensor->registers->bgap_mask_ctrl);
>>> +
>>> +     /* kobject_uvent to user space telling thermal threshold crossed */
>>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_CHANGE);
>>> +
>>> +     mutex_unlock(&temp_sensor->sensor_mutex);
>>> +
>>> +     return IRQ_HANDLED;
>>> +}
>>> +
>>> +static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
>>> +{
>>> +     struct omap_temp_sensor_pdata   *pdata  = pdev->dev.platform_data;
>>> +     struct omap_temp_sensor         *temp_sensor;
>>> +     struct resource                 *mem;
>>> +     int                             ret = 0;
>>> +     int                             val, clk_rate;
>>> +
>>> +     if (!pdata) {
>>> +             dev_err(&pdev->dev, "platform data missing\n");
>>> +             return -EINVAL;
>>> +     }
>>> +
>>> +     temp_sensor = kzalloc(sizeof(*temp_sensor), GFP_KERNEL);
>>> +     if (!temp_sensor)
>>> +             return -ENOMEM;
>>> +
>>> +     mutex_init(&temp_sensor->sensor_mutex);
>>> +
>>> +     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +     if (!mem) {
>>> +             dev_err(&pdev->dev, "no mem resource\n");
>>> +             ret = -EINVAL;
>>
>> You can do PTR_ERR(mem) to get the return error value as an integer.
>> Otherwise, it makes more sense to be -ENOMEM
>
> Ok
>
>>
>>> +             goto plat_res_err;
>>> +     }
>>> +
>>> +     temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
>>> +     if (temp_sensor->irq = -ENXIO) {
>>> +             dev_err(&pdev->dev, "get_irq_byname failed\n");
>>> +             ret = temp_sensor->irq;
>>> +             goto plat_res_err;
>>> +     }
>>> +
>>
>> This flow can better be:
>> ret = platform_get_irq_byname(...)
>> if (ret < 0) //because it is an IRQ number
>> { ... }
>>
>
> Ok
>
>
>> Then assign ret to temp_sensor->irq
>
> Ok
>
>>
>>> +     temp_sensor->phy_base = ioremap(mem->start, resource_size(mem));
>>> +     temp_sensor->clock = NULL;
>>> +     temp_sensor->registers = pdata->registers;
>>> +     temp_sensor->hwmon_dev = &pdev->dev;
>>> +
>>> +     pm_runtime_enable(&pdev->dev);
>>> +     pm_runtime_irq_safe(&pdev->dev);
>>> +
>>> +     /*
>>> +      * check if the efuse has a non-zero value if not
>>> +      * it is an untrimmed sample and the temperatures
>>> +      * may not be accurate
>>> +      */
>>> +
>>> +     if (omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->bgap_efuse))
>>> +             temp_sensor->is_efuse_valid = 1;
>>> +
>>> +     platform_set_drvdata(pdev, temp_sensor);
>>> +     dev_set_drvdata(&pdev->dev, temp_sensor);
>>> +     temp_sensor->clock = clk_get(temp_sensor->hwmon_dev, "fck");
>>> +     if (IS_ERR(temp_sensor->clock)) {
>>> +             ret = PTR_ERR(temp_sensor->clock);
>>> +             dev_err(temp_sensor->hwmon_dev,
>>> +                     "unable to get fclk: %d\n", ret);
>>> +             ret = -EINVAL;
>>
>> Same case here. Do not assign -EINVAL to ret
>
> Ok
>
>>
>>> +             goto plat_res_err;
>>> +     }
>>> +
>>> +     ret = omap_temp_sensor_clk_enable(temp_sensor);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev, "Cannot enable temp sensor\n");
>>> +             goto clken_err;
>>> +     }
>>> +
>>> +     clk_rate = clk_round_rate(temp_sensor->clock, 2000000);
>>> +     if (clk_rate < 1000000 || clk_rate = 0xffffffff) {
>>> +             dev_err(&pdev->dev, "Error round rate\n");
>>
>> You might want to assign something to 'ret' here.
>
> Ok
>
>>
>>> +             goto clken_err;
>>> +     }
>>> +
>>> +     ret = clk_set_rate(temp_sensor->clock, clk_rate);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev, "Cannot set clock rate\n");
>>> +             goto clken_err;
>>> +     }
>>> +
>>> +     temp_sensor->clk_rate = clk_rate;
>>> +     omap_enable_continuous_mode(temp_sensor, 1);
>>> +     omap_configure_temp_sensor_thresholds(temp_sensor);
>>> +     /* 1 ms */
>>> +     omap_configure_temp_sensor_counter(temp_sensor, 1);
>>> +
>>> +     /* Wait till the first conversion is done wait for at least 1ms */
>>> +     usleep_range(1000, 2000);
>>> +
>>> +     /* Read the temperature once due to hw issue*/
>>> +     omap_temp_sensor_readl(temp_sensor,
>>> +                     temp_sensor->registers->temp_sensor_ctrl);
>>> +
>>> +     /* Set 2 seconds time as default counter */
>>> +     omap_configure_temp_sensor_counter(temp_sensor,
>>> +                                             temp_sensor->clk_rate * 2);
>>> +
>>> +     temp_sensor->hwmon_dev = hwmon_device_register(&pdev->dev);
>>> +     if (IS_ERR(temp_sensor->hwmon_dev)) {
>>> +             dev_err(&pdev->dev, "hwmon_device_register failed.\n");
>>> +             ret = PTR_ERR(temp_sensor->hwmon_dev);
>>> +             goto hwmon_reg_err;
>>> +     }
>>> +
>>> +     ret = sysfs_create_group(&pdev->dev.kobj,
>>> +                              &omap_temp_sensor_group);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev, "could not create sysfs files\n");
>>> +             goto sysfs_create_err;
>>> +     }
>>> +
>>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_ADD);
>>> +
>>> +     ret = request_threaded_irq(temp_sensor->irq, NULL,
>>> +             omap_talert_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
>>> +                     "temp_sensor", temp_sensor);
>>> +     if (ret) {
>>> +             dev_err(&pdev->dev, "Request threaded irq failed.\n");
>>> +             goto req_irq_err;
>>> +     }
>>> +
>>> +     /* unmask the T_COLD and unmask T_HOT at init */
>>> +     val = omap_temp_sensor_readl(temp_sensor,
>>> +             temp_sensor->registers->bgap_mask_ctrl);
>>> +     val |= temp_sensor->registers->mask_cold_mask
>>> +             | temp_sensor->registers->mask_hot_mask;
>>> +
>>> +     omap_temp_sensor_writel(temp_sensor, val,
>>> +             temp_sensor->registers->bgap_mask_ctrl);
>>> +
>>> +     return 0;
>>> +
>>> +req_irq_err:
>>> +     kobject_uevent(&temp_sensor->hwmon_dev->kobj, KOBJ_REMOVE);
>>> +     sysfs_remove_group(&temp_sensor->hwmon_dev->kobj,
>>> +                             &omap_temp_sensor_group);
>>> +sysfs_create_err:
>>> +     hwmon_device_unregister(&pdev->dev);
>>> +hwmon_reg_err:
>>> +     omap_temp_sensor_clk_disable(temp_sensor);
>>> +clken_err:
>>> +     if (temp_sensor->clock)
>>
>> Looking at the probe flow, this 'if' check seems unnecessary.
>
> Ok
>
>>
>> Thanks,
>> Durga
>>
>>
>
>

Hi Guenter,

Any inputs on the driver?

>
> --
> Regards and Thanks,
> Keerthy
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-17 10:49         ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
@ 2011-08-17 13:45           ` Guenter Roeck
  -1 siblings, 0 replies; 105+ messages in thread
From: Guenter Roeck @ 2011-08-17 13:45 UTC (permalink / raw)
  To: J, KEERTHY; +Cc: b-cousson, rnayak, lm-sensors, vishwanath.bs, linux-omap

On Wed, Aug 17, 2011 at 06:37:10AM -0400, J, KEERTHY wrote:
[ ... ]
> 
> Hi Guenter,
> 
> Any inputs on the driver?
> 
Hi Keerthy.

I think there was so much feedback that I would just add noise
at this time, and stumble over the same issues.
I'll look into it after the feedback has been applied.

Thanks,
Guenter

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-17 13:45           ` Guenter Roeck
  0 siblings, 0 replies; 105+ messages in thread
From: Guenter Roeck @ 2011-08-17 13:45 UTC (permalink / raw)
  To: J, KEERTHY; +Cc: b-cousson, rnayak, lm-sensors, vishwanath.bs, linux-omap

On Wed, Aug 17, 2011 at 06:37:10AM -0400, J, KEERTHY wrote:
[ ... ]
> 
> Hi Guenter,
> 
> Any inputs on the driver?
> 
Hi Keerthy.

I think there was so much feedback that I would just add noise
at this time, and stumble over the same issues.
I'll look into it after the feedback has been applied.

Thanks,
Guenter

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-17 13:45           ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Guenter Roeck
@ 2011-08-17 15:15             ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-17 15:03 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak, R, Durgadoss

On Wed, Aug 17, 2011 at 7:15 PM, Guenter Roeck
<guenter.roeck@ericsson.com> wrote:
> On Wed, Aug 17, 2011 at 06:37:10AM -0400, J, KEERTHY wrote:
> [ ... ]
>>
>> Hi Guenter,
>>
>> Any inputs on the driver?
>>
> Hi Keerthy.
>
> I think there was so much feedback that I would just add noise
> at this time, and stumble over the same issues.
> I'll look into it after the feedback has been applied.
>
Hi Guenter,

Thanks for the response. I will resend with the comments incorporated.

> Thanks,
> Guenter
>



-- 
Regards and Thanks,
Keerthy

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-17 15:15             ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-17 15:15 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: lm-sensors, vishwanath.bs, linux-omap, b-cousson, rnayak, R, Durgadoss

On Wed, Aug 17, 2011 at 7:15 PM, Guenter Roeck
<guenter.roeck@ericsson.com> wrote:
> On Wed, Aug 17, 2011 at 06:37:10AM -0400, J, KEERTHY wrote:
> [ ... ]
>>
>> Hi Guenter,
>>
>> Any inputs on the driver?
>>
> Hi Keerthy.
>
> I think there was so much feedback that I would just add noise
> at this time, and stumble over the same issues.
> I'll look into it after the feedback has been applied.
>
Hi Guenter,

Thanks for the response. I will resend with the comments incorporated.

> Thanks,
> Guenter
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-12  3:26                       ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Rajendra Nayak
  (?)
@ 2011-08-22 23:58                         ` Kevin Hilman
  -1 siblings, 0 replies; 105+ messages in thread
From: Kevin Hilman @ 2011-08-22 23:58 UTC (permalink / raw)
  To: Rajendra Nayak
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

Rajendra Nayak <rnayak@ti.com> writes:

[...]

> FWIK, its a one time requirement to set the clock rate to the
> right rate the device can operate in based on what a platform
> supports. 

Except $SUBJECT patch hard-codes the clock rate for all platforms in the
driver.

If the clock rate is to be platform-specific, it should be done in
platform-specific code.

Kevin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-22 23:58                         ` Kevin Hilman
  0 siblings, 0 replies; 105+ messages in thread
From: Kevin Hilman @ 2011-08-22 23:58 UTC (permalink / raw)
  To: linux-arm-kernel

Rajendra Nayak <rnayak@ti.com> writes:

[...]

> FWIK, its a one time requirement to set the clock rate to the
> right rate the device can operate in based on what a platform
> supports. 

Except $SUBJECT patch hard-codes the clock rate for all platforms in the
driver.

If the clock rate is to be platform-specific, it should be done in
platform-specific code.

Kevin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-22 23:58                         ` Kevin Hilman
  0 siblings, 0 replies; 105+ messages in thread
From: Kevin Hilman @ 2011-08-22 23:58 UTC (permalink / raw)
  To: Rajendra Nayak
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

Rajendra Nayak <rnayak@ti.com> writes:

[...]

> FWIK, its a one time requirement to set the clock rate to the
> right rate the device can operate in based on what a platform
> supports. 

Except $SUBJECT patch hard-codes the clock rate for all platforms in the
driver.

If the clock rate is to be platform-specific, it should be done in
platform-specific code.

Kevin

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-22 23:58                         ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Kevin Hilman
  (?)
@ 2011-08-23  4:18                           ` Rajendra Nayak
  -1 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-23  4:18 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

On 8/23/2011 5:28 AM, Kevin Hilman wrote:
> Rajendra Nayak<rnayak@ti.com>  writes:
>
> [...]
>
>> FWIK, its a one time requirement to set the clock rate to the
>> right rate the device can operate in based on what a platform
>> supports.
>
> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
> driver.

The device has a requirement to operate in a 1Mhz to 2Mhz range. So the
driver is using a clk_round_rate() to get the closest rate supported and
sets it using a clk_set_rate().

>
> If the clock rate is to be platform-specific, it should be done in
> platform-specific code.

I am fine if this needs to be moved to platform-specific code, but I
wasn't quite sure this needs to be done in clock framework as was
suggested.

>
> Kevin


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-23  4:18                           ` Rajendra Nayak
  0 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-23  4:18 UTC (permalink / raw)
  To: linux-arm-kernel

On 8/23/2011 5:28 AM, Kevin Hilman wrote:
> Rajendra Nayak<rnayak@ti.com>  writes:
>
> [...]
>
>> FWIK, its a one time requirement to set the clock rate to the
>> right rate the device can operate in based on what a platform
>> supports.
>
> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
> driver.

The device has a requirement to operate in a 1Mhz to 2Mhz range. So the
driver is using a clk_round_rate() to get the closest rate supported and
sets it using a clk_set_rate().

>
> If the clock rate is to be platform-specific, it should be done in
> platform-specific code.

I am fine if this needs to be moved to platform-specific code, but I
wasn't quite sure this needs to be done in clock framework as was
suggested.

>
> Kevin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-23  4:18                           ` Rajendra Nayak
  0 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-23  4:30 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

On 8/23/2011 5:28 AM, Kevin Hilman wrote:
> Rajendra Nayak<rnayak@ti.com>  writes:
>
> [...]
>
>> FWIK, its a one time requirement to set the clock rate to the
>> right rate the device can operate in based on what a platform
>> supports.
>
> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
> driver.

The device has a requirement to operate in a 1Mhz to 2Mhz range. So the
driver is using a clk_round_rate() to get the closest rate supported and
sets it using a clk_set_rate().

>
> If the clock rate is to be platform-specific, it should be done in
> platform-specific code.

I am fine if this needs to be moved to platform-specific code, but I
wasn't quite sure this needs to be done in clock framework as was
suggested.

>
> Kevin


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-23  4:18                           ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Rajendra Nayak
  (?)
@ 2011-08-23  6:42                             ` J, KEERTHY
  -1 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-23  6:42 UTC (permalink / raw)
  To: Rajendra Nayak, Kevin Hilman
  Cc: Roger Quadros, balbi, Tony Lindgren, lm-sensors, vishwanath.bs,
	linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

On Tue, Aug 23, 2011 at 9:48 AM, Rajendra Nayak <rnayak@ti.com> wrote:
> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>>
>> Rajendra Nayak<rnayak@ti.com>  writes:
>>
>> [...]
>>
>>> FWIK, its a one time requirement to set the clock rate to the
>>> right rate the device can operate in based on what a platform
>>> supports.
>>
>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>> driver.
>
> The device has a requirement to operate in a 1Mhz to 2Mhz range. So the
> driver is using a clk_round_rate() to get the closest rate supported and
> sets it using a clk_set_rate().
>
>>
>> If the clock rate is to be platform-specific, it should be done in
>> platform-specific code.
>
> I am fine if this needs to be moved to platform-specific code, but I
> wasn't quite sure this needs to be done in clock framework as was
> suggested.

The range can be (ex: 1MHz to 2Mhz) can be sent via pdata
as max and min frequencies and the driver can round the rate
to get the appropriate rate inside the specified range? Is this approach
Fine?

>
>>
>> Kevin
>
>



-- 
Regards and Thanks,
Keerthy
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-23  6:42                             ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-23  6:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 23, 2011 at 9:48 AM, Rajendra Nayak <rnayak@ti.com> wrote:
> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>>
>> Rajendra Nayak<rnayak@ti.com> ?writes:
>>
>> [...]
>>
>>> FWIK, its a one time requirement to set the clock rate to the
>>> right rate the device can operate in based on what a platform
>>> supports.
>>
>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>> driver.
>
> The device has a requirement to operate in a 1Mhz to 2Mhz range. So the
> driver is using a clk_round_rate() to get the closest rate supported and
> sets it using a clk_set_rate().
>
>>
>> If the clock rate is to be platform-specific, it should be done in
>> platform-specific code.
>
> I am fine if this needs to be moved to platform-specific code, but I
> wasn't quite sure this needs to be done in clock framework as was
> suggested.

The range can be (ex: 1MHz to 2Mhz) can be sent via pdata
as max and min frequencies and the driver can round the rate
to get the appropriate rate inside the specified range? Is this approach
Fine?

>
>>
>> Kevin
>
>



-- 
Regards and Thanks,
Keerthy

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-23  6:42                             ` J, KEERTHY
  0 siblings, 0 replies; 105+ messages in thread
From: J, KEERTHY @ 2011-08-23  6:54 UTC (permalink / raw)
  To: Rajendra Nayak, Kevin Hilman
  Cc: Roger Quadros, balbi, Tony Lindgren, lm-sensors, vishwanath.bs,
	linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

On Tue, Aug 23, 2011 at 9:48 AM, Rajendra Nayak <rnayak@ti.com> wrote:
> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>>
>> Rajendra Nayak<rnayak@ti.com>  writes:
>>
>> [...]
>>
>>> FWIK, its a one time requirement to set the clock rate to the
>>> right rate the device can operate in based on what a platform
>>> supports.
>>
>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>> driver.
>
> The device has a requirement to operate in a 1Mhz to 2Mhz range. So the
> driver is using a clk_round_rate() to get the closest rate supported and
> sets it using a clk_set_rate().
>
>>
>> If the clock rate is to be platform-specific, it should be done in
>> platform-specific code.
>
> I am fine if this needs to be moved to platform-specific code, but I
> wasn't quite sure this needs to be done in clock framework as was
> suggested.

The range can be (ex: 1MHz to 2Mhz) can be sent via pdata
as max and min frequencies and the driver can round the rate
to get the appropriate rate inside the specified range? Is this approach
Fine?

>
>>
>> Kevin
>
>



-- 
Regards and Thanks,
Keerthy

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-23  4:18                           ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Rajendra Nayak
  (?)
@ 2011-08-23 17:15                             ` Kevin Hilman
  -1 siblings, 0 replies; 105+ messages in thread
From: Kevin Hilman @ 2011-08-23 17:15 UTC (permalink / raw)
  To: Rajendra Nayak
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

Rajendra Nayak <rnayak@ti.com> writes:

> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>> Rajendra Nayak<rnayak@ti.com>  writes:
>>
>> [...]
>>
>>> FWIK, its a one time requirement to set the clock rate to the
>>> right rate the device can operate in based on what a platform
>>> supports.
>>
>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>> driver.
>
> The device has a requirement to operate in a 1Mhz to 2Mhz range. 

You mean the device on OMAP4 has this requirement.   

Will this requirement exist on every platform that uses any version of
this IP (or future similar IPs)?  I suspect not.

> So the driver is using a clk_round_rate() to get the closest rate
> supported and sets it using a clk_set_rate().
>
>>
>> If the clock rate is to be platform-specific, it should be done in
>> platform-specific code.
>
> I am fine if this needs to be moved to platform-specific code, but I
> wasn't quite sure this needs to be done in clock framework as was
> suggested.

No, it should't be in clock framework.  But since the frequency range is
platform-specific, it should be initialized in platform-specific code.
Having min/max parameters passed by platform data as suggested by
J. Keerthy is fine.

Probably even better is to have the driver have a default min/max rang
which can be overridden by platform_data only if needed.

Kevin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-23 17:15                             ` Kevin Hilman
  0 siblings, 0 replies; 105+ messages in thread
From: Kevin Hilman @ 2011-08-23 17:15 UTC (permalink / raw)
  To: linux-arm-kernel

Rajendra Nayak <rnayak@ti.com> writes:

> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>> Rajendra Nayak<rnayak@ti.com>  writes:
>>
>> [...]
>>
>>> FWIK, its a one time requirement to set the clock rate to the
>>> right rate the device can operate in based on what a platform
>>> supports.
>>
>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>> driver.
>
> The device has a requirement to operate in a 1Mhz to 2Mhz range. 

You mean the device on OMAP4 has this requirement.   

Will this requirement exist on every platform that uses any version of
this IP (or future similar IPs)?  I suspect not.

> So the driver is using a clk_round_rate() to get the closest rate
> supported and sets it using a clk_set_rate().
>
>>
>> If the clock rate is to be platform-specific, it should be done in
>> platform-specific code.
>
> I am fine if this needs to be moved to platform-specific code, but I
> wasn't quite sure this needs to be done in clock framework as was
> suggested.

No, it should't be in clock framework.  But since the frequency range is
platform-specific, it should be initialized in platform-specific code.
Having min/max parameters passed by platform data as suggested by
J. Keerthy is fine.

Probably even better is to have the driver have a default min/max rang
which can be overridden by platform_data only if needed.

Kevin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-23 17:15                             ` Kevin Hilman
  0 siblings, 0 replies; 105+ messages in thread
From: Kevin Hilman @ 2011-08-23 17:15 UTC (permalink / raw)
  To: Rajendra Nayak
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

Rajendra Nayak <rnayak@ti.com> writes:

> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>> Rajendra Nayak<rnayak@ti.com>  writes:
>>
>> [...]
>>
>>> FWIK, its a one time requirement to set the clock rate to the
>>> right rate the device can operate in based on what a platform
>>> supports.
>>
>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>> driver.
>
> The device has a requirement to operate in a 1Mhz to 2Mhz range. 

You mean the device on OMAP4 has this requirement.   

Will this requirement exist on every platform that uses any version of
this IP (or future similar IPs)?  I suspect not.

> So the driver is using a clk_round_rate() to get the closest rate
> supported and sets it using a clk_set_rate().
>
>>
>> If the clock rate is to be platform-specific, it should be done in
>> platform-specific code.
>
> I am fine if this needs to be moved to platform-specific code, but I
> wasn't quite sure this needs to be done in clock framework as was
> suggested.

No, it should't be in clock framework.  But since the frequency range is
platform-specific, it should be initialized in platform-specific code.
Having min/max parameters passed by platform data as suggested by
J. Keerthy is fine.

Probably even better is to have the driver have a default min/max rang
which can be overridden by platform_data only if needed.

Kevin

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
  2011-08-23 17:15                             ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Kevin Hilman
  (?)
@ 2011-08-24  4:07                               ` Rajendra Nayak
  -1 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-24  4:07 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

On 8/23/2011 10:45 PM, Kevin Hilman wrote:
> Rajendra Nayak<rnayak@ti.com>  writes:
>
>> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>>> Rajendra Nayak<rnayak@ti.com>   writes:
>>>
>>> [...]
>>>
>>>> FWIK, its a one time requirement to set the clock rate to the
>>>> right rate the device can operate in based on what a platform
>>>> supports.
>>>
>>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>>> driver.
>>
>> The device has a requirement to operate in a 1Mhz to 2Mhz range.
>
> You mean the device on OMAP4 has this requirement.
>
> Will this requirement exist on every platform that uses any version of
> this IP (or future similar IPs)?  I suspect not.

I agree, the current limitation is specific to the IP rev used, and
might change for a never version of the IP.

>
>> So the driver is using a clk_round_rate() to get the closest rate
>> supported and sets it using a clk_set_rate().
>>
>>>
>>> If the clock rate is to be platform-specific, it should be done in
>>> platform-specific code.
>>
>> I am fine if this needs to be moved to platform-specific code, but I
>> wasn't quite sure this needs to be done in clock framework as was
>> suggested.
>
> No, it should't be in clock framework.  But since the frequency range is
> platform-specific, it should be initialized in platform-specific code.
> Having min/max parameters passed by platform data as suggested by
> J. Keerthy is fine.
>
> Probably even better is to have the driver have a default min/max rang
> which can be overridden by platform_data only if needed.

This sounds better since if the same IP rev is used on other platforms
which does not change the min/max, the driver can do with the default
and that would avoid duplications of same min/max having to be passed
for multiple platforms.

>
> Kevin


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
@ 2011-08-24  4:07                               ` Rajendra Nayak
  0 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-24  4:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 8/23/2011 10:45 PM, Kevin Hilman wrote:
> Rajendra Nayak<rnayak@ti.com>  writes:
>
>> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>>> Rajendra Nayak<rnayak@ti.com>   writes:
>>>
>>> [...]
>>>
>>>> FWIK, its a one time requirement to set the clock rate to the
>>>> right rate the device can operate in based on what a platform
>>>> supports.
>>>
>>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>>> driver.
>>
>> The device has a requirement to operate in a 1Mhz to 2Mhz range.
>
> You mean the device on OMAP4 has this requirement.
>
> Will this requirement exist on every platform that uses any version of
> this IP (or future similar IPs)?  I suspect not.

I agree, the current limitation is specific to the IP rev used, and
might change for a never version of the IP.

>
>> So the driver is using a clk_round_rate() to get the closest rate
>> supported and sets it using a clk_set_rate().
>>
>>>
>>> If the clock rate is to be platform-specific, it should be done in
>>> platform-specific code.
>>
>> I am fine if this needs to be moved to platform-specific code, but I
>> wasn't quite sure this needs to be done in clock framework as was
>> suggested.
>
> No, it should't be in clock framework.  But since the frequency range is
> platform-specific, it should be initialized in platform-specific code.
> Having min/max parameters passed by platform data as suggested by
> J. Keerthy is fine.
>
> Probably even better is to have the driver have a default min/max rang
> which can be overridden by platform_data only if needed.

This sounds better since if the same IP rev is used on other platforms
which does not change the min/max, the driver can do with the default
and that would avoid duplications of same min/max having to be passed
for multiple platforms.

>
> Kevin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature
@ 2011-08-24  4:07                               ` Rajendra Nayak
  0 siblings, 0 replies; 105+ messages in thread
From: Rajendra Nayak @ 2011-08-24  4:19 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Roger Quadros, balbi, J, KEERTHY, Tony Lindgren, lm-sensors,
	vishwanath.bs, linux-omap, b-cousson, Russell King,
	Linux ARM Kernel Mailing List, khali, guenter.roeck

On 8/23/2011 10:45 PM, Kevin Hilman wrote:
> Rajendra Nayak<rnayak@ti.com>  writes:
>
>> On 8/23/2011 5:28 AM, Kevin Hilman wrote:
>>> Rajendra Nayak<rnayak@ti.com>   writes:
>>>
>>> [...]
>>>
>>>> FWIK, its a one time requirement to set the clock rate to the
>>>> right rate the device can operate in based on what a platform
>>>> supports.
>>>
>>> Except $SUBJECT patch hard-codes the clock rate for all platforms in the
>>> driver.
>>
>> The device has a requirement to operate in a 1Mhz to 2Mhz range.
>
> You mean the device on OMAP4 has this requirement.
>
> Will this requirement exist on every platform that uses any version of
> this IP (or future similar IPs)?  I suspect not.

I agree, the current limitation is specific to the IP rev used, and
might change for a never version of the IP.

>
>> So the driver is using a clk_round_rate() to get the closest rate
>> supported and sets it using a clk_set_rate().
>>
>>>
>>> If the clock rate is to be platform-specific, it should be done in
>>> platform-specific code.
>>
>> I am fine if this needs to be moved to platform-specific code, but I
>> wasn't quite sure this needs to be done in clock framework as was
>> suggested.
>
> No, it should't be in clock framework.  But since the frequency range is
> platform-specific, it should be initialized in platform-specific code.
> Having min/max parameters passed by platform data as suggested by
> J. Keerthy is fine.
>
> Probably even better is to have the driver have a default min/max rang
> which can be overridden by platform_data only if needed.

This sounds better since if the same IP rev is used on other platforms
which does not change the min/max, the driver can do with the default
and that would avoid duplications of same min/max having to be passed
for multiple platforms.

>
> Kevin


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 105+ messages in thread

end of thread, other threads:[~2011-08-24  4:19 UTC | newest]

Thread overview: 105+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-10 12:25 [RFC PATCH 0/6] OMAP4: Temperature sensor driver Keerthy
2011-08-10 12:37 ` [lm-sensors] " Keerthy
2011-08-10 12:25 ` [RFC PATCH 1/6] OMAP4: Clock: Associate clocks for OMAP temperature sensor Keerthy
2011-08-10 12:37   ` [lm-sensors] [RFC PATCH 1/6] OMAP4: Clock: Associate clocks for Keerthy
2011-08-10 12:25 ` [RFC PATCH 2/6] OMAP4: Adding the temperature sensor register set bit fields Keerthy
2011-08-10 12:37   ` [lm-sensors] [RFC PATCH 2/6] OMAP4: Adding the temperature sensor Keerthy
2011-08-10 12:25 ` [RFC PATCH 3/6] OMAP4: Hwmod: OMAP " Keerthy
2011-08-10 12:37   ` [lm-sensors] " Keerthy
2011-08-10 12:25 ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support Keerthy
2011-08-10 12:37   ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Keerthy
2011-08-10 12:36   ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support Felipe Balbi
2011-08-10 12:36     ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
2011-08-10 12:41     ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support Tony Lindgren
2011-08-10 12:41       ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Tony Lindgren
2011-08-10 12:48       ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support Felipe Balbi
2011-08-10 12:48         ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
2011-08-10 14:17         ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support Cousson, Benoit
2011-08-10 14:17           ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Cousson, Benoit
2011-08-10 21:37           ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support Felipe Balbi
2011-08-10 21:37             ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
2011-08-11  2:40     ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support J, KEERTHY
2011-08-11  2:52       ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device J, KEERTHY
2011-08-11 10:30       ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support Felipe Balbi
2011-08-11 10:30         ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
2011-08-11 11:01         ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support J, KEERTHY
2011-08-11 11:13           ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device J, KEERTHY
2011-08-11 14:05           ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support Felipe Balbi
2011-08-11 14:05             ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device Felipe Balbi
2011-08-11 14:15             ` [RFC PATCH 4/6] OMAP4: Temperature sensor device support J, KEERTHY
2011-08-11 14:27               ` [lm-sensors] [RFC PATCH 4/6] OMAP4: Temperature sensor device J, KEERTHY
2011-08-10 12:25 ` [RFC PATCH 5/6] OMAP4460: Temperature sensor data Keerthy
2011-08-10 12:37   ` [lm-sensors] " Keerthy
2011-08-10 12:37   ` Felipe Balbi
2011-08-10 12:37     ` [lm-sensors] " Felipe Balbi
2011-08-10 15:08     ` J, KEERTHY
2011-08-10 15:20       ` [lm-sensors] " J, KEERTHY
2011-08-10 12:25 ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Keerthy
2011-08-10 12:37   ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Keerthy
2011-08-10 12:46   ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
2011-08-10 12:46     ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Felipe Balbi
2011-08-10 12:46     ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
2011-08-11  9:57     ` J, KEERTHY
2011-08-11 10:09       ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
2011-08-11  9:57       ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
2011-08-11 10:36       ` Felipe Balbi
2011-08-11 10:36         ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Felipe Balbi
2011-08-11 10:36         ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
2011-08-11 13:00         ` J, KEERTHY
2011-08-11 13:12           ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
2011-08-11 13:00           ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
2011-08-11 14:12           ` Felipe Balbi
2011-08-11 14:12             ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Felipe Balbi
2011-08-11 14:12             ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
2011-08-11 14:25             ` Rajendra Nayak
2011-08-11 14:37               ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Rajendra Nayak
2011-08-11 14:25               ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Rajendra Nayak
2011-08-11 14:32             ` J, KEERTHY
2011-08-11 14:44               ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
2011-08-11 14:32               ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
2011-08-11 18:54               ` Felipe Balbi
2011-08-11 18:54                 ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Felipe Balbi
2011-08-11 18:54                 ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
2011-08-11 18:55                 ` Felipe Balbi
2011-08-11 18:55                   ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Felipe Balbi
2011-08-11 18:55                   ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
2011-08-11 21:37                   ` Roger Quadros
2011-08-11 21:37                     ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Roger Quadros
2011-08-11 21:37                     ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Roger Quadros
2011-08-12  1:02                     ` J, KEERTHY
2011-08-12  1:14                       ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
2011-08-12  1:02                       ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
2011-08-12  3:26                     ` Rajendra Nayak
2011-08-12  3:38                       ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Rajendra Nayak
2011-08-12  3:26                       ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Rajendra Nayak
2011-08-12  8:44                       ` Felipe Balbi
2011-08-12  8:44                         ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Felipe Balbi
2011-08-12  8:44                         ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Felipe Balbi
2011-08-22 23:58                       ` Kevin Hilman
2011-08-22 23:58                         ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Kevin Hilman
2011-08-22 23:58                         ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Kevin Hilman
2011-08-23  4:18                         ` Rajendra Nayak
2011-08-23  4:30                           ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Rajendra Nayak
2011-08-23  4:18                           ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Rajendra Nayak
2011-08-23  6:42                           ` J, KEERTHY
2011-08-23  6:54                             ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
2011-08-23  6:42                             ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
2011-08-23 17:15                           ` Kevin Hilman
2011-08-23 17:15                             ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Kevin Hilman
2011-08-23 17:15                             ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Kevin Hilman
2011-08-24  4:07                             ` Rajendra Nayak
2011-08-24  4:19                               ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Rajendra Nayak
2011-08-24  4:07                               ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Rajendra Nayak
2011-08-11 16:38           ` Guenter Roeck
2011-08-11 16:38             ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Guenter Roeck
2011-08-11 16:38             ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Guenter Roeck
2011-08-10 16:35   ` [lm-sensors] " R, Durgadoss
2011-08-10 16:47     ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die R, Durgadoss
2011-08-15  6:22     ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
2011-08-15  6:34       ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
2011-08-17 10:37       ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
2011-08-17 10:49         ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY
2011-08-17 13:45         ` [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver Guenter Roeck
2011-08-17 13:45           ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature Guenter Roeck
2011-08-17 15:03           ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver J, KEERTHY
2011-08-17 15:15             ` [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature J, KEERTHY

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.