OMAP4: Temperature sensor driver
Subsystems (6)
cover OMAP4: Temperature sensor driver
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
RFC PATCH 1/6 OMAP4: Clock: Associate clocks for OMAP temperature sensor
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.
--- arch/arm/mach-omap2/clock44xx_data.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/clock44xx_data.c +1 -1
@@ -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),
Signature · 1 line
1.7.0.4
RFC PATCH 2/6 OMAP4: Adding the temperature sensor register set bit fields
In reply to KeerthyOMAP4460 specific temperature sensor register bit fields are added.
--- .../include/mach/ctrl_module_core_44xx.h | 70 ++++++++++++++++---- 1 files changed, 57 insertions(+), 13 deletions(-)
arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h +57 -13
@@ -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
Signature · 1 line
1.7.0.4
RFC PATCH 3/6 OMAP4: Hwmod: OMAP temperature sensor
In reply to KeerthyFrom: Benoit Cousson <[email protected]>
OMAP4460 temperature sensor hwmod cannot be auto generated since it is part of ctrl module. Hence populating the necessary hwmod info manually.
--- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 61 ++++++++++++++++++++++++++++ 1 files changed, 61 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +61 -0
@@ -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,
Signature · 1 line
1.7.0.4
RFC PATCH 4/6 OMAP4: Temperature sensor device support
In reply to KeerthyThe device file adds the device support for OMAP4
on die temperature sensor.
--- 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
arch/arm/mach-omap2/Makefile +2 -1
@@ -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)
arch/arm/mach-omap2/temp_sensor_device.c new file +85 -0
85 lines not on this page · raw message
arch/arm/plat-omap/Kconfig +12 -0
@@ -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
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +87 -0
87 lines not on this page · raw message
Signature · 1 line
1.7.0.4
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Hi,
(you should Cc Tony, as he's OMAP maintainer)
Quoted 67 lines · Keerthy
The device file adds the device support for OMAP4
on die temperature sensor.Signed-off-by Keerthy <[email protected]>--- 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.harch/arm/mach-omap2/Makefile +2
-1@@ -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)arch/arm/mach-omap2/temp_sensor_device.c new file +27
-0@@ -0,0 +1,85 @@ +/* +* OMAP on die Temperature sensor device file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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>
arch/arm/mach-omap2/temp_sensor_device.c line 37
Quoted 10 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +10
-0+#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.
arch/arm/mach-omap2/temp_sensor_device.c line 46
Quoted 9 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +9
-0+}; + +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)
arch/arm/mach-omap2/temp_sensor_device.c line 48
Quoted 1 line
arch/arm/mach-omap2/temp_sensor_device.c new file +1
-0+ ret =0 ;
initialize on the declarion and you can avoid this line.
Quoted 27 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +27
-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; +} +
arch/arm/mach-omap2/temp_sensor_device.c line 85
Quoted 10 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +10
-0+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.
Quoted 9 lines
arch/arm/plat-omap/Kconfig +1
-0@@ -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
arch/arm/plat-omap/Kconfig config OMAP_MCBSP · line 128
Quoted 10 lines
arch/arm/plat-omap/Kconfig +10
-0+ 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 useomap_hwmod_for_each_by_class() ??
Quoted 64 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +58
-0@@ -0,0 +1,87 @@ +/* +* OMAP Temperature sensor header file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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;
arch/arm/plat-omap/include/plat/temperature_sensor.h line 68
Quoted 10 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +10
-0+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.
arch/arm/plat-omap/include/plat/temperature_sensor.h line 72
Quoted 3 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +3
-0+/* +* @name: Name of the domain of the temperature sensor +*/
comment fits in one line.
Signature · 1 line
balbi
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Tony Lindgren
maintainerRe: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Quoted 16 lines · Felipe Balbi
arch/arm/mach-omap2/temp_sensor_device.c line 85
Quoted 11 lines · Keerthy
arch/arm/mach-omap2/temp_sensor_device.c new file +11
-0+ +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
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Hi,
Quoted 18 lines · Tony Lindgren
Quoted 16 lines · Felipe Balbi
arch/arm/mach-omap2/temp_sensor_device.c line 85
Quoted 11 lines · Keerthy
arch/arm/mach-omap2/temp_sensor_device.c new file +11
-0+ +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.
Quoted 4 lines
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...
Signature · 1 line
balbi
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Quoted 24 lines · Felipe
Hi,
Quoted 21 lines · Tony Lindgren
Quoted 16 lines · Felipe Balbi
arch/arm/mach-omap2/temp_sensor_device.c line 85
Quoted 11 lines · Keerthy
arch/arm/mach-omap2/temp_sensor_device.c new file +11
-0+ +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?
Quoted 6 lines
Quoted 1 line
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 ownarch_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
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Hi,
Quoted 38 lines · Benoit
Quoted 24 lines · Felipe
Hi,
Quoted 21 lines · Tony Lindgren
Quoted 16 lines · Felipe Balbi
arch/arm/mach-omap2/temp_sensor_device.c line 85
Quoted 11 lines · Keerthy
arch/arm/mach-omap2/temp_sensor_device.c new file +11
-0+ +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?Quoted 6 lines
Quoted 1 line
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 ownarch_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.
Quoted 5 lines
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.
Signature · 1 line
balbi
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
In reply to Felipe BalbiQuoted 76 lines · Felipe Balbi
Hi,
(you should Cc Tony, as he's OMAP maintainer)
Quoted 71 lines · Keerthy
The device file adds the device support for OMAP4
on die temperature sensor.Signed-off-by Keerthy <[email protected]>---
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.ccreate mode 100644arch/arm/plat-omap/include/plat/temperature_sensor.harch/arm/mach-omap2/Makefile +0
-0@@ -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
arch/arm/mach-omap2/Makefile +1
-1@@ -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)arch/arm/mach-omap2/temp_sensor_device.c new file +31
-0@@ -0,0 +1,85 @@ +/* +* OMAP on die Temperature sensor device file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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> +
Quoted 9 lines
arch/arm/mach-omap2/temp_sensor_device.c line 37
Quoted 6 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +6
-0+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.
Quoted 11 lines
arch/arm/mach-omap2/temp_sensor_device.c line 46
Quoted 9 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +9
-0+}; + +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.
Quoted 4 lines
arch/arm/mach-omap2/temp_sensor_device.c line 48
Quoted 2 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +1
-0+ ret = 0;initialize on the declarion and you can avoid this line.
Ok
Quoted 50 lines
Quoted 28 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +27
-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; +} +arch/arm/mach-omap2/temp_sensor_device.c line 85
Quoted 10 lines
arch/arm/mach-omap2/temp_sensor_device.c new file +10
-0+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.Quoted 8 lines
arch/arm/plat-omap/Kconfig +0
-0@@ -115,6 +115,18 @@ config OMAP_MCBSPSay Y here if you want support for the OMAP Multichannel Buffered Serial Port.
Quoted 14 lines
arch/arm/plat-omap/Kconfig config OMAP_MCBSP · line 128
Quoted 11 lines
arch/arm/plat-omap/Kconfig +11
-0+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().
Quoted 70 lines
Quoted 70 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +63
-0@@ -0,0 +1,87 @@ +/* +* OMAP Temperature sensor header file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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;
Quoted 8 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h line 68
Quoted 5 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +5
-0+ 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.
Quoted 6 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h line 72
Quoted 4 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +3
-0+/* +* @name: Name of the domain of the temperature sensor +*/ comment fits in one line.
Ok
Quoted 5 lines
--
balbi
Signature · 6 lines
Regards and Thanks, Keerthy -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Hi,
Quoted 23 lines · KEERTHY
Quoted 8 lines
Quoted 8 lines
arch/arm/plat-omap/Kconfig +0
-0@@ -115,6 +115,18 @@ config OMAP_MCBSPSay Y here if you want support for the OMAP Multichannel Buffered Serial Port.
Quoted 14 lines
arch/arm/plat-omap/Kconfig config OMAP_MCBSP · line 128
Quoted 11 lines
arch/arm/plat-omap/Kconfig +11
-0+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()??
Quoted 2 lines
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 ?
Quoted 78 lines
Quoted 69 lines
Quoted 69 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +63
-0@@ -0,0 +1,87 @@ +/* +* OMAP Temperature sensor header file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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;Quoted 8 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h line 68
Quoted 5 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +5
-0+ 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.
Quoted 2 lines
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.
Signature · 1 line
balbi
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Quoted 26 lines · Felipe Balbi
Hi,
Quoted 23 lines · KEERTHY
Quoted 22 lines
Quoted 9 lines
arch/arm/plat-omap/Kconfig +0
-0@@ -115,6 +115,18 @@ config OMAP_MCBSPSay Y here if you want support for the OMAP Multichannel Buffered Serial Port.
arch/arm/plat-omap/Kconfig +1
-0+config OMAP_TEMP_SENSORarch/arm/plat-omap/Kconfig config OMAP_MCBSP · line 128
Quoted 10 lines
arch/arm/plat-omap/Kconfig +10
-0+ 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()??
Quoted 5 lines
Quoted 2 lines
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?
Quoted 79 lines
Quoted 79 lines
Quoted 78 lines
Quoted 65 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +58
-0@@ -0,0 +1,87 @@ +/* +* OMAP Temperature sensor header file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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;arch/arm/plat-omap/include/plat/temperature_sensor.h line 68
Quoted 10 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +10
-0+ 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.
Quoted 5 lines
Quoted 2 lines
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.
Quoted 4 lines
--
balbi
Signature · 6 lines
Regards and Thanks, Keerthy -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Hi,
Quoted 30 lines · KEERTHY
Quoted 29 lines · Felipe Balbi
Hi,
Quoted 25 lines · KEERTHY
Quoted 8 lines
Quoted 8 lines
arch/arm/plat-omap/Kconfig +0
-0@@ -115,6 +115,18 @@ config OMAP_MCBSPSay Y here if you want support for the OMAP Multichannel Buffered Serial Port.
Quoted 14 lines
arch/arm/plat-omap/Kconfig config OMAP_MCBSP · line 128
Quoted 11 lines
arch/arm/plat-omap/Kconfig +11
-0+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().
Quoted 6 lines
Quoted 2 lines
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.
Quoted 78 lines
Quoted 78 lines
Quoted 78 lines
Quoted 77 lines
Quoted 64 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +58
-0@@ -0,0 +1,87 @@ +/* +* OMAP Temperature sensor header file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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;arch/arm/plat-omap/include/plat/temperature_sensor.h line 68
Quoted 10 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +10
-0+ 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.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
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.
Signature · 1 line
balbi
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [RFC PATCH 4/6] OMAP4: Temperature sensor device support
Quoted 127 lines · Felipe Balbi
Hi,
Quoted 30 lines · KEERTHY
Quoted 29 lines · Felipe Balbi
Hi,
Quoted 25 lines · KEERTHY
Quoted 8 lines
Quoted 8 lines
arch/arm/plat-omap/Kconfig +0
-0@@ -115,6 +115,18 @@ config OMAP_MCBSPSay Y here if you want support for the OMAP Multichannel Buffered Serial Port.
Quoted 14 lines
arch/arm/plat-omap/Kconfig config OMAP_MCBSP · line 128
Quoted 11 lines
arch/arm/plat-omap/Kconfig +11
-0+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().Quoted 6 lines
Quoted 2 lines
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.
Quoted 84 lines
Quoted 83 lines
Quoted 78 lines
Quoted 69 lines
Quoted 69 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +63
-0@@ -0,0 +1,87 @@ +/* +* OMAP Temperature sensor header file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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;Quoted 8 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h line 68
Quoted 5 lines
arch/arm/plat-omap/include/plat/temperature_sensor.h new file +5
-0+ 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.Quoted 2 lines
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.
Quoted 6 lines
Quoted 2 lines
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.
Quoted 4 lines
--
balbi
Signature · 6 lines
Regards and Thanks, Keerthy -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
RFC PATCH 5/6 OMAP4460: Temperature sensor data
In reply to KeerthyThe 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.
--- 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
arch/arm/mach-omap2/temp_sensor4460_data.c new file +63 -0
@@ -0,0 +1,63 @@ +/* +* OMAP4460 on die Temperature sensor data file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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 , +};
Signature · 1 line
1.7.0.4
Re: [RFC PATCH 5/6] OMAP4460: Temperature sensor data
Hi,
Quoted 41 lines · 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 <[email protected]>--- 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.carch/arm/mach-omap2/temp_sensor4460_data.c new file +21
-0@@ -0,0 +1,63 @@ +/* +* OMAP4460 on die Temperature sensor data file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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 +* +*/
arch/arm/mach-omap2/temp_sensor4460_data.c line 31
Quoted 10 lines
arch/arm/mach-omap2/temp_sensor4460_data.c new file +10
-0+ +#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.
Signature · 1 line
balbi
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [RFC PATCH 5/6] OMAP4460: Temperature sensor data
Quoted 48 lines · Felipe Balbi
Hi,
Quoted 45 lines · 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 <[email protected]>---
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.carch/arm/mach-omap2/temp_sensor4460_data.c new file +25
-0@@ -0,0 +1,63 @@ +/* +* OMAP4460 on die Temperature sensor data file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* +* 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>
Quoted 8 lines
arch/arm/mach-omap2/temp_sensor4460_data.c line 31
Quoted 6 lines
arch/arm/mach-omap2/temp_sensor4460_data.c new file +6
-0+ +/* +* 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.
Quoted 4 lines
--
balbi
Signature · 7 lines
Regards and Thanks, Keerthy _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
In reply to KeerthyOn 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.
--- 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
drivers/hwmon/Kconfig +11 -0
@@ -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
drivers/hwmon/Makefile +1 -0
@@ -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
drivers/hwmon/omap_temp_sensor.c new file +950 -0
950 lines not on this page · raw message
Signature · 1 line
1.7.0.4
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Hi,
(why aren't below in Cc ?
HARDWARE MONITORING
M: Jean Delvare <[email protected]>
M: Guenter Roeck <[email protected]>
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)
Quoted 69 lines · 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_ueventinterface. The user is allowed to configure the temperature thresholds vis sysfs nodes exposed using hwmon interface.Signed-off-by Keerthy <[email protected]>--- 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.cdrivers/hwmon/Kconfig +11
-0@@ -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" helpdrivers/hwmon/Makefile +1
-0@@ -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.odrivers/hwmon/omap_temp_sensor.c new file +15
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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.
drivers/hwmon/omap_temp_sensor.c line 25
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+* +* 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 ??
drivers/hwmon/omap_temp_sensor.c line 27
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +2
-0+#include <linux/io.h> +#include <linux/debugfs.h>
why ??
drivers/hwmon/omap_temp_sensor.c line 32
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <plat/omap_device.h>
why ??
drivers/hwmon/omap_temp_sensor.c line 45
Quoted 13 lines
drivers/hwmon/omap_temp_sensor.c new file +13
-0+#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 ?
drivers/hwmon/omap_temp_sensor.c line 46
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <plat/temperature_sensor.h>
why ?
drivers/hwmon/omap_temp_sensor.c line 47
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/ctrl_module_core_44xx.h>
why ?
drivers/hwmon/omap_temp_sensor.c line 48
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/gpio.h>
linux/gpio.h for crying out loud... how many times Russell has to say the exact same thing ??????
Quoted 405 lines
drivers/hwmon/omap_temp_sensor.c new file +405
-0+#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); +
drivers/hwmon/omap_temp_sensor.c line 464
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+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 &= ??
drivers/hwmon/omap_temp_sensor.c line 465
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+ temp = temp *1000 / (temp_sensor->clk_rate);
temp *= ??
Quoted 105 lines
drivers/hwmon/omap_temp_sensor.c new file +105
-0+ +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 ;
drivers/hwmon/omap_temp_sensor.c line 580
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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 ??
Quoted 119 lines
drivers/hwmon/omap_temp_sensor.c new file +119
-0+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;
drivers/hwmon/omap_temp_sensor.c line 709
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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 ??
drivers/hwmon/omap_temp_sensor.c line 722
Quoted 12 lines
drivers/hwmon/omap_temp_sensor.c new file +12
-0+/* +* 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 ???
drivers/hwmon/omap_temp_sensor.c line 723
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+ temp_sensor->clock =clk_get (temp_sensor->hwmon_dev,"fck" );
why ?
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+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 ;
drivers/hwmon/omap_temp_sensor.c line 738
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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 ?
drivers/hwmon/omap_temp_sensor.c line 744
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+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 ??
Quoted 213 lines
drivers/hwmon/omap_temp_sensor.c new file +206
-0+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 <[email protected]>" );Signature · 6 lines
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
Signature · 8 lines
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>
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Quoted 3 lines · Felipe Balbi
Hi,
(why aren't below in Cc ?
I will add them.
Quoted 87 lines
HARDWARE MONITORING
M: ? ? ?Jean Delvare <[email protected]>
M: ? ? ?Guenter Roeck <[email protected]>
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: ? ? ?gitgit://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)Quoted 73 lines · 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_ueventinterface. The user is allowed to configure the temperature thresholds vis sysfs nodes exposed using hwmon interface.Signed-off-by Keerthy <[email protected]>---
?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.cdrivers/hwmon/Kconfig +0
-0@@ -323,6 +323,17 @@ config SENSORS_F71805F? ? ? ? This driver can also be built as a module. ?If so, the module ? ? ? ? will be called f71805f.
drivers/hwmon/Kconfig +11
-0+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"
? ? ? helpdrivers/hwmon/Makefile +0
-0@@ -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
drivers/hwmon/omap_temp_sensor.c new file +19
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 25
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+* 02110-1301 USA +* +*/ + +#include <linux/interrupt.h> +#include <linux/clk.h> why ??
Clock rate setting functions.
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c line 27
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c new file +2
-0+#include <linux/io.h> +#include <linux/debugfs.h> why ??
It will be removed.
Quoted 9 lines
drivers/hwmon/omap_temp_sensor.c line 32
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+#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
Quoted 7 lines
Quoted 7 lines
drivers/hwmon/omap_temp_sensor.c new file +7
-0+#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>
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 45
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+#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.
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c line 46
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <plat/temperature_sensor.h>
It is the header file with the structure definitions used in the driver.
Quoted 5 lines
why ?
drivers/hwmon/omap_temp_sensor.c line 47
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/ctrl_module_core_44xx.h> why ?
It will be removed
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c line 48
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/gpio.h>
linux/gpio.hfor crying out loud... how many times Russell has to say the exact same thing ??????
It will be removed
Quoted 418 lines
Quoted 405 lines
drivers/hwmon/omap_temp_sensor.c new file +405
-0+#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); +drivers/hwmon/omap_temp_sensor.c line 463
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ ? ? 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 &= ??
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c line 464
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+ ? ? 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.
Quoted 110 lines
Quoted 110 lines
drivers/hwmon/omap_temp_sensor.c new file +109
-0+ +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,
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 579
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ ? ? ? ? ? ? ? ? ? ? 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.
Quoted 125 lines
Quoted 125 lines
drivers/hwmon/omap_temp_sensor.c new file +124
-0+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;
Quoted 9 lines
drivers/hwmon/omap_temp_sensor.c line 708
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+ ? ? 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
Quoted 15 lines
drivers/hwmon/omap_temp_sensor.c line 720
Quoted 12 lines
drivers/hwmon/omap_temp_sensor.c new file +12
-0+ ? ? /* + ? ? ?* 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 ???
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c line 721
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+ ? ? 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.
Quoted 10 lines
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +9
-0+ ? ? 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);
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 736
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ ? ? 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.
Quoted 9 lines
drivers/hwmon/omap_temp_sensor.c line 742
Quoted 7 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ ? ? 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.
Quoted 218 lines
Quoted 210 lines
drivers/hwmon/omap_temp_sensor.c new file +206
-1+ ? ? 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 <[email protected]>" ); --1.7.0.4
Quoted 4 lines
--
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
Signature · 2 lines
Regards and Thanks, Keerthy
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Hi,
Quoted 103 lines · KEERTHY
Quoted 3 lines · Felipe Balbi
Hi,
(why aren't below in Cc ?
I will add them.
Quoted 87 lines
HARDWARE MONITORING
M: ? ? ?Jean Delvare <[email protected]>
M: ? ? ?Guenter Roeck <[email protected]>
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: ? ? ?gitgit://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)Quoted 73 lines · 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_ueventinterface. The user is allowed to configure the temperature thresholds vis sysfs nodes exposed using hwmon interface.Signed-off-by Keerthy <[email protected]>---
?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.cdrivers/hwmon/Kconfig +0
-0@@ -323,6 +323,17 @@ config SENSORS_F71805F? ? ? ? This driver can also be built as a module. ?If so, the module ? ? ? ? will be called f71805f.
drivers/hwmon/Kconfig +11
-0+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"
? ? ? helpdrivers/hwmon/Makefile +0
-0@@ -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
drivers/hwmon/omap_temp_sensor.c new file +19
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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 Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 25
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+* 02110-1301 USA +* +*/ + +#include <linux/interrupt.h> +#include <linux/clk.h> why ??
Quoted 1 line
Clock rate setting functions.
you shouldn't need in drivers.
Quoted 17 lines
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c line 27
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +2
-0+#include <linux/io.h> +#include <linux/debugfs.h> why ??
It will be removed.
Quoted 9 lines
drivers/hwmon/omap_temp_sensor.c line 32
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <plat/omap_device.h> why ??
Quoted 1 line
Context loss count
shouldn't use in drivers.
Quoted 16 lines
Quoted 7 lines
Quoted 7 lines
drivers/hwmon/omap_temp_sensor.c new file +7
-0+#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> Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 45
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+#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 ?
Quoted 1 line
usleep_rangefunction.
plat/common for usleep_range ?? usleep_range is defined in <linux/delay.h>
Quoted 5 lines
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c line 46
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#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/....> ??
Quoted 7 lines
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c line 47
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/ctrl_module_core_44xx.h> why ?
It will be removed
Quoted 1 line
Quoted 7 lines
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c line 48
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/gpio.h>
linux/gpio.hfor 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 ???
Quoted 418 lines
Quoted 418 lines
Quoted 405 lines
drivers/hwmon/omap_temp_sensor.c new file +405
-0+#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); +drivers/hwmon/omap_temp_sensor.c line 463
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ ? ? 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 &= ??
Quoted 6 lines
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c line 464
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+ ? ? 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;
Quoted 117 lines
Quoted 108 lines
Quoted 108 lines
drivers/hwmon/omap_temp_sensor.c new file +108
-0+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,Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 578
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ ? ? ? ? ? ? ? ? ? ? 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 ??
Quoted 2 lines
This is the programming sequence indicated.
BGAP_TEMPSOFFshould be set to 0 to enable the temperature sensor.
why isn't this done as part of your runtime_resume() function ??
Quoted 37 lines
Quoted 37 lines
Quoted 37 lines
drivers/hwmon/omap_temp_sensor.c new file +37
-0+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) {
Quoted 8 lines
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 623
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c new file +8
-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.
Signature · 8 lines
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>
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Quoted 106 lines · Felipe Balbi
Hi,
Quoted 103 lines · KEERTHY
Quoted 3 lines · Felipe Balbi
Hi,
(why aren't below in Cc ?
I will add them.
Quoted 95 lines
HARDWARE MONITORING
M: ? ? ?Jean Delvare <[email protected]>
M: ? ? ?Guenter Roeck <[email protected]>
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: ? ? ?gitgit://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)Quoted 69 lines · 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_ueventinterface. The user is allowed to configure the temperature thresholds vis sysfs nodes exposed using hwmon interface.Signed-off-by Keerthy <[email protected]>---
?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.cdrivers/hwmon/Kconfig +0
-0@@ -323,6 +323,17 @@ config SENSORS_F71805F? ? ? ? This driver can also be built as a module. ?If so, the module ? ? ? ? will be called f71805f.
drivers/hwmon/Kconfig +11
-0+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"
? ? ? helpdrivers/hwmon/Makefile +0
-0@@ -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
drivers/hwmon/omap_temp_sensor.c new file +15
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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. drivers/hwmon/omap_temp_sensor.c line 25
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+* +* 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 ??
Quoted 3 lines
Quoted 1 line
Clock rate setting functions.
you shouldn't need in drivers.
It is a one time setting of the rate so keeping it in drivers.
Quoted 18 lines
Quoted 18 lines
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c line 27
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c new file +2
-0+#include <linux/io.h> +#include <linux/debugfs.h> why ??
It will be removed.
Quoted 9 lines
drivers/hwmon/omap_temp_sensor.c line 32
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <plat/omap_device.h> why ??
Quoted 3 lines
Quoted 1 line
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.
Quoted 17 lines
Quoted 17 lines
Quoted 16 lines
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c new file +3
-0+#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> drivers/hwmon/omap_temp_sensor.c line 45
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+#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 ?
Quoted 4 lines
Quoted 1 line
usleep_rangefunction.plat/common for
usleep_range??usleep_rangeis defined in <linux/delay.h>
Ok it was indirect inclusion. I got it.
I will change this.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c line 46
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#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?
Quoted 10 lines
Quoted 10 lines
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c line 47
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/ctrl_module_core_44xx.h> why ?
It will be removed
Quoted 3 lines
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/gpio.h>
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
linux/gpio.hfor 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.
Quoted 421 lines
Quoted 421 lines
Quoted 421 lines
Quoted 406 lines
drivers/hwmon/omap_temp_sensor.c new file +405
-0+#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); +drivers/hwmon/omap_temp_sensor.c line 463
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ ? ? 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 &= ??
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+ ? ? temp = temp * 1000 / (temp_sensor->clk_rate);
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
? ? ? ?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.
Quoted 117 lines
Quoted 117 lines
Quoted 116 lines
Quoted 104 lines
drivers/hwmon/omap_temp_sensor.c new file +104
-0+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;drivers/hwmon/omap_temp_sensor.c line 578
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ ? ? ? ? ? ? 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 ??
Quoted 4 lines
Quoted 2 lines
This is the programming sequence indicated.
BGAP_TEMPSOFFshould 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.
Quoted 40 lines
Quoted 40 lines
Quoted 40 lines
Quoted 40 lines
drivers/hwmon/omap_temp_sensor.c new file +39
-0+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;
Quoted 8 lines
Quoted 6 lines
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c line 623
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ ? ? ? ? ? ? goto out; + ? ? } + ? ? temp_sensor->clk_on = 0; +out: + ? ? return ret; +}add a blank line here.
Ok
Quoted 4 lines
--
balbi
Signature · 2 lines
Regards and Thanks, Keerthy
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Hi,
Quoted 34 lines · KEERTHY
Quoted 34 lines
Quoted 34 lines
Quoted 33 lines
Quoted 21 lines
drivers/hwmon/omap_temp_sensor.c new file +15
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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. drivers/hwmon/omap_temp_sensor.c line 25
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+* +* 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 ??
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
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.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 32
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <plat/omap_device.h> why ??
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Context loss count
shouldn't use in drivers.
I guess already mmc and display are using
omap_pm_get_dev_context_loss_countbut 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.
Quoted 10 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c line 46
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#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.
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c line 47
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/ctrl_module_core_44xx.h> why ?
It will be removed
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c line 48
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/gpio.h>
linux/gpio.hfor crying out loud... how many times Russell has to say the exact same thing ??????
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
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.
Signature · 8 lines
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>
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Quoted 37 lines · Felipe Balbi
Hi,
Quoted 34 lines · KEERTHY
Quoted 34 lines
Quoted 34 lines
Quoted 34 lines
Quoted 34 lines
Quoted 34 lines
Quoted 33 lines
Quoted 33 lines
Quoted 23 lines
Quoted 23 lines
diff --git
a/drivers/hwmon/omap_temp_sensor.cb/drivers/hwmon/omap_temp_sensor.cnew 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<[email protected]>
+ * Author: Moiz Sonasath<[email protected]>
+ *
+ * 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 LicenseQuoted 8 lines
Quoted 8 lines
+ * 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 ??
Quoted 7 lines
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
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.
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
In reply to Felipe BalbiQuoted 41 lines · Felipe Balbi
Hi,
Quoted 38 lines · KEERTHY
Quoted 37 lines
Quoted 34 lines
Quoted 25 lines
Quoted 25 lines
drivers/hwmon/omap_temp_sensor.c new file +19
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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 Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 25
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+* 02110-1301 USA +* +*/ + +#include <linux/interrupt.h> +#include <linux/clk.h> why ??
Quoted 1 line
Clock rate setting functions.
you shouldn't need in drivers.
Quoted 8 lines
Quoted 1 line
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.
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
Quoted 11 lines
Quoted 9 lines
drivers/hwmon/omap_temp_sensor.c line 32
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+#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.
Quoted 7 lines
Quoted 4 lines
I guess already mmc and display are using
omap_pm_get_dev_context_loss_countbut 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
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c line 46
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <plat/temperature_sensor.h> It is the header file with the structure definitions used in the driver.
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
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.
Quoted 21 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c line 47
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/ctrl_module_core_44xx.h> why ?
It will be removed
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c line 48
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#include <mach/gpio.h>
linux/gpio.hfor crying out loud... how many times Russell has to say the exact same thing ??????Quoted 6 lines
Quoted 4 lines
Quoted 1 line
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.
Quoted 7 lines
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.
Quoted 4 lines
--
balbi
Signature · 2 lines
Regards and Thanks, Keerthy
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Hi,
Quoted 44 lines · KEERTHY
Quoted 43 lines · Felipe Balbi
Hi,
Quoted 39 lines · KEERTHY
Quoted 34 lines
Quoted 34 lines
Quoted 33 lines
Quoted 21 lines
drivers/hwmon/omap_temp_sensor.c new file +15
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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. drivers/hwmon/omap_temp_sensor.c line 25
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+* +* 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 ??
Quoted 3 lines
Quoted 1 line
Clock rate setting functions.
you shouldn't need in drivers.
It is a one time setting of the rate so keeping it in drivers.
Quoted 8 lines
Quoted 6 lines
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 ?
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
drivers/hwmon/omap_temp_sensor.c line 26
Quoted 1 line
drivers/hwmon/omap_temp_sensor.c new file +1
-0+#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/....> ??
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
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...
Signature · 8 lines
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>
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Hi,
Quoted 10 lines · Felipe Balbi
Quoted 8 lines
Quoted 6 lines
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.
Signature · 8 lines
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>
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Quoted 10 lines · Felipe Balbi
Hi,
Quoted 7 lines · Felipe Balbi
Quoted 7 lines
Quoted 6 lines
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.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
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
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Quoted 13 lines · Roger Quadros
Quoted 12 lines · Felipe Balbi
Hi,
Quoted 9 lines · Felipe Balbi
Quoted 8 lines
Quoted 6 lines
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.
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
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_latencycallbacks 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.
Quoted 19 lines
e.g. in the following snippet from
mach-omap2/temp_sensor_device.c(quoted diff) +7
-0+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_functoomap_device_enable_hwmods, it could point to a function that sets the required clock rate and then enables the hwmod.regards,
-roger
Signature · 2 lines
Regards and Thanks, Keerthy
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
In reply to Roger QuadrosQuoted 31 lines · Roger Quadros
Quoted 10 lines · Felipe Balbi
Hi,
Quoted 7 lines · Felipe Balbi
Quoted 7 lines
Quoted 6 lines
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.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
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_latencycallbacks the right place to do it?e.g. in the following snippet from
mach-omap2/temp_sensor_device.c(quoted diff) +7
-0+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, + } +};
Quoted 3 lines
instead of directly pointing
activate_functoomap_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.
Quoted 4 lines
regards,
-roger
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Hi,
Quoted 32 lines · Rajendra Nayak
Quoted 31 lines · Roger Quadros
Quoted 10 lines · Felipe Balbi
Hi,
Quoted 7 lines · Felipe Balbi
Quoted 7 lines
Quoted 6 lines
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.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
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_latencycallbacks the right place to do it?e.g. in the following snippet from
mach-omap2/temp_sensor_device.c(quoted diff) +7
-0+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, + } +};
Quoted 8 lines
Quoted 3 lines
instead of directly pointing
activate_functoomap_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 ?
Signature · 8 lines
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>
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
In reply to Rajendra NayakRajendra Nayak <[email protected]> writes:
[...]
Quoted 3 lines
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
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Quoted 10 lines · Kevin Hilman
Rajendra Nayak<[email protected]> writes:
[...]
Quoted 3 lines
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().
Quoted 3 lines
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.
Quoted 2 lines
Kevin
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Quoted 18 lines · Rajendra Nayak
Quoted 11 lines · Kevin Hilman
Rajendra Nayak<[email protected]> ?writes:
[...]
Quoted 3 lines
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 aclk_set_rate().Quoted 1 line
Quoted 6 lines
Quoted 2 lines
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?
Quoted 5 lines
Quoted 3 lines
Kevin
Signature · 2 lines
Regards and Thanks, Keerthy
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
In reply to Rajendra NayakQuoted 5 lines · Rajendra Nayak
Quoted 4 lines · Kevin Hilman
Rajendra Nayak<[email protected]> writes:
[...]
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
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.
Quoted 10 lines
So the driver is using a
clk_round_rate()to get the closest rate supported and sets it using aclk_set_rate().Quoted 3 lines
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
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
Quoted 14 lines · Kevin Hilman
Quoted 12 lines · Rajendra Nayak
Quoted 10 lines · Kevin Hilman
Rajendra Nayak<[email protected]> writes:
[...]
Quoted 3 lines
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.
Quoted 6 lines
Quoted 1 line
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.
Quoted 12 lines
Quoted 11 lines
So the driver is using a
clk_round_rate()to get the closest rate supported and sets it using aclk_set_rate().Quoted 3 lines
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.
Quoted 7 lines
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_dataonly 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.
Quoted 2 lines
Kevin
RFC PATCH 6/6 hwmon: OMAP4: On die temperature sensor driver
In reply to J, KEERTHYQuoted 1 line · KEERTHY
On Thu, Aug 11, 2011 at 4:06 PM, Felipe Balbi <[email protected]> wrote:
[ ... ]
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c line 464
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c new file +4
-0+ 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 &= ??Quoted 1 line
+ temp = temp * 1000 / (
temp_sensor->clk_rate);temp *= ??
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines
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
RE: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
In reply to KeerthyHi,
Quoted 308 lines
-----Original Message-----
From: [email protected] [mailto:lm-sensors-bounces@lm- sensors.org] On Behalf Of Keerthy
Sent: Wednesday, August 10, 2011 5:55 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]
Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driverOn 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_ueventinterface. The user is allowed to configure the temperature thresholds vis sysfs nodes exposed using hwmon interface.Signed-off-by Keerthy <[email protected]>--- 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.cdrivers/hwmon/Kconfig +11
-0@@ -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" helpdrivers/hwmon/Makefile +1
-0@@ -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.odrivers/hwmon/omap_temp_sensor.c new file +243
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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); +
drivers/hwmon/omap_temp_sensor.c line 253
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+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.. ?
Quoted 90 lines
drivers/hwmon/omap_temp_sensor.c new file +90
-0+} + +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; +
drivers/hwmon/omap_temp_sensor.c line 353
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+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..
drivers/hwmon/omap_temp_sensor.c line 248
Quoted 3 lines
drivers/hwmon/omap_temp_sensor.c new file +3
-0+ } + + temp =adc_to_temp_conversion (temp);
...subsequently,
ret = snprintf(buf, 16, "%d\n", temp);
drivers/hwmon/omap_temp_sensor.c line 253
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c new file +4
-0+out: +mutex_unlock (&temp_sensor->sensor_mutex); + +return snprintf (buf,16 ,"%d\n" , temp);
Return ret here..
Quoted 101 lines
drivers/hwmon/omap_temp_sensor.c new file +101
-0+} + +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,
drivers/hwmon/omap_temp_sensor.c line 471
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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..
Quoted 53 lines
drivers/hwmon/omap_temp_sensor.c new file +47
-0+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 notaccurate\n");
drivers/hwmon/omap_temp_sensor.c new file +5
-0+ +/* 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 ;
drivers/hwmon/omap_temp_sensor.c line 533
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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..
Quoted 28 lines
drivers/hwmon/omap_temp_sensor.c new file +8
-0+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,drivers/hwmon/omap_temp_sensor.c new file +19
-0+ 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;
drivers/hwmon/omap_temp_sensor.c line 570
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ +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...
Quoted 25 lines
drivers/hwmon/omap_temp_sensor.c new file +25
-0+ 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);
drivers/hwmon/omap_temp_sensor.c line 605
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c new file +4
-0+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);
drivers/hwmon/omap_temp_sensor.c line 619
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+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.
Quoted 63 lines
drivers/hwmon/omap_temp_sensor.c new file +63
-0+ 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 ; + } +
drivers/hwmon/omap_temp_sensor.c line 692
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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
drivers/hwmon/omap_temp_sensor.c line 702
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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
Quoted 16 lines
drivers/hwmon/omap_temp_sensor.c new file +16
-0+ 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))
drivers/hwmon/omap_temp_sensor.c line 728
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ 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
drivers/hwmon/omap_temp_sensor.c line 740
Quoted 12 lines
drivers/hwmon/omap_temp_sensor.c new file +12
-0+ 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.
Quoted 61 lines
drivers/hwmon/omap_temp_sensor.c new file +61
-0+ 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 ; +
drivers/hwmon/omap_temp_sensor.c line 811
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-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
Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
Hi,
Thanks for the Review Durga.
Quoted 315 lines · Durgadoss
Hi,
Quoted 313 lines
-----Original Message-----
From: [email protected] [mailto:lm-sensors-bounces@lm- sensors.org] On Behalf Of Keerthy
Sent: Wednesday, August 10, 2011 5:55 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]
Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driverOn 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_ueventinterface. The user is allowed to configure the temperature thresholds vis sysfs nodes exposed using hwmon interface.Signed-off-by Keerthy <[email protected]>---
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.cdrivers/hwmon/Kconfig +0
-0@@ -323,6 +323,17 @@ config SENSORS_F71805FThis driver can also be built as a module. If so, the module will be called f71805f.
drivers/hwmon/Kconfig +11
-0+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"
helpdrivers/hwmon/Makefile +0
-0@@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639) += max6639.oobj-$(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
drivers/hwmon/omap_temp_sensor.c new file +248
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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);
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 253
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+ +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-EINVALinside the 'if' check.
Ok
Quoted 3 lines
Moreover, you are just doing a read.
So, do you really need amutex_lockin 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.
Quoted 96 lines
Quoted 96 lines
drivers/hwmon/omap_temp_sensor.c new file +95
-0+} + +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) >>
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 353
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+ __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 =-EINVALhere..
Ok
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 248
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c new file +3
-0+ } + + temp = adc_to_temp_conversion(temp);...subsequently,
ret =snprintf(buf, 16, "%d\n", temp);
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c line 253
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c new file +4
-0+out: + mutex_unlock(&temp_sensor->sensor_mutex); + + return snprintf(buf, 16, "%d\n", temp);Return ret here..
Ok
Quoted 106 lines
Quoted 106 lines
drivers/hwmon/omap_temp_sensor.c new file +105
-0+} + +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);
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 471
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ +out: + mutex_unlock(&temp_sensor->sensor_mutex); + if (!ret) + return sprintf(buf, "%d\n", temp); + elseThe 'else' is not necessary..
Ok
Quoted 58 lines
Quoted 58 lines
drivers/hwmon/omap_temp_sensor.c new file +47
-0+ 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 notaccurate\n");
drivers/hwmon/omap_temp_sensor.c new file +9
-0+ + /* 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];
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 471
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ +out: + mutex_unlock(&temp_sensor->sensor_mutex); + if (!ret) + return sprintf(buf, "%d\n", temp); + elseSame here..
Ok
Quoted 73 lines
Quoted 29 lines
+ return ret;
drivers/hwmon/omap_temp_sensor.c new file +7
-0+} + +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);drivers/hwmon/omap_temp_sensor.c new file +18
-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;drivers/hwmon/omap_temp_sensor.c line 570
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ + 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 theget_sync.
Anyway, you are returning 'ret' in the end...Quoted 29 lines
+ goto out;
+ }drivers/hwmon/omap_temp_sensor.c new file +27
-0+ + 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,
Quoted 8 lines
Quoted 6 lines
+
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.
Quoted 16 lines
Quoted 15 lines
+ 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;
Quoted 1 line
Same case as
get_sync. Don't mask the return value.
Ok
Quoted 69 lines
Quoted 69 lines
+ goto out;
+ }
+temp_sensor->clk_on= 0;drivers/hwmon/omap_temp_sensor.c new file +65
-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);
Quoted 8 lines
Quoted 5 lines
+
+ 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
Quoted 17 lines
drivers/hwmon/omap_temp_sensor.c line 702
Quoted 11 lines
+ goto
plat_res_err;
+ }drivers/hwmon/omap_temp_sensor.c new file +8
-0+ + 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
Quoted 1 line
Then assign ret to
temp_sensor->irq
Ok
Quoted 21 lines
Quoted 21 lines
+
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;drivers/hwmon/omap_temp_sensor.c new file +16
-0+ + 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);
Quoted 8 lines
Quoted 6 lines
+
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
-EINVALto ret
Ok
Quoted 15 lines
drivers/hwmon/omap_temp_sensor.c line 740
Quoted 13 lines
+ goto
plat_res_err;
+ }drivers/hwmon/omap_temp_sensor.c new file +10
-0+ + 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
Quoted 66 lines
Quoted 66 lines
+ goto
clken_err;
+ }drivers/hwmon/omap_temp_sensor.c new file +63
-0+ + 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);
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 811
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+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
Quoted 5 lines
Thanks,
Durga
Signature · 6 lines
Regards and Thanks, Keerthy -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
Quoted 982 lines · KEERTHY
Hi,
Thanks for the Review Durga.
Quoted 315 lines · Durgadoss
Hi,
Quoted 313 lines
-----Original Message-----
From: [email protected] [mailto:lm-sensors-bounces@lm- sensors.org] On Behalf Of Keerthy
Sent: Wednesday, August 10, 2011 5:55 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]
Subject: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driverOn 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_ueventinterface. The user is allowed to configure the temperature thresholds vis sysfs nodes exposed using hwmon interface.Signed-off-by Keerthy <[email protected]>---
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.cdrivers/hwmon/Kconfig +0
-0@@ -323,6 +323,17 @@ config SENSORS_F71805FThis driver can also be built as a module. If so, the module will be called f71805f.
drivers/hwmon/Kconfig +11
-0+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"
helpdrivers/hwmon/Makefile +0
-0@@ -91,6 +91,7 @@ obj-$(CONFIG_SENSORS_MAX6639) += max6639.oobj-$(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
drivers/hwmon/omap_temp_sensor.c new file +248
-0@@ -0,0 +1,950 @@ +/* +* OMAP4 Temperature sensor driver file +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* Author: J Keerthy <[email protected]> +* Author: Moiz Sonasath <[email protected]> +* +* 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);Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 253
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+ +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-EINVALinside the 'if' check.Ok
Quoted 3 lines
Moreover, you are just doing a read.
So, do you really need amutex_lockin this function.. ?These values are RW. So the user can write a new value while you are reading. To be consistent
mutex_lockis needed.Quoted 96 lines
Quoted 96 lines
drivers/hwmon/omap_temp_sensor.c new file +95
-0+} + +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) >>Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 353
Quoted 5 lines
drivers/hwmon/omap_temp_sensor.c new file +5
-0+ __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 =-EINVALhere..Ok
Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 248
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c new file +3
-0+ } + + temp = adc_to_temp_conversion(temp);...subsequently,
ret =snprintf(buf, 16, "%d\n", temp);Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c line 253
Quoted 4 lines
drivers/hwmon/omap_temp_sensor.c new file +4
-0+out: + mutex_unlock(&temp_sensor->sensor_mutex); + + return snprintf(buf, 16, "%d\n", temp);Return ret here..
Ok
Quoted 106 lines
Quoted 106 lines
drivers/hwmon/omap_temp_sensor.c new file +105
-0+} + +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);Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 471
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ +out: + mutex_unlock(&temp_sensor->sensor_mutex); + if (!ret) + return sprintf(buf, "%d\n", temp); + elseThe 'else' is not necessary..
Ok
Quoted 58 lines
Quoted 58 lines
drivers/hwmon/omap_temp_sensor.c new file +47
-0+ 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 notaccurate\n");
drivers/hwmon/omap_temp_sensor.c new file +9
-0+ + /* 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];Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 471
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+ +out: + mutex_unlock(&temp_sensor->sensor_mutex); + if (!ret) + return sprintf(buf, "%d\n", temp); + elseSame here..
Ok
Quoted 73 lines
Quoted 29 lines
+ return ret;
drivers/hwmon/omap_temp_sensor.c new file +7
-0+} + +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);drivers/hwmon/omap_temp_sensor.c new file +18
-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;drivers/hwmon/omap_temp_sensor.c line 570
Quoted 10 lines
drivers/hwmon/omap_temp_sensor.c new file +10
-0+ + 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 theget_sync.
Anyway, you are returning 'ret' in the end...Quoted 29 lines
+ goto out;
+ }drivers/hwmon/omap_temp_sensor.c new file +27
-0+ + 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,Quoted 8 lines
Quoted 6 lines
+
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.
Quoted 16 lines
Quoted 15 lines
+ 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;Quoted 1 line
Same case as
get_sync. Don't mask the return value.Ok
Quoted 69 lines
Quoted 69 lines
+ goto out;
+ }
+temp_sensor->clk_on= 0;drivers/hwmon/omap_temp_sensor.c new file +65
-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);Quoted 8 lines
Quoted 5 lines
+
+ 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-ENOMEMOk
Quoted 17 lines
drivers/hwmon/omap_temp_sensor.c line 702
Quoted 11 lines
+ goto
plat_res_err;
+ }drivers/hwmon/omap_temp_sensor.c new file +8
-0+ + 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
Quoted 1 line
Then assign ret to
temp_sensor->irqOk
Quoted 21 lines
Quoted 21 lines
+
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;drivers/hwmon/omap_temp_sensor.c new file +16
-0+ + 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);Quoted 8 lines
Quoted 6 lines
+
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
-EINVALto retOk
Quoted 15 lines
drivers/hwmon/omap_temp_sensor.c line 740
Quoted 13 lines
+ goto
plat_res_err;
+ }drivers/hwmon/omap_temp_sensor.c new file +10
-0+ + 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
Quoted 66 lines
Quoted 66 lines
+ goto
clken_err;
+ }drivers/hwmon/omap_temp_sensor.c new file +63
-0+ + 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);Quoted 8 lines
drivers/hwmon/omap_temp_sensor.c line 811
Quoted 6 lines
drivers/hwmon/omap_temp_sensor.c new file +6
-0+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.
Quoted 9 lines
Ok
Quoted 5 lines
Thanks,
Durga
Hi Guenter,
Any inputs on the driver?
Quoted 5 lines
--
Regards and Thanks,
Keerthy
Signature · 6 lines
Regards and Thanks, Keerthy -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
On Wed, Aug 17, 2011 at 06:37:10AM -0400, J, KEERTHY wrote:
[ ... ]
Quoted 5 lines
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
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [lm-sensors] [RFC PATCH 6/6] hwmon: OMAP4: On die temperature sensor driver
Quoted 5 lines · Guenter Roeck
On Wed, Aug 17, 2011 at 06:37:10AM -0400, J, KEERTHY wrote:
[ ... ]Quoted 3 lines
Hi Guenter,
Quoted 8 lines
Quoted 2 lines
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.
Quoted 3 lines
Thanks,
Guenter
Signature · 2 lines
Regards and Thanks, Keerthy