]> code.ossystems Code Review - openembedded-core.git/blob
667db0207687326f549d4ab2066046ddd2da6fb6
[openembedded-core.git] /
1 From e11104658a3b8eabbb4eb74b38645a4f114b745d Mon Sep 17 00:00:00 2001
2 From: Kalhan Trisal <kalhan.trisal@intel.com>
3 Date: Fri, 4 Sep 2009 18:10:52 -0400
4 Subject: [PATCH 075/104] Thermal patch for emc1403 driver
5
6 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.
7
8 Signed-off-by: Kalhan Trisal <kalhan.trisal@intel.com>
9 ---
10  drivers/hwmon/Kconfig   |    2 +-
11  drivers/hwmon/emc1403.c |  128 +++++++++++++++++++++--------------------------
12  2 files changed, 58 insertions(+), 72 deletions(-)
13
14 diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
15 index 55637c3..c8fefbc 100644
16 --- a/drivers/hwmon/Kconfig
17 +++ b/drivers/hwmon/Kconfig
18 @@ -55,7 +55,7 @@ config SENSORS_LIS331DL
19  
20  config SENSORS_EMC1403
21         tristate "SMSC EMC1403 Thermal"
22 -       depends on I2C_MRST && GPE && GPIO_MAX7315 && MSTWN_POWER_MGMT
23 +       depends on I2C
24         help
25           If you say yes here you get support for the SMSC Devices
26           EMC1403 temperature monitoring chip.
27 diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
28 index 45cf5d0..75e3b15 100644
29 --- a/drivers/hwmon/emc1403.c
30 +++ b/drivers/hwmon/emc1403.c
31 @@ -44,8 +44,7 @@ MODULE_LICENSE("GPL v2");
32  /* To support the interrupt mechanism for moorestown interrupt flag is added
33   * If the flag is not enabled it support generic emc1403 chip */
34  
35 -#if defined(CONFIG_GPIO_LNWPMIC) && defined(CONFIG_GPIO_MAX7315) \
36 -                       && defined(CONFIG_MSTWN_POWER_MGMT)
37 +#if defined(CONFIG_GPIO_LANGWELL_PMIC) && defined(CONFIG_MSTWN_POWER_MGMT)
38  #define MOORESTOWN_INTERRUPT_ENABLE
39  #endif
40  
41 @@ -335,40 +334,6 @@ static ssize_t store_power_state(struct device *dev,
42         return count;
43  }
44  
45 -static ssize_t show_mode(struct device *dev,
46 -                       struct device_attribute *attr, char *buf)
47 -{
48 -       struct i2c_client *client = to_i2c_client(dev);
49 -       int ret_val;
50 -
51 -       ret_val = i2c_read_current_data(client, 0x03);
52 -       ret_val = ret_val & 0x80;
53 -       if (ret_val == 0x80)
54 -               ret_val = 1;
55 -       return sprintf(buf, "%x", ret_val);
56 -}
57 -
58 -static ssize_t store_mode(struct device *dev,
59 -               struct device_attribute *attr, const char *buf, size_t count)
60 -{
61 -       struct i2c_client *client = to_i2c_client(dev);
62 -       unsigned long val = 0;
63 -       char curr_val;
64 -
65 -       if (strict_strtoul(buf, 10, &val))
66 -               return -EINVAL;
67 -
68 -       curr_val = i2c_read_current_data(client, 0x03);
69 -       if (val == INTERRUPT_MODE_ENABLE)
70 -               curr_val = curr_val & 0x7F;
71 -       else if (val == INTERRUPT_MODE_DISABLE)
72 -               curr_val = curr_val | 0x80;
73 -       else
74 -               return -EINVAL;
75 -       i2c_write_current_data(client, 0x03, curr_val);
76 -       return count;
77 -}
78 -
79  static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR,
80         show_temp_auto_offset, store_temp_auto_offset, 0, 1);
81  static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
82 @@ -398,7 +363,6 @@ static DEVICE_ATTR(status, S_IRUGO, show_status_reg, NULL);
83  
84  static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
85         show_power_state, store_power_state);
86 -static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode);
87  
88  static struct attribute *mid_att_thermal[] = {
89         &sensor_dev_attr_temp1_min.dev_attr.attr,
90 @@ -416,7 +380,6 @@ static struct attribute *mid_att_thermal[] = {
91         &dev_attr_hyster.attr,
92         &dev_attr_status.attr,
93         &dev_attr_power_state.attr,
94 -       &dev_attr_mode.attr,
95         NULL
96  };
97  
98 @@ -449,102 +412,124 @@ static irqreturn_t alert_interrupt_handler(int id, void *dev)
99         return IRQ_HANDLED;
100  }
101  
102 +
103  /* when the device raise the interrupt we mask the interrupt
104   * bit for that device as the status register is R-C
105   * so that till thermal governor doesnot take action  we need
106   * not to send continuous events */
107  
108  static int interrupt_status(struct i2c_client *client, u8 diode_reg_val,
109 -                               u8 *status, u8 event)
110 +                               u8 *mask_status, u8 event, u8 *status)
111  {
112 -       u8 crit_st = 0, set_mask = 0;
113 +       u8 crit_st = 0, set_mask = 0, event_status = 0;
114  
115         set_mask = i2c_read_current_data(client, 0x1F);
116         if (diode_reg_val & THM_CHAN_TEMP[3]) {
117 -               set_mask = (set_mask | 0x02);
118 -               crit_st = (crit_st  | 2);
119 +               if (set_mask & TEMP2)
120 +                       event_status = event_status | TEMP2;
121 +               else
122 +                       set_mask = set_mask | 0x02;
123 +               crit_st = crit_st  | 2;
124         }
125         if (diode_reg_val & THM_CHAN_TEMP[2]) {
126 -               set_mask = (set_mask | 0x04);
127 -               crit_st = (crit_st  | 4);
128 +               if (set_mask & TEMP3)
129 +                       event_status = event_status | TEMP3;
130 +               else
131 +                       set_mask = set_mask | 0x04;
132 +               crit_st = crit_st  | 4;
133         }
134         if (diode_reg_val & THM_CHAN_TEMP[4]) {
135 -               set_mask = (set_mask | 0x01);
136 -               crit_st = (crit_st  | 1);
137 +               if (set_mask & TEMP1)
138 +                       event_status = event_status | TEMP1;
139 +               else
140 +                       set_mask = set_mask | 0x01;
141 +               crit_st = crit_st  | 1;
142         }
143         if (event == ALERT_EVENT)
144 -               i2c_smbus_write_byte_data(client, 0x1F, set_mask);
145 -       *status = crit_st;
146 +               i2c_smbus_write_byte_data(client, 0x1f, set_mask);
147 +       *mask_status = crit_st;
148 +       *status = event_status;
149         return 0;
150  }
151  
152  static void ospm_event(int event_id, int sensor_id, int curr_temp)
153  {
154         if (event_id == THERM_EVENT) {
155 -               printk(KERN_ALERT "emc1403: Sensor Id = %d crit event \
156 +               printk(KERN_ALERT "emc1403: sensor id = %d crit event \
157                                         temp = %d \n", sensor_id, curr_temp);
158                 ospm_generate_netlink_event(sensor_id,
159                                         OSPM_EVENT_THERMAL_CRITICAL);
160         }
161         if (event_id == HIGH_EVENT) {
162 -               printk(KERN_ALERT "emc1403: Sensor Id = %d AUX1 event \
163 +               printk(KERN_ALERT "emc1403: sensor id = %d aux1 event \
164                                         temp = %d \n", sensor_id, curr_temp);
165                 ospm_generate_netlink_event(sensor_id,
166                                         OSPM_EVENT_THERMAL_AUX1);
167         }
168         if (event_id == LOW_EVENT) {
169 -               printk(KERN_ALERT "emc1403: Sensor Id = %d AUX0 event \
170 +               printk(KERN_ALERT "emc1403: sensor id = %d aux0 event \
171                                         temp = %d \n", sensor_id, curr_temp);
172         ospm_generate_netlink_event(sensor_id,
173                                         OSPM_EVENT_THERMAL_AUX0);
174         }
175         if (event_id == FAULT_EVENT) {
176 -               printk(KERN_ALERT "emc1403: Sensor Id  = %d Fault event \
177 +               printk(KERN_ALERT "emc1403: sensor id  = %d fault event \
178                                         temp = %d \n", sensor_id, curr_temp);
179                 ospm_generate_netlink_event(sensor_id,
180                                         OSPM_EVENT_THERMAL_DEV_FAULT);
181         }
182  }
183  
184 -static void send_event(struct i2c_client *client, int status, int event_id)
185 +static void send_event(struct i2c_client *client, int status, u8 mask_event,
186 +                       int event_id)
187  {
188         int ret_val;
189  
190         if (status & TEMP1) {
191 -               ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[0]);
192 -               ospm_event(event_id, TEMP_DEV_ID1, ret_val);
193 +               if (!(TEMP1 & mask_event)) {
194 +                       ret_val = i2c_read_current_data(client,
195 +                                                       THM_REG_CURR_TEMP[0]);
196 +                       ospm_event(event_id, TEMP_DEV_ID1, ret_val);
197 +               }
198         }
199         if (status & TEMP2) {
200 -               ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[1]);
201 -               ospm_event(event_id, TEMP_DEV_ID2, ret_val);
202 +               if (!(TEMP2 & mask_event)) {
203 +                       ret_val = i2c_read_current_data(client,
204 +                                                       THM_REG_CURR_TEMP[1]);
205 +                       ospm_event(event_id, TEMP_DEV_ID2, ret_val);
206 +               }
207         }
208         if (status & TEMP3) {
209 -               ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[2]);
210 -               ospm_event(event_id, TEMP_DEV_ID3, ret_val);
211 +               if (!(TEMP3 & mask_event)) {
212 +                       ret_val = i2c_read_current_data(client,
213 +                                                       THM_REG_CURR_TEMP[2]);
214 +                       ospm_event(event_id, TEMP_DEV_ID3, ret_val);
215 +               }
216         }
217  }
218  
219  static void therm_handle_intrpt(struct work_struct *work)
220  {
221 -       u8 status, reg_val;
222 +       u8 status, reg_val, mask_status;
223         struct thermal_data *data = container_of(work,
224                                         struct thermal_data, therm_handler);
225  
226         /* check if therm_module_info is initialized */
227         if (!data)
228                 return;
229 -       /* Which DIODE has raised the interrupt 0x1B
230 -               internal/External1/External2 */
231 +       /* which diode has raised the interrupt 0x1b
232 +               internal/external1/external2 */
233         reg_val = i2c_smbus_read_byte_data(data->client,
234                                                 THM_STAT_REG_TEMP[0]);
235 -       interrupt_status(data->client, reg_val, &status, THERM_EVENT);
236 -       send_event(data->client, status, THERM_EVENT);
237 +       interrupt_status(data->client, reg_val, &status, THERM_EVENT,
238 +                       &mask_status);
239 +       send_event(data->client, status, 0, THERM_EVENT);
240  }
241  
242  static void alert_handle_intrpt(struct work_struct *work)
243  {
244         int sta_reg_val, reg_val;
245 -       u8 status;
246 +       u8 status, mask_status;
247         struct thermal_data *data = container_of(work,
248                                         struct thermal_data, alert_handler);
249         if (!data)
250 @@ -557,25 +542,26 @@ static void alert_handle_intrpt(struct work_struct *work)
251                 internal/External1/External2 */
252                 sta_reg_val = i2c_smbus_read_byte_data(data->client,
253                                         THM_STAT_REG_TEMP[1]);
254 +       /*chek if the mask is already enabled then donot send the event again*/
255                 interrupt_status(data->client, sta_reg_val, &status,
256 -                                       ALERT_EVENT);
257 -               send_event(data->client, status, HIGH_EVENT);
258 +                                       ALERT_EVENT, &mask_status);
259 +               send_event(data->client, status, mask_status, HIGH_EVENT);
260         }
261         /* Low status bit is set */
262         if (reg_val & THM_CHAN_TEMP[1]) {
263                 sta_reg_val = i2c_smbus_read_byte_data(data->client,
264                                         THM_STAT_REG_TEMP[2]);
265                 interrupt_status(data->client, sta_reg_val, &status,
266 -                                       ALERT_EVENT);
267 -               send_event(data->client, status, LOW_EVENT);
268 +                                       ALERT_EVENT, &mask_status);
269 +               send_event(data->client, status, mask_status, LOW_EVENT);
270         }
271         /* Fault status bit is set */
272         if (reg_val & THM_CHAN_TEMP[2]) {
273                 sta_reg_val = i2c_smbus_read_byte_data(data->client,
274                                         THM_STAT_REG_TEMP[3]);
275                 interrupt_status(data->client, sta_reg_val, &status,
276 -                                       ALERT_EVENT);
277 -               send_event(data->client, status, FAULT_EVENT);
278 +                                       ALERT_EVENT, &mask_status);
279 +               send_event(data->client, status, mask_status, FAULT_EVENT);
280         }
281  }
282  #endif
283 -- 
284 1.6.2.5
285