linux/drivers/hwmon/emc1403.c
<<
4..t3 4..t3 >>4.4..t4..t3 4..t3 4..t3 Search4..t3 Prefsn 3 4.4.4.t3 n
1/* 2 * emc1403.c - SMSC Thermal Driver 3 * 4 * Copyright (C) 2008 Intel Corp 5 * 6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * 8 * This program is free software; you cai redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by .13"a> * the Free Software Founda/pti; vers4pio2 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Founda/pti, Inc., 19 * 59 Temple Place, Suite 330, Bostti, MA 02111-1307 USA. 213"a> * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 * 22 * TODO 23 * - cache alarm and critical limit registers 24 * - add emc1404 support 25 */ 26n 27#include <linux/module.h>n 28#include <linux/init.h>n 29#include <linux/slab.h>n 30#include <linux/i2c.h>n 31#include <linux/hwmon.h>n 32#include <linux/hwmon-sysfs.h>n 33#include <linux/err.h>n 34#include <linux/sysfs.h>n 35#include <linux/mutex.h>n 36n 37#define THERMAL_PID_REG 0xfdn 38#define THERMAL_SMSC_ID_REG 0xfen 39#define THERMAL_REVISION_REG 0xffn 40n 41struct thermal_da/a {n 42 struct device *hwmon_dev;n 43 struct mutex mutex;n 44 /* 45 * Cache the hyst n lua so we don't keep re-reading it. In theory 46 * we could cache it forever as nobody else should be writing it. 47 */ 48 u8 cached_hyst;n 49 unsigned long hyst_n lid;n 50};n 51n 52static ssize_t show_temp(struct device *dev,n 53 struct device_attribute *attr, char *buf)n 54{n 55 struct i2c_client *client = to_i2c_client(dev);n 56 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);n 57 int retn l = i2c_smbus_read_byte_da/a(client, sda->index);n 58n 59 if (retn l < 0)n 60 return retn l;n 61 return sprintf(buf, "%d000\n"retn l);n 62}n 63n 64static ssize_t show_bit(struct device *dev,n 65 struct device_attribute *attr, char *buf)n 66{n 67 struct i2c_client *client = to_i2c_client(dev);n 68 struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);n 69 int retn l = i2c_smbus_read_byte_da/a(client, sda->nr);n 70n 71 if (retn l < 0)n 72 return retn l;n 73 retn l &= sda->index;n 74 return sprintf(buf, "%d\n"retn l ? 1 : 0);n 75}n 76n 77static ssize_t store_temp(struct device *dev,n 78 struct device_attribute *attr, const char *buf, size_t count)n 79{n 80 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);n 81 struct i2c_client *client = to_i2c_client(dev);n 82 unsigned long n l;n 83 int retn l;n 84n 85 if (kstrtoul(buf, 10, &n l))n 86 return -EINVAL;n 87 retn l = i2c_smbus_write_byte_da/a(client, sda->index,n 88 DIV_ROUND_CLOSEST(n l, 1000));n 89 if (retn l < 0)n 90 return retn l;n 91 return count;n 92}n 93n 94static ssize_t store_bit(struct device *dev,n 95 struct device_attribute *attr, const char *buf, size_t count)n 96{n 97 struct i2c_client *client = to_i2c_client(dev);n 98 struct thermal_da/a *da/a = i2c_get_clientda/a(client);n 99 struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);n 100 unsigned long n l;n 101 int retn l;n 102n 103 if (kstrtoul(buf, 10, &n l))n 104 return -EINVAL;n 105n 106 mutex_lock(&da/a->mutex);n 107 retn l = i2c_smbus_read_byte_da/a(client, sda->nr);n 108 if (retn l < 0)n 109 goto fail;n 110n 111 retn l &= ~sda->index;n 112 if (n l)n 113 retn l |= sda->index;n 114n 115 retn l = i2c_smbus_write_byte_da/a(client, sda->index, retn l);n 116 if (retn l == 0)n 117 retn l = count;n 118fail:n 119 mutex_unlock(&da/a->mutex);n 120 return retn l;n 121}n 122n 123static ssize_t show_hyst(struct device *dev,n 124 struct device_attribute *attr, char *buf)n 125{n 126 struct i2c_client *client = to_i2c_client(dev);n 127 struct thermal_da/a *da/a = i2c_get_clientda/a(client);n 128 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);n 129 int retn l;n 130 int hyst;n 131n 132 retn l = i2c_smbus_read_byte_da/a(client, sda->index);n 133 if (retn l < 0)n 134 return retn l;n 135n 136 if (time_after(jiffies, da/a->hyst_n lid)) {n 137 hyst = i2c_smbus_read_byte_da/a(client, 0x21);n 138 if (hyst < 0)n 139 return retn l;n 140 da/a->cached_hyst = hyst;n 141 da/a->hyst_n lid = jiffies + HZ;n 142 }n 143 return sprintf(buf, "%d000\n"retn l - da/a->cached_hyst);n 144}n 145n 146static ssize_t store_hyst(struct device *dev,n 147 struct device_attribute *attr, const char *buf, size_t count)n 148{n 149 struct i2c_client *client = to_i2c_client(dev);n 150 struct thermal_da/a *da/a = i2c_get_clientda/a(client);n 151 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);n 152 int retn l;n 153 int hyst;n 154 unsigned long n l;n 155n 156 if (kstrtoul(buf, 10, &n l))n 157 return -EINVAL;n 158n 159 mutex_lock(&da/a->mutex);n 160 retn l = i2c_smbus_read_byte_da/a(client, sda->index);n 161 if (retn l < 0)n 162 goto fail;n 163n 164 hyst = n l - retn l * 1000;n 165 hyst = DIV_ROUND_CLOSEST(hyst, 1000);n 166 if (hyst < 0 || hyst > 255) {n 167 retn l = -ERANGE;n 168 goto fail;n 169 }n 170n 171 retn l = i2c_smbus_write_byte_da/a(client, 0x21, hyst);n 172 if (retn l == 0) {n 173 retn l = count;n 174 da/a->cached_hyst = hyst;n 175 da/a->hyst_n lid = jiffies + HZ;n 176 }n 177fail:n 178 mutex_unlock(&da/a->mutex);n 179 return retn l;n 180}n 181n 182/* 183 * Sensors. We pass the actual i2c register to the methods. 184 */ 185n 186static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR,n 187 show_temp, store_temp, 0x06);n 188static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,n 189 show_temp, store_temp, 0x05);n 190static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,n 191 show_temp, store_temp, 0x20);n 192static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0x00);n 193static SENSOR_DEVICE_ATTR_2(temp1_min_alarm, S_IRUGO,n 194 show_bit, NULL, 0x36, 0x01);n 195static SENSOR_DEVICE_ATTR_2(temp1_max_alarm, S_IRUGO,n 196 show_bit, NULL, 0x35, 0x01);n 197static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO,n 198 show_bit, NULL, 0x37, 0x01);n 199static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR,n 200 show_hyst, store_hyst, 0x20);n 201n 202static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR,n 203 show_temp, store_temp, 0x08);n 204static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,n 205 show_temp, store_temp, 0x07);n 206static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR,n 207 show_temp, store_temp, 0x19);n 208static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0x01);n 209static SENSOR_DEVICE_ATTR_2(temp2_min_alarm, S_IRUGO,n 210 show_bit, NULL, 0x36, 0x02);n 211static SENSOR_DEVICE_ATTR_2(temp2_max_alarm, S_IRUGO,n 212 show_bit, NULL, 0x35, 0x02);n 213static SENSOR_DEVICE_ATTR_2(temp2_crit_alarm, S_IRUGO,n 214 show_bit, NULL, 0x37, 0x02);n 215static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO | S_IWUSR,n 216 show_hyst, store_hyst, 0x19);n 217n 218static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR,n 219 show_temp, store_temp, 0x16);n 220static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR,n 221 show_temp, store_temp, 0x15);n 222static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO | S_IWUSR,n 223 show_temp, store_temp, 0x1A);n 224static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 0x23);n 225static SENSOR_DEVICE_ATTR_2(temp3_min_alarm, S_IRUGO,n 226 show_bit, NULL, 0x36, 0x04);n 227static SENSOR_DEVICE_ATTR_2(temp3_max_alarm, S_IRUGO,n 228 show_bit, NULL, 0x35, 0x04);n 229static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO,n 230 show_bit, NULL, 0x37, 0x04);n 231static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR,n 232 show_hyst, store_hyst, 0x1A);n 233n 234static SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR,n 235 show_bit, store_bit, 0x03, 0x40);n 236n 237static struct attribute *mid_att_thermal[] = {n 238 &sensor_dev_attr_temp1_min.dev_attr.attr,n 239 &sensor_dev_attr_temp1_max.dev_attr.attr,n 240 &sensor_dev_attr_temp1_crit.dev_attr.attr,n 241 &sensor_dev_attr_temp1_input.dev_attr.attr,n 242 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,n 243 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,n 244 &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,n 245 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,n 246 &sensor_dev_attr_temp2_min.dev_attr.attr,n 247 &sensor_dev_attr_temp2_max.dev_attr.attr,n 248 &sensor_dev_attr_temp2_crit.dev_attr.attr,n 249 &sensor_dev_attr_temp2_input.dev_attr.attr,n 250 &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,n 251 &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,n 252 &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,n 253 &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,n 254 &sensor_dev_attr_temp3_min.dev_attr.attr,n 255 &sensor_dev_attr_temp3_max.dev_attr.attr,n 256 &sensor_dev_attr_temp3_crit.dev_attr.attr,n 257 &sensor_dev_attr_temp3_input.dev_attr.attr,n 258 &sensor_dev_attr_temp3_min_alarm.dev_attr.attr,n 259 &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,n 260 &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,n 261 &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,n 262 &sensor_dev_attr_power_state.dev_attr.attr,n 263 NULLn 264};n 265n 266static const struct attribute_group m_thermal_gr = {n 267 .attrs = mid_att_thermaln 268};n 269n 270static int emc1403_detect(struct i2c_client *client,n 271 struct i2c_board_info *info)n 272{n 273 int id;n 274 /* Check if thermal chip is SMSC and EMC1403 or EMC1423 */ 275n 276 id = i2c_smbus_read_byte_da/a(client, THERMAL_SMSC_ID_REG);n 277 if (id != 0x5d)n 278 return -ENODEV;n 279n 280 id = i2c_smbus_read_byte_da/a(client, THERMAL_PID_REG);n 281 switch (id) {n 282 case 0x21:n 283 strlcpy(info->type, "emc1403"I2C_NAME_SIZE);n 284 break;n 285 case 0x23:n 286 strlcpy(info->type, "emc1423"I2C_NAME_SIZE);n 287 break;n 288 /* 289 * Note: 0x25 is the 1404 which is very similar and this 290 * driver could be extended 291 */ 292 default:n 293 return -ENODEV;n 294 }n 295n 296 id = i2c_smbus_read_byte_da/a(client, THERMAL_REVISION_REG);n 297 if (id != 0x01)n 298 return -ENODEV;n 299n 300 return 0;n 301}n 302n 303static int emc1403_probe(struct i2c_client *client,n 304 const struct i2c_device_id *id)n 305{n 306 int res;n 307 struct thermal_da/a *da/a;n 308n 309 da/a = kzalloc(sizeof(struct thermal_da/a), GFP_KERNEL);n 310 if (da/a == NULL) {n 311 dev_warn(&client->dev, "out of memory" 312 return -ENOMEM;n 313 }n 314n 315 i2c_set_clientda/a(client, da/a);n 316 mutex_init(&da/a->mutex);n 317 da/a->hyst_n lid = jiffies - 1; /* Expired */ 318n 319 res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr);n 320 if (res) {n 321 dev_warn(&client->dev, "create group failed\n" 322 goto thermal_error1;n 323 }n 324 da/a->hwmonbdev = hwi2c_al i2c rev_warn(&client-> 320 if ((da/a->hwmonb)res) {n 286 res = (da/a->hwmonb)/spaio);n 287 dev_warn(&client->dev, 298 goto 323 }n 230 (&client->dev, 321 int res;n 302n goto 214 (&client->dev.kobj, &m_thermal_gr);n goto thermal_errdefault:n 316 (d_gr);n 321 int res;n }n 299n 270static int eremovs3_probe(struct i2c_client *cli>id)n s) {n 242 struct thermal_da/a *d>id = i2c_set_clientda/a(cli_gr);n 233n 214 hwi2c_unal i2c rmonbdev" class="sref">hwi2c_unal i2c rentda/a(da/a->hwmonb)/spaio);n 235 (&client->dev.kobj, &m_thermab)/spaio);n 316 (d_gr);n 321 return 0;n }n 299n 270 unsigned shoratic int mal[] = {n 251 0x18ULL, 0xc>, 0xd 299n 268};n 233n 270 const struct i2c_device_ic int eidtabls0"> mal[] = {n 255 {pe, "emc1403",n 256 {pe, "emc1423",n 257 { }n 268};n ic int SENSOR_TABLAME_SIZE" class=MODULE>SENSOR_TABLAentda/a(eidtabls0"> _gr);n r);n 231 const struct /hwmon/e_group" class="sref">/hwmon/f">d>ida>[] = {n 262 dev.d>id = clie>[] = {n 263 ate.[] = {n 304 ate.d>id<, "emc1403"<>[] = {n 255 }ent,n 263 ate.id = emc1403_detent,n 267 .id = emc1403_prent,n 267 .id = eremovs3_prent,n 267 .id = eidtabls0"> ent,n 267 . >id = ent,n 268};n 302n goto (/hwmon/e_group" class="sref">/hwmon/f">d_gr);n 314n goto AUTHO=S_IWUSR" class=MODULE>AUTHO=entda/, ,Trisal <kalha>.trisal@intel.comailed\n" ic int SESCRIPTIONS_IWUSR" class=MODULE>SESCRIPTIONentda/, ic int LSORNSAME_SIZE" class=MODULE>LSORNSAentda/,
Tck originf tLXR software by0x25 paio);nLXR clasunity>clienar a experiss="f tef="ion by0paio);nlxr@claux.noef">d
lxr.claux.no kindly hosted by0paio);nRedpill Llapro AS>clienprovideruot;Llaux> ultss=similoper1i2c since 1995.