aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pc87427.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/hwmon/pc87427.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/hwmon/pc87427.c')
-rw-r--r--drivers/hwmon/pc87427.c139
1 files changed, 75 insertions, 64 deletions
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index 6086ad039d7..8da2181630b 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -46,11 +46,9 @@ static struct platform_device *pdev;
46 46
47#define DRVNAME "pc87427" 47#define DRVNAME "pc87427"
48 48
49/* 49/* The lock mutex protects both the I/O accesses (needed because the
50 * The lock mutex protects both the I/O accesses (needed because the 50 device is using banked registers) and the register cache (needed to keep
51 * device is using banked registers) and the register cache (needed to keep 51 the data in the registers and the cache in sync at any time). */
52 * the data in the registers and the cache in sync at any time).
53 */
54struct pc87427_data { 52struct pc87427_data {
55 struct device *hwmon_dev; 53 struct device *hwmon_dev;
56 struct mutex lock; 54 struct mutex lock;
@@ -175,12 +173,10 @@ static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
175#define FAN_STATUS_LOSPD (1 << 1) 173#define FAN_STATUS_LOSPD (1 << 1)
176#define FAN_STATUS_MONEN (1 << 0) 174#define FAN_STATUS_MONEN (1 << 0)
177 175
178/* 176/* Dedicated function to read all registers related to a given fan input.
179 * Dedicated function to read all registers related to a given fan input. 177 This saves us quite a few locks and bank selections.
180 * This saves us quite a few locks and bank selections. 178 Must be called with data->lock held.
181 * Must be called with data->lock held. 179 nr is from 0 to 7 */
182 * nr is from 0 to 7
183 */
184static void pc87427_readall_fan(struct pc87427_data *data, u8 nr) 180static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
185{ 181{
186 int iobase = data->address[LD_FAN]; 182 int iobase = data->address[LD_FAN];
@@ -193,10 +189,8 @@ static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
193 outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS); 189 outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
194} 190}
195 191
196/* 192/* The 2 LSB of fan speed registers are used for something different.
197 * The 2 LSB of fan speed registers are used for something different. 193 The actual 2 LSB of the measurements are not available. */
198 * The actual 2 LSB of the measurements are not available.
199 */
200static inline unsigned long fan_from_reg(u16 reg) 194static inline unsigned long fan_from_reg(u16 reg)
201{ 195{
202 reg &= 0xfffc; 196 reg &= 0xfffc;
@@ -230,12 +224,10 @@ static inline u16 fan_to_reg(unsigned long val)
230#define PWM_MODE_OFF (2 << 4) 224#define PWM_MODE_OFF (2 << 4)
231#define PWM_MODE_ON (7 << 4) 225#define PWM_MODE_ON (7 << 4)
232 226
233/* 227/* Dedicated function to read all registers related to a given PWM output.
234 * Dedicated function to read all registers related to a given PWM output. 228 This saves us quite a few locks and bank selections.
235 * This saves us quite a few locks and bank selections. 229 Must be called with data->lock held.
236 * Must be called with data->lock held. 230 nr is from 0 to 3 */
237 * nr is from 0 to 3
238 */
239static void pc87427_readall_pwm(struct pc87427_data *data, u8 nr) 231static void pc87427_readall_pwm(struct pc87427_data *data, u8 nr)
240{ 232{
241 int iobase = data->address[LD_FAN]; 233 int iobase = data->address[LD_FAN];
@@ -294,12 +286,10 @@ static inline u8 pwm_enable_to_reg(unsigned long val, u8 pwmval)
294#define TEMP_TYPE_REMOTE_DIODE (2 << 5) 286#define TEMP_TYPE_REMOTE_DIODE (2 << 5)
295#define TEMP_TYPE_LOCAL_DIODE (3 << 5) 287#define TEMP_TYPE_LOCAL_DIODE (3 << 5)
296 288
297/* 289/* Dedicated function to read all registers related to a given temperature
298 * Dedicated function to read all registers related to a given temperature 290 input. This saves us quite a few locks and bank selections.
299 * input. This saves us quite a few locks and bank selections. 291 Must be called with data->lock held.
300 * Must be called with data->lock held. 292 nr is from 0 to 5 */
301 * nr is from 0 to 5
302 */
303static void pc87427_readall_temp(struct pc87427_data *data, u8 nr) 293static void pc87427_readall_temp(struct pc87427_data *data, u8 nr)
304{ 294{
305 int iobase = data->address[LD_TEMP]; 295 int iobase = data->address[LD_TEMP];
@@ -328,10 +318,8 @@ static inline unsigned int temp_type_from_reg(u8 reg)
328 } 318 }
329} 319}
330 320
331/* 321/* We assume 8-bit thermal sensors; 9-bit thermal sensors are possible
332 * We assume 8-bit thermal sensors; 9-bit thermal sensors are possible 322 too, but I have no idea how to figure out when they are used. */
333 * too, but I have no idea how to figure out when they are used.
334 */
335static inline long temp_from_reg(s16 reg) 323static inline long temp_from_reg(s16 reg)
336{ 324{
337 return reg * 1000 / 256; 325 return reg * 1000 / 256;
@@ -430,16 +418,14 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
430 unsigned long val; 418 unsigned long val;
431 int iobase = data->address[LD_FAN]; 419 int iobase = data->address[LD_FAN];
432 420
433 if (kstrtoul(buf, 10, &val) < 0) 421 if (strict_strtoul(buf, 10, &val) < 0)
434 return -EINVAL; 422 return -EINVAL;
435 423
436 mutex_lock(&data->lock); 424 mutex_lock(&data->lock);
437 outb(BANK_FM(nr), iobase + PC87427_REG_BANK); 425 outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
438 /* 426 /* The low speed limit registers are read-only while monitoring
439 * The low speed limit registers are read-only while monitoring 427 is enabled, so we have to disable monitoring, then change the
440 * is enabled, so we have to disable monitoring, then change the 428 limit, and finally enable monitoring again. */
441 * limit, and finally enable monitoring again.
442 */
443 outb(0, iobase + PC87427_REG_FAN_STATUS); 429 outb(0, iobase + PC87427_REG_FAN_STATUS);
444 data->fan_min[nr] = fan_to_reg(val); 430 data->fan_min[nr] = fan_to_reg(val);
445 outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN); 431 outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
@@ -556,10 +542,8 @@ static const struct attribute_group pc87427_group_fan[8] = {
556 { .attrs = pc87427_attributes_fan[7] }, 542 { .attrs = pc87427_attributes_fan[7] },
557}; 543};
558 544
559/* 545/* Must be called with data->lock held and pc87427_readall_pwm() freshly
560 * Must be called with data->lock held and pc87427_readall_pwm() freshly 546 called */
561 * called
562 */
563static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode) 547static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode)
564{ 548{
565 int iobase = data->address[LD_FAN]; 549 int iobase = data->address[LD_FAN];
@@ -588,7 +572,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
588 int nr = to_sensor_dev_attr(devattr)->index; 572 int nr = to_sensor_dev_attr(devattr)->index;
589 unsigned long val; 573 unsigned long val;
590 574
591 if (kstrtoul(buf, 10, &val) < 0 || val > 2) 575 if (strict_strtoul(buf, 10, &val) < 0 || val > 2)
592 return -EINVAL; 576 return -EINVAL;
593 /* Can't go to automatic mode if it isn't configured */ 577 /* Can't go to automatic mode if it isn't configured */
594 if (val == 2 && !(data->pwm_auto_ok & (1 << nr))) 578 if (val == 2 && !(data->pwm_auto_ok & (1 << nr)))
@@ -620,7 +604,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute
620 int iobase = data->address[LD_FAN]; 604 int iobase = data->address[LD_FAN];
621 u8 mode; 605 u8 mode;
622 606
623 if (kstrtoul(buf, 10, &val) < 0 || val > 0xff) 607 if (strict_strtoul(buf, 10, &val) < 0 || val > 0xff)
624 return -EINVAL; 608 return -EINVAL;
625 609
626 mutex_lock(&data->lock); 610 mutex_lock(&data->lock);
@@ -956,31 +940,47 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
956 * Device detection, attach and detach 940 * Device detection, attach and detach
957 */ 941 */
958 942
959static int pc87427_request_regions(struct platform_device *pdev, 943static void pc87427_release_regions(struct platform_device *pdev, int count)
960 int count)
961{ 944{
962 struct resource *res; 945 struct resource *res;
963 int i; 946 int i;
964 947
965 for (i = 0; i < count; i++) { 948 for (i = 0; i < count; i++) {
966 res = platform_get_resource(pdev, IORESOURCE_IO, i); 949 res = platform_get_resource(pdev, IORESOURCE_IO, i);
950 release_region(res->start, resource_size(res));
951 }
952}
953
954static int __devinit pc87427_request_regions(struct platform_device *pdev,
955 int count)
956{
957 struct resource *res;
958 int i, err = 0;
959
960 for (i = 0; i < count; i++) {
961 res = platform_get_resource(pdev, IORESOURCE_IO, i);
967 if (!res) { 962 if (!res) {
963 err = -ENOENT;
968 dev_err(&pdev->dev, "Missing resource #%d\n", i); 964 dev_err(&pdev->dev, "Missing resource #%d\n", i);
969 return -ENOENT; 965 break;
970 } 966 }
971 if (!devm_request_region(&pdev->dev, res->start, 967 if (!request_region(res->start, resource_size(res), DRVNAME)) {
972 resource_size(res), DRVNAME)) { 968 err = -EBUSY;
973 dev_err(&pdev->dev, 969 dev_err(&pdev->dev,
974 "Failed to request region 0x%lx-0x%lx\n", 970 "Failed to request region 0x%lx-0x%lx\n",
975 (unsigned long)res->start, 971 (unsigned long)res->start,
976 (unsigned long)res->end); 972 (unsigned long)res->end);
977 return -EBUSY; 973 break;
978 } 974 }
979 } 975 }
980 return 0; 976
977 if (err && i)
978 pc87427_release_regions(pdev, i);
979
980 return err;
981} 981}
982 982
983static void pc87427_init_device(struct device *dev) 983static void __devinit pc87427_init_device(struct device *dev)
984{ 984{
985 struct pc87427_sio_data *sio_data = dev->platform_data; 985 struct pc87427_sio_data *sio_data = dev->platform_data;
986 struct pc87427_data *data = dev_get_drvdata(dev); 986 struct pc87427_data *data = dev_get_drvdata(dev);
@@ -1023,11 +1023,9 @@ static void pc87427_init_device(struct device *dev)
1023 if (reg & PWM_ENABLE_CTLEN) 1023 if (reg & PWM_ENABLE_CTLEN)
1024 data->pwm_enabled |= (1 << i); 1024 data->pwm_enabled |= (1 << i);
1025 1025
1026 /* 1026 /* We don't expose an interface to reconfigure the automatic
1027 * We don't expose an interface to reconfigure the automatic 1027 fan control mode, so only allow to return to this mode if
1028 * fan control mode, so only allow to return to this mode if 1028 it was originally set. */
1029 * it was originally set.
1030 */
1031 if ((reg & PWM_ENABLE_MODE_MASK) == PWM_MODE_AUTO) { 1029 if ((reg & PWM_ENABLE_MODE_MASK) == PWM_MODE_AUTO) {
1032 dev_dbg(dev, "PWM%d is in automatic control mode\n", 1030 dev_dbg(dev, "PWM%d is in automatic control mode\n",
1033 i + 1); 1031 i + 1);
@@ -1072,17 +1070,17 @@ static void pc87427_remove_files(struct device *dev)
1072 } 1070 }
1073} 1071}
1074 1072
1075static int pc87427_probe(struct platform_device *pdev) 1073static int __devinit pc87427_probe(struct platform_device *pdev)
1076{ 1074{
1077 struct pc87427_sio_data *sio_data = pdev->dev.platform_data; 1075 struct pc87427_sio_data *sio_data = pdev->dev.platform_data;
1078 struct pc87427_data *data; 1076 struct pc87427_data *data;
1079 int i, err, res_count; 1077 int i, err, res_count;
1080 1078
1081 data = devm_kzalloc(&pdev->dev, sizeof(struct pc87427_data), 1079 data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL);
1082 GFP_KERNEL);
1083 if (!data) { 1080 if (!data) {
1081 err = -ENOMEM;
1084 pr_err("Out of memory\n"); 1082 pr_err("Out of memory\n");
1085 return -ENOMEM; 1083 goto exit;
1086 } 1084 }
1087 1085
1088 data->address[0] = sio_data->address[0]; 1086 data->address[0] = sio_data->address[0];
@@ -1091,7 +1089,7 @@ static int pc87427_probe(struct platform_device *pdev)
1091 1089
1092 err = pc87427_request_regions(pdev, res_count); 1090 err = pc87427_request_regions(pdev, res_count);
1093 if (err) 1091 if (err)
1094 return err; 1092 goto exit_kfree;
1095 1093
1096 mutex_init(&data->lock); 1094 mutex_init(&data->lock);
1097 data->name = "pc87427"; 1095 data->name = "pc87427";
@@ -1101,7 +1099,7 @@ static int pc87427_probe(struct platform_device *pdev)
1101 /* Register sysfs hooks */ 1099 /* Register sysfs hooks */
1102 err = device_create_file(&pdev->dev, &dev_attr_name); 1100 err = device_create_file(&pdev->dev, &dev_attr_name);
1103 if (err) 1101 if (err)
1104 return err; 1102 goto exit_release_region;
1105 for (i = 0; i < 8; i++) { 1103 for (i = 0; i < 8; i++) {
1106 if (!(data->fan_enabled & (1 << i))) 1104 if (!(data->fan_enabled & (1 << i)))
1107 continue; 1105 continue;
@@ -1138,15 +1136,28 @@ static int pc87427_probe(struct platform_device *pdev)
1138 1136
1139exit_remove_files: 1137exit_remove_files:
1140 pc87427_remove_files(&pdev->dev); 1138 pc87427_remove_files(&pdev->dev);
1139exit_release_region:
1140 pc87427_release_regions(pdev, res_count);
1141exit_kfree:
1142 platform_set_drvdata(pdev, NULL);
1143 kfree(data);
1144exit:
1141 return err; 1145 return err;
1142} 1146}
1143 1147
1144static int pc87427_remove(struct platform_device *pdev) 1148static int __devexit pc87427_remove(struct platform_device *pdev)
1145{ 1149{
1146 struct pc87427_data *data = platform_get_drvdata(pdev); 1150 struct pc87427_data *data = platform_get_drvdata(pdev);
1151 int res_count;
1152
1153 res_count = (data->address[0] != 0) + (data->address[1] != 0);
1147 1154
1148 hwmon_device_unregister(data->hwmon_dev); 1155 hwmon_device_unregister(data->hwmon_dev);
1149 pc87427_remove_files(&pdev->dev); 1156 pc87427_remove_files(&pdev->dev);
1157 platform_set_drvdata(pdev, NULL);
1158 kfree(data);
1159
1160 pc87427_release_regions(pdev, res_count);
1150 1161
1151 return 0; 1162 return 0;
1152} 1163}
@@ -1158,7 +1169,7 @@ static struct platform_driver pc87427_driver = {
1158 .name = DRVNAME, 1169 .name = DRVNAME,
1159 }, 1170 },
1160 .probe = pc87427_probe, 1171 .probe = pc87427_probe,
1161 .remove = pc87427_remove, 1172 .remove = __devexit_p(pc87427_remove),
1162}; 1173};
1163 1174
1164static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data) 1175static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data)