286 lines
9.3 KiB
Diff
286 lines
9.3 KiB
Diff
From e11104658a3b8eabbb4eb74b38645a4f114b745d Mon Sep 17 00:00:00 2001
|
|
From: Kalhan Trisal <kalhan.trisal@intel.com>
|
|
Date: Fri, 4 Sep 2009 18:10:52 -0400
|
|
Subject: [PATCH 075/104] Thermal patch for emc1403 driver
|
|
|
|
Thermal driver will handle event generation even if alert handler is called multiple time due to GPE->GPIO changes. The IRQ has become now shared and the handler will be called on every event as shared with other devices also.
|
|
|
|
Signed-off-by: Kalhan Trisal <kalhan.trisal@intel.com>
|
|
---
|
|
drivers/hwmon/Kconfig | 2 +-
|
|
drivers/hwmon/emc1403.c | 128 +++++++++++++++++++++--------------------------
|
|
2 files changed, 58 insertions(+), 72 deletions(-)
|
|
|
|
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
|
|
index 55637c3..c8fefbc 100644
|
|
--- a/drivers/hwmon/Kconfig
|
|
+++ b/drivers/hwmon/Kconfig
|
|
@@ -55,7 +55,7 @@ config SENSORS_LIS331DL
|
|
|
|
config SENSORS_EMC1403
|
|
tristate "SMSC EMC1403 Thermal"
|
|
- depends on I2C_MRST && GPE && GPIO_MAX7315 && MSTWN_POWER_MGMT
|
|
+ depends on I2C
|
|
help
|
|
If you say yes here you get support for the SMSC Devices
|
|
EMC1403 temperature monitoring chip.
|
|
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
|
|
index 45cf5d0..75e3b15 100644
|
|
--- a/drivers/hwmon/emc1403.c
|
|
+++ b/drivers/hwmon/emc1403.c
|
|
@@ -44,8 +44,7 @@ MODULE_LICENSE("GPL v2");
|
|
/* To support the interrupt mechanism for moorestown interrupt flag is added
|
|
* If the flag is not enabled it support generic emc1403 chip */
|
|
|
|
-#if defined(CONFIG_GPIO_LNWPMIC) && defined(CONFIG_GPIO_MAX7315) \
|
|
- && defined(CONFIG_MSTWN_POWER_MGMT)
|
|
+#if defined(CONFIG_GPIO_LANGWELL_PMIC) && defined(CONFIG_MSTWN_POWER_MGMT)
|
|
#define MOORESTOWN_INTERRUPT_ENABLE
|
|
#endif
|
|
|
|
@@ -335,40 +334,6 @@ static ssize_t store_power_state(struct device *dev,
|
|
return count;
|
|
}
|
|
|
|
-static ssize_t show_mode(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- struct i2c_client *client = to_i2c_client(dev);
|
|
- int ret_val;
|
|
-
|
|
- ret_val = i2c_read_current_data(client, 0x03);
|
|
- ret_val = ret_val & 0x80;
|
|
- if (ret_val == 0x80)
|
|
- ret_val = 1;
|
|
- return sprintf(buf, "%x", ret_val);
|
|
-}
|
|
-
|
|
-static ssize_t store_mode(struct device *dev,
|
|
- struct device_attribute *attr, const char *buf, size_t count)
|
|
-{
|
|
- struct i2c_client *client = to_i2c_client(dev);
|
|
- unsigned long val = 0;
|
|
- char curr_val;
|
|
-
|
|
- if (strict_strtoul(buf, 10, &val))
|
|
- return -EINVAL;
|
|
-
|
|
- curr_val = i2c_read_current_data(client, 0x03);
|
|
- if (val == INTERRUPT_MODE_ENABLE)
|
|
- curr_val = curr_val & 0x7F;
|
|
- else if (val == INTERRUPT_MODE_DISABLE)
|
|
- curr_val = curr_val | 0x80;
|
|
- else
|
|
- return -EINVAL;
|
|
- i2c_write_current_data(client, 0x03, curr_val);
|
|
- return count;
|
|
-}
|
|
-
|
|
static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR,
|
|
show_temp_auto_offset, store_temp_auto_offset, 0, 1);
|
|
static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
|
|
@@ -398,7 +363,6 @@ static DEVICE_ATTR(status, S_IRUGO, show_status_reg, NULL);
|
|
|
|
static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
|
|
show_power_state, store_power_state);
|
|
-static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode);
|
|
|
|
static struct attribute *mid_att_thermal[] = {
|
|
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
|
@@ -416,7 +380,6 @@ static struct attribute *mid_att_thermal[] = {
|
|
&dev_attr_hyster.attr,
|
|
&dev_attr_status.attr,
|
|
&dev_attr_power_state.attr,
|
|
- &dev_attr_mode.attr,
|
|
NULL
|
|
};
|
|
|
|
@@ -449,102 +412,124 @@ static irqreturn_t alert_interrupt_handler(int id, void *dev)
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
+
|
|
/* when the device raise the interrupt we mask the interrupt
|
|
* bit for that device as the status register is R-C
|
|
* so that till thermal governor doesnot take action we need
|
|
* not to send continuous events */
|
|
|
|
static int interrupt_status(struct i2c_client *client, u8 diode_reg_val,
|
|
- u8 *status, u8 event)
|
|
+ u8 *mask_status, u8 event, u8 *status)
|
|
{
|
|
- u8 crit_st = 0, set_mask = 0;
|
|
+ u8 crit_st = 0, set_mask = 0, event_status = 0;
|
|
|
|
set_mask = i2c_read_current_data(client, 0x1F);
|
|
if (diode_reg_val & THM_CHAN_TEMP[3]) {
|
|
- set_mask = (set_mask | 0x02);
|
|
- crit_st = (crit_st | 2);
|
|
+ if (set_mask & TEMP2)
|
|
+ event_status = event_status | TEMP2;
|
|
+ else
|
|
+ set_mask = set_mask | 0x02;
|
|
+ crit_st = crit_st | 2;
|
|
}
|
|
if (diode_reg_val & THM_CHAN_TEMP[2]) {
|
|
- set_mask = (set_mask | 0x04);
|
|
- crit_st = (crit_st | 4);
|
|
+ if (set_mask & TEMP3)
|
|
+ event_status = event_status | TEMP3;
|
|
+ else
|
|
+ set_mask = set_mask | 0x04;
|
|
+ crit_st = crit_st | 4;
|
|
}
|
|
if (diode_reg_val & THM_CHAN_TEMP[4]) {
|
|
- set_mask = (set_mask | 0x01);
|
|
- crit_st = (crit_st | 1);
|
|
+ if (set_mask & TEMP1)
|
|
+ event_status = event_status | TEMP1;
|
|
+ else
|
|
+ set_mask = set_mask | 0x01;
|
|
+ crit_st = crit_st | 1;
|
|
}
|
|
if (event == ALERT_EVENT)
|
|
- i2c_smbus_write_byte_data(client, 0x1F, set_mask);
|
|
- *status = crit_st;
|
|
+ i2c_smbus_write_byte_data(client, 0x1f, set_mask);
|
|
+ *mask_status = crit_st;
|
|
+ *status = event_status;
|
|
return 0;
|
|
}
|
|
|
|
static void ospm_event(int event_id, int sensor_id, int curr_temp)
|
|
{
|
|
if (event_id == THERM_EVENT) {
|
|
- printk(KERN_ALERT "emc1403: Sensor Id = %d crit event \
|
|
+ printk(KERN_ALERT "emc1403: sensor id = %d crit event \
|
|
temp = %d \n", sensor_id, curr_temp);
|
|
ospm_generate_netlink_event(sensor_id,
|
|
OSPM_EVENT_THERMAL_CRITICAL);
|
|
}
|
|
if (event_id == HIGH_EVENT) {
|
|
- printk(KERN_ALERT "emc1403: Sensor Id = %d AUX1 event \
|
|
+ printk(KERN_ALERT "emc1403: sensor id = %d aux1 event \
|
|
temp = %d \n", sensor_id, curr_temp);
|
|
ospm_generate_netlink_event(sensor_id,
|
|
OSPM_EVENT_THERMAL_AUX1);
|
|
}
|
|
if (event_id == LOW_EVENT) {
|
|
- printk(KERN_ALERT "emc1403: Sensor Id = %d AUX0 event \
|
|
+ printk(KERN_ALERT "emc1403: sensor id = %d aux0 event \
|
|
temp = %d \n", sensor_id, curr_temp);
|
|
ospm_generate_netlink_event(sensor_id,
|
|
OSPM_EVENT_THERMAL_AUX0);
|
|
}
|
|
if (event_id == FAULT_EVENT) {
|
|
- printk(KERN_ALERT "emc1403: Sensor Id = %d Fault event \
|
|
+ printk(KERN_ALERT "emc1403: sensor id = %d fault event \
|
|
temp = %d \n", sensor_id, curr_temp);
|
|
ospm_generate_netlink_event(sensor_id,
|
|
OSPM_EVENT_THERMAL_DEV_FAULT);
|
|
}
|
|
}
|
|
|
|
-static void send_event(struct i2c_client *client, int status, int event_id)
|
|
+static void send_event(struct i2c_client *client, int status, u8 mask_event,
|
|
+ int event_id)
|
|
{
|
|
int ret_val;
|
|
|
|
if (status & TEMP1) {
|
|
- ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[0]);
|
|
- ospm_event(event_id, TEMP_DEV_ID1, ret_val);
|
|
+ if (!(TEMP1 & mask_event)) {
|
|
+ ret_val = i2c_read_current_data(client,
|
|
+ THM_REG_CURR_TEMP[0]);
|
|
+ ospm_event(event_id, TEMP_DEV_ID1, ret_val);
|
|
+ }
|
|
}
|
|
if (status & TEMP2) {
|
|
- ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[1]);
|
|
- ospm_event(event_id, TEMP_DEV_ID2, ret_val);
|
|
+ if (!(TEMP2 & mask_event)) {
|
|
+ ret_val = i2c_read_current_data(client,
|
|
+ THM_REG_CURR_TEMP[1]);
|
|
+ ospm_event(event_id, TEMP_DEV_ID2, ret_val);
|
|
+ }
|
|
}
|
|
if (status & TEMP3) {
|
|
- ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[2]);
|
|
- ospm_event(event_id, TEMP_DEV_ID3, ret_val);
|
|
+ if (!(TEMP3 & mask_event)) {
|
|
+ ret_val = i2c_read_current_data(client,
|
|
+ THM_REG_CURR_TEMP[2]);
|
|
+ ospm_event(event_id, TEMP_DEV_ID3, ret_val);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
static void therm_handle_intrpt(struct work_struct *work)
|
|
{
|
|
- u8 status, reg_val;
|
|
+ u8 status, reg_val, mask_status;
|
|
struct thermal_data *data = container_of(work,
|
|
struct thermal_data, therm_handler);
|
|
|
|
/* check if therm_module_info is initialized */
|
|
if (!data)
|
|
return;
|
|
- /* Which DIODE has raised the interrupt 0x1B
|
|
- internal/External1/External2 */
|
|
+ /* which diode has raised the interrupt 0x1b
|
|
+ internal/external1/external2 */
|
|
reg_val = i2c_smbus_read_byte_data(data->client,
|
|
THM_STAT_REG_TEMP[0]);
|
|
- interrupt_status(data->client, reg_val, &status, THERM_EVENT);
|
|
- send_event(data->client, status, THERM_EVENT);
|
|
+ interrupt_status(data->client, reg_val, &status, THERM_EVENT,
|
|
+ &mask_status);
|
|
+ send_event(data->client, status, 0, THERM_EVENT);
|
|
}
|
|
|
|
static void alert_handle_intrpt(struct work_struct *work)
|
|
{
|
|
int sta_reg_val, reg_val;
|
|
- u8 status;
|
|
+ u8 status, mask_status;
|
|
struct thermal_data *data = container_of(work,
|
|
struct thermal_data, alert_handler);
|
|
if (!data)
|
|
@@ -557,25 +542,26 @@ static void alert_handle_intrpt(struct work_struct *work)
|
|
internal/External1/External2 */
|
|
sta_reg_val = i2c_smbus_read_byte_data(data->client,
|
|
THM_STAT_REG_TEMP[1]);
|
|
+ /*chek if the mask is already enabled then donot send the event again*/
|
|
interrupt_status(data->client, sta_reg_val, &status,
|
|
- ALERT_EVENT);
|
|
- send_event(data->client, status, HIGH_EVENT);
|
|
+ ALERT_EVENT, &mask_status);
|
|
+ send_event(data->client, status, mask_status, HIGH_EVENT);
|
|
}
|
|
/* Low status bit is set */
|
|
if (reg_val & THM_CHAN_TEMP[1]) {
|
|
sta_reg_val = i2c_smbus_read_byte_data(data->client,
|
|
THM_STAT_REG_TEMP[2]);
|
|
interrupt_status(data->client, sta_reg_val, &status,
|
|
- ALERT_EVENT);
|
|
- send_event(data->client, status, LOW_EVENT);
|
|
+ ALERT_EVENT, &mask_status);
|
|
+ send_event(data->client, status, mask_status, LOW_EVENT);
|
|
}
|
|
/* Fault status bit is set */
|
|
if (reg_val & THM_CHAN_TEMP[2]) {
|
|
sta_reg_val = i2c_smbus_read_byte_data(data->client,
|
|
THM_STAT_REG_TEMP[3]);
|
|
interrupt_status(data->client, sta_reg_val, &status,
|
|
- ALERT_EVENT);
|
|
- send_event(data->client, status, FAULT_EVENT);
|
|
+ ALERT_EVENT, &mask_status);
|
|
+ send_event(data->client, status, mask_status, FAULT_EVENT);
|
|
}
|
|
}
|
|
#endif
|
|
--
|
|
1.6.2.5
|
|
|