diff options
Diffstat (limited to 'drivers')
37 files changed, 1930 insertions, 1473 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 32b957efa420..45d58002b06c 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -742,7 +742,7 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read); | |||
742 | * the module usage count. | 742 | * the module usage count. |
743 | */ | 743 | */ |
744 | #define TPM_ORD_PCR_EXTEND cpu_to_be32(20) | 744 | #define TPM_ORD_PCR_EXTEND cpu_to_be32(20) |
745 | #define EXTEND_PCR_SIZE 34 | 745 | #define EXTEND_PCR_RESULT_SIZE 34 |
746 | static struct tpm_input_header pcrextend_header = { | 746 | static struct tpm_input_header pcrextend_header = { |
747 | .tag = TPM_TAG_RQU_COMMAND, | 747 | .tag = TPM_TAG_RQU_COMMAND, |
748 | .length = cpu_to_be32(34), | 748 | .length = cpu_to_be32(34), |
@@ -760,10 +760,9 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | |||
760 | return -ENODEV; | 760 | return -ENODEV; |
761 | 761 | ||
762 | cmd.header.in = pcrextend_header; | 762 | cmd.header.in = pcrextend_header; |
763 | BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); | ||
764 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); | 763 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); |
765 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); | 764 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); |
766 | rc = transmit_cmd(chip, &cmd, cmd.header.in.length, | 765 | rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, |
767 | "attempting extend a PCR value"); | 766 | "attempting extend a PCR value"); |
768 | 767 | ||
769 | module_put(chip->dev->driver->owner); | 768 | module_put(chip->dev->driver->owner); |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index ed7711d11ae8..6857560144bd 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -325,34 +325,6 @@ config SENSORS_F75375S | |||
325 | This driver can also be built as a module. If so, the module | 325 | This driver can also be built as a module. If so, the module |
326 | will be called f75375s. | 326 | will be called f75375s. |
327 | 327 | ||
328 | config SENSORS_FSCHER | ||
329 | tristate "FSC Hermes (DEPRECATED)" | ||
330 | depends on X86 && I2C | ||
331 | help | ||
332 | This driver is DEPRECATED please use the new merged fschmd | ||
333 | ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver | ||
334 | instead. | ||
335 | |||
336 | If you say yes here you get support for Fujitsu Siemens | ||
337 | Computers Hermes sensor chips. | ||
338 | |||
339 | This driver can also be built as a module. If so, the module | ||
340 | will be called fscher. | ||
341 | |||
342 | config SENSORS_FSCPOS | ||
343 | tristate "FSC Poseidon (DEPRECATED)" | ||
344 | depends on X86 && I2C | ||
345 | help | ||
346 | This driver is DEPRECATED please use the new merged fschmd | ||
347 | ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver | ||
348 | instead. | ||
349 | |||
350 | If you say yes here you get support for Fujitsu Siemens | ||
351 | Computers Poseidon sensor chips. | ||
352 | |||
353 | This driver can also be built as a module. If so, the module | ||
354 | will be called fscpos. | ||
355 | |||
356 | config SENSORS_FSCHMD | 328 | config SENSORS_FSCHMD |
357 | tristate "Fujitsu Siemens Computers sensor chips" | 329 | tristate "Fujitsu Siemens Computers sensor chips" |
358 | depends on X86 && I2C | 330 | depends on X86 && I2C |
@@ -401,12 +373,12 @@ config SENSORS_GL520SM | |||
401 | will be called gl520sm. | 373 | will be called gl520sm. |
402 | 374 | ||
403 | config SENSORS_CORETEMP | 375 | config SENSORS_CORETEMP |
404 | tristate "Intel Core (2) Duo/Solo temperature sensor" | 376 | tristate "Intel Core/Core2/Atom temperature sensor" |
405 | depends on X86 && EXPERIMENTAL | 377 | depends on X86 && EXPERIMENTAL |
406 | help | 378 | help |
407 | If you say yes here you get support for the temperature | 379 | If you say yes here you get support for the temperature |
408 | sensor inside your CPU. Supported all are all known variants | 380 | sensor inside your CPU. Most of the family 6 CPUs |
409 | of Intel Core family. | 381 | are supported. Check documentation/driver for details. |
410 | 382 | ||
411 | config SENSORS_IBMAEM | 383 | config SENSORS_IBMAEM |
412 | tristate "IBM Active Energy Manager temperature/power sensors and control" | 384 | tristate "IBM Active Energy Manager temperature/power sensors and control" |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index bcf73a9bb619..9f46cb019cc6 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -42,9 +42,7 @@ obj-$(CONFIG_SENSORS_DS1621) += ds1621.o | |||
42 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o | 42 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o |
43 | obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o | 43 | obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o |
44 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o | 44 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o |
45 | obj-$(CONFIG_SENSORS_FSCHER) += fscher.o | ||
46 | obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o | 45 | obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o |
47 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o | ||
48 | obj-$(CONFIG_SENSORS_G760A) += g760a.o | 46 | obj-$(CONFIG_SENSORS_G760A) += g760a.o |
49 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o | 47 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o |
50 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o | 48 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o |
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 789441830cd8..56905955352c 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #define ADM1031_REG_PWM (0x22) | 37 | #define ADM1031_REG_PWM (0x22) |
38 | #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) | 38 | #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) |
39 | 39 | ||
40 | #define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) | ||
40 | #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) | 41 | #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) |
41 | #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) | 42 | #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) |
42 | #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) | 43 | #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) |
@@ -93,6 +94,7 @@ struct adm1031_data { | |||
93 | u8 auto_temp_min[3]; | 94 | u8 auto_temp_min[3]; |
94 | u8 auto_temp_off[3]; | 95 | u8 auto_temp_off[3]; |
95 | u8 auto_temp_max[3]; | 96 | u8 auto_temp_max[3]; |
97 | s8 temp_offset[3]; | ||
96 | s8 temp_min[3]; | 98 | s8 temp_min[3]; |
97 | s8 temp_max[3]; | 99 | s8 temp_max[3]; |
98 | s8 temp_crit[3]; | 100 | s8 temp_crit[3]; |
@@ -145,6 +147,10 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) | |||
145 | 147 | ||
146 | #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) | 148 | #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) |
147 | 149 | ||
150 | #define TEMP_OFFSET_TO_REG(val) (TEMP_TO_REG(val) & 0x8f) | ||
151 | #define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \ | ||
152 | (val) | 0x70 : (val)) | ||
153 | |||
148 | #define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) : 0) | 154 | #define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) : 0) |
149 | 155 | ||
150 | static int FAN_TO_REG(int reg, int div) | 156 | static int FAN_TO_REG(int reg, int div) |
@@ -585,6 +591,14 @@ static ssize_t show_temp(struct device *dev, | |||
585 | (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); | 591 | (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); |
586 | return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); | 592 | return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); |
587 | } | 593 | } |
594 | static ssize_t show_temp_offset(struct device *dev, | ||
595 | struct device_attribute *attr, char *buf) | ||
596 | { | ||
597 | int nr = to_sensor_dev_attr(attr)->index; | ||
598 | struct adm1031_data *data = adm1031_update_device(dev); | ||
599 | return sprintf(buf, "%d\n", | ||
600 | TEMP_OFFSET_FROM_REG(data->temp_offset[nr])); | ||
601 | } | ||
588 | static ssize_t show_temp_min(struct device *dev, | 602 | static ssize_t show_temp_min(struct device *dev, |
589 | struct device_attribute *attr, char *buf) | 603 | struct device_attribute *attr, char *buf) |
590 | { | 604 | { |
@@ -606,6 +620,24 @@ static ssize_t show_temp_crit(struct device *dev, | |||
606 | struct adm1031_data *data = adm1031_update_device(dev); | 620 | struct adm1031_data *data = adm1031_update_device(dev); |
607 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); | 621 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); |
608 | } | 622 | } |
623 | static ssize_t set_temp_offset(struct device *dev, | ||
624 | struct device_attribute *attr, const char *buf, | ||
625 | size_t count) | ||
626 | { | ||
627 | struct i2c_client *client = to_i2c_client(dev); | ||
628 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
629 | int nr = to_sensor_dev_attr(attr)->index; | ||
630 | int val; | ||
631 | |||
632 | val = simple_strtol(buf, NULL, 10); | ||
633 | val = SENSORS_LIMIT(val, -15000, 15000); | ||
634 | mutex_lock(&data->update_lock); | ||
635 | data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val); | ||
636 | adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr), | ||
637 | data->temp_offset[nr]); | ||
638 | mutex_unlock(&data->update_lock); | ||
639 | return count; | ||
640 | } | ||
609 | static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | 641 | static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, |
610 | const char *buf, size_t count) | 642 | const char *buf, size_t count) |
611 | { | 643 | { |
@@ -661,6 +693,8 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, | |||
661 | #define temp_reg(offset) \ | 693 | #define temp_reg(offset) \ |
662 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ | 694 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ |
663 | show_temp, NULL, offset - 1); \ | 695 | show_temp, NULL, offset - 1); \ |
696 | static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ | ||
697 | show_temp_offset, set_temp_offset, offset - 1); \ | ||
664 | static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ | 698 | static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ |
665 | show_temp_min, set_temp_min, offset - 1); \ | 699 | show_temp_min, set_temp_min, offset - 1); \ |
666 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ | 700 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ |
@@ -714,6 +748,7 @@ static struct attribute *adm1031_attributes[] = { | |||
714 | &sensor_dev_attr_pwm1.dev_attr.attr, | 748 | &sensor_dev_attr_pwm1.dev_attr.attr, |
715 | &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, | 749 | &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, |
716 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 750 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
751 | &sensor_dev_attr_temp1_offset.dev_attr.attr, | ||
717 | &sensor_dev_attr_temp1_min.dev_attr.attr, | 752 | &sensor_dev_attr_temp1_min.dev_attr.attr, |
718 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | 753 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, |
719 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 754 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
@@ -721,6 +756,7 @@ static struct attribute *adm1031_attributes[] = { | |||
721 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | 756 | &sensor_dev_attr_temp1_crit.dev_attr.attr, |
722 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | 757 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, |
723 | &sensor_dev_attr_temp2_input.dev_attr.attr, | 758 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
759 | &sensor_dev_attr_temp2_offset.dev_attr.attr, | ||
724 | &sensor_dev_attr_temp2_min.dev_attr.attr, | 760 | &sensor_dev_attr_temp2_min.dev_attr.attr, |
725 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | 761 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, |
726 | &sensor_dev_attr_temp2_max.dev_attr.attr, | 762 | &sensor_dev_attr_temp2_max.dev_attr.attr, |
@@ -757,6 +793,7 @@ static struct attribute *adm1031_attributes_opt[] = { | |||
757 | &sensor_dev_attr_pwm2.dev_attr.attr, | 793 | &sensor_dev_attr_pwm2.dev_attr.attr, |
758 | &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, | 794 | &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, |
759 | &sensor_dev_attr_temp3_input.dev_attr.attr, | 795 | &sensor_dev_attr_temp3_input.dev_attr.attr, |
796 | &sensor_dev_attr_temp3_offset.dev_attr.attr, | ||
760 | &sensor_dev_attr_temp3_min.dev_attr.attr, | 797 | &sensor_dev_attr_temp3_min.dev_attr.attr, |
761 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, | 798 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, |
762 | &sensor_dev_attr_temp3_max.dev_attr.attr, | 799 | &sensor_dev_attr_temp3_max.dev_attr.attr, |
@@ -937,6 +974,9 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) | |||
937 | } | 974 | } |
938 | data->temp[chan] = newh; | 975 | data->temp[chan] = newh; |
939 | 976 | ||
977 | data->temp_offset[chan] = | ||
978 | adm1031_read_value(client, | ||
979 | ADM1031_REG_TEMP_OFFSET(chan)); | ||
940 | data->temp_min[chan] = | 980 | data->temp_min[chan] = |
941 | adm1031_read_value(client, | 981 | adm1031_read_value(client, |
942 | ADM1031_REG_TEMP_MIN(chan)); | 982 | ADM1031_REG_TEMP_MIN(chan)); |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 972cf4ba963c..caef39cda8c8 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -157,17 +157,26 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * | |||
157 | /* The 100C is default for both mobile and non mobile CPUs */ | 157 | /* The 100C is default for both mobile and non mobile CPUs */ |
158 | 158 | ||
159 | int tjmax = 100000; | 159 | int tjmax = 100000; |
160 | int ismobile = 1; | 160 | int tjmax_ee = 85000; |
161 | int usemsr_ee = 1; | ||
161 | int err; | 162 | int err; |
162 | u32 eax, edx; | 163 | u32 eax, edx; |
163 | 164 | ||
164 | /* Early chips have no MSR for TjMax */ | 165 | /* Early chips have no MSR for TjMax */ |
165 | 166 | ||
166 | if ((c->x86_model == 0xf) && (c->x86_mask < 4)) { | 167 | if ((c->x86_model == 0xf) && (c->x86_mask < 4)) { |
167 | ismobile = 0; | 168 | usemsr_ee = 0; |
168 | } | 169 | } |
169 | 170 | ||
170 | if ((c->x86_model > 0xe) && (ismobile)) { | 171 | /* Atoms seems to have TjMax at 90C */ |
172 | |||
173 | if (c->x86_model == 0x1c) { | ||
174 | usemsr_ee = 0; | ||
175 | tjmax = 90000; | ||
176 | } | ||
177 | |||
178 | if ((c->x86_model > 0xe) && (usemsr_ee)) { | ||
179 | u8 platform_id; | ||
171 | 180 | ||
172 | /* Now we can detect the mobile CPU using Intel provided table | 181 | /* Now we can detect the mobile CPU using Intel provided table |
173 | http://softwarecommunity.intel.com/Wiki/Mobility/720.htm | 182 | http://softwarecommunity.intel.com/Wiki/Mobility/720.htm |
@@ -179,13 +188,29 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * | |||
179 | dev_warn(dev, | 188 | dev_warn(dev, |
180 | "Unable to access MSR 0x17, assuming desktop" | 189 | "Unable to access MSR 0x17, assuming desktop" |
181 | " CPU\n"); | 190 | " CPU\n"); |
182 | ismobile = 0; | 191 | usemsr_ee = 0; |
183 | } else if (!(eax & 0x10000000)) { | 192 | } else if (c->x86_model < 0x17 && !(eax & 0x10000000)) { |
184 | ismobile = 0; | 193 | /* Trust bit 28 up to Penryn, I could not find any |
194 | documentation on that; if you happen to know | ||
195 | someone at Intel please ask */ | ||
196 | usemsr_ee = 0; | ||
197 | } else { | ||
198 | /* Platform ID bits 52:50 (EDX starts at bit 32) */ | ||
199 | platform_id = (edx >> 18) & 0x7; | ||
200 | |||
201 | /* Mobile Penryn CPU seems to be platform ID 7 or 5 | ||
202 | (guesswork) */ | ||
203 | if ((c->x86_model == 0x17) && | ||
204 | ((platform_id == 5) || (platform_id == 7))) { | ||
205 | /* If MSR EE bit is set, set it to 90 degrees C, | ||
206 | otherwise 105 degrees C */ | ||
207 | tjmax_ee = 90000; | ||
208 | tjmax = 105000; | ||
209 | } | ||
185 | } | 210 | } |
186 | } | 211 | } |
187 | 212 | ||
188 | if (ismobile || c->x86_model == 0x1c) { | 213 | if (usemsr_ee) { |
189 | 214 | ||
190 | err = rdmsr_safe_on_cpu(id, 0xee, &eax, &edx); | 215 | err = rdmsr_safe_on_cpu(id, 0xee, &eax, &edx); |
191 | if (err) { | 216 | if (err) { |
@@ -193,9 +218,11 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * | |||
193 | "Unable to access MSR 0xEE, for Tjmax, left" | 218 | "Unable to access MSR 0xEE, for Tjmax, left" |
194 | " at default"); | 219 | " at default"); |
195 | } else if (eax & 0x40000000) { | 220 | } else if (eax & 0x40000000) { |
196 | tjmax = 85000; | 221 | tjmax = tjmax_ee; |
197 | } | 222 | } |
198 | } else { | 223 | /* if we dont use msr EE it means we are desktop CPU (with exeception |
224 | of Atom) */ | ||
225 | } else if (tjmax == 100000) { | ||
199 | dev_warn(dev, "Using relative temperature scale!\n"); | 226 | dev_warn(dev, "Using relative temperature scale!\n"); |
200 | } | 227 | } |
201 | 228 | ||
@@ -248,9 +275,9 @@ static int __devinit coretemp_probe(struct platform_device *pdev) | |||
248 | platform_set_drvdata(pdev, data); | 275 | platform_set_drvdata(pdev, data); |
249 | 276 | ||
250 | /* read the still undocumented IA32_TEMPERATURE_TARGET it exists | 277 | /* read the still undocumented IA32_TEMPERATURE_TARGET it exists |
251 | on older CPUs but not in this register */ | 278 | on older CPUs but not in this register, Atoms don't have it either */ |
252 | 279 | ||
253 | if (c->x86_model > 0xe) { | 280 | if ((c->x86_model > 0xe) && (c->x86_model != 0x1c)) { |
254 | err = rdmsr_safe_on_cpu(data->id, 0x1a2, &eax, &edx); | 281 | err = rdmsr_safe_on_cpu(data->id, 0x1a2, &eax, &edx); |
255 | if (err) { | 282 | if (err) { |
256 | dev_warn(&pdev->dev, "Unable to read" | 283 | dev_warn(&pdev->dev, "Unable to read" |
@@ -413,11 +440,15 @@ static int __init coretemp_init(void) | |||
413 | for_each_online_cpu(i) { | 440 | for_each_online_cpu(i) { |
414 | struct cpuinfo_x86 *c = &cpu_data(i); | 441 | struct cpuinfo_x86 *c = &cpu_data(i); |
415 | 442 | ||
416 | /* check if family 6, models 0xe, 0xf, 0x16, 0x17, 0x1A */ | 443 | /* check if family 6, models 0xe (Pentium M DC), |
444 | 0xf (Core 2 DC 65nm), 0x16 (Core 2 SC 65nm), | ||
445 | 0x17 (Penryn 45nm), 0x1a (Nehalem), 0x1c (Atom), | ||
446 | 0x1e (Lynnfield) */ | ||
417 | if ((c->cpuid_level < 0) || (c->x86 != 0x6) || | 447 | if ((c->cpuid_level < 0) || (c->x86 != 0x6) || |
418 | !((c->x86_model == 0xe) || (c->x86_model == 0xf) || | 448 | !((c->x86_model == 0xe) || (c->x86_model == 0xf) || |
419 | (c->x86_model == 0x16) || (c->x86_model == 0x17) || | 449 | (c->x86_model == 0x16) || (c->x86_model == 0x17) || |
420 | (c->x86_model == 0x1A) || (c->x86_model == 0x1c))) { | 450 | (c->x86_model == 0x1a) || (c->x86_model == 0x1c) || |
451 | (c->x86_model == 0x1e))) { | ||
421 | 452 | ||
422 | /* supported CPU not found, but report the unknown | 453 | /* supported CPU not found, but report the unknown |
423 | family 6 CPU */ | 454 | family 6 CPU */ |
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c deleted file mode 100644 index 12c70e402cb2..000000000000 --- a/drivers/hwmon/fscher.c +++ /dev/null | |||
@@ -1,680 +0,0 @@ | |||
1 | /* | ||
2 | * fscher.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | * monitoring | ||
4 | * Copyright (C) 2003, 2004 Reinhard Nissl <rnissl@gmx.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * fujitsu siemens hermes chip, | ||
23 | * module based on fscpos.c | ||
24 | * Copyright (C) 2000 Hermann Jung <hej@odn.de> | ||
25 | * Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> | ||
26 | * and Philip Edelbrock <phil@netroedge.com> | ||
27 | */ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/jiffies.h> | ||
33 | #include <linux/i2c.h> | ||
34 | #include <linux/hwmon.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/mutex.h> | ||
37 | #include <linux/sysfs.h> | ||
38 | |||
39 | /* | ||
40 | * Addresses to scan | ||
41 | */ | ||
42 | |||
43 | static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; | ||
44 | |||
45 | /* | ||
46 | * Insmod parameters | ||
47 | */ | ||
48 | |||
49 | I2C_CLIENT_INSMOD_1(fscher); | ||
50 | |||
51 | /* | ||
52 | * The FSCHER registers | ||
53 | */ | ||
54 | |||
55 | /* chip identification */ | ||
56 | #define FSCHER_REG_IDENT_0 0x00 | ||
57 | #define FSCHER_REG_IDENT_1 0x01 | ||
58 | #define FSCHER_REG_IDENT_2 0x02 | ||
59 | #define FSCHER_REG_REVISION 0x03 | ||
60 | |||
61 | /* global control and status */ | ||
62 | #define FSCHER_REG_EVENT_STATE 0x04 | ||
63 | #define FSCHER_REG_CONTROL 0x05 | ||
64 | |||
65 | /* watchdog */ | ||
66 | #define FSCHER_REG_WDOG_PRESET 0x28 | ||
67 | #define FSCHER_REG_WDOG_STATE 0x23 | ||
68 | #define FSCHER_REG_WDOG_CONTROL 0x21 | ||
69 | |||
70 | /* fan 0 */ | ||
71 | #define FSCHER_REG_FAN0_MIN 0x55 | ||
72 | #define FSCHER_REG_FAN0_ACT 0x0e | ||
73 | #define FSCHER_REG_FAN0_STATE 0x0d | ||
74 | #define FSCHER_REG_FAN0_RIPPLE 0x0f | ||
75 | |||
76 | /* fan 1 */ | ||
77 | #define FSCHER_REG_FAN1_MIN 0x65 | ||
78 | #define FSCHER_REG_FAN1_ACT 0x6b | ||
79 | #define FSCHER_REG_FAN1_STATE 0x62 | ||
80 | #define FSCHER_REG_FAN1_RIPPLE 0x6f | ||
81 | |||
82 | /* fan 2 */ | ||
83 | #define FSCHER_REG_FAN2_MIN 0xb5 | ||
84 | #define FSCHER_REG_FAN2_ACT 0xbb | ||
85 | #define FSCHER_REG_FAN2_STATE 0xb2 | ||
86 | #define FSCHER_REG_FAN2_RIPPLE 0xbf | ||
87 | |||
88 | /* voltage supervision */ | ||
89 | #define FSCHER_REG_VOLT_12 0x45 | ||
90 | #define FSCHER_REG_VOLT_5 0x42 | ||
91 | #define FSCHER_REG_VOLT_BATT 0x48 | ||
92 | |||
93 | /* temperature 0 */ | ||
94 | #define FSCHER_REG_TEMP0_ACT 0x64 | ||
95 | #define FSCHER_REG_TEMP0_STATE 0x71 | ||
96 | |||
97 | /* temperature 1 */ | ||
98 | #define FSCHER_REG_TEMP1_ACT 0x32 | ||
99 | #define FSCHER_REG_TEMP1_STATE 0x81 | ||
100 | |||
101 | /* temperature 2 */ | ||
102 | #define FSCHER_REG_TEMP2_ACT 0x35 | ||
103 | #define FSCHER_REG_TEMP2_STATE 0x91 | ||
104 | |||
105 | /* | ||
106 | * Functions declaration | ||
107 | */ | ||
108 | |||
109 | static int fscher_probe(struct i2c_client *client, | ||
110 | const struct i2c_device_id *id); | ||
111 | static int fscher_detect(struct i2c_client *client, int kind, | ||
112 | struct i2c_board_info *info); | ||
113 | static int fscher_remove(struct i2c_client *client); | ||
114 | static struct fscher_data *fscher_update_device(struct device *dev); | ||
115 | static void fscher_init_client(struct i2c_client *client); | ||
116 | |||
117 | static int fscher_read_value(struct i2c_client *client, u8 reg); | ||
118 | static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value); | ||
119 | |||
120 | /* | ||
121 | * Driver data (common to all clients) | ||
122 | */ | ||
123 | |||
124 | static const struct i2c_device_id fscher_id[] = { | ||
125 | { "fscher", fscher }, | ||
126 | { } | ||
127 | }; | ||
128 | |||
129 | static struct i2c_driver fscher_driver = { | ||
130 | .class = I2C_CLASS_HWMON, | ||
131 | .driver = { | ||
132 | .name = "fscher", | ||
133 | }, | ||
134 | .probe = fscher_probe, | ||
135 | .remove = fscher_remove, | ||
136 | .id_table = fscher_id, | ||
137 | .detect = fscher_detect, | ||
138 | .address_data = &addr_data, | ||
139 | }; | ||
140 | |||
141 | /* | ||
142 | * Client data (each client gets its own) | ||
143 | */ | ||
144 | |||
145 | struct fscher_data { | ||
146 | struct device *hwmon_dev; | ||
147 | struct mutex update_lock; | ||
148 | char valid; /* zero until following fields are valid */ | ||
149 | unsigned long last_updated; /* in jiffies */ | ||
150 | |||
151 | /* register values */ | ||
152 | u8 revision; /* revision of chip */ | ||
153 | u8 global_event; /* global event status */ | ||
154 | u8 global_control; /* global control register */ | ||
155 | u8 watchdog[3]; /* watchdog */ | ||
156 | u8 volt[3]; /* 12, 5, battery voltage */ | ||
157 | u8 temp_act[3]; /* temperature */ | ||
158 | u8 temp_status[3]; /* status of sensor */ | ||
159 | u8 fan_act[3]; /* fans revolutions per second */ | ||
160 | u8 fan_status[3]; /* fan status */ | ||
161 | u8 fan_min[3]; /* fan min value for rps */ | ||
162 | u8 fan_ripple[3]; /* divider for rps */ | ||
163 | }; | ||
164 | |||
165 | /* | ||
166 | * Sysfs stuff | ||
167 | */ | ||
168 | |||
169 | #define sysfs_r(kind, sub, offset, reg) \ | ||
170 | static ssize_t show_##kind##sub (struct fscher_data *, char *, int); \ | ||
171 | static ssize_t show_##kind##offset##sub (struct device *, struct device_attribute *attr, char *); \ | ||
172 | static ssize_t show_##kind##offset##sub (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
173 | { \ | ||
174 | struct fscher_data *data = fscher_update_device(dev); \ | ||
175 | return show_##kind##sub(data, buf, (offset)); \ | ||
176 | } | ||
177 | |||
178 | #define sysfs_w(kind, sub, offset, reg) \ | ||
179 | static ssize_t set_##kind##sub (struct i2c_client *, struct fscher_data *, const char *, size_t, int, int); \ | ||
180 | static ssize_t set_##kind##offset##sub (struct device *, struct device_attribute *attr, const char *, size_t); \ | ||
181 | static ssize_t set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
182 | { \ | ||
183 | struct i2c_client *client = to_i2c_client(dev); \ | ||
184 | struct fscher_data *data = i2c_get_clientdata(client); \ | ||
185 | return set_##kind##sub(client, data, buf, count, (offset), reg); \ | ||
186 | } | ||
187 | |||
188 | #define sysfs_rw_n(kind, sub, offset, reg) \ | ||
189 | sysfs_r(kind, sub, offset, reg) \ | ||
190 | sysfs_w(kind, sub, offset, reg) \ | ||
191 | static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, show_##kind##offset##sub, set_##kind##offset##sub); | ||
192 | |||
193 | #define sysfs_rw(kind, sub, reg) \ | ||
194 | sysfs_r(kind, sub, 0, reg) \ | ||
195 | sysfs_w(kind, sub, 0, reg) \ | ||
196 | static DEVICE_ATTR(kind##sub, S_IRUGO | S_IWUSR, show_##kind##0##sub, set_##kind##0##sub); | ||
197 | |||
198 | #define sysfs_ro_n(kind, sub, offset, reg) \ | ||
199 | sysfs_r(kind, sub, offset, reg) \ | ||
200 | static DEVICE_ATTR(kind##offset##sub, S_IRUGO, show_##kind##offset##sub, NULL); | ||
201 | |||
202 | #define sysfs_ro(kind, sub, reg) \ | ||
203 | sysfs_r(kind, sub, 0, reg) \ | ||
204 | static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL); | ||
205 | |||
206 | #define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \ | ||
207 | sysfs_rw_n(pwm, , offset, reg_min) \ | ||
208 | sysfs_rw_n(fan, _status, offset, reg_status) \ | ||
209 | sysfs_rw_n(fan, _div , offset, reg_ripple) \ | ||
210 | sysfs_ro_n(fan, _input , offset, reg_act) | ||
211 | |||
212 | #define sysfs_temp(offset, reg_status, reg_act) \ | ||
213 | sysfs_rw_n(temp, _status, offset, reg_status) \ | ||
214 | sysfs_ro_n(temp, _input , offset, reg_act) | ||
215 | |||
216 | #define sysfs_in(offset, reg_act) \ | ||
217 | sysfs_ro_n(in, _input, offset, reg_act) | ||
218 | |||
219 | #define sysfs_revision(reg_revision) \ | ||
220 | sysfs_ro(revision, , reg_revision) | ||
221 | |||
222 | #define sysfs_alarms(reg_events) \ | ||
223 | sysfs_ro(alarms, , reg_events) | ||
224 | |||
225 | #define sysfs_control(reg_control) \ | ||
226 | sysfs_rw(control, , reg_control) | ||
227 | |||
228 | #define sysfs_watchdog(reg_control, reg_status, reg_preset) \ | ||
229 | sysfs_rw(watchdog, _control, reg_control) \ | ||
230 | sysfs_rw(watchdog, _status , reg_status) \ | ||
231 | sysfs_rw(watchdog, _preset , reg_preset) | ||
232 | |||
233 | sysfs_fan(1, FSCHER_REG_FAN0_STATE, FSCHER_REG_FAN0_MIN, | ||
234 | FSCHER_REG_FAN0_RIPPLE, FSCHER_REG_FAN0_ACT) | ||
235 | sysfs_fan(2, FSCHER_REG_FAN1_STATE, FSCHER_REG_FAN1_MIN, | ||
236 | FSCHER_REG_FAN1_RIPPLE, FSCHER_REG_FAN1_ACT) | ||
237 | sysfs_fan(3, FSCHER_REG_FAN2_STATE, FSCHER_REG_FAN2_MIN, | ||
238 | FSCHER_REG_FAN2_RIPPLE, FSCHER_REG_FAN2_ACT) | ||
239 | |||
240 | sysfs_temp(1, FSCHER_REG_TEMP0_STATE, FSCHER_REG_TEMP0_ACT) | ||
241 | sysfs_temp(2, FSCHER_REG_TEMP1_STATE, FSCHER_REG_TEMP1_ACT) | ||
242 | sysfs_temp(3, FSCHER_REG_TEMP2_STATE, FSCHER_REG_TEMP2_ACT) | ||
243 | |||
244 | sysfs_in(0, FSCHER_REG_VOLT_12) | ||
245 | sysfs_in(1, FSCHER_REG_VOLT_5) | ||
246 | sysfs_in(2, FSCHER_REG_VOLT_BATT) | ||
247 | |||
248 | sysfs_revision(FSCHER_REG_REVISION) | ||
249 | sysfs_alarms(FSCHER_REG_EVENTS) | ||
250 | sysfs_control(FSCHER_REG_CONTROL) | ||
251 | sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET) | ||
252 | |||
253 | static struct attribute *fscher_attributes[] = { | ||
254 | &dev_attr_revision.attr, | ||
255 | &dev_attr_alarms.attr, | ||
256 | &dev_attr_control.attr, | ||
257 | |||
258 | &dev_attr_watchdog_status.attr, | ||
259 | &dev_attr_watchdog_control.attr, | ||
260 | &dev_attr_watchdog_preset.attr, | ||
261 | |||
262 | &dev_attr_in0_input.attr, | ||
263 | &dev_attr_in1_input.attr, | ||
264 | &dev_attr_in2_input.attr, | ||
265 | |||
266 | &dev_attr_fan1_status.attr, | ||
267 | &dev_attr_fan1_div.attr, | ||
268 | &dev_attr_fan1_input.attr, | ||
269 | &dev_attr_pwm1.attr, | ||
270 | &dev_attr_fan2_status.attr, | ||
271 | &dev_attr_fan2_div.attr, | ||
272 | &dev_attr_fan2_input.attr, | ||
273 | &dev_attr_pwm2.attr, | ||
274 | &dev_attr_fan3_status.attr, | ||
275 | &dev_attr_fan3_div.attr, | ||
276 | &dev_attr_fan3_input.attr, | ||
277 | &dev_attr_pwm3.attr, | ||
278 | |||
279 | &dev_attr_temp1_status.attr, | ||
280 | &dev_attr_temp1_input.attr, | ||
281 | &dev_attr_temp2_status.attr, | ||
282 | &dev_attr_temp2_input.attr, | ||
283 | &dev_attr_temp3_status.attr, | ||
284 | &dev_attr_temp3_input.attr, | ||
285 | NULL | ||
286 | }; | ||
287 | |||
288 | static const struct attribute_group fscher_group = { | ||
289 | .attrs = fscher_attributes, | ||
290 | }; | ||
291 | |||
292 | /* | ||
293 | * Real code | ||
294 | */ | ||
295 | |||
296 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
297 | static int fscher_detect(struct i2c_client *new_client, int kind, | ||
298 | struct i2c_board_info *info) | ||
299 | { | ||
300 | struct i2c_adapter *adapter = new_client->adapter; | ||
301 | |||
302 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
303 | return -ENODEV; | ||
304 | |||
305 | /* Do the remaining detection unless force or force_fscher parameter */ | ||
306 | if (kind < 0) { | ||
307 | if ((i2c_smbus_read_byte_data(new_client, | ||
308 | FSCHER_REG_IDENT_0) != 0x48) /* 'H' */ | ||
309 | || (i2c_smbus_read_byte_data(new_client, | ||
310 | FSCHER_REG_IDENT_1) != 0x45) /* 'E' */ | ||
311 | || (i2c_smbus_read_byte_data(new_client, | ||
312 | FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */ | ||
313 | return -ENODEV; | ||
314 | } | ||
315 | |||
316 | strlcpy(info->type, "fscher", I2C_NAME_SIZE); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int fscher_probe(struct i2c_client *new_client, | ||
322 | const struct i2c_device_id *id) | ||
323 | { | ||
324 | struct fscher_data *data; | ||
325 | int err; | ||
326 | |||
327 | data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL); | ||
328 | if (!data) { | ||
329 | err = -ENOMEM; | ||
330 | goto exit; | ||
331 | } | ||
332 | |||
333 | i2c_set_clientdata(new_client, data); | ||
334 | data->valid = 0; | ||
335 | mutex_init(&data->update_lock); | ||
336 | |||
337 | fscher_init_client(new_client); | ||
338 | |||
339 | /* Register sysfs hooks */ | ||
340 | if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group))) | ||
341 | goto exit_free; | ||
342 | |||
343 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | ||
344 | if (IS_ERR(data->hwmon_dev)) { | ||
345 | err = PTR_ERR(data->hwmon_dev); | ||
346 | goto exit_remove_files; | ||
347 | } | ||
348 | |||
349 | return 0; | ||
350 | |||
351 | exit_remove_files: | ||
352 | sysfs_remove_group(&new_client->dev.kobj, &fscher_group); | ||
353 | exit_free: | ||
354 | kfree(data); | ||
355 | exit: | ||
356 | return err; | ||
357 | } | ||
358 | |||
359 | static int fscher_remove(struct i2c_client *client) | ||
360 | { | ||
361 | struct fscher_data *data = i2c_get_clientdata(client); | ||
362 | |||
363 | hwmon_device_unregister(data->hwmon_dev); | ||
364 | sysfs_remove_group(&client->dev.kobj, &fscher_group); | ||
365 | |||
366 | kfree(data); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int fscher_read_value(struct i2c_client *client, u8 reg) | ||
371 | { | ||
372 | dev_dbg(&client->dev, "read reg 0x%02x\n", reg); | ||
373 | |||
374 | return i2c_smbus_read_byte_data(client, reg); | ||
375 | } | ||
376 | |||
377 | static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value) | ||
378 | { | ||
379 | dev_dbg(&client->dev, "write reg 0x%02x, val 0x%02x\n", | ||
380 | reg, value); | ||
381 | |||
382 | return i2c_smbus_write_byte_data(client, reg, value); | ||
383 | } | ||
384 | |||
385 | /* Called when we have found a new FSC Hermes. */ | ||
386 | static void fscher_init_client(struct i2c_client *client) | ||
387 | { | ||
388 | struct fscher_data *data = i2c_get_clientdata(client); | ||
389 | |||
390 | /* Read revision from chip */ | ||
391 | data->revision = fscher_read_value(client, FSCHER_REG_REVISION); | ||
392 | } | ||
393 | |||
394 | static struct fscher_data *fscher_update_device(struct device *dev) | ||
395 | { | ||
396 | struct i2c_client *client = to_i2c_client(dev); | ||
397 | struct fscher_data *data = i2c_get_clientdata(client); | ||
398 | |||
399 | mutex_lock(&data->update_lock); | ||
400 | |||
401 | if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { | ||
402 | |||
403 | dev_dbg(&client->dev, "Starting fscher update\n"); | ||
404 | |||
405 | data->temp_act[0] = fscher_read_value(client, FSCHER_REG_TEMP0_ACT); | ||
406 | data->temp_act[1] = fscher_read_value(client, FSCHER_REG_TEMP1_ACT); | ||
407 | data->temp_act[2] = fscher_read_value(client, FSCHER_REG_TEMP2_ACT); | ||
408 | data->temp_status[0] = fscher_read_value(client, FSCHER_REG_TEMP0_STATE); | ||
409 | data->temp_status[1] = fscher_read_value(client, FSCHER_REG_TEMP1_STATE); | ||
410 | data->temp_status[2] = fscher_read_value(client, FSCHER_REG_TEMP2_STATE); | ||
411 | |||
412 | data->volt[0] = fscher_read_value(client, FSCHER_REG_VOLT_12); | ||
413 | data->volt[1] = fscher_read_value(client, FSCHER_REG_VOLT_5); | ||
414 | data->volt[2] = fscher_read_value(client, FSCHER_REG_VOLT_BATT); | ||
415 | |||
416 | data->fan_act[0] = fscher_read_value(client, FSCHER_REG_FAN0_ACT); | ||
417 | data->fan_act[1] = fscher_read_value(client, FSCHER_REG_FAN1_ACT); | ||
418 | data->fan_act[2] = fscher_read_value(client, FSCHER_REG_FAN2_ACT); | ||
419 | data->fan_status[0] = fscher_read_value(client, FSCHER_REG_FAN0_STATE); | ||
420 | data->fan_status[1] = fscher_read_value(client, FSCHER_REG_FAN1_STATE); | ||
421 | data->fan_status[2] = fscher_read_value(client, FSCHER_REG_FAN2_STATE); | ||
422 | data->fan_min[0] = fscher_read_value(client, FSCHER_REG_FAN0_MIN); | ||
423 | data->fan_min[1] = fscher_read_value(client, FSCHER_REG_FAN1_MIN); | ||
424 | data->fan_min[2] = fscher_read_value(client, FSCHER_REG_FAN2_MIN); | ||
425 | data->fan_ripple[0] = fscher_read_value(client, FSCHER_REG_FAN0_RIPPLE); | ||
426 | data->fan_ripple[1] = fscher_read_value(client, FSCHER_REG_FAN1_RIPPLE); | ||
427 | data->fan_ripple[2] = fscher_read_value(client, FSCHER_REG_FAN2_RIPPLE); | ||
428 | |||
429 | data->watchdog[0] = fscher_read_value(client, FSCHER_REG_WDOG_PRESET); | ||
430 | data->watchdog[1] = fscher_read_value(client, FSCHER_REG_WDOG_STATE); | ||
431 | data->watchdog[2] = fscher_read_value(client, FSCHER_REG_WDOG_CONTROL); | ||
432 | |||
433 | data->global_event = fscher_read_value(client, FSCHER_REG_EVENT_STATE); | ||
434 | data->global_control = fscher_read_value(client, | ||
435 | FSCHER_REG_CONTROL); | ||
436 | |||
437 | data->last_updated = jiffies; | ||
438 | data->valid = 1; | ||
439 | } | ||
440 | |||
441 | mutex_unlock(&data->update_lock); | ||
442 | |||
443 | return data; | ||
444 | } | ||
445 | |||
446 | |||
447 | |||
448 | #define FAN_INDEX_FROM_NUM(nr) ((nr) - 1) | ||
449 | |||
450 | static ssize_t set_fan_status(struct i2c_client *client, struct fscher_data *data, | ||
451 | const char *buf, size_t count, int nr, int reg) | ||
452 | { | ||
453 | /* bits 0..1, 3..7 reserved => mask with 0x04 */ | ||
454 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04; | ||
455 | |||
456 | mutex_lock(&data->update_lock); | ||
457 | data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v; | ||
458 | fscher_write_value(client, reg, v); | ||
459 | mutex_unlock(&data->update_lock); | ||
460 | return count; | ||
461 | } | ||
462 | |||
463 | static ssize_t show_fan_status(struct fscher_data *data, char *buf, int nr) | ||
464 | { | ||
465 | /* bits 0..1, 3..7 reserved => mask with 0x04 */ | ||
466 | return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04); | ||
467 | } | ||
468 | |||
469 | static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data, | ||
470 | const char *buf, size_t count, int nr, int reg) | ||
471 | { | ||
472 | unsigned long v = simple_strtoul(buf, NULL, 10); | ||
473 | |||
474 | mutex_lock(&data->update_lock); | ||
475 | data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; | ||
476 | fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); | ||
477 | mutex_unlock(&data->update_lock); | ||
478 | return count; | ||
479 | } | ||
480 | |||
481 | static ssize_t show_pwm(struct fscher_data *data, char *buf, int nr) | ||
482 | { | ||
483 | return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]); | ||
484 | } | ||
485 | |||
486 | static ssize_t set_fan_div(struct i2c_client *client, struct fscher_data *data, | ||
487 | const char *buf, size_t count, int nr, int reg) | ||
488 | { | ||
489 | /* supported values: 2, 4, 8 */ | ||
490 | unsigned long v = simple_strtoul(buf, NULL, 10); | ||
491 | |||
492 | switch (v) { | ||
493 | case 2: v = 1; break; | ||
494 | case 4: v = 2; break; | ||
495 | case 8: v = 3; break; | ||
496 | default: | ||
497 | dev_err(&client->dev, "fan_div value %ld not " | ||
498 | "supported. Choose one of 2, 4 or 8!\n", v); | ||
499 | return -EINVAL; | ||
500 | } | ||
501 | |||
502 | mutex_lock(&data->update_lock); | ||
503 | |||
504 | /* bits 2..7 reserved => mask with 0x03 */ | ||
505 | data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03; | ||
506 | data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v; | ||
507 | |||
508 | fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]); | ||
509 | mutex_unlock(&data->update_lock); | ||
510 | return count; | ||
511 | } | ||
512 | |||
513 | static ssize_t show_fan_div(struct fscher_data *data, char *buf, int nr) | ||
514 | { | ||
515 | /* bits 2..7 reserved => mask with 0x03 */ | ||
516 | return sprintf(buf, "%u\n", 1 << (data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] & 0x03)); | ||
517 | } | ||
518 | |||
519 | #define RPM_FROM_REG(val) (val*60) | ||
520 | |||
521 | static ssize_t show_fan_input (struct fscher_data *data, char *buf, int nr) | ||
522 | { | ||
523 | return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[FAN_INDEX_FROM_NUM(nr)])); | ||
524 | } | ||
525 | |||
526 | |||
527 | |||
528 | #define TEMP_INDEX_FROM_NUM(nr) ((nr) - 1) | ||
529 | |||
530 | static ssize_t set_temp_status(struct i2c_client *client, struct fscher_data *data, | ||
531 | const char *buf, size_t count, int nr, int reg) | ||
532 | { | ||
533 | /* bits 2..7 reserved, 0 read only => mask with 0x02 */ | ||
534 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; | ||
535 | |||
536 | mutex_lock(&data->update_lock); | ||
537 | data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v; | ||
538 | fscher_write_value(client, reg, v); | ||
539 | mutex_unlock(&data->update_lock); | ||
540 | return count; | ||
541 | } | ||
542 | |||
543 | static ssize_t show_temp_status(struct fscher_data *data, char *buf, int nr) | ||
544 | { | ||
545 | /* bits 2..7 reserved => mask with 0x03 */ | ||
546 | return sprintf(buf, "%u\n", data->temp_status[TEMP_INDEX_FROM_NUM(nr)] & 0x03); | ||
547 | } | ||
548 | |||
549 | #define TEMP_FROM_REG(val) (((val) - 128) * 1000) | ||
550 | |||
551 | static ssize_t show_temp_input(struct fscher_data *data, char *buf, int nr) | ||
552 | { | ||
553 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[TEMP_INDEX_FROM_NUM(nr)])); | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | * The final conversion is specified in sensors.conf, as it depends on | ||
558 | * mainboard specific values. We export the registers contents as | ||
559 | * pseudo-hundredths-of-Volts (range 0V - 2.55V). Not that it makes much | ||
560 | * sense per se, but it minimizes the conversions count and keeps the | ||
561 | * values within a usual range. | ||
562 | */ | ||
563 | #define VOLT_FROM_REG(val) ((val) * 10) | ||
564 | |||
565 | static ssize_t show_in_input(struct fscher_data *data, char *buf, int nr) | ||
566 | { | ||
567 | return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[nr])); | ||
568 | } | ||
569 | |||
570 | |||
571 | |||
572 | static ssize_t show_revision(struct fscher_data *data, char *buf, int nr) | ||
573 | { | ||
574 | return sprintf(buf, "%u\n", data->revision); | ||
575 | } | ||
576 | |||
577 | |||
578 | |||
579 | static ssize_t show_alarms(struct fscher_data *data, char *buf, int nr) | ||
580 | { | ||
581 | /* bits 2, 5..6 reserved => mask with 0x9b */ | ||
582 | return sprintf(buf, "%u\n", data->global_event & 0x9b); | ||
583 | } | ||
584 | |||
585 | |||
586 | |||
587 | static ssize_t set_control(struct i2c_client *client, struct fscher_data *data, | ||
588 | const char *buf, size_t count, int nr, int reg) | ||
589 | { | ||
590 | /* bits 1..7 reserved => mask with 0x01 */ | ||
591 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; | ||
592 | |||
593 | mutex_lock(&data->update_lock); | ||
594 | data->global_control = v; | ||
595 | fscher_write_value(client, reg, v); | ||
596 | mutex_unlock(&data->update_lock); | ||
597 | return count; | ||
598 | } | ||
599 | |||
600 | static ssize_t show_control(struct fscher_data *data, char *buf, int nr) | ||
601 | { | ||
602 | /* bits 1..7 reserved => mask with 0x01 */ | ||
603 | return sprintf(buf, "%u\n", data->global_control & 0x01); | ||
604 | } | ||
605 | |||
606 | |||
607 | |||
608 | static ssize_t set_watchdog_control(struct i2c_client *client, struct | ||
609 | fscher_data *data, const char *buf, size_t count, | ||
610 | int nr, int reg) | ||
611 | { | ||
612 | /* bits 0..3 reserved => mask with 0xf0 */ | ||
613 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; | ||
614 | |||
615 | mutex_lock(&data->update_lock); | ||
616 | data->watchdog[2] &= ~0xf0; | ||
617 | data->watchdog[2] |= v; | ||
618 | fscher_write_value(client, reg, data->watchdog[2]); | ||
619 | mutex_unlock(&data->update_lock); | ||
620 | return count; | ||
621 | } | ||
622 | |||
623 | static ssize_t show_watchdog_control(struct fscher_data *data, char *buf, int nr) | ||
624 | { | ||
625 | /* bits 0..3 reserved, bit 5 write only => mask with 0xd0 */ | ||
626 | return sprintf(buf, "%u\n", data->watchdog[2] & 0xd0); | ||
627 | } | ||
628 | |||
629 | static ssize_t set_watchdog_status(struct i2c_client *client, struct fscher_data *data, | ||
630 | const char *buf, size_t count, int nr, int reg) | ||
631 | { | ||
632 | /* bits 0, 2..7 reserved => mask with 0x02 */ | ||
633 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; | ||
634 | |||
635 | mutex_lock(&data->update_lock); | ||
636 | data->watchdog[1] &= ~v; | ||
637 | fscher_write_value(client, reg, v); | ||
638 | mutex_unlock(&data->update_lock); | ||
639 | return count; | ||
640 | } | ||
641 | |||
642 | static ssize_t show_watchdog_status(struct fscher_data *data, char *buf, int nr) | ||
643 | { | ||
644 | /* bits 0, 2..7 reserved => mask with 0x02 */ | ||
645 | return sprintf(buf, "%u\n", data->watchdog[1] & 0x02); | ||
646 | } | ||
647 | |||
648 | static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data *data, | ||
649 | const char *buf, size_t count, int nr, int reg) | ||
650 | { | ||
651 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; | ||
652 | |||
653 | mutex_lock(&data->update_lock); | ||
654 | data->watchdog[0] = v; | ||
655 | fscher_write_value(client, reg, data->watchdog[0]); | ||
656 | mutex_unlock(&data->update_lock); | ||
657 | return count; | ||
658 | } | ||
659 | |||
660 | static ssize_t show_watchdog_preset(struct fscher_data *data, char *buf, int nr) | ||
661 | { | ||
662 | return sprintf(buf, "%u\n", data->watchdog[0]); | ||
663 | } | ||
664 | |||
665 | static int __init sensors_fscher_init(void) | ||
666 | { | ||
667 | return i2c_add_driver(&fscher_driver); | ||
668 | } | ||
669 | |||
670 | static void __exit sensors_fscher_exit(void) | ||
671 | { | ||
672 | i2c_del_driver(&fscher_driver); | ||
673 | } | ||
674 | |||
675 | MODULE_AUTHOR("Reinhard Nissl <rnissl@gmx.de>"); | ||
676 | MODULE_DESCRIPTION("FSC Hermes driver"); | ||
677 | MODULE_LICENSE("GPL"); | ||
678 | |||
679 | module_init(sensors_fscher_init); | ||
680 | module_exit(sensors_fscher_exit); | ||
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c deleted file mode 100644 index 8a7bcf500b4e..000000000000 --- a/drivers/hwmon/fscpos.c +++ /dev/null | |||
@@ -1,654 +0,0 @@ | |||
1 | /* | ||
2 | fscpos.c - Kernel module for hardware monitoring with FSC Poseidon chips | ||
3 | Copyright (C) 2004, 2005 Stefan Ott <stefan@desire.ch> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | fujitsu siemens poseidon chip, | ||
22 | module based on the old fscpos module by Hermann Jung <hej@odn.de> and | ||
23 | the fscher module by Reinhard Nissl <rnissl@gmx.de> | ||
24 | |||
25 | original module based on lm80.c | ||
26 | Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> | ||
27 | and Philip Edelbrock <phil@netroedge.com> | ||
28 | |||
29 | Thanks to Jean Delvare for reviewing my code and suggesting a lot of | ||
30 | improvements. | ||
31 | */ | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/jiffies.h> | ||
36 | #include <linux/i2c.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/hwmon.h> | ||
39 | #include <linux/err.h> | ||
40 | #include <linux/mutex.h> | ||
41 | #include <linux/sysfs.h> | ||
42 | |||
43 | /* | ||
44 | * Addresses to scan | ||
45 | */ | ||
46 | static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; | ||
47 | |||
48 | /* | ||
49 | * Insmod parameters | ||
50 | */ | ||
51 | I2C_CLIENT_INSMOD_1(fscpos); | ||
52 | |||
53 | /* | ||
54 | * The FSCPOS registers | ||
55 | */ | ||
56 | |||
57 | /* chip identification */ | ||
58 | #define FSCPOS_REG_IDENT_0 0x00 | ||
59 | #define FSCPOS_REG_IDENT_1 0x01 | ||
60 | #define FSCPOS_REG_IDENT_2 0x02 | ||
61 | #define FSCPOS_REG_REVISION 0x03 | ||
62 | |||
63 | /* global control and status */ | ||
64 | #define FSCPOS_REG_EVENT_STATE 0x04 | ||
65 | #define FSCPOS_REG_CONTROL 0x05 | ||
66 | |||
67 | /* watchdog */ | ||
68 | #define FSCPOS_REG_WDOG_PRESET 0x28 | ||
69 | #define FSCPOS_REG_WDOG_STATE 0x23 | ||
70 | #define FSCPOS_REG_WDOG_CONTROL 0x21 | ||
71 | |||
72 | /* voltages */ | ||
73 | #define FSCPOS_REG_VOLT_12 0x45 | ||
74 | #define FSCPOS_REG_VOLT_5 0x42 | ||
75 | #define FSCPOS_REG_VOLT_BATT 0x48 | ||
76 | |||
77 | /* fans - the chip does not support minimum speed for fan2 */ | ||
78 | static u8 FSCPOS_REG_PWM[] = { 0x55, 0x65 }; | ||
79 | static u8 FSCPOS_REG_FAN_ACT[] = { 0x0e, 0x6b, 0xab }; | ||
80 | static u8 FSCPOS_REG_FAN_STATE[] = { 0x0d, 0x62, 0xa2 }; | ||
81 | static u8 FSCPOS_REG_FAN_RIPPLE[] = { 0x0f, 0x6f, 0xaf }; | ||
82 | |||
83 | /* temperatures */ | ||
84 | static u8 FSCPOS_REG_TEMP_ACT[] = { 0x64, 0x32, 0x35 }; | ||
85 | static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 }; | ||
86 | |||
87 | /* | ||
88 | * Functions declaration | ||
89 | */ | ||
90 | static int fscpos_probe(struct i2c_client *client, | ||
91 | const struct i2c_device_id *id); | ||
92 | static int fscpos_detect(struct i2c_client *client, int kind, | ||
93 | struct i2c_board_info *info); | ||
94 | static int fscpos_remove(struct i2c_client *client); | ||
95 | |||
96 | static int fscpos_read_value(struct i2c_client *client, u8 reg); | ||
97 | static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); | ||
98 | static struct fscpos_data *fscpos_update_device(struct device *dev); | ||
99 | static void fscpos_init_client(struct i2c_client *client); | ||
100 | |||
101 | static void reset_fan_alarm(struct i2c_client *client, int nr); | ||
102 | |||
103 | /* | ||
104 | * Driver data (common to all clients) | ||
105 | */ | ||
106 | static const struct i2c_device_id fscpos_id[] = { | ||
107 | { "fscpos", fscpos }, | ||
108 | { } | ||
109 | }; | ||
110 | |||
111 | static struct i2c_driver fscpos_driver = { | ||
112 | .class = I2C_CLASS_HWMON, | ||
113 | .driver = { | ||
114 | .name = "fscpos", | ||
115 | }, | ||
116 | .probe = fscpos_probe, | ||
117 | .remove = fscpos_remove, | ||
118 | .id_table = fscpos_id, | ||
119 | .detect = fscpos_detect, | ||
120 | .address_data = &addr_data, | ||
121 | }; | ||
122 | |||
123 | /* | ||
124 | * Client data (each client gets its own) | ||
125 | */ | ||
126 | struct fscpos_data { | ||
127 | struct device *hwmon_dev; | ||
128 | struct mutex update_lock; | ||
129 | char valid; /* 0 until following fields are valid */ | ||
130 | unsigned long last_updated; /* In jiffies */ | ||
131 | |||
132 | /* register values */ | ||
133 | u8 revision; /* revision of chip */ | ||
134 | u8 global_event; /* global event status */ | ||
135 | u8 global_control; /* global control register */ | ||
136 | u8 wdog_control; /* watchdog control */ | ||
137 | u8 wdog_state; /* watchdog status */ | ||
138 | u8 wdog_preset; /* watchdog preset */ | ||
139 | u8 volt[3]; /* 12, 5, battery current */ | ||
140 | u8 temp_act[3]; /* temperature */ | ||
141 | u8 temp_status[3]; /* status of sensor */ | ||
142 | u8 fan_act[3]; /* fans revolutions per second */ | ||
143 | u8 fan_status[3]; /* fan status */ | ||
144 | u8 pwm[2]; /* fan min value for rps */ | ||
145 | u8 fan_ripple[3]; /* divider for rps */ | ||
146 | }; | ||
147 | |||
148 | /* Temperature */ | ||
149 | #define TEMP_FROM_REG(val) (((val) - 128) * 1000) | ||
150 | |||
151 | static ssize_t show_temp_input(struct fscpos_data *data, char *buf, int nr) | ||
152 | { | ||
153 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[nr - 1])); | ||
154 | } | ||
155 | |||
156 | static ssize_t show_temp_status(struct fscpos_data *data, char *buf, int nr) | ||
157 | { | ||
158 | /* bits 2..7 reserved => mask with 0x03 */ | ||
159 | return sprintf(buf, "%u\n", data->temp_status[nr - 1] & 0x03); | ||
160 | } | ||
161 | |||
162 | static ssize_t show_temp_reset(struct fscpos_data *data, char *buf, int nr) | ||
163 | { | ||
164 | return sprintf(buf, "1\n"); | ||
165 | } | ||
166 | |||
167 | static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data | ||
168 | *data, const char *buf, size_t count, int nr, int reg) | ||
169 | { | ||
170 | unsigned long v = simple_strtoul(buf, NULL, 10); | ||
171 | if (v != 1) { | ||
172 | dev_err(&client->dev, "temp_reset value %ld not supported. " | ||
173 | "Use 1 to reset the alarm!\n", v); | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | dev_info(&client->dev, "You used the temp_reset feature which has not " | ||
178 | "been proplerly tested. Please report your " | ||
179 | "experience to the module author.\n"); | ||
180 | |||
181 | /* Supported value: 2 (clears the status) */ | ||
182 | fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr - 1], 2); | ||
183 | return count; | ||
184 | } | ||
185 | |||
186 | /* Fans */ | ||
187 | #define RPM_FROM_REG(val) ((val) * 60) | ||
188 | |||
189 | static ssize_t show_fan_status(struct fscpos_data *data, char *buf, int nr) | ||
190 | { | ||
191 | /* bits 0..1, 3..7 reserved => mask with 0x04 */ | ||
192 | return sprintf(buf, "%u\n", data->fan_status[nr - 1] & 0x04); | ||
193 | } | ||
194 | |||
195 | static ssize_t show_fan_input(struct fscpos_data *data, char *buf, int nr) | ||
196 | { | ||
197 | return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[nr - 1])); | ||
198 | } | ||
199 | |||
200 | static ssize_t show_fan_ripple(struct fscpos_data *data, char *buf, int nr) | ||
201 | { | ||
202 | /* bits 2..7 reserved => mask with 0x03 */ | ||
203 | return sprintf(buf, "%u\n", data->fan_ripple[nr - 1] & 0x03); | ||
204 | } | ||
205 | |||
206 | static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data | ||
207 | *data, const char *buf, size_t count, int nr, int reg) | ||
208 | { | ||
209 | /* supported values: 2, 4, 8 */ | ||
210 | unsigned long v = simple_strtoul(buf, NULL, 10); | ||
211 | |||
212 | switch (v) { | ||
213 | case 2: v = 1; break; | ||
214 | case 4: v = 2; break; | ||
215 | case 8: v = 3; break; | ||
216 | default: | ||
217 | dev_err(&client->dev, "fan_ripple value %ld not supported. " | ||
218 | "Must be one of 2, 4 or 8!\n", v); | ||
219 | return -EINVAL; | ||
220 | } | ||
221 | |||
222 | mutex_lock(&data->update_lock); | ||
223 | /* bits 2..7 reserved => mask with 0x03 */ | ||
224 | data->fan_ripple[nr - 1] &= ~0x03; | ||
225 | data->fan_ripple[nr - 1] |= v; | ||
226 | |||
227 | fscpos_write_value(client, reg, data->fan_ripple[nr - 1]); | ||
228 | mutex_unlock(&data->update_lock); | ||
229 | return count; | ||
230 | } | ||
231 | |||
232 | static ssize_t show_pwm(struct fscpos_data *data, char *buf, int nr) | ||
233 | { | ||
234 | return sprintf(buf, "%u\n", data->pwm[nr - 1]); | ||
235 | } | ||
236 | |||
237 | static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data, | ||
238 | const char *buf, size_t count, int nr, int reg) | ||
239 | { | ||
240 | unsigned long v = simple_strtoul(buf, NULL, 10); | ||
241 | |||
242 | /* Range: 0..255 */ | ||
243 | if (v < 0) v = 0; | ||
244 | if (v > 255) v = 255; | ||
245 | |||
246 | mutex_lock(&data->update_lock); | ||
247 | data->pwm[nr - 1] = v; | ||
248 | fscpos_write_value(client, reg, data->pwm[nr - 1]); | ||
249 | mutex_unlock(&data->update_lock); | ||
250 | return count; | ||
251 | } | ||
252 | |||
253 | static void reset_fan_alarm(struct i2c_client *client, int nr) | ||
254 | { | ||
255 | fscpos_write_value(client, FSCPOS_REG_FAN_STATE[nr], 4); | ||
256 | } | ||
257 | |||
258 | /* Volts */ | ||
259 | #define VOLT_FROM_REG(val, mult) ((val) * (mult) / 255) | ||
260 | |||
261 | static ssize_t show_volt_12(struct device *dev, struct device_attribute *attr, char *buf) | ||
262 | { | ||
263 | struct fscpos_data *data = fscpos_update_device(dev); | ||
264 | return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200)); | ||
265 | } | ||
266 | |||
267 | static ssize_t show_volt_5(struct device *dev, struct device_attribute *attr, char *buf) | ||
268 | { | ||
269 | struct fscpos_data *data = fscpos_update_device(dev); | ||
270 | return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600)); | ||
271 | } | ||
272 | |||
273 | static ssize_t show_volt_batt(struct device *dev, struct device_attribute *attr, char *buf) | ||
274 | { | ||
275 | struct fscpos_data *data = fscpos_update_device(dev); | ||
276 | return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300)); | ||
277 | } | ||
278 | |||
279 | /* Watchdog */ | ||
280 | static ssize_t show_wdog_control(struct fscpos_data *data, char *buf) | ||
281 | { | ||
282 | /* bits 0..3 reserved, bit 6 write only => mask with 0xb0 */ | ||
283 | return sprintf(buf, "%u\n", data->wdog_control & 0xb0); | ||
284 | } | ||
285 | |||
286 | static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data | ||
287 | *data, const char *buf, size_t count, int reg) | ||
288 | { | ||
289 | /* bits 0..3 reserved => mask with 0xf0 */ | ||
290 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; | ||
291 | |||
292 | mutex_lock(&data->update_lock); | ||
293 | data->wdog_control &= ~0xf0; | ||
294 | data->wdog_control |= v; | ||
295 | fscpos_write_value(client, reg, data->wdog_control); | ||
296 | mutex_unlock(&data->update_lock); | ||
297 | return count; | ||
298 | } | ||
299 | |||
300 | static ssize_t show_wdog_state(struct fscpos_data *data, char *buf) | ||
301 | { | ||
302 | /* bits 0, 2..7 reserved => mask with 0x02 */ | ||
303 | return sprintf(buf, "%u\n", data->wdog_state & 0x02); | ||
304 | } | ||
305 | |||
306 | static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data | ||
307 | *data, const char *buf, size_t count, int reg) | ||
308 | { | ||
309 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; | ||
310 | |||
311 | /* Valid values: 2 (clear) */ | ||
312 | if (v != 2) { | ||
313 | dev_err(&client->dev, "wdog_state value %ld not supported. " | ||
314 | "Must be 2 to clear the state!\n", v); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | mutex_lock(&data->update_lock); | ||
319 | data->wdog_state &= ~v; | ||
320 | fscpos_write_value(client, reg, v); | ||
321 | mutex_unlock(&data->update_lock); | ||
322 | return count; | ||
323 | } | ||
324 | |||
325 | static ssize_t show_wdog_preset(struct fscpos_data *data, char *buf) | ||
326 | { | ||
327 | return sprintf(buf, "%u\n", data->wdog_preset); | ||
328 | } | ||
329 | |||
330 | static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data | ||
331 | *data, const char *buf, size_t count, int reg) | ||
332 | { | ||
333 | unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; | ||
334 | |||
335 | mutex_lock(&data->update_lock); | ||
336 | data->wdog_preset = v; | ||
337 | fscpos_write_value(client, reg, data->wdog_preset); | ||
338 | mutex_unlock(&data->update_lock); | ||
339 | return count; | ||
340 | } | ||
341 | |||
342 | /* Event */ | ||
343 | static ssize_t show_event(struct device *dev, struct device_attribute *attr, char *buf) | ||
344 | { | ||
345 | /* bits 5..7 reserved => mask with 0x1f */ | ||
346 | struct fscpos_data *data = fscpos_update_device(dev); | ||
347 | return sprintf(buf, "%u\n", data->global_event & 0x9b); | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Sysfs stuff | ||
352 | */ | ||
353 | #define create_getter(kind, sub) \ | ||
354 | static ssize_t sysfs_show_##kind##sub(struct device *dev, struct device_attribute *attr, char *buf) \ | ||
355 | { \ | ||
356 | struct fscpos_data *data = fscpos_update_device(dev); \ | ||
357 | return show_##kind##sub(data, buf); \ | ||
358 | } | ||
359 | |||
360 | #define create_getter_n(kind, offset, sub) \ | ||
361 | static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, struct device_attribute *attr, char\ | ||
362 | *buf) \ | ||
363 | { \ | ||
364 | struct fscpos_data *data = fscpos_update_device(dev); \ | ||
365 | return show_##kind##sub(data, buf, offset); \ | ||
366 | } | ||
367 | |||
368 | #define create_setter(kind, sub, reg) \ | ||
369 | static ssize_t sysfs_set_##kind##sub (struct device *dev, struct device_attribute *attr, const char \ | ||
370 | *buf, size_t count) \ | ||
371 | { \ | ||
372 | struct i2c_client *client = to_i2c_client(dev); \ | ||
373 | struct fscpos_data *data = i2c_get_clientdata(client); \ | ||
374 | return set_##kind##sub(client, data, buf, count, reg); \ | ||
375 | } | ||
376 | |||
377 | #define create_setter_n(kind, offset, sub, reg) \ | ||
378 | static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, \ | ||
379 | const char *buf, size_t count) \ | ||
380 | { \ | ||
381 | struct i2c_client *client = to_i2c_client(dev); \ | ||
382 | struct fscpos_data *data = i2c_get_clientdata(client); \ | ||
383 | return set_##kind##sub(client, data, buf, count, offset, reg);\ | ||
384 | } | ||
385 | |||
386 | #define create_sysfs_device_ro(kind, sub, offset) \ | ||
387 | static DEVICE_ATTR(kind##offset##sub, S_IRUGO, \ | ||
388 | sysfs_show_##kind##offset##sub, NULL); | ||
389 | |||
390 | #define create_sysfs_device_rw(kind, sub, offset) \ | ||
391 | static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, \ | ||
392 | sysfs_show_##kind##offset##sub, sysfs_set_##kind##offset##sub); | ||
393 | |||
394 | #define sysfs_ro_n(kind, sub, offset) \ | ||
395 | create_getter_n(kind, offset, sub); \ | ||
396 | create_sysfs_device_ro(kind, sub, offset); | ||
397 | |||
398 | #define sysfs_rw_n(kind, sub, offset, reg) \ | ||
399 | create_getter_n(kind, offset, sub); \ | ||
400 | create_setter_n(kind, offset, sub, reg); \ | ||
401 | create_sysfs_device_rw(kind, sub, offset); | ||
402 | |||
403 | #define sysfs_rw(kind, sub, reg) \ | ||
404 | create_getter(kind, sub); \ | ||
405 | create_setter(kind, sub, reg); \ | ||
406 | create_sysfs_device_rw(kind, sub,); | ||
407 | |||
408 | #define sysfs_fan_with_min(offset, reg_status, reg_ripple, reg_min) \ | ||
409 | sysfs_fan(offset, reg_status, reg_ripple); \ | ||
410 | sysfs_rw_n(pwm,, offset, reg_min); | ||
411 | |||
412 | #define sysfs_fan(offset, reg_status, reg_ripple) \ | ||
413 | sysfs_ro_n(fan, _input, offset); \ | ||
414 | sysfs_ro_n(fan, _status, offset); \ | ||
415 | sysfs_rw_n(fan, _ripple, offset, reg_ripple); | ||
416 | |||
417 | #define sysfs_temp(offset, reg_status) \ | ||
418 | sysfs_ro_n(temp, _input, offset); \ | ||
419 | sysfs_ro_n(temp, _status, offset); \ | ||
420 | sysfs_rw_n(temp, _reset, offset, reg_status); | ||
421 | |||
422 | #define sysfs_watchdog(reg_wdog_preset, reg_wdog_state, reg_wdog_control) \ | ||
423 | sysfs_rw(wdog, _control, reg_wdog_control); \ | ||
424 | sysfs_rw(wdog, _preset, reg_wdog_preset); \ | ||
425 | sysfs_rw(wdog, _state, reg_wdog_state); | ||
426 | |||
427 | sysfs_fan_with_min(1, FSCPOS_REG_FAN_STATE[0], FSCPOS_REG_FAN_RIPPLE[0], | ||
428 | FSCPOS_REG_PWM[0]); | ||
429 | sysfs_fan_with_min(2, FSCPOS_REG_FAN_STATE[1], FSCPOS_REG_FAN_RIPPLE[1], | ||
430 | FSCPOS_REG_PWM[1]); | ||
431 | sysfs_fan(3, FSCPOS_REG_FAN_STATE[2], FSCPOS_REG_FAN_RIPPLE[2]); | ||
432 | |||
433 | sysfs_temp(1, FSCPOS_REG_TEMP_STATE[0]); | ||
434 | sysfs_temp(2, FSCPOS_REG_TEMP_STATE[1]); | ||
435 | sysfs_temp(3, FSCPOS_REG_TEMP_STATE[2]); | ||
436 | |||
437 | sysfs_watchdog(FSCPOS_REG_WDOG_PRESET, FSCPOS_REG_WDOG_STATE, | ||
438 | FSCPOS_REG_WDOG_CONTROL); | ||
439 | |||
440 | static DEVICE_ATTR(event, S_IRUGO, show_event, NULL); | ||
441 | static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL); | ||
442 | static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL); | ||
443 | static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL); | ||
444 | |||
445 | static struct attribute *fscpos_attributes[] = { | ||
446 | &dev_attr_event.attr, | ||
447 | &dev_attr_in0_input.attr, | ||
448 | &dev_attr_in1_input.attr, | ||
449 | &dev_attr_in2_input.attr, | ||
450 | |||
451 | &dev_attr_wdog_control.attr, | ||
452 | &dev_attr_wdog_preset.attr, | ||
453 | &dev_attr_wdog_state.attr, | ||
454 | |||
455 | &dev_attr_temp1_input.attr, | ||
456 | &dev_attr_temp1_status.attr, | ||
457 | &dev_attr_temp1_reset.attr, | ||
458 | &dev_attr_temp2_input.attr, | ||
459 | &dev_attr_temp2_status.attr, | ||
460 | &dev_attr_temp2_reset.attr, | ||
461 | &dev_attr_temp3_input.attr, | ||
462 | &dev_attr_temp3_status.attr, | ||
463 | &dev_attr_temp3_reset.attr, | ||
464 | |||
465 | &dev_attr_fan1_input.attr, | ||
466 | &dev_attr_fan1_status.attr, | ||
467 | &dev_attr_fan1_ripple.attr, | ||
468 | &dev_attr_pwm1.attr, | ||
469 | &dev_attr_fan2_input.attr, | ||
470 | &dev_attr_fan2_status.attr, | ||
471 | &dev_attr_fan2_ripple.attr, | ||
472 | &dev_attr_pwm2.attr, | ||
473 | &dev_attr_fan3_input.attr, | ||
474 | &dev_attr_fan3_status.attr, | ||
475 | &dev_attr_fan3_ripple.attr, | ||
476 | NULL | ||
477 | }; | ||
478 | |||
479 | static const struct attribute_group fscpos_group = { | ||
480 | .attrs = fscpos_attributes, | ||
481 | }; | ||
482 | |||
483 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
484 | static int fscpos_detect(struct i2c_client *new_client, int kind, | ||
485 | struct i2c_board_info *info) | ||
486 | { | ||
487 | struct i2c_adapter *adapter = new_client->adapter; | ||
488 | |||
489 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
490 | return -ENODEV; | ||
491 | |||
492 | /* Do the remaining detection unless force or force_fscpos parameter */ | ||
493 | if (kind < 0) { | ||
494 | if ((fscpos_read_value(new_client, FSCPOS_REG_IDENT_0) | ||
495 | != 0x50) /* 'P' */ | ||
496 | || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1) | ||
497 | != 0x45) /* 'E' */ | ||
498 | || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2) | ||
499 | != 0x47))/* 'G' */ | ||
500 | return -ENODEV; | ||
501 | } | ||
502 | |||
503 | strlcpy(info->type, "fscpos", I2C_NAME_SIZE); | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int fscpos_probe(struct i2c_client *new_client, | ||
509 | const struct i2c_device_id *id) | ||
510 | { | ||
511 | struct fscpos_data *data; | ||
512 | int err; | ||
513 | |||
514 | data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL); | ||
515 | if (!data) { | ||
516 | err = -ENOMEM; | ||
517 | goto exit; | ||
518 | } | ||
519 | |||
520 | i2c_set_clientdata(new_client, data); | ||
521 | data->valid = 0; | ||
522 | mutex_init(&data->update_lock); | ||
523 | |||
524 | /* Inizialize the fscpos chip */ | ||
525 | fscpos_init_client(new_client); | ||
526 | |||
527 | /* Announce that the chip was found */ | ||
528 | dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision); | ||
529 | |||
530 | /* Register sysfs hooks */ | ||
531 | if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group))) | ||
532 | goto exit_free; | ||
533 | |||
534 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | ||
535 | if (IS_ERR(data->hwmon_dev)) { | ||
536 | err = PTR_ERR(data->hwmon_dev); | ||
537 | goto exit_remove_files; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | |||
542 | exit_remove_files: | ||
543 | sysfs_remove_group(&new_client->dev.kobj, &fscpos_group); | ||
544 | exit_free: | ||
545 | kfree(data); | ||
546 | exit: | ||
547 | return err; | ||
548 | } | ||
549 | |||
550 | static int fscpos_remove(struct i2c_client *client) | ||
551 | { | ||
552 | struct fscpos_data *data = i2c_get_clientdata(client); | ||
553 | |||
554 | hwmon_device_unregister(data->hwmon_dev); | ||
555 | sysfs_remove_group(&client->dev.kobj, &fscpos_group); | ||
556 | |||
557 | kfree(data); | ||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int fscpos_read_value(struct i2c_client *client, u8 reg) | ||
562 | { | ||
563 | dev_dbg(&client->dev, "Read reg 0x%02x\n", reg); | ||
564 | return i2c_smbus_read_byte_data(client, reg); | ||
565 | } | ||
566 | |||
567 | static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value) | ||
568 | { | ||
569 | dev_dbg(&client->dev, "Write reg 0x%02x, val 0x%02x\n", reg, value); | ||
570 | return i2c_smbus_write_byte_data(client, reg, value); | ||
571 | } | ||
572 | |||
573 | /* Called when we have found a new FSCPOS chip */ | ||
574 | static void fscpos_init_client(struct i2c_client *client) | ||
575 | { | ||
576 | struct fscpos_data *data = i2c_get_clientdata(client); | ||
577 | |||
578 | /* read revision from chip */ | ||
579 | data->revision = fscpos_read_value(client, FSCPOS_REG_REVISION); | ||
580 | } | ||
581 | |||
582 | static struct fscpos_data *fscpos_update_device(struct device *dev) | ||
583 | { | ||
584 | struct i2c_client *client = to_i2c_client(dev); | ||
585 | struct fscpos_data *data = i2c_get_clientdata(client); | ||
586 | |||
587 | mutex_lock(&data->update_lock); | ||
588 | |||
589 | if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { | ||
590 | int i; | ||
591 | |||
592 | dev_dbg(&client->dev, "Starting fscpos update\n"); | ||
593 | |||
594 | for (i = 0; i < 3; i++) { | ||
595 | data->temp_act[i] = fscpos_read_value(client, | ||
596 | FSCPOS_REG_TEMP_ACT[i]); | ||
597 | data->temp_status[i] = fscpos_read_value(client, | ||
598 | FSCPOS_REG_TEMP_STATE[i]); | ||
599 | data->fan_act[i] = fscpos_read_value(client, | ||
600 | FSCPOS_REG_FAN_ACT[i]); | ||
601 | data->fan_status[i] = fscpos_read_value(client, | ||
602 | FSCPOS_REG_FAN_STATE[i]); | ||
603 | data->fan_ripple[i] = fscpos_read_value(client, | ||
604 | FSCPOS_REG_FAN_RIPPLE[i]); | ||
605 | if (i < 2) { | ||
606 | /* fan2_min is not supported by the chip */ | ||
607 | data->pwm[i] = fscpos_read_value(client, | ||
608 | FSCPOS_REG_PWM[i]); | ||
609 | } | ||
610 | /* reset fan status if speed is back to > 0 */ | ||
611 | if (data->fan_status[i] != 0 && data->fan_act[i] > 0) { | ||
612 | reset_fan_alarm(client, i); | ||
613 | } | ||
614 | } | ||
615 | |||
616 | data->volt[0] = fscpos_read_value(client, FSCPOS_REG_VOLT_12); | ||
617 | data->volt[1] = fscpos_read_value(client, FSCPOS_REG_VOLT_5); | ||
618 | data->volt[2] = fscpos_read_value(client, FSCPOS_REG_VOLT_BATT); | ||
619 | |||
620 | data->wdog_preset = fscpos_read_value(client, | ||
621 | FSCPOS_REG_WDOG_PRESET); | ||
622 | data->wdog_state = fscpos_read_value(client, | ||
623 | FSCPOS_REG_WDOG_STATE); | ||
624 | data->wdog_control = fscpos_read_value(client, | ||
625 | FSCPOS_REG_WDOG_CONTROL); | ||
626 | |||
627 | data->global_event = fscpos_read_value(client, | ||
628 | FSCPOS_REG_EVENT_STATE); | ||
629 | |||
630 | data->last_updated = jiffies; | ||
631 | data->valid = 1; | ||
632 | } | ||
633 | mutex_unlock(&data->update_lock); | ||
634 | return data; | ||
635 | } | ||
636 | |||
637 | static int __init sm_fscpos_init(void) | ||
638 | { | ||
639 | return i2c_add_driver(&fscpos_driver); | ||
640 | } | ||
641 | |||
642 | static void __exit sm_fscpos_exit(void) | ||
643 | { | ||
644 | i2c_del_driver(&fscpos_driver); | ||
645 | } | ||
646 | |||
647 | MODULE_AUTHOR("Stefan Ott <stefan@desire.ch> based on work from Hermann Jung " | ||
648 | "<hej@odn.de>, Frodo Looijaard <frodol@dds.nl>" | ||
649 | " and Philip Edelbrock <phil@netroedge.com>"); | ||
650 | MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver"); | ||
651 | MODULE_LICENSE("GPL"); | ||
652 | |||
653 | module_init(sm_fscpos_init); | ||
654 | module_exit(sm_fscpos_exit); | ||
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c index 9386e2a39211..6c9a04136e0a 100644 --- a/drivers/hwmon/ltc4215.c +++ b/drivers/hwmon/ltc4215.c | |||
@@ -259,7 +259,7 @@ static int ltc4215_probe(struct i2c_client *client, | |||
259 | mutex_init(&data->update_lock); | 259 | mutex_init(&data->update_lock); |
260 | 260 | ||
261 | /* Initialize the LTC4215 chip */ | 261 | /* Initialize the LTC4215 chip */ |
262 | /* TODO */ | 262 | i2c_smbus_write_byte_data(client, LTC4215_FAULT, 0x00); |
263 | 263 | ||
264 | /* Register sysfs hooks */ | 264 | /* Register sysfs hooks */ |
265 | ret = sysfs_create_group(&client->dev.kobj, <c4215_group); | 265 | ret = sysfs_create_group(&client->dev.kobj, <c4215_group); |
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index 034b2c515848..e38964333612 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c | |||
@@ -382,7 +382,8 @@ static int ltc4245_probe(struct i2c_client *client, | |||
382 | mutex_init(&data->update_lock); | 382 | mutex_init(&data->update_lock); |
383 | 383 | ||
384 | /* Initialize the LTC4245 chip */ | 384 | /* Initialize the LTC4245 chip */ |
385 | /* TODO */ | 385 | i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00); |
386 | i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00); | ||
386 | 387 | ||
387 | /* Register sysfs hooks */ | 388 | /* Register sysfs hooks */ |
388 | ret = sysfs_create_group(&client->dev.kobj, <c4245_group); | 389 | ret = sysfs_create_group(&client->dev.kobj, <c4245_group); |
diff --git a/drivers/input/input.c b/drivers/input/input.c index 556539d617a4..e828aab7dace 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/types.h> | ||
14 | #include <linux/input.h> | 15 | #include <linux/input.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/random.h> | 17 | #include <linux/random.h> |
@@ -514,7 +515,7 @@ static void input_disconnect_device(struct input_dev *dev) | |||
514 | * that there are no threads in the middle of input_open_device() | 515 | * that there are no threads in the middle of input_open_device() |
515 | */ | 516 | */ |
516 | mutex_lock(&dev->mutex); | 517 | mutex_lock(&dev->mutex); |
517 | dev->going_away = 1; | 518 | dev->going_away = true; |
518 | mutex_unlock(&dev->mutex); | 519 | mutex_unlock(&dev->mutex); |
519 | 520 | ||
520 | spin_lock_irq(&dev->event_lock); | 521 | spin_lock_irq(&dev->event_lock); |
@@ -1259,10 +1260,71 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) | |||
1259 | return 0; | 1260 | return 0; |
1260 | } | 1261 | } |
1261 | 1262 | ||
1263 | #define INPUT_DO_TOGGLE(dev, type, bits, on) \ | ||
1264 | do { \ | ||
1265 | int i; \ | ||
1266 | if (!test_bit(EV_##type, dev->evbit)) \ | ||
1267 | break; \ | ||
1268 | for (i = 0; i < type##_MAX; i++) { \ | ||
1269 | if (!test_bit(i, dev->bits##bit) || \ | ||
1270 | !test_bit(i, dev->bits)) \ | ||
1271 | continue; \ | ||
1272 | dev->event(dev, EV_##type, i, on); \ | ||
1273 | } \ | ||
1274 | } while (0) | ||
1275 | |||
1276 | static void input_dev_reset(struct input_dev *dev, bool activate) | ||
1277 | { | ||
1278 | if (!dev->event) | ||
1279 | return; | ||
1280 | |||
1281 | INPUT_DO_TOGGLE(dev, LED, led, activate); | ||
1282 | INPUT_DO_TOGGLE(dev, SND, snd, activate); | ||
1283 | |||
1284 | if (activate && test_bit(EV_REP, dev->evbit)) { | ||
1285 | dev->event(dev, EV_REP, REP_PERIOD, dev->rep[REP_PERIOD]); | ||
1286 | dev->event(dev, EV_REP, REP_DELAY, dev->rep[REP_DELAY]); | ||
1287 | } | ||
1288 | } | ||
1289 | |||
1290 | #ifdef CONFIG_PM | ||
1291 | static int input_dev_suspend(struct device *dev) | ||
1292 | { | ||
1293 | struct input_dev *input_dev = to_input_dev(dev); | ||
1294 | |||
1295 | mutex_lock(&input_dev->mutex); | ||
1296 | input_dev_reset(input_dev, false); | ||
1297 | mutex_unlock(&input_dev->mutex); | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | static int input_dev_resume(struct device *dev) | ||
1303 | { | ||
1304 | struct input_dev *input_dev = to_input_dev(dev); | ||
1305 | |||
1306 | mutex_lock(&input_dev->mutex); | ||
1307 | input_dev_reset(input_dev, true); | ||
1308 | mutex_unlock(&input_dev->mutex); | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | static const struct dev_pm_ops input_dev_pm_ops = { | ||
1314 | .suspend = input_dev_suspend, | ||
1315 | .resume = input_dev_resume, | ||
1316 | .poweroff = input_dev_suspend, | ||
1317 | .restore = input_dev_resume, | ||
1318 | }; | ||
1319 | #endif /* CONFIG_PM */ | ||
1320 | |||
1262 | static struct device_type input_dev_type = { | 1321 | static struct device_type input_dev_type = { |
1263 | .groups = input_dev_attr_groups, | 1322 | .groups = input_dev_attr_groups, |
1264 | .release = input_dev_release, | 1323 | .release = input_dev_release, |
1265 | .uevent = input_dev_uevent, | 1324 | .uevent = input_dev_uevent, |
1325 | #ifdef CONFIG_PM | ||
1326 | .pm = &input_dev_pm_ops, | ||
1327 | #endif | ||
1266 | }; | 1328 | }; |
1267 | 1329 | ||
1268 | static char *input_devnode(struct device *dev, mode_t *mode) | 1330 | static char *input_devnode(struct device *dev, mode_t *mode) |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 3525c19be428..ee98b1bc5d89 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -24,6 +24,16 @@ config KEYBOARD_AAED2000 | |||
24 | To compile this driver as a module, choose M here: the | 24 | To compile this driver as a module, choose M here: the |
25 | module will be called aaed2000_kbd. | 25 | module will be called aaed2000_kbd. |
26 | 26 | ||
27 | config KEYBOARD_ADP5588 | ||
28 | tristate "ADP5588 I2C QWERTY Keypad and IO Expander" | ||
29 | depends on I2C | ||
30 | help | ||
31 | Say Y here if you want to use a ADP5588 attached to your | ||
32 | system I2C bus. | ||
33 | |||
34 | To compile this driver as a module, choose M here: the | ||
35 | module will be called adp5588-keys. | ||
36 | |||
27 | config KEYBOARD_AMIGA | 37 | config KEYBOARD_AMIGA |
28 | tristate "Amiga keyboard" | 38 | tristate "Amiga keyboard" |
29 | depends on AMIGA | 39 | depends on AMIGA |
@@ -104,6 +114,16 @@ config KEYBOARD_ATKBD_RDI_KEYCODES | |||
104 | right-hand column will be interpreted as the key shown in the | 114 | right-hand column will be interpreted as the key shown in the |
105 | left-hand column. | 115 | left-hand column. |
106 | 116 | ||
117 | config QT2160 | ||
118 | tristate "Atmel AT42QT2160 Touch Sensor Chip" | ||
119 | depends on I2C && EXPERIMENTAL | ||
120 | help | ||
121 | If you say yes here you get support for Atmel AT42QT2160 Touch | ||
122 | Sensor chip as a keyboard input. | ||
123 | |||
124 | This driver can also be built as a module. If so, the module | ||
125 | will be called qt2160. | ||
126 | |||
107 | config KEYBOARD_BFIN | 127 | config KEYBOARD_BFIN |
108 | tristate "Blackfin BF54x keypad support" | 128 | tristate "Blackfin BF54x keypad support" |
109 | depends on (BF54x && !BF544) | 129 | depends on (BF54x && !BF544) |
@@ -251,6 +271,17 @@ config KEYBOARD_MAPLE | |||
251 | To compile this driver as a module, choose M here: the | 271 | To compile this driver as a module, choose M here: the |
252 | module will be called maple_keyb. | 272 | module will be called maple_keyb. |
253 | 273 | ||
274 | config KEYBOARD_MAX7359 | ||
275 | tristate "Maxim MAX7359 Key Switch Controller" | ||
276 | depends on I2C | ||
277 | help | ||
278 | If you say yes here you get support for the Maxim MAX7359 Key | ||
279 | Switch Controller chip. This providers microprocessors with | ||
280 | management of up to 64 key switches | ||
281 | |||
282 | To compile this driver as a module, choose M here: the | ||
283 | module will be called max7359_keypad. | ||
284 | |||
254 | config KEYBOARD_NEWTON | 285 | config KEYBOARD_NEWTON |
255 | tristate "Newton keyboard" | 286 | tristate "Newton keyboard" |
256 | select SERIO | 287 | select SERIO |
@@ -260,6 +291,15 @@ config KEYBOARD_NEWTON | |||
260 | To compile this driver as a module, choose M here: the | 291 | To compile this driver as a module, choose M here: the |
261 | module will be called newtonkbd. | 292 | module will be called newtonkbd. |
262 | 293 | ||
294 | config KEYBOARD_OPENCORES | ||
295 | tristate "OpenCores Keyboard Controller" | ||
296 | help | ||
297 | Say Y here if you want to use the OpenCores Keyboard Controller | ||
298 | http://www.opencores.org/project,keyboardcontroller | ||
299 | |||
300 | To compile this driver as a module, choose M here; the | ||
301 | module will be called opencores-kbd. | ||
302 | |||
263 | config KEYBOARD_PXA27x | 303 | config KEYBOARD_PXA27x |
264 | tristate "PXA27x/PXA3xx keypad support" | 304 | tristate "PXA27x/PXA3xx keypad support" |
265 | depends on PXA27x || PXA3xx | 305 | depends on PXA27x || PXA3xx |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 8a7a22b30266..babad5e58b77 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
8 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o | ||
8 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 9 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
9 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 10 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
10 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
@@ -21,10 +22,13 @@ obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o | |||
21 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | 22 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o |
22 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | 23 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o |
23 | obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o | 24 | obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o |
25 | obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o | ||
24 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 26 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
25 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 27 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
28 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o | ||
26 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | 29 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o |
27 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 30 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
31 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | ||
28 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 32 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
29 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | 33 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o |
30 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 34 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c new file mode 100644 index 000000000000..d48c808d5928 --- /dev/null +++ b/drivers/input/keyboard/adp5588-keys.c | |||
@@ -0,0 +1,361 @@ | |||
1 | /* | ||
2 | * File: drivers/input/keyboard/adp5588_keys.c | ||
3 | * Description: keypad driver for ADP5588 I2C QWERTY Keypad and IO Expander | ||
4 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
5 | * | ||
6 | * Copyright (C) 2008-2009 Analog Devices Inc. | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/version.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/i2c.h> | ||
21 | |||
22 | #include <linux/i2c/adp5588.h> | ||
23 | |||
24 | /* Configuration Register1 */ | ||
25 | #define AUTO_INC (1 << 7) | ||
26 | #define GPIEM_CFG (1 << 6) | ||
27 | #define OVR_FLOW_M (1 << 5) | ||
28 | #define INT_CFG (1 << 4) | ||
29 | #define OVR_FLOW_IEN (1 << 3) | ||
30 | #define K_LCK_IM (1 << 2) | ||
31 | #define GPI_IEN (1 << 1) | ||
32 | #define KE_IEN (1 << 0) | ||
33 | |||
34 | /* Interrupt Status Register */ | ||
35 | #define CMP2_INT (1 << 5) | ||
36 | #define CMP1_INT (1 << 4) | ||
37 | #define OVR_FLOW_INT (1 << 3) | ||
38 | #define K_LCK_INT (1 << 2) | ||
39 | #define GPI_INT (1 << 1) | ||
40 | #define KE_INT (1 << 0) | ||
41 | |||
42 | /* Key Lock and Event Counter Register */ | ||
43 | #define K_LCK_EN (1 << 6) | ||
44 | #define LCK21 0x30 | ||
45 | #define KEC 0xF | ||
46 | |||
47 | /* Key Event Register xy */ | ||
48 | #define KEY_EV_PRESSED (1 << 7) | ||
49 | #define KEY_EV_MASK (0x7F) | ||
50 | |||
51 | #define KP_SEL(x) (0xFFFF >> (16 - x)) /* 2^x-1 */ | ||
52 | |||
53 | #define KEYP_MAX_EVENT 10 | ||
54 | |||
55 | /* | ||
56 | * Early pre 4.0 Silicon required to delay readout by at least 25ms, | ||
57 | * since the Event Counter Register updated 25ms after the interrupt | ||
58 | * asserted. | ||
59 | */ | ||
60 | #define WA_DELAYED_READOUT_REVID(rev) ((rev) < 4) | ||
61 | |||
62 | struct adp5588_kpad { | ||
63 | struct i2c_client *client; | ||
64 | struct input_dev *input; | ||
65 | struct delayed_work work; | ||
66 | unsigned long delay; | ||
67 | unsigned short keycode[ADP5588_KEYMAPSIZE]; | ||
68 | }; | ||
69 | |||
70 | static int adp5588_read(struct i2c_client *client, u8 reg) | ||
71 | { | ||
72 | int ret = i2c_smbus_read_byte_data(client, reg); | ||
73 | |||
74 | if (ret < 0) | ||
75 | dev_err(&client->dev, "Read Error\n"); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | static int adp5588_write(struct i2c_client *client, u8 reg, u8 val) | ||
81 | { | ||
82 | return i2c_smbus_write_byte_data(client, reg, val); | ||
83 | } | ||
84 | |||
85 | static void adp5588_work(struct work_struct *work) | ||
86 | { | ||
87 | struct adp5588_kpad *kpad = container_of(work, | ||
88 | struct adp5588_kpad, work.work); | ||
89 | struct i2c_client *client = kpad->client; | ||
90 | int i, key, status, ev_cnt; | ||
91 | |||
92 | status = adp5588_read(client, INT_STAT); | ||
93 | |||
94 | if (status & OVR_FLOW_INT) /* Unlikely and should never happen */ | ||
95 | dev_err(&client->dev, "Event Overflow Error\n"); | ||
96 | |||
97 | if (status & KE_INT) { | ||
98 | ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC; | ||
99 | if (ev_cnt) { | ||
100 | for (i = 0; i < ev_cnt; i++) { | ||
101 | key = adp5588_read(client, Key_EVENTA + i); | ||
102 | input_report_key(kpad->input, | ||
103 | kpad->keycode[(key & KEY_EV_MASK) - 1], | ||
104 | key & KEY_EV_PRESSED); | ||
105 | } | ||
106 | input_sync(kpad->input); | ||
107 | } | ||
108 | } | ||
109 | adp5588_write(client, INT_STAT, status); /* Status is W1C */ | ||
110 | } | ||
111 | |||
112 | static irqreturn_t adp5588_irq(int irq, void *handle) | ||
113 | { | ||
114 | struct adp5588_kpad *kpad = handle; | ||
115 | |||
116 | /* | ||
117 | * use keventd context to read the event fifo registers | ||
118 | * Schedule readout at least 25ms after notification for | ||
119 | * REVID < 4 | ||
120 | */ | ||
121 | |||
122 | schedule_delayed_work(&kpad->work, kpad->delay); | ||
123 | |||
124 | return IRQ_HANDLED; | ||
125 | } | ||
126 | |||
127 | static int __devinit adp5588_setup(struct i2c_client *client) | ||
128 | { | ||
129 | struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; | ||
130 | int i, ret; | ||
131 | |||
132 | ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows)); | ||
133 | ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF); | ||
134 | ret |= adp5588_write(client, KP_GPIO3, KP_SEL(pdata->cols) >> 8); | ||
135 | |||
136 | if (pdata->en_keylock) { | ||
137 | ret |= adp5588_write(client, UNLOCK1, pdata->unlock_key1); | ||
138 | ret |= adp5588_write(client, UNLOCK2, pdata->unlock_key2); | ||
139 | ret |= adp5588_write(client, KEY_LCK_EC_STAT, K_LCK_EN); | ||
140 | } | ||
141 | |||
142 | for (i = 0; i < KEYP_MAX_EVENT; i++) | ||
143 | ret |= adp5588_read(client, Key_EVENTA); | ||
144 | |||
145 | ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT | | ||
146 | OVR_FLOW_INT | K_LCK_INT | | ||
147 | GPI_INT | KE_INT); /* Status is W1C */ | ||
148 | |||
149 | ret |= adp5588_write(client, CFG, INT_CFG | OVR_FLOW_IEN | KE_IEN); | ||
150 | |||
151 | if (ret < 0) { | ||
152 | dev_err(&client->dev, "Write Error\n"); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int __devinit adp5588_probe(struct i2c_client *client, | ||
160 | const struct i2c_device_id *id) | ||
161 | { | ||
162 | struct adp5588_kpad *kpad; | ||
163 | struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; | ||
164 | struct input_dev *input; | ||
165 | unsigned int revid; | ||
166 | int ret, i; | ||
167 | int error; | ||
168 | |||
169 | if (!i2c_check_functionality(client->adapter, | ||
170 | I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
171 | dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); | ||
172 | return -EIO; | ||
173 | } | ||
174 | |||
175 | if (!pdata) { | ||
176 | dev_err(&client->dev, "no platform data?\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | ||
181 | dev_err(&client->dev, "no rows, cols or keymap from pdata\n"); | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | if (pdata->keymapsize != ADP5588_KEYMAPSIZE) { | ||
186 | dev_err(&client->dev, "invalid keymapsize\n"); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | |||
190 | if (!client->irq) { | ||
191 | dev_err(&client->dev, "no IRQ?\n"); | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | |||
195 | kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); | ||
196 | input = input_allocate_device(); | ||
197 | if (!kpad || !input) { | ||
198 | error = -ENOMEM; | ||
199 | goto err_free_mem; | ||
200 | } | ||
201 | |||
202 | kpad->client = client; | ||
203 | kpad->input = input; | ||
204 | INIT_DELAYED_WORK(&kpad->work, adp5588_work); | ||
205 | |||
206 | ret = adp5588_read(client, DEV_ID); | ||
207 | if (ret < 0) { | ||
208 | error = ret; | ||
209 | goto err_free_mem; | ||
210 | } | ||
211 | |||
212 | revid = (u8) ret & ADP5588_DEVICE_ID_MASK; | ||
213 | if (WA_DELAYED_READOUT_REVID(revid)) | ||
214 | kpad->delay = msecs_to_jiffies(30); | ||
215 | |||
216 | input->name = client->name; | ||
217 | input->phys = "adp5588-keys/input0"; | ||
218 | input->dev.parent = &client->dev; | ||
219 | |||
220 | input_set_drvdata(input, kpad); | ||
221 | |||
222 | input->id.bustype = BUS_I2C; | ||
223 | input->id.vendor = 0x0001; | ||
224 | input->id.product = 0x0001; | ||
225 | input->id.version = revid; | ||
226 | |||
227 | input->keycodesize = sizeof(kpad->keycode[0]); | ||
228 | input->keycodemax = pdata->keymapsize; | ||
229 | input->keycode = kpad->keycode; | ||
230 | |||
231 | memcpy(kpad->keycode, pdata->keymap, | ||
232 | pdata->keymapsize * input->keycodesize); | ||
233 | |||
234 | /* setup input device */ | ||
235 | __set_bit(EV_KEY, input->evbit); | ||
236 | |||
237 | if (pdata->repeat) | ||
238 | __set_bit(EV_REP, input->evbit); | ||
239 | |||
240 | for (i = 0; i < input->keycodemax; i++) | ||
241 | __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit); | ||
242 | __clear_bit(KEY_RESERVED, input->keybit); | ||
243 | |||
244 | error = input_register_device(input); | ||
245 | if (error) { | ||
246 | dev_err(&client->dev, "unable to register input device\n"); | ||
247 | goto err_free_mem; | ||
248 | } | ||
249 | |||
250 | error = request_irq(client->irq, adp5588_irq, | ||
251 | IRQF_TRIGGER_FALLING | IRQF_DISABLED, | ||
252 | client->dev.driver->name, kpad); | ||
253 | if (error) { | ||
254 | dev_err(&client->dev, "irq %d busy?\n", client->irq); | ||
255 | goto err_unreg_dev; | ||
256 | } | ||
257 | |||
258 | error = adp5588_setup(client); | ||
259 | if (error) | ||
260 | goto err_free_irq; | ||
261 | |||
262 | device_init_wakeup(&client->dev, 1); | ||
263 | i2c_set_clientdata(client, kpad); | ||
264 | |||
265 | dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq); | ||
266 | return 0; | ||
267 | |||
268 | err_free_irq: | ||
269 | free_irq(client->irq, kpad); | ||
270 | err_unreg_dev: | ||
271 | input_unregister_device(input); | ||
272 | input = NULL; | ||
273 | err_free_mem: | ||
274 | input_free_device(input); | ||
275 | kfree(kpad); | ||
276 | |||
277 | return error; | ||
278 | } | ||
279 | |||
280 | static int __devexit adp5588_remove(struct i2c_client *client) | ||
281 | { | ||
282 | struct adp5588_kpad *kpad = i2c_get_clientdata(client); | ||
283 | |||
284 | adp5588_write(client, CFG, 0); | ||
285 | free_irq(client->irq, kpad); | ||
286 | cancel_delayed_work_sync(&kpad->work); | ||
287 | input_unregister_device(kpad->input); | ||
288 | i2c_set_clientdata(client, NULL); | ||
289 | kfree(kpad); | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | #ifdef CONFIG_PM | ||
295 | static int adp5588_suspend(struct device *dev) | ||
296 | { | ||
297 | struct adp5588_kpad *kpad = dev_get_drvdata(dev); | ||
298 | struct i2c_client *client = kpad->client; | ||
299 | |||
300 | disable_irq(client->irq); | ||
301 | cancel_delayed_work_sync(&kpad->work); | ||
302 | |||
303 | if (device_may_wakeup(&client->dev)) | ||
304 | enable_irq_wake(client->irq); | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int adp5588_resume(struct device *dev) | ||
310 | { | ||
311 | struct adp5588_kpad *kpad = dev_get_drvdata(dev); | ||
312 | struct i2c_client *client = kpad->client; | ||
313 | |||
314 | if (device_may_wakeup(&client->dev)) | ||
315 | disable_irq_wake(client->irq); | ||
316 | |||
317 | enable_irq(client->irq); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static struct dev_pm_ops adp5588_dev_pm_ops = { | ||
323 | .suspend = adp5588_suspend, | ||
324 | .resume = adp5588_resume, | ||
325 | }; | ||
326 | #endif | ||
327 | |||
328 | static const struct i2c_device_id adp5588_id[] = { | ||
329 | { KBUILD_MODNAME, 0 }, | ||
330 | { } | ||
331 | }; | ||
332 | MODULE_DEVICE_TABLE(i2c, adp5588_id); | ||
333 | |||
334 | static struct i2c_driver adp5588_driver = { | ||
335 | .driver = { | ||
336 | .name = KBUILD_MODNAME, | ||
337 | #ifdef CONFIG_PM | ||
338 | .pm = &adp5588_dev_pm_ops, | ||
339 | #endif | ||
340 | }, | ||
341 | .probe = adp5588_probe, | ||
342 | .remove = __devexit_p(adp5588_remove), | ||
343 | .id_table = adp5588_id, | ||
344 | }; | ||
345 | |||
346 | static int __init adp5588_init(void) | ||
347 | { | ||
348 | return i2c_add_driver(&adp5588_driver); | ||
349 | } | ||
350 | module_init(adp5588_init); | ||
351 | |||
352 | static void __exit adp5588_exit(void) | ||
353 | { | ||
354 | i2c_del_driver(&adp5588_driver); | ||
355 | } | ||
356 | module_exit(adp5588_exit); | ||
357 | |||
358 | MODULE_LICENSE("GPL"); | ||
359 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
360 | MODULE_DESCRIPTION("ADP5588 Keypad driver"); | ||
361 | MODULE_ALIAS("platform:adp5588-keys"); | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index adb09e2ba394..4709e15af607 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -773,23 +773,6 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra | |||
773 | static int atkbd_activate(struct atkbd *atkbd) | 773 | static int atkbd_activate(struct atkbd *atkbd) |
774 | { | 774 | { |
775 | struct ps2dev *ps2dev = &atkbd->ps2dev; | 775 | struct ps2dev *ps2dev = &atkbd->ps2dev; |
776 | unsigned char param[1]; | ||
777 | |||
778 | /* | ||
779 | * Set the LEDs to a defined state. | ||
780 | */ | ||
781 | |||
782 | param[0] = 0; | ||
783 | if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS)) | ||
784 | return -1; | ||
785 | |||
786 | /* | ||
787 | * Set autorepeat to fastest possible. | ||
788 | */ | ||
789 | |||
790 | param[0] = 0; | ||
791 | if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP)) | ||
792 | return -1; | ||
793 | 776 | ||
794 | /* | 777 | /* |
795 | * Enable the keyboard to receive keystrokes. | 778 | * Enable the keyboard to receive keystrokes. |
@@ -1158,14 +1141,6 @@ static int atkbd_reconnect(struct serio *serio) | |||
1158 | return -1; | 1141 | return -1; |
1159 | 1142 | ||
1160 | atkbd_activate(atkbd); | 1143 | atkbd_activate(atkbd); |
1161 | |||
1162 | /* | ||
1163 | * Restore repeat rate and LEDs (that were reset by atkbd_activate) | ||
1164 | * to pre-resume state | ||
1165 | */ | ||
1166 | if (!atkbd->softrepeat) | ||
1167 | atkbd_set_repeat_rate(atkbd); | ||
1168 | atkbd_set_leds(atkbd); | ||
1169 | } | 1144 | } |
1170 | 1145 | ||
1171 | atkbd_enable(atkbd); | 1146 | atkbd_enable(atkbd); |
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c new file mode 100644 index 000000000000..3b5b948eba39 --- /dev/null +++ b/drivers/input/keyboard/max7359_keypad.c | |||
@@ -0,0 +1,330 @@ | |||
1 | /* | ||
2 | * max7359_keypad.c - MAX7359 Key Switch Controller Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics | ||
5 | * Kim Kyuwon <q1.kim@samsung.com> | ||
6 | * | ||
7 | * Based on pxa27x_keypad.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * Datasheet: http://www.maxim-ic.com/quick_view2.cfm/qv_pk/5456 | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/input/matrix_keypad.h> | ||
21 | |||
22 | #define MAX7359_MAX_KEY_ROWS 8 | ||
23 | #define MAX7359_MAX_KEY_COLS 8 | ||
24 | #define MAX7359_MAX_KEY_NUM (MAX7359_MAX_KEY_ROWS * MAX7359_MAX_KEY_COLS) | ||
25 | #define MAX7359_ROW_SHIFT 3 | ||
26 | |||
27 | /* | ||
28 | * MAX7359 registers | ||
29 | */ | ||
30 | #define MAX7359_REG_KEYFIFO 0x00 | ||
31 | #define MAX7359_REG_CONFIG 0x01 | ||
32 | #define MAX7359_REG_DEBOUNCE 0x02 | ||
33 | #define MAX7359_REG_INTERRUPT 0x03 | ||
34 | #define MAX7359_REG_PORTS 0x04 | ||
35 | #define MAX7359_REG_KEYREP 0x05 | ||
36 | #define MAX7359_REG_SLEEP 0x06 | ||
37 | |||
38 | /* | ||
39 | * Configuration register bits | ||
40 | */ | ||
41 | #define MAX7359_CFG_SLEEP (1 << 7) | ||
42 | #define MAX7359_CFG_INTERRUPT (1 << 5) | ||
43 | #define MAX7359_CFG_KEY_RELEASE (1 << 3) | ||
44 | #define MAX7359_CFG_WAKEUP (1 << 1) | ||
45 | #define MAX7359_CFG_TIMEOUT (1 << 0) | ||
46 | |||
47 | /* | ||
48 | * Autosleep register values (ms) | ||
49 | */ | ||
50 | #define MAX7359_AUTOSLEEP_8192 0x01 | ||
51 | #define MAX7359_AUTOSLEEP_4096 0x02 | ||
52 | #define MAX7359_AUTOSLEEP_2048 0x03 | ||
53 | #define MAX7359_AUTOSLEEP_1024 0x04 | ||
54 | #define MAX7359_AUTOSLEEP_512 0x05 | ||
55 | #define MAX7359_AUTOSLEEP_256 0x06 | ||
56 | |||
57 | struct max7359_keypad { | ||
58 | /* matrix key code map */ | ||
59 | unsigned short keycodes[MAX7359_MAX_KEY_NUM]; | ||
60 | |||
61 | struct input_dev *input_dev; | ||
62 | struct i2c_client *client; | ||
63 | }; | ||
64 | |||
65 | static int max7359_write_reg(struct i2c_client *client, u8 reg, u8 val) | ||
66 | { | ||
67 | int ret = i2c_smbus_write_byte_data(client, reg, val); | ||
68 | |||
69 | if (ret < 0) | ||
70 | dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", | ||
71 | __func__, reg, val, ret); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | static int max7359_read_reg(struct i2c_client *client, int reg) | ||
76 | { | ||
77 | int ret = i2c_smbus_read_byte_data(client, reg); | ||
78 | |||
79 | if (ret < 0) | ||
80 | dev_err(&client->dev, "%s: reg 0x%x, err %d\n", | ||
81 | __func__, reg, ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static void max7359_build_keycode(struct max7359_keypad *keypad, | ||
86 | const struct matrix_keymap_data *keymap_data) | ||
87 | { | ||
88 | struct input_dev *input_dev = keypad->input_dev; | ||
89 | int i; | ||
90 | |||
91 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
92 | unsigned int key = keymap_data->keymap[i]; | ||
93 | unsigned int row = KEY_ROW(key); | ||
94 | unsigned int col = KEY_COL(key); | ||
95 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, | ||
96 | MAX7359_ROW_SHIFT); | ||
97 | unsigned short keycode = KEY_VAL(key); | ||
98 | |||
99 | keypad->keycodes[scancode] = keycode; | ||
100 | __set_bit(keycode, input_dev->keybit); | ||
101 | } | ||
102 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
103 | } | ||
104 | |||
105 | /* runs in an IRQ thread -- can (and will!) sleep */ | ||
106 | static irqreturn_t max7359_interrupt(int irq, void *dev_id) | ||
107 | { | ||
108 | struct max7359_keypad *keypad = dev_id; | ||
109 | struct input_dev *input_dev = keypad->input_dev; | ||
110 | int val, row, col, release, code; | ||
111 | |||
112 | val = max7359_read_reg(keypad->client, MAX7359_REG_KEYFIFO); | ||
113 | row = val & 0x7; | ||
114 | col = (val >> 3) & 0x7; | ||
115 | release = val & 0x40; | ||
116 | |||
117 | code = MATRIX_SCAN_CODE(row, col, MAX7359_ROW_SHIFT); | ||
118 | |||
119 | dev_dbg(&keypad->client->dev, | ||
120 | "key[%d:%d] %s\n", row, col, release ? "release" : "press"); | ||
121 | |||
122 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
123 | input_report_key(input_dev, keypad->keycodes[code], !release); | ||
124 | input_sync(input_dev); | ||
125 | |||
126 | return IRQ_HANDLED; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Let MAX7359 fall into a deep sleep: | ||
131 | * If no keys are pressed, enter sleep mode for 8192 ms. And if any | ||
132 | * key is pressed, the MAX7359 returns to normal operating mode. | ||
133 | */ | ||
134 | static inline void max7359_fall_deepsleep(struct i2c_client *client) | ||
135 | { | ||
136 | max7359_write_reg(client, MAX7359_REG_SLEEP, MAX7359_AUTOSLEEP_8192); | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Let MAX7359 take a catnap: | ||
141 | * Autosleep just for 256 ms. | ||
142 | */ | ||
143 | static inline void max7359_take_catnap(struct i2c_client *client) | ||
144 | { | ||
145 | max7359_write_reg(client, MAX7359_REG_SLEEP, MAX7359_AUTOSLEEP_256); | ||
146 | } | ||
147 | |||
148 | static int max7359_open(struct input_dev *dev) | ||
149 | { | ||
150 | struct max7359_keypad *keypad = input_get_drvdata(dev); | ||
151 | |||
152 | max7359_take_catnap(keypad->client); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static void max7359_close(struct input_dev *dev) | ||
158 | { | ||
159 | struct max7359_keypad *keypad = input_get_drvdata(dev); | ||
160 | |||
161 | max7359_fall_deepsleep(keypad->client); | ||
162 | } | ||
163 | |||
164 | static void max7359_initialize(struct i2c_client *client) | ||
165 | { | ||
166 | max7359_write_reg(client, MAX7359_REG_CONFIG, | ||
167 | MAX7359_CFG_INTERRUPT | /* Irq clears after host read */ | ||
168 | MAX7359_CFG_KEY_RELEASE | /* Key release enable */ | ||
169 | MAX7359_CFG_WAKEUP); /* Key press wakeup enable */ | ||
170 | |||
171 | /* Full key-scan functionality */ | ||
172 | max7359_write_reg(client, MAX7359_REG_DEBOUNCE, 0x1F); | ||
173 | |||
174 | /* nINT asserts every debounce cycles */ | ||
175 | max7359_write_reg(client, MAX7359_REG_INTERRUPT, 0x01); | ||
176 | |||
177 | max7359_fall_deepsleep(client); | ||
178 | } | ||
179 | |||
180 | static int __devinit max7359_probe(struct i2c_client *client, | ||
181 | const struct i2c_device_id *id) | ||
182 | { | ||
183 | const struct matrix_keymap_data *keymap_data = client->dev.platform_data; | ||
184 | struct max7359_keypad *keypad; | ||
185 | struct input_dev *input_dev; | ||
186 | int ret; | ||
187 | int error; | ||
188 | |||
189 | if (!client->irq) { | ||
190 | dev_err(&client->dev, "The irq number should not be zero\n"); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | /* Detect MAX7359: The initial Keys FIFO value is '0x3F' */ | ||
195 | ret = max7359_read_reg(client, MAX7359_REG_KEYFIFO); | ||
196 | if (ret < 0) { | ||
197 | dev_err(&client->dev, "failed to detect device\n"); | ||
198 | return -ENODEV; | ||
199 | } | ||
200 | |||
201 | dev_dbg(&client->dev, "keys FIFO is 0x%02x\n", ret); | ||
202 | |||
203 | keypad = kzalloc(sizeof(struct max7359_keypad), GFP_KERNEL); | ||
204 | input_dev = input_allocate_device(); | ||
205 | if (!keypad || !input_dev) { | ||
206 | dev_err(&client->dev, "failed to allocate memory\n"); | ||
207 | error = -ENOMEM; | ||
208 | goto failed_free_mem; | ||
209 | } | ||
210 | |||
211 | keypad->client = client; | ||
212 | keypad->input_dev = input_dev; | ||
213 | |||
214 | input_dev->name = client->name; | ||
215 | input_dev->id.bustype = BUS_I2C; | ||
216 | input_dev->open = max7359_open; | ||
217 | input_dev->close = max7359_close; | ||
218 | input_dev->dev.parent = &client->dev; | ||
219 | |||
220 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
221 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
222 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
223 | input_dev->keycode = keypad->keycodes; | ||
224 | |||
225 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
226 | input_set_drvdata(input_dev, keypad); | ||
227 | |||
228 | max7359_build_keycode(keypad, keymap_data); | ||
229 | |||
230 | error = request_threaded_irq(client->irq, NULL, max7359_interrupt, | ||
231 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
232 | client->name, keypad); | ||
233 | if (error) { | ||
234 | dev_err(&client->dev, "failed to register interrupt\n"); | ||
235 | goto failed_free_mem; | ||
236 | } | ||
237 | |||
238 | /* Register the input device */ | ||
239 | error = input_register_device(input_dev); | ||
240 | if (error) { | ||
241 | dev_err(&client->dev, "failed to register input device\n"); | ||
242 | goto failed_free_irq; | ||
243 | } | ||
244 | |||
245 | /* Initialize MAX7359 */ | ||
246 | max7359_initialize(client); | ||
247 | |||
248 | i2c_set_clientdata(client, keypad); | ||
249 | device_init_wakeup(&client->dev, 1); | ||
250 | |||
251 | return 0; | ||
252 | |||
253 | failed_free_irq: | ||
254 | free_irq(client->irq, keypad); | ||
255 | failed_free_mem: | ||
256 | input_free_device(input_dev); | ||
257 | kfree(keypad); | ||
258 | return error; | ||
259 | } | ||
260 | |||
261 | static int __devexit max7359_remove(struct i2c_client *client) | ||
262 | { | ||
263 | struct max7359_keypad *keypad = i2c_get_clientdata(client); | ||
264 | |||
265 | free_irq(client->irq, keypad); | ||
266 | input_unregister_device(keypad->input_dev); | ||
267 | i2c_set_clientdata(client, NULL); | ||
268 | kfree(keypad); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | #ifdef CONFIG_PM | ||
274 | static int max7359_suspend(struct i2c_client *client, pm_message_t mesg) | ||
275 | { | ||
276 | max7359_fall_deepsleep(client); | ||
277 | |||
278 | if (device_may_wakeup(&client->dev)) | ||
279 | enable_irq_wake(client->irq); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int max7359_resume(struct i2c_client *client) | ||
285 | { | ||
286 | if (device_may_wakeup(&client->dev)) | ||
287 | disable_irq_wake(client->irq); | ||
288 | |||
289 | /* Restore the default setting */ | ||
290 | max7359_take_catnap(client); | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | #else | ||
295 | #define max7359_suspend NULL | ||
296 | #define max7359_resume NULL | ||
297 | #endif | ||
298 | |||
299 | static const struct i2c_device_id max7359_ids[] = { | ||
300 | { "max7359", 0 }, | ||
301 | { } | ||
302 | }; | ||
303 | MODULE_DEVICE_TABLE(i2c, max7359_ids); | ||
304 | |||
305 | static struct i2c_driver max7359_i2c_driver = { | ||
306 | .driver = { | ||
307 | .name = "max7359", | ||
308 | }, | ||
309 | .probe = max7359_probe, | ||
310 | .remove = __devexit_p(max7359_remove), | ||
311 | .suspend = max7359_suspend, | ||
312 | .resume = max7359_resume, | ||
313 | .id_table = max7359_ids, | ||
314 | }; | ||
315 | |||
316 | static int __init max7359_init(void) | ||
317 | { | ||
318 | return i2c_add_driver(&max7359_i2c_driver); | ||
319 | } | ||
320 | module_init(max7359_init); | ||
321 | |||
322 | static void __exit max7359_exit(void) | ||
323 | { | ||
324 | i2c_del_driver(&max7359_i2c_driver); | ||
325 | } | ||
326 | module_exit(max7359_exit); | ||
327 | |||
328 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); | ||
329 | MODULE_DESCRIPTION("MAX7359 Key Switch Controller Driver"); | ||
330 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c new file mode 100644 index 000000000000..78cccddbf551 --- /dev/null +++ b/drivers/input/keyboard/opencores-kbd.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * OpenCores Keyboard Controller Driver | ||
3 | * http://www.opencores.org/project,keyboardcontroller | ||
4 | * | ||
5 | * Copyright 2007-2009 HV Sistemas S.L. | ||
6 | * | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/input.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/ioport.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | struct opencores_kbd { | ||
19 | struct input_dev *input; | ||
20 | struct resource *addr_res; | ||
21 | void __iomem *addr; | ||
22 | int irq; | ||
23 | unsigned short keycodes[128]; | ||
24 | }; | ||
25 | |||
26 | static irqreturn_t opencores_kbd_isr(int irq, void *dev_id) | ||
27 | { | ||
28 | struct opencores_kbd *opencores_kbd = dev_id; | ||
29 | struct input_dev *input = opencores_kbd->input; | ||
30 | unsigned char c; | ||
31 | |||
32 | c = readb(opencores_kbd->addr); | ||
33 | input_report_key(input, c & 0x7f, c & 0x80 ? 0 : 1); | ||
34 | input_sync(input); | ||
35 | |||
36 | return IRQ_HANDLED; | ||
37 | } | ||
38 | |||
39 | static int __devinit opencores_kbd_probe(struct platform_device *pdev) | ||
40 | { | ||
41 | struct input_dev *input; | ||
42 | struct opencores_kbd *opencores_kbd; | ||
43 | struct resource *res; | ||
44 | int irq, i, error; | ||
45 | |||
46 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
47 | if (!res) { | ||
48 | dev_err(&pdev->dev, "missing board memory resource\n"); | ||
49 | return -EINVAL; | ||
50 | } | ||
51 | |||
52 | irq = platform_get_irq(pdev, 0); | ||
53 | if (irq < 0) { | ||
54 | dev_err(&pdev->dev, "missing board IRQ resource\n"); | ||
55 | return -EINVAL; | ||
56 | } | ||
57 | |||
58 | opencores_kbd = kzalloc(sizeof(*opencores_kbd), GFP_KERNEL); | ||
59 | input = input_allocate_device(); | ||
60 | if (!opencores_kbd || !input) { | ||
61 | dev_err(&pdev->dev, "failed to allocate device structures\n"); | ||
62 | error = -ENOMEM; | ||
63 | goto err_free_mem; | ||
64 | } | ||
65 | |||
66 | opencores_kbd->addr_res = res; | ||
67 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
68 | if (!res) { | ||
69 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
70 | error = -EBUSY; | ||
71 | goto err_free_mem; | ||
72 | } | ||
73 | |||
74 | opencores_kbd->addr = ioremap(res->start, resource_size(res)); | ||
75 | if (!opencores_kbd->addr) { | ||
76 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
77 | error = -ENXIO; | ||
78 | goto err_rel_mem; | ||
79 | } | ||
80 | |||
81 | opencores_kbd->input = input; | ||
82 | opencores_kbd->irq = irq; | ||
83 | |||
84 | input->name = pdev->name; | ||
85 | input->phys = "opencores-kbd/input0"; | ||
86 | input->dev.parent = &pdev->dev; | ||
87 | |||
88 | input_set_drvdata(input, opencores_kbd); | ||
89 | |||
90 | input->id.bustype = BUS_HOST; | ||
91 | input->id.vendor = 0x0001; | ||
92 | input->id.product = 0x0001; | ||
93 | input->id.version = 0x0100; | ||
94 | |||
95 | input->keycode = opencores_kbd->keycodes; | ||
96 | input->keycodesize = sizeof(opencores_kbd->keycodes[0]); | ||
97 | input->keycodemax = ARRAY_SIZE(opencores_kbd->keycodes); | ||
98 | |||
99 | __set_bit(EV_KEY, input->evbit); | ||
100 | |||
101 | for (i = 0; i < ARRAY_SIZE(opencores_kbd->keycodes); i++) { | ||
102 | /* | ||
103 | * OpenCores controller happens to have scancodes match | ||
104 | * our KEY_* definitions. | ||
105 | */ | ||
106 | opencores_kbd->keycodes[i] = i; | ||
107 | __set_bit(opencores_kbd->keycodes[i], input->keybit); | ||
108 | } | ||
109 | __clear_bit(KEY_RESERVED, input->keybit); | ||
110 | |||
111 | error = request_irq(irq, &opencores_kbd_isr, | ||
112 | IRQF_TRIGGER_RISING, pdev->name, opencores_kbd); | ||
113 | if (error) { | ||
114 | dev_err(&pdev->dev, "unable to claim irq %d\n", irq); | ||
115 | goto err_unmap_mem; | ||
116 | } | ||
117 | |||
118 | error = input_register_device(input); | ||
119 | if (error) { | ||
120 | dev_err(&pdev->dev, "unable to register input device\n"); | ||
121 | goto err_free_irq; | ||
122 | } | ||
123 | |||
124 | platform_set_drvdata(pdev, opencores_kbd); | ||
125 | |||
126 | return 0; | ||
127 | |||
128 | err_free_irq: | ||
129 | free_irq(irq, opencores_kbd); | ||
130 | err_unmap_mem: | ||
131 | iounmap(opencores_kbd->addr); | ||
132 | err_rel_mem: | ||
133 | release_mem_region(res->start, resource_size(res)); | ||
134 | err_free_mem: | ||
135 | input_free_device(input); | ||
136 | kfree(opencores_kbd); | ||
137 | |||
138 | return error; | ||
139 | } | ||
140 | |||
141 | static int __devexit opencores_kbd_remove(struct platform_device *pdev) | ||
142 | { | ||
143 | struct opencores_kbd *opencores_kbd = platform_get_drvdata(pdev); | ||
144 | |||
145 | free_irq(opencores_kbd->irq, opencores_kbd); | ||
146 | |||
147 | iounmap(opencores_kbd->addr); | ||
148 | release_mem_region(opencores_kbd->addr_res->start, | ||
149 | resource_size(opencores_kbd->addr_res)); | ||
150 | input_unregister_device(opencores_kbd->input); | ||
151 | kfree(opencores_kbd); | ||
152 | |||
153 | platform_set_drvdata(pdev, NULL); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct platform_driver opencores_kbd_device_driver = { | ||
159 | .probe = opencores_kbd_probe, | ||
160 | .remove = __devexit_p(opencores_kbd_remove), | ||
161 | .driver = { | ||
162 | .name = "opencores-kbd", | ||
163 | }, | ||
164 | }; | ||
165 | |||
166 | static int __init opencores_kbd_init(void) | ||
167 | { | ||
168 | return platform_driver_register(&opencores_kbd_device_driver); | ||
169 | } | ||
170 | module_init(opencores_kbd_init); | ||
171 | |||
172 | static void __exit opencores_kbd_exit(void) | ||
173 | { | ||
174 | platform_driver_unregister(&opencores_kbd_device_driver); | ||
175 | } | ||
176 | module_exit(opencores_kbd_exit); | ||
177 | |||
178 | MODULE_LICENSE("GPL"); | ||
179 | MODULE_AUTHOR("Javier Herrero <jherrero@hvsistemas.es>"); | ||
180 | MODULE_DESCRIPTION("Keyboard driver for OpenCores Keyboard Controller"); | ||
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c new file mode 100644 index 000000000000..191cc51d6cf8 --- /dev/null +++ b/drivers/input/keyboard/qt2160.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | * qt2160.c - Atmel AT42QT2160 Touch Sense Controller | ||
3 | * | ||
4 | * Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/jiffies.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/input.h> | ||
30 | |||
31 | #define QT2160_VALID_CHIPID 0x11 | ||
32 | |||
33 | #define QT2160_CMD_CHIPID 0 | ||
34 | #define QT2160_CMD_CODEVER 1 | ||
35 | #define QT2160_CMD_GSTAT 2 | ||
36 | #define QT2160_CMD_KEYS3 3 | ||
37 | #define QT2160_CMD_KEYS4 4 | ||
38 | #define QT2160_CMD_SLIDE 5 | ||
39 | #define QT2160_CMD_GPIOS 6 | ||
40 | #define QT2160_CMD_SUBVER 7 | ||
41 | #define QT2160_CMD_CALIBRATE 10 | ||
42 | |||
43 | #define QT2160_CYCLE_INTERVAL (2*HZ) | ||
44 | |||
45 | static unsigned char qt2160_key2code[] = { | ||
46 | KEY_0, KEY_1, KEY_2, KEY_3, | ||
47 | KEY_4, KEY_5, KEY_6, KEY_7, | ||
48 | KEY_8, KEY_9, KEY_A, KEY_B, | ||
49 | KEY_C, KEY_D, KEY_E, KEY_F, | ||
50 | }; | ||
51 | |||
52 | struct qt2160_data { | ||
53 | struct i2c_client *client; | ||
54 | struct input_dev *input; | ||
55 | struct delayed_work dwork; | ||
56 | spinlock_t lock; /* Protects canceling/rescheduling of dwork */ | ||
57 | unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; | ||
58 | u16 key_matrix; | ||
59 | }; | ||
60 | |||
61 | static int qt2160_read_block(struct i2c_client *client, | ||
62 | u8 inireg, u8 *buffer, unsigned int count) | ||
63 | { | ||
64 | int error, idx = 0; | ||
65 | |||
66 | /* | ||
67 | * Can't use SMBus block data read. Check for I2C functionality to speed | ||
68 | * things up whenever possible. Otherwise we will be forced to read | ||
69 | * sequentially. | ||
70 | */ | ||
71 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
72 | |||
73 | error = i2c_smbus_write_byte(client, inireg + idx); | ||
74 | if (error) { | ||
75 | dev_err(&client->dev, | ||
76 | "couldn't send request. Returned %d\n", error); | ||
77 | return error; | ||
78 | } | ||
79 | |||
80 | error = i2c_master_recv(client, buffer, count); | ||
81 | if (error != count) { | ||
82 | dev_err(&client->dev, | ||
83 | "couldn't read registers. Returned %d bytes\n", error); | ||
84 | return error; | ||
85 | } | ||
86 | } else { | ||
87 | |||
88 | while (count--) { | ||
89 | int data; | ||
90 | |||
91 | error = i2c_smbus_write_byte(client, inireg + idx); | ||
92 | if (error) { | ||
93 | dev_err(&client->dev, | ||
94 | "couldn't send request. Returned %d\n", error); | ||
95 | return error; | ||
96 | } | ||
97 | |||
98 | data = i2c_smbus_read_byte(client); | ||
99 | if (data < 0) { | ||
100 | dev_err(&client->dev, | ||
101 | "couldn't read register. Returned %d\n", data); | ||
102 | return data; | ||
103 | } | ||
104 | |||
105 | buffer[idx++] = data; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int qt2160_get_key_matrix(struct qt2160_data *qt2160) | ||
113 | { | ||
114 | struct i2c_client *client = qt2160->client; | ||
115 | struct input_dev *input = qt2160->input; | ||
116 | u8 regs[6]; | ||
117 | u16 old_matrix, new_matrix; | ||
118 | int ret, i, mask; | ||
119 | |||
120 | dev_dbg(&client->dev, "requesting keys...\n"); | ||
121 | |||
122 | /* | ||
123 | * Read all registers from General Status Register | ||
124 | * to GPIOs register | ||
125 | */ | ||
126 | ret = qt2160_read_block(client, QT2160_CMD_GSTAT, regs, 6); | ||
127 | if (ret) { | ||
128 | dev_err(&client->dev, | ||
129 | "could not perform chip read.\n"); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | old_matrix = qt2160->key_matrix; | ||
134 | qt2160->key_matrix = new_matrix = (regs[2] << 8) | regs[1]; | ||
135 | |||
136 | mask = 0x01; | ||
137 | for (i = 0; i < 16; ++i, mask <<= 1) { | ||
138 | int keyval = new_matrix & mask; | ||
139 | |||
140 | if ((old_matrix & mask) != keyval) { | ||
141 | input_report_key(input, qt2160->keycodes[i], keyval); | ||
142 | dev_dbg(&client->dev, "key %d %s\n", | ||
143 | i, keyval ? "pressed" : "released"); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | input_sync(input); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static irqreturn_t qt2160_irq(int irq, void *_qt2160) | ||
153 | { | ||
154 | struct qt2160_data *qt2160 = _qt2160; | ||
155 | unsigned long flags; | ||
156 | |||
157 | spin_lock_irqsave(&qt2160->lock, flags); | ||
158 | |||
159 | __cancel_delayed_work(&qt2160->dwork); | ||
160 | schedule_delayed_work(&qt2160->dwork, 0); | ||
161 | |||
162 | spin_unlock_irqrestore(&qt2160->lock, flags); | ||
163 | |||
164 | return IRQ_HANDLED; | ||
165 | } | ||
166 | |||
167 | static void qt2160_schedule_read(struct qt2160_data *qt2160) | ||
168 | { | ||
169 | spin_lock_irq(&qt2160->lock); | ||
170 | schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL); | ||
171 | spin_unlock_irq(&qt2160->lock); | ||
172 | } | ||
173 | |||
174 | static void qt2160_worker(struct work_struct *work) | ||
175 | { | ||
176 | struct qt2160_data *qt2160 = | ||
177 | container_of(work, struct qt2160_data, dwork.work); | ||
178 | |||
179 | dev_dbg(&qt2160->client->dev, "worker\n"); | ||
180 | |||
181 | qt2160_get_key_matrix(qt2160); | ||
182 | |||
183 | /* Avoid device lock up by checking every so often */ | ||
184 | qt2160_schedule_read(qt2160); | ||
185 | } | ||
186 | |||
187 | static int __devinit qt2160_read(struct i2c_client *client, u8 reg) | ||
188 | { | ||
189 | int ret; | ||
190 | |||
191 | ret = i2c_smbus_write_byte(client, reg); | ||
192 | if (ret) { | ||
193 | dev_err(&client->dev, | ||
194 | "couldn't send request. Returned %d\n", ret); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | ret = i2c_smbus_read_byte(client); | ||
199 | if (ret < 0) { | ||
200 | dev_err(&client->dev, | ||
201 | "couldn't read register. Returned %d\n", ret); | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static int __devinit qt2160_write(struct i2c_client *client, u8 reg, u8 data) | ||
209 | { | ||
210 | int error; | ||
211 | |||
212 | error = i2c_smbus_write_byte(client, reg); | ||
213 | if (error) { | ||
214 | dev_err(&client->dev, | ||
215 | "couldn't send request. Returned %d\n", error); | ||
216 | return error; | ||
217 | } | ||
218 | |||
219 | error = i2c_smbus_write_byte(client, data); | ||
220 | if (error) { | ||
221 | dev_err(&client->dev, | ||
222 | "couldn't write data. Returned %d\n", error); | ||
223 | return error; | ||
224 | } | ||
225 | |||
226 | return error; | ||
227 | } | ||
228 | |||
229 | |||
230 | static bool __devinit qt2160_identify(struct i2c_client *client) | ||
231 | { | ||
232 | int id, ver, rev; | ||
233 | |||
234 | /* Read Chid ID to check if chip is valid */ | ||
235 | id = qt2160_read(client, QT2160_CMD_CHIPID); | ||
236 | if (id != QT2160_VALID_CHIPID) { | ||
237 | dev_err(&client->dev, "ID %d not supported\n", id); | ||
238 | return false; | ||
239 | } | ||
240 | |||
241 | /* Read chip firmware version */ | ||
242 | ver = qt2160_read(client, QT2160_CMD_CODEVER); | ||
243 | if (ver < 0) { | ||
244 | dev_err(&client->dev, "could not get firmware version\n"); | ||
245 | return false; | ||
246 | } | ||
247 | |||
248 | /* Read chip firmware revision */ | ||
249 | rev = qt2160_read(client, QT2160_CMD_SUBVER); | ||
250 | if (rev < 0) { | ||
251 | dev_err(&client->dev, "could not get firmware revision\n"); | ||
252 | return false; | ||
253 | } | ||
254 | |||
255 | dev_info(&client->dev, "AT42QT2160 firmware version %d.%d.%d\n", | ||
256 | ver >> 4, ver & 0xf, rev); | ||
257 | |||
258 | return true; | ||
259 | } | ||
260 | |||
261 | static int __devinit qt2160_probe(struct i2c_client *client, | ||
262 | const struct i2c_device_id *id) | ||
263 | { | ||
264 | struct qt2160_data *qt2160; | ||
265 | struct input_dev *input; | ||
266 | int i; | ||
267 | int error; | ||
268 | |||
269 | /* Check functionality */ | ||
270 | error = i2c_check_functionality(client->adapter, | ||
271 | I2C_FUNC_SMBUS_BYTE); | ||
272 | if (!error) { | ||
273 | dev_err(&client->dev, "%s adapter not supported\n", | ||
274 | dev_driver_string(&client->adapter->dev)); | ||
275 | return -ENODEV; | ||
276 | } | ||
277 | |||
278 | if (!qt2160_identify(client)) | ||
279 | return -ENODEV; | ||
280 | |||
281 | /* Chip is valid and active. Allocate structure */ | ||
282 | qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL); | ||
283 | input = input_allocate_device(); | ||
284 | if (!qt2160 || !input) { | ||
285 | dev_err(&client->dev, "insufficient memory\n"); | ||
286 | error = -ENOMEM; | ||
287 | goto err_free_mem; | ||
288 | } | ||
289 | |||
290 | qt2160->client = client; | ||
291 | qt2160->input = input; | ||
292 | INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker); | ||
293 | spin_lock_init(&qt2160->lock); | ||
294 | |||
295 | input->name = "AT42QT2160 Touch Sense Keyboard"; | ||
296 | input->id.bustype = BUS_I2C; | ||
297 | |||
298 | input->keycode = qt2160->keycodes; | ||
299 | input->keycodesize = sizeof(qt2160->keycodes[0]); | ||
300 | input->keycodemax = ARRAY_SIZE(qt2160_key2code); | ||
301 | |||
302 | __set_bit(EV_KEY, input->evbit); | ||
303 | __clear_bit(EV_REP, input->evbit); | ||
304 | for (i = 0; i < ARRAY_SIZE(qt2160_key2code); i++) { | ||
305 | qt2160->keycodes[i] = qt2160_key2code[i]; | ||
306 | __set_bit(qt2160_key2code[i], input->keybit); | ||
307 | } | ||
308 | __clear_bit(KEY_RESERVED, input->keybit); | ||
309 | |||
310 | /* Calibrate device */ | ||
311 | error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1); | ||
312 | if (error) { | ||
313 | dev_err(&client->dev, "failed to calibrate device\n"); | ||
314 | goto err_free_mem; | ||
315 | } | ||
316 | |||
317 | if (client->irq) { | ||
318 | error = request_irq(client->irq, qt2160_irq, | ||
319 | IRQF_TRIGGER_FALLING, "qt2160", qt2160); | ||
320 | if (error) { | ||
321 | dev_err(&client->dev, | ||
322 | "failed to allocate irq %d\n", client->irq); | ||
323 | goto err_free_mem; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | error = input_register_device(qt2160->input); | ||
328 | if (error) { | ||
329 | dev_err(&client->dev, | ||
330 | "Failed to register input device\n"); | ||
331 | goto err_free_irq; | ||
332 | } | ||
333 | |||
334 | i2c_set_clientdata(client, qt2160); | ||
335 | qt2160_schedule_read(qt2160); | ||
336 | |||
337 | return 0; | ||
338 | |||
339 | err_free_irq: | ||
340 | if (client->irq) | ||
341 | free_irq(client->irq, qt2160); | ||
342 | err_free_mem: | ||
343 | input_free_device(input); | ||
344 | kfree(qt2160); | ||
345 | return error; | ||
346 | } | ||
347 | |||
348 | static int __devexit qt2160_remove(struct i2c_client *client) | ||
349 | { | ||
350 | struct qt2160_data *qt2160 = i2c_get_clientdata(client); | ||
351 | |||
352 | /* Release IRQ so no queue will be scheduled */ | ||
353 | if (client->irq) | ||
354 | free_irq(client->irq, qt2160); | ||
355 | |||
356 | cancel_delayed_work_sync(&qt2160->dwork); | ||
357 | |||
358 | input_unregister_device(qt2160->input); | ||
359 | kfree(qt2160); | ||
360 | |||
361 | i2c_set_clientdata(client, NULL); | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static struct i2c_device_id qt2160_idtable[] = { | ||
366 | { "qt2160", 0, }, | ||
367 | { } | ||
368 | }; | ||
369 | |||
370 | MODULE_DEVICE_TABLE(i2c, qt2160_idtable); | ||
371 | |||
372 | static struct i2c_driver qt2160_driver = { | ||
373 | .driver = { | ||
374 | .name = "qt2160", | ||
375 | .owner = THIS_MODULE, | ||
376 | }, | ||
377 | |||
378 | .id_table = qt2160_idtable, | ||
379 | .probe = qt2160_probe, | ||
380 | .remove = __devexit_p(qt2160_remove), | ||
381 | }; | ||
382 | |||
383 | static int __init qt2160_init(void) | ||
384 | { | ||
385 | return i2c_add_driver(&qt2160_driver); | ||
386 | } | ||
387 | module_init(qt2160_init); | ||
388 | |||
389 | static void __exit qt2160_cleanup(void) | ||
390 | { | ||
391 | i2c_del_driver(&qt2160_driver); | ||
392 | } | ||
393 | module_exit(qt2160_cleanup); | ||
394 | |||
395 | MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>"); | ||
396 | MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor"); | ||
397 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index 0918acae584a..f2b67dc81d80 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c | |||
@@ -96,7 +96,13 @@ static struct { | |||
96 | { 0x3169, KEY_PAUSE, }, | 96 | { 0x3169, KEY_PAUSE, }, |
97 | }; | 97 | }; |
98 | 98 | ||
99 | /* runs in an IRQ thread -- can (and will!) sleep */ | 99 | /* |
100 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
101 | * in Linux sleep, we use a threaded IRQ handler. The IRQ itself is | ||
102 | * active low, but we go through the GPIO controller so we can trigger | ||
103 | * on falling edges and not worry about enabling/disabling the IRQ in | ||
104 | * the keypress handling path. | ||
105 | */ | ||
100 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | 106 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) |
101 | { | 107 | { |
102 | struct dm355evm_keys *keys = _keys; | 108 | struct dm355evm_keys *keys = _keys; |
@@ -171,18 +177,6 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | |||
171 | return IRQ_HANDLED; | 177 | return IRQ_HANDLED; |
172 | } | 178 | } |
173 | 179 | ||
174 | /* | ||
175 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
176 | * in Linux sleep, we use a threaded IRQ handler. The IRQ itself is | ||
177 | * active low, but we go through the GPIO controller so we can trigger | ||
178 | * on falling edges and not worry about enabling/disabling the IRQ in | ||
179 | * the keypress handling path. | ||
180 | */ | ||
181 | static irqreturn_t dm355evm_keys_hardirq(int irq, void *_keys) | ||
182 | { | ||
183 | return IRQ_WAKE_THREAD; | ||
184 | } | ||
185 | |||
186 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | 180 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) |
187 | { | 181 | { |
188 | u16 old_keycode; | 182 | u16 old_keycode; |
@@ -257,10 +251,8 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
257 | 251 | ||
258 | /* REVISIT: flush the event queue? */ | 252 | /* REVISIT: flush the event queue? */ |
259 | 253 | ||
260 | status = request_threaded_irq(keys->irq, | 254 | status = request_threaded_irq(keys->irq, NULL, dm355evm_keys_irq, |
261 | dm355evm_keys_hardirq, dm355evm_keys_irq, | 255 | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), keys); |
262 | IRQF_TRIGGER_FALLING, | ||
263 | dev_name(&pdev->dev), keys); | ||
264 | if (status < 0) | 256 | if (status < 0) |
265 | goto fail1; | 257 | goto fail1; |
266 | 258 | ||
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 84e2fc04d11b..f84cbd97c884 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
@@ -92,7 +92,8 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
92 | */ | 92 | */ |
93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | 93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); |
94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
95 | mutex_lock(&ps2dev->cmd_mutex); | 95 | |
96 | ps2_begin_command(ps2dev); | ||
96 | 97 | ||
97 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 98 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
98 | goto out; | 99 | goto out; |
@@ -126,7 +127,7 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
126 | rc = 0; | 127 | rc = 0; |
127 | 128 | ||
128 | out: | 129 | out: |
129 | mutex_unlock(&ps2dev->cmd_mutex); | 130 | ps2_end_command(ps2dev); |
130 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 131 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
131 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 132 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
132 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", | 133 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", |
@@ -140,7 +141,7 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | |||
140 | unsigned char v; | 141 | unsigned char v; |
141 | int rc = -1; | 142 | int rc = -1; |
142 | 143 | ||
143 | mutex_lock(&ps2dev->cmd_mutex); | 144 | ps2_begin_command(ps2dev); |
144 | 145 | ||
145 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 146 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
146 | goto out; | 147 | goto out; |
@@ -179,7 +180,7 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | |||
179 | rc = 0; | 180 | rc = 0; |
180 | 181 | ||
181 | out: | 182 | out: |
182 | mutex_unlock(&ps2dev->cmd_mutex); | 183 | ps2_end_command(ps2dev); |
183 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", | 184 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", |
184 | reg_addr, reg_val, rc); | 185 | reg_addr, reg_val, rc); |
185 | return rc; | 186 | return rc; |
@@ -214,7 +215,8 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
214 | 215 | ||
215 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | 216 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); |
216 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 217 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
217 | mutex_lock(&ps2dev->cmd_mutex); | 218 | |
219 | ps2_begin_command(ps2dev); | ||
218 | 220 | ||
219 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 221 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
220 | goto out; | 222 | goto out; |
@@ -236,7 +238,7 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
236 | rc = 0; | 238 | rc = 0; |
237 | 239 | ||
238 | out: | 240 | out: |
239 | mutex_unlock(&ps2dev->cmd_mutex); | 241 | ps2_end_command(ps2dev); |
240 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 242 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
241 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 243 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
242 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", | 244 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", |
@@ -250,7 +252,7 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | |||
250 | unsigned char v; | 252 | unsigned char v; |
251 | int rc = -1; | 253 | int rc = -1; |
252 | 254 | ||
253 | mutex_lock(&ps2dev->cmd_mutex); | 255 | ps2_begin_command(ps2dev); |
254 | 256 | ||
255 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 257 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
256 | goto out; | 258 | goto out; |
@@ -275,7 +277,7 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | |||
275 | rc = 0; | 277 | rc = 0; |
276 | 278 | ||
277 | out: | 279 | out: |
278 | mutex_unlock(&ps2dev->cmd_mutex); | 280 | ps2_end_command(ps2dev); |
279 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", | 281 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", |
280 | reg_val, rc); | 282 | reg_val, rc); |
281 | return rc; | 283 | return rc; |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index eac9fdde7ee9..7283c78044af 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c | |||
@@ -203,7 +203,7 @@ MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); | |||
203 | * and the irq configuration should be set to Falling Edge Trigger | 203 | * and the irq configuration should be set to Falling Edge Trigger |
204 | */ | 204 | */ |
205 | /* Control IRQ / Polling option */ | 205 | /* Control IRQ / Polling option */ |
206 | static int polling_req; | 206 | static bool polling_req; |
207 | module_param(polling_req, bool, 0444); | 207 | module_param(polling_req, bool, 0444); |
208 | MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); | 208 | MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); |
209 | 209 | ||
@@ -217,6 +217,7 @@ struct synaptics_i2c { | |||
217 | struct i2c_client *client; | 217 | struct i2c_client *client; |
218 | struct input_dev *input; | 218 | struct input_dev *input; |
219 | struct delayed_work dwork; | 219 | struct delayed_work dwork; |
220 | spinlock_t lock; | ||
220 | int no_data_count; | 221 | int no_data_count; |
221 | int no_decel_param; | 222 | int no_decel_param; |
222 | int reduce_report_param; | 223 | int reduce_report_param; |
@@ -366,17 +367,28 @@ static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) | |||
366 | return xy_delta || gesture; | 367 | return xy_delta || gesture; |
367 | } | 368 | } |
368 | 369 | ||
369 | static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) | 370 | static void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch, |
371 | unsigned long delay) | ||
370 | { | 372 | { |
371 | struct synaptics_i2c *touch = dev_id; | 373 | unsigned long flags; |
374 | |||
375 | spin_lock_irqsave(&touch->lock, flags); | ||
372 | 376 | ||
373 | /* | 377 | /* |
374 | * We want to have the work run immediately but it might have | 378 | * If work is already scheduled then subsequent schedules will not |
375 | * already been scheduled with a delay, that's why we have to | 379 | * change the scheduled time that's why we have to cancel it first. |
376 | * cancel it first. | ||
377 | */ | 380 | */ |
378 | cancel_delayed_work(&touch->dwork); | 381 | __cancel_delayed_work(&touch->dwork); |
379 | schedule_delayed_work(&touch->dwork, 0); | 382 | schedule_delayed_work(&touch->dwork, delay); |
383 | |||
384 | spin_unlock_irqrestore(&touch->lock, flags); | ||
385 | } | ||
386 | |||
387 | static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) | ||
388 | { | ||
389 | struct synaptics_i2c *touch = dev_id; | ||
390 | |||
391 | synaptics_i2c_reschedule_work(touch, 0); | ||
380 | 392 | ||
381 | return IRQ_HANDLED; | 393 | return IRQ_HANDLED; |
382 | } | 394 | } |
@@ -452,7 +464,7 @@ static void synaptics_i2c_work_handler(struct work_struct *work) | |||
452 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and | 464 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and |
453 | * if error is detected, we try to reset and reconfigure the touchpad. | 465 | * if error is detected, we try to reset and reconfigure the touchpad. |
454 | */ | 466 | */ |
455 | schedule_delayed_work(&touch->dwork, delay); | 467 | synaptics_i2c_reschedule_work(touch, delay); |
456 | } | 468 | } |
457 | 469 | ||
458 | static int synaptics_i2c_open(struct input_dev *input) | 470 | static int synaptics_i2c_open(struct input_dev *input) |
@@ -465,8 +477,8 @@ static int synaptics_i2c_open(struct input_dev *input) | |||
465 | return ret; | 477 | return ret; |
466 | 478 | ||
467 | if (polling_req) | 479 | if (polling_req) |
468 | schedule_delayed_work(&touch->dwork, | 480 | synaptics_i2c_reschedule_work(touch, |
469 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | 481 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); |
470 | 482 | ||
471 | return 0; | 483 | return 0; |
472 | } | 484 | } |
@@ -521,6 +533,7 @@ struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) | |||
521 | touch->scan_rate_param = scan_rate; | 533 | touch->scan_rate_param = scan_rate; |
522 | set_scan_rate(touch, scan_rate); | 534 | set_scan_rate(touch, scan_rate); |
523 | INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); | 535 | INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); |
536 | spin_lock_init(&touch->lock); | ||
524 | 537 | ||
525 | return touch; | 538 | return touch; |
526 | } | 539 | } |
@@ -535,14 +548,12 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, | |||
535 | if (!touch) | 548 | if (!touch) |
536 | return -ENOMEM; | 549 | return -ENOMEM; |
537 | 550 | ||
538 | i2c_set_clientdata(client, touch); | ||
539 | |||
540 | ret = synaptics_i2c_reset_config(client); | 551 | ret = synaptics_i2c_reset_config(client); |
541 | if (ret) | 552 | if (ret) |
542 | goto err_mem_free; | 553 | goto err_mem_free; |
543 | 554 | ||
544 | if (client->irq < 1) | 555 | if (client->irq < 1) |
545 | polling_req = 1; | 556 | polling_req = true; |
546 | 557 | ||
547 | touch->input = input_allocate_device(); | 558 | touch->input = input_allocate_device(); |
548 | if (!touch->input) { | 559 | if (!touch->input) { |
@@ -563,7 +574,7 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, | |||
563 | dev_warn(&touch->client->dev, | 574 | dev_warn(&touch->client->dev, |
564 | "IRQ request failed: %d, " | 575 | "IRQ request failed: %d, " |
565 | "falling back to polling\n", ret); | 576 | "falling back to polling\n", ret); |
566 | polling_req = 1; | 577 | polling_req = true; |
567 | synaptics_i2c_reg_set(touch->client, | 578 | synaptics_i2c_reg_set(touch->client, |
568 | INTERRUPT_EN_REG, 0); | 579 | INTERRUPT_EN_REG, 0); |
569 | } | 580 | } |
@@ -580,12 +591,14 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, | |||
580 | "Input device register failed: %d\n", ret); | 591 | "Input device register failed: %d\n", ret); |
581 | goto err_input_free; | 592 | goto err_input_free; |
582 | } | 593 | } |
594 | |||
595 | i2c_set_clientdata(client, touch); | ||
596 | |||
583 | return 0; | 597 | return 0; |
584 | 598 | ||
585 | err_input_free: | 599 | err_input_free: |
586 | input_free_device(touch->input); | 600 | input_free_device(touch->input); |
587 | err_mem_free: | 601 | err_mem_free: |
588 | i2c_set_clientdata(client, NULL); | ||
589 | kfree(touch); | 602 | kfree(touch); |
590 | 603 | ||
591 | return ret; | 604 | return ret; |
@@ -596,7 +609,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) | |||
596 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | 609 | struct synaptics_i2c *touch = i2c_get_clientdata(client); |
597 | 610 | ||
598 | if (!polling_req) | 611 | if (!polling_req) |
599 | free_irq(touch->client->irq, touch); | 612 | free_irq(client->irq, touch); |
600 | 613 | ||
601 | input_unregister_device(touch->input); | 614 | input_unregister_device(touch->input); |
602 | i2c_set_clientdata(client, NULL); | 615 | i2c_set_clientdata(client, NULL); |
@@ -627,8 +640,8 @@ static int synaptics_i2c_resume(struct i2c_client *client) | |||
627 | if (ret) | 640 | if (ret) |
628 | return ret; | 641 | return ret; |
629 | 642 | ||
630 | schedule_delayed_work(&touch->dwork, | 643 | synaptics_i2c_reschedule_work(touch, |
631 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | 644 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); |
632 | 645 | ||
633 | return 0; | 646 | return 0; |
634 | } | 647 | } |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index eb3ff94af58c..bc56e52b945f 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -87,8 +87,22 @@ static bool i8042_bypass_aux_irq_test; | |||
87 | 87 | ||
88 | #include "i8042.h" | 88 | #include "i8042.h" |
89 | 89 | ||
90 | /* | ||
91 | * i8042_lock protects serialization between i8042_command and | ||
92 | * the interrupt handler. | ||
93 | */ | ||
90 | static DEFINE_SPINLOCK(i8042_lock); | 94 | static DEFINE_SPINLOCK(i8042_lock); |
91 | 95 | ||
96 | /* | ||
97 | * Writers to AUX and KBD ports as well as users issuing i8042_command | ||
98 | * directly should acquire i8042_mutex (by means of calling | ||
99 | * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that | ||
100 | * they do not disturb each other (unfortunately in many i8042 | ||
101 | * implementations write to one of the ports will immediately abort | ||
102 | * command that is being processed by another port). | ||
103 | */ | ||
104 | static DEFINE_MUTEX(i8042_mutex); | ||
105 | |||
92 | struct i8042_port { | 106 | struct i8042_port { |
93 | struct serio *serio; | 107 | struct serio *serio; |
94 | int irq; | 108 | int irq; |
@@ -113,6 +127,18 @@ static struct platform_device *i8042_platform_device; | |||
113 | 127 | ||
114 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); | 128 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); |
115 | 129 | ||
130 | void i8042_lock_chip(void) | ||
131 | { | ||
132 | mutex_lock(&i8042_mutex); | ||
133 | } | ||
134 | EXPORT_SYMBOL(i8042_lock_chip); | ||
135 | |||
136 | void i8042_unlock_chip(void) | ||
137 | { | ||
138 | mutex_unlock(&i8042_mutex); | ||
139 | } | ||
140 | EXPORT_SYMBOL(i8042_unlock_chip); | ||
141 | |||
116 | /* | 142 | /* |
117 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to | 143 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to |
118 | * be ready for reading values from it / writing values to it. | 144 | * be ready for reading values from it / writing values to it. |
@@ -1161,6 +1187,21 @@ static void __devexit i8042_unregister_ports(void) | |||
1161 | } | 1187 | } |
1162 | } | 1188 | } |
1163 | 1189 | ||
1190 | /* | ||
1191 | * Checks whether port belongs to i8042 controller. | ||
1192 | */ | ||
1193 | bool i8042_check_port_owner(const struct serio *port) | ||
1194 | { | ||
1195 | int i; | ||
1196 | |||
1197 | for (i = 0; i < I8042_NUM_PORTS; i++) | ||
1198 | if (i8042_ports[i].serio == port) | ||
1199 | return true; | ||
1200 | |||
1201 | return false; | ||
1202 | } | ||
1203 | EXPORT_SYMBOL(i8042_check_port_owner); | ||
1204 | |||
1164 | static void i8042_free_irqs(void) | 1205 | static void i8042_free_irqs(void) |
1165 | { | 1206 | { |
1166 | if (i8042_aux_irq_registered) | 1207 | if (i8042_aux_irq_registered) |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 3a95b508bf27..769ba65a585a 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
19 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
20 | #include <linux/i8042.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/libps2.h> | 22 | #include <linux/libps2.h> |
22 | 23 | ||
@@ -54,6 +55,24 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | |||
54 | } | 55 | } |
55 | EXPORT_SYMBOL(ps2_sendbyte); | 56 | EXPORT_SYMBOL(ps2_sendbyte); |
56 | 57 | ||
58 | void ps2_begin_command(struct ps2dev *ps2dev) | ||
59 | { | ||
60 | mutex_lock(&ps2dev->cmd_mutex); | ||
61 | |||
62 | if (i8042_check_port_owner(ps2dev->serio)) | ||
63 | i8042_lock_chip(); | ||
64 | } | ||
65 | EXPORT_SYMBOL(ps2_begin_command); | ||
66 | |||
67 | void ps2_end_command(struct ps2dev *ps2dev) | ||
68 | { | ||
69 | if (i8042_check_port_owner(ps2dev->serio)) | ||
70 | i8042_unlock_chip(); | ||
71 | |||
72 | mutex_unlock(&ps2dev->cmd_mutex); | ||
73 | } | ||
74 | EXPORT_SYMBOL(ps2_end_command); | ||
75 | |||
57 | /* | 76 | /* |
58 | * ps2_drain() waits for device to transmit requested number of bytes | 77 | * ps2_drain() waits for device to transmit requested number of bytes |
59 | * and discards them. | 78 | * and discards them. |
@@ -66,7 +85,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | |||
66 | maxbytes = sizeof(ps2dev->cmdbuf); | 85 | maxbytes = sizeof(ps2dev->cmdbuf); |
67 | } | 86 | } |
68 | 87 | ||
69 | mutex_lock(&ps2dev->cmd_mutex); | 88 | ps2_begin_command(ps2dev); |
70 | 89 | ||
71 | serio_pause_rx(ps2dev->serio); | 90 | serio_pause_rx(ps2dev->serio); |
72 | ps2dev->flags = PS2_FLAG_CMD; | 91 | ps2dev->flags = PS2_FLAG_CMD; |
@@ -76,7 +95,8 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | |||
76 | wait_event_timeout(ps2dev->wait, | 95 | wait_event_timeout(ps2dev->wait, |
77 | !(ps2dev->flags & PS2_FLAG_CMD), | 96 | !(ps2dev->flags & PS2_FLAG_CMD), |
78 | msecs_to_jiffies(timeout)); | 97 | msecs_to_jiffies(timeout)); |
79 | mutex_unlock(&ps2dev->cmd_mutex); | 98 | |
99 | ps2_end_command(ps2dev); | ||
80 | } | 100 | } |
81 | EXPORT_SYMBOL(ps2_drain); | 101 | EXPORT_SYMBOL(ps2_drain); |
82 | 102 | ||
@@ -237,9 +257,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
237 | { | 257 | { |
238 | int rc; | 258 | int rc; |
239 | 259 | ||
240 | mutex_lock(&ps2dev->cmd_mutex); | 260 | ps2_begin_command(ps2dev); |
241 | rc = __ps2_command(ps2dev, param, command); | 261 | rc = __ps2_command(ps2dev, param, command); |
242 | mutex_unlock(&ps2dev->cmd_mutex); | 262 | ps2_end_command(ps2dev); |
243 | 263 | ||
244 | return rc; | 264 | return rc; |
245 | } | 265 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index ab02d72afbf3..8cc453c85ea7 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -48,8 +48,8 @@ config TOUCHSCREEN_AD7879_I2C | |||
48 | select TOUCHSCREEN_AD7879 | 48 | select TOUCHSCREEN_AD7879 |
49 | help | 49 | help |
50 | Say Y here if you have a touchscreen interface using the | 50 | Say Y here if you have a touchscreen interface using the |
51 | AD7879-1 controller, and your board-specific initialization | 51 | AD7879-1/AD7889-1 controller, and your board-specific |
52 | code includes that in its table of I2C devices. | 52 | initialization code includes that in its table of I2C devices. |
53 | 53 | ||
54 | If unsure, say N (but it's safe to say "Y"). | 54 | If unsure, say N (but it's safe to say "Y"). |
55 | 55 | ||
@@ -62,7 +62,7 @@ config TOUCHSCREEN_AD7879_SPI | |||
62 | select TOUCHSCREEN_AD7879 | 62 | select TOUCHSCREEN_AD7879 |
63 | help | 63 | help |
64 | Say Y here if you have a touchscreen interface using the | 64 | Say Y here if you have a touchscreen interface using the |
65 | AD7879 controller, and your board-specific initialization | 65 | AD7879/AD7889 controller, and your board-specific initialization |
66 | code includes that in its table of SPI devices. | 66 | code includes that in its table of SPI devices. |
67 | 67 | ||
68 | If unsure, say N (but it's safe to say "Y"). | 68 | If unsure, say N (but it's safe to say "Y"). |
@@ -169,6 +169,17 @@ config TOUCHSCREEN_WACOM_W8001 | |||
169 | To compile this driver as a module, choose M here: the | 169 | To compile this driver as a module, choose M here: the |
170 | module will be called wacom_w8001. | 170 | module will be called wacom_w8001. |
171 | 171 | ||
172 | config TOUCHSCREEN_MCS5000 | ||
173 | tristate "MELFAS MCS-5000 touchscreen" | ||
174 | depends on I2C | ||
175 | help | ||
176 | Say Y here if you have the MELFAS MCS-5000 touchscreen controller | ||
177 | chip in your system. | ||
178 | |||
179 | If unsure, say N. | ||
180 | |||
181 | To compile this driver as a module, choose M here: the | ||
182 | module will be called mcs5000_ts. | ||
172 | 183 | ||
173 | config TOUCHSCREEN_MTOUCH | 184 | config TOUCHSCREEN_MTOUCH |
174 | tristate "MicroTouch serial touchscreens" | 185 | tristate "MicroTouch serial touchscreens" |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 4599bf7ad819..15fa62cffc77 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | |||
17 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 17 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
18 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
19 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 19 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
20 | obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o | ||
20 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o | 21 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o |
21 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 22 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
22 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o | 23 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o |
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 19b4db7e974d..f06332c9e21b 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2008 Michael Hennerich, Analog Devices Inc. | 2 | * Copyright (C) 2008-2009 Michael Hennerich, Analog Devices Inc. |
3 | * | 3 | * |
4 | * Description: AD7879 based touchscreen, and GPIO driver (I2C/SPI Interface) | 4 | * Description: AD7879/AD7889 based touchscreen, and GPIO driver |
5 | * (I2C/SPI Interface) | ||
5 | * | 6 | * |
6 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 7 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
7 | * | 8 | * |
@@ -747,6 +748,7 @@ static int __devexit ad7879_remove(struct i2c_client *client) | |||
747 | 748 | ||
748 | static const struct i2c_device_id ad7879_id[] = { | 749 | static const struct i2c_device_id ad7879_id[] = { |
749 | { "ad7879", 0 }, | 750 | { "ad7879", 0 }, |
751 | { "ad7889", 0 }, | ||
750 | { } | 752 | { } |
751 | }; | 753 | }; |
752 | MODULE_DEVICE_TABLE(i2c, ad7879_id); | 754 | MODULE_DEVICE_TABLE(i2c, ad7879_id); |
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c new file mode 100644 index 000000000000..4c28b89757f9 --- /dev/null +++ b/drivers/input/touchscreen/mcs5000_ts.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * mcs5000_ts.c - Touchscreen driver for MELFAS MCS-5000 controller | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * | ||
7 | * Based on wm97xx-core.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/i2c/mcs5000_ts.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/irq.h> | ||
23 | |||
24 | /* Registers */ | ||
25 | #define MCS5000_TS_STATUS 0x00 | ||
26 | #define STATUS_OFFSET 0 | ||
27 | #define STATUS_NO (0 << STATUS_OFFSET) | ||
28 | #define STATUS_INIT (1 << STATUS_OFFSET) | ||
29 | #define STATUS_SENSING (2 << STATUS_OFFSET) | ||
30 | #define STATUS_COORD (3 << STATUS_OFFSET) | ||
31 | #define STATUS_GESTURE (4 << STATUS_OFFSET) | ||
32 | #define ERROR_OFFSET 4 | ||
33 | #define ERROR_NO (0 << ERROR_OFFSET) | ||
34 | #define ERROR_POWER_ON_RESET (1 << ERROR_OFFSET) | ||
35 | #define ERROR_INT_RESET (2 << ERROR_OFFSET) | ||
36 | #define ERROR_EXT_RESET (3 << ERROR_OFFSET) | ||
37 | #define ERROR_INVALID_REG_ADDRESS (8 << ERROR_OFFSET) | ||
38 | #define ERROR_INVALID_REG_VALUE (9 << ERROR_OFFSET) | ||
39 | |||
40 | #define MCS5000_TS_OP_MODE 0x01 | ||
41 | #define RESET_OFFSET 0 | ||
42 | #define RESET_NO (0 << RESET_OFFSET) | ||
43 | #define RESET_EXT_SOFT (1 << RESET_OFFSET) | ||
44 | #define OP_MODE_OFFSET 1 | ||
45 | #define OP_MODE_SLEEP (0 << OP_MODE_OFFSET) | ||
46 | #define OP_MODE_ACTIVE (1 << OP_MODE_OFFSET) | ||
47 | #define GESTURE_OFFSET 4 | ||
48 | #define GESTURE_DISABLE (0 << GESTURE_OFFSET) | ||
49 | #define GESTURE_ENABLE (1 << GESTURE_OFFSET) | ||
50 | #define PROXIMITY_OFFSET 5 | ||
51 | #define PROXIMITY_DISABLE (0 << PROXIMITY_OFFSET) | ||
52 | #define PROXIMITY_ENABLE (1 << PROXIMITY_OFFSET) | ||
53 | #define SCAN_MODE_OFFSET 6 | ||
54 | #define SCAN_MODE_INTERRUPT (0 << SCAN_MODE_OFFSET) | ||
55 | #define SCAN_MODE_POLLING (1 << SCAN_MODE_OFFSET) | ||
56 | #define REPORT_RATE_OFFSET 7 | ||
57 | #define REPORT_RATE_40 (0 << REPORT_RATE_OFFSET) | ||
58 | #define REPORT_RATE_80 (1 << REPORT_RATE_OFFSET) | ||
59 | |||
60 | #define MCS5000_TS_SENS_CTL 0x02 | ||
61 | #define MCS5000_TS_FILTER_CTL 0x03 | ||
62 | #define PRI_FILTER_OFFSET 0 | ||
63 | #define SEC_FILTER_OFFSET 4 | ||
64 | |||
65 | #define MCS5000_TS_X_SIZE_UPPER 0x08 | ||
66 | #define MCS5000_TS_X_SIZE_LOWER 0x09 | ||
67 | #define MCS5000_TS_Y_SIZE_UPPER 0x0A | ||
68 | #define MCS5000_TS_Y_SIZE_LOWER 0x0B | ||
69 | |||
70 | #define MCS5000_TS_INPUT_INFO 0x10 | ||
71 | #define INPUT_TYPE_OFFSET 0 | ||
72 | #define INPUT_TYPE_NONTOUCH (0 << INPUT_TYPE_OFFSET) | ||
73 | #define INPUT_TYPE_SINGLE (1 << INPUT_TYPE_OFFSET) | ||
74 | #define INPUT_TYPE_DUAL (2 << INPUT_TYPE_OFFSET) | ||
75 | #define INPUT_TYPE_PALM (3 << INPUT_TYPE_OFFSET) | ||
76 | #define INPUT_TYPE_PROXIMITY (7 << INPUT_TYPE_OFFSET) | ||
77 | #define GESTURE_CODE_OFFSET 3 | ||
78 | #define GESTURE_CODE_NO (0 << GESTURE_CODE_OFFSET) | ||
79 | |||
80 | #define MCS5000_TS_X_POS_UPPER 0x11 | ||
81 | #define MCS5000_TS_X_POS_LOWER 0x12 | ||
82 | #define MCS5000_TS_Y_POS_UPPER 0x13 | ||
83 | #define MCS5000_TS_Y_POS_LOWER 0x14 | ||
84 | #define MCS5000_TS_Z_POS 0x15 | ||
85 | #define MCS5000_TS_WIDTH 0x16 | ||
86 | #define MCS5000_TS_GESTURE_VAL 0x17 | ||
87 | #define MCS5000_TS_MODULE_REV 0x20 | ||
88 | #define MCS5000_TS_FIRMWARE_VER 0x21 | ||
89 | |||
90 | /* Touchscreen absolute values */ | ||
91 | #define MCS5000_MAX_XC 0x3ff | ||
92 | #define MCS5000_MAX_YC 0x3ff | ||
93 | |||
94 | enum mcs5000_ts_read_offset { | ||
95 | READ_INPUT_INFO, | ||
96 | READ_X_POS_UPPER, | ||
97 | READ_X_POS_LOWER, | ||
98 | READ_Y_POS_UPPER, | ||
99 | READ_Y_POS_LOWER, | ||
100 | READ_BLOCK_SIZE, | ||
101 | }; | ||
102 | |||
103 | /* Each client has this additional data */ | ||
104 | struct mcs5000_ts_data { | ||
105 | struct i2c_client *client; | ||
106 | struct input_dev *input_dev; | ||
107 | const struct mcs5000_ts_platform_data *platform_data; | ||
108 | }; | ||
109 | |||
110 | static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id) | ||
111 | { | ||
112 | struct mcs5000_ts_data *data = dev_id; | ||
113 | struct i2c_client *client = data->client; | ||
114 | u8 buffer[READ_BLOCK_SIZE]; | ||
115 | int err; | ||
116 | int x; | ||
117 | int y; | ||
118 | |||
119 | err = i2c_smbus_read_i2c_block_data(client, MCS5000_TS_INPUT_INFO, | ||
120 | READ_BLOCK_SIZE, buffer); | ||
121 | if (err < 0) { | ||
122 | dev_err(&client->dev, "%s, err[%d]\n", __func__, err); | ||
123 | goto out; | ||
124 | } | ||
125 | |||
126 | switch (buffer[READ_INPUT_INFO]) { | ||
127 | case INPUT_TYPE_NONTOUCH: | ||
128 | input_report_key(data->input_dev, BTN_TOUCH, 0); | ||
129 | input_sync(data->input_dev); | ||
130 | break; | ||
131 | |||
132 | case INPUT_TYPE_SINGLE: | ||
133 | x = (buffer[READ_X_POS_UPPER] << 8) | buffer[READ_X_POS_LOWER]; | ||
134 | y = (buffer[READ_Y_POS_UPPER] << 8) | buffer[READ_Y_POS_LOWER]; | ||
135 | |||
136 | input_report_key(data->input_dev, BTN_TOUCH, 1); | ||
137 | input_report_abs(data->input_dev, ABS_X, x); | ||
138 | input_report_abs(data->input_dev, ABS_Y, y); | ||
139 | input_sync(data->input_dev); | ||
140 | break; | ||
141 | |||
142 | case INPUT_TYPE_DUAL: | ||
143 | /* TODO */ | ||
144 | break; | ||
145 | |||
146 | case INPUT_TYPE_PALM: | ||
147 | /* TODO */ | ||
148 | break; | ||
149 | |||
150 | case INPUT_TYPE_PROXIMITY: | ||
151 | /* TODO */ | ||
152 | break; | ||
153 | |||
154 | default: | ||
155 | dev_err(&client->dev, "Unknown ts input type %d\n", | ||
156 | buffer[READ_INPUT_INFO]); | ||
157 | break; | ||
158 | } | ||
159 | |||
160 | out: | ||
161 | return IRQ_HANDLED; | ||
162 | } | ||
163 | |||
164 | static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data) | ||
165 | { | ||
166 | const struct mcs5000_ts_platform_data *platform_data = | ||
167 | data->platform_data; | ||
168 | struct i2c_client *client = data->client; | ||
169 | |||
170 | /* Touch reset & sleep mode */ | ||
171 | i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, | ||
172 | RESET_EXT_SOFT | OP_MODE_SLEEP); | ||
173 | |||
174 | /* Touch size */ | ||
175 | i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_UPPER, | ||
176 | platform_data->x_size >> 8); | ||
177 | i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_LOWER, | ||
178 | platform_data->x_size & 0xff); | ||
179 | i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_UPPER, | ||
180 | platform_data->y_size >> 8); | ||
181 | i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_LOWER, | ||
182 | platform_data->y_size & 0xff); | ||
183 | |||
184 | /* Touch active mode & 80 report rate */ | ||
185 | i2c_smbus_write_byte_data(data->client, MCS5000_TS_OP_MODE, | ||
186 | OP_MODE_ACTIVE | REPORT_RATE_80); | ||
187 | } | ||
188 | |||
189 | static int __devinit mcs5000_ts_probe(struct i2c_client *client, | ||
190 | const struct i2c_device_id *id) | ||
191 | { | ||
192 | struct mcs5000_ts_data *data; | ||
193 | struct input_dev *input_dev; | ||
194 | int ret; | ||
195 | |||
196 | if (!client->dev.platform_data) | ||
197 | return -EINVAL; | ||
198 | |||
199 | data = kzalloc(sizeof(struct mcs5000_ts_data), GFP_KERNEL); | ||
200 | input_dev = input_allocate_device(); | ||
201 | if (!data || !input_dev) { | ||
202 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
203 | ret = -ENOMEM; | ||
204 | goto err_free_mem; | ||
205 | } | ||
206 | |||
207 | data->client = client; | ||
208 | data->input_dev = input_dev; | ||
209 | data->platform_data = client->dev.platform_data; | ||
210 | |||
211 | input_dev->name = "MELPAS MCS-5000 Touchscreen"; | ||
212 | input_dev->id.bustype = BUS_I2C; | ||
213 | input_dev->dev.parent = &client->dev; | ||
214 | |||
215 | __set_bit(EV_ABS, input_dev->evbit); | ||
216 | __set_bit(EV_KEY, input_dev->evbit); | ||
217 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
218 | input_set_abs_params(input_dev, ABS_X, 0, MCS5000_MAX_XC, 0, 0); | ||
219 | input_set_abs_params(input_dev, ABS_Y, 0, MCS5000_MAX_YC, 0, 0); | ||
220 | |||
221 | input_set_drvdata(input_dev, data); | ||
222 | |||
223 | if (data->platform_data->cfg_pin) | ||
224 | data->platform_data->cfg_pin(); | ||
225 | |||
226 | ret = request_threaded_irq(client->irq, NULL, mcs5000_ts_interrupt, | ||
227 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, "mcs5000_ts", data); | ||
228 | |||
229 | if (ret < 0) { | ||
230 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
231 | goto err_free_mem; | ||
232 | } | ||
233 | |||
234 | ret = input_register_device(data->input_dev); | ||
235 | if (ret < 0) | ||
236 | goto err_free_irq; | ||
237 | |||
238 | mcs5000_ts_phys_init(data); | ||
239 | i2c_set_clientdata(client, data); | ||
240 | |||
241 | return 0; | ||
242 | |||
243 | err_free_irq: | ||
244 | free_irq(client->irq, data); | ||
245 | err_free_mem: | ||
246 | input_free_device(input_dev); | ||
247 | kfree(data); | ||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | static int __devexit mcs5000_ts_remove(struct i2c_client *client) | ||
252 | { | ||
253 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); | ||
254 | |||
255 | free_irq(client->irq, data); | ||
256 | input_unregister_device(data->input_dev); | ||
257 | kfree(data); | ||
258 | i2c_set_clientdata(client, NULL); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | #ifdef CONFIG_PM | ||
264 | static int mcs5000_ts_suspend(struct i2c_client *client, pm_message_t mesg) | ||
265 | { | ||
266 | /* Touch sleep mode */ | ||
267 | i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int mcs5000_ts_resume(struct i2c_client *client) | ||
273 | { | ||
274 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); | ||
275 | |||
276 | mcs5000_ts_phys_init(data); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | #else | ||
281 | #define mcs5000_ts_suspend NULL | ||
282 | #define mcs5000_ts_resume NULL | ||
283 | #endif | ||
284 | |||
285 | static const struct i2c_device_id mcs5000_ts_id[] = { | ||
286 | { "mcs5000_ts", 0 }, | ||
287 | { } | ||
288 | }; | ||
289 | MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); | ||
290 | |||
291 | static struct i2c_driver mcs5000_ts_driver = { | ||
292 | .probe = mcs5000_ts_probe, | ||
293 | .remove = __devexit_p(mcs5000_ts_remove), | ||
294 | .suspend = mcs5000_ts_suspend, | ||
295 | .resume = mcs5000_ts_resume, | ||
296 | .driver = { | ||
297 | .name = "mcs5000_ts", | ||
298 | }, | ||
299 | .id_table = mcs5000_ts_id, | ||
300 | }; | ||
301 | |||
302 | static int __init mcs5000_ts_init(void) | ||
303 | { | ||
304 | return i2c_add_driver(&mcs5000_ts_driver); | ||
305 | } | ||
306 | |||
307 | static void __exit mcs5000_ts_exit(void) | ||
308 | { | ||
309 | i2c_del_driver(&mcs5000_ts_driver); | ||
310 | } | ||
311 | |||
312 | module_init(mcs5000_ts_init); | ||
313 | module_exit(mcs5000_ts_exit); | ||
314 | |||
315 | /* Module information */ | ||
316 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
317 | MODULE_DESCRIPTION("Touchscreen driver for MELFAS MCS-5000 controller"); | ||
318 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c index 1813c84ea5fc..f2242db54016 100644 --- a/drivers/leds/leds-clevo-mail.c +++ b/drivers/leds/leds-clevo-mail.c | |||
@@ -93,6 +93,8 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = { | |||
93 | static void clevo_mail_led_set(struct led_classdev *led_cdev, | 93 | static void clevo_mail_led_set(struct led_classdev *led_cdev, |
94 | enum led_brightness value) | 94 | enum led_brightness value) |
95 | { | 95 | { |
96 | i8042_lock_chip(); | ||
97 | |||
96 | if (value == LED_OFF) | 98 | if (value == LED_OFF) |
97 | i8042_command(NULL, CLEVO_MAIL_LED_OFF); | 99 | i8042_command(NULL, CLEVO_MAIL_LED_OFF); |
98 | else if (value <= LED_HALF) | 100 | else if (value <= LED_HALF) |
@@ -100,6 +102,8 @@ static void clevo_mail_led_set(struct led_classdev *led_cdev, | |||
100 | else | 102 | else |
101 | i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ); | 103 | i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ); |
102 | 104 | ||
105 | i8042_unlock_chip(); | ||
106 | |||
103 | } | 107 | } |
104 | 108 | ||
105 | static int clevo_mail_led_blink(struct led_classdev *led_cdev, | 109 | static int clevo_mail_led_blink(struct led_classdev *led_cdev, |
@@ -108,6 +112,8 @@ static int clevo_mail_led_blink(struct led_classdev *led_cdev, | |||
108 | { | 112 | { |
109 | int status = -EINVAL; | 113 | int status = -EINVAL; |
110 | 114 | ||
115 | i8042_lock_chip(); | ||
116 | |||
111 | if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) { | 117 | if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) { |
112 | /* Special case: the leds subsystem requested us to | 118 | /* Special case: the leds subsystem requested us to |
113 | * chose one user friendly blinking of the LED, and | 119 | * chose one user friendly blinking of the LED, and |
@@ -135,6 +141,8 @@ static int clevo_mail_led_blink(struct led_classdev *led_cdev, | |||
135 | *delay_on, *delay_off); | 141 | *delay_on, *delay_off); |
136 | } | 142 | } |
137 | 143 | ||
144 | i8042_unlock_chip(); | ||
145 | |||
138 | return status; | 146 | return status; |
139 | } | 147 | } |
140 | 148 | ||
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 6ba16abeebdd..e0f91e4ab653 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/timer.h> | 28 | #include <linux/timer.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
31 | #include <linux/utsname.h> | ||
32 | #include <linux/highmem.h> | 31 | #include <linux/highmem.h> |
33 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
34 | #include <linux/module.h> | 33 | #include <linux/module.h> |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index f97fd06d5948..c19f51dba2ee 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/utsname.h> | ||
32 | #include <linux/init.h> | 31 | #include <linux/init.h> |
33 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
34 | #include <linux/ioport.h> | 33 | #include <linux/ioport.h> |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 90d9b5c0e9a7..a2a50d608a3f 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
53 | #include <linux/smp_lock.h> | 53 | #include <linux/smp_lock.h> |
54 | #include <linux/mm.h> | 54 | #include <linux/mm.h> |
55 | #include <linux/utsname.h> | ||
56 | #include <linux/highmem.h> | 55 | #include <linux/highmem.h> |
57 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
58 | #include <linux/module.h> | 57 | #include <linux/module.h> |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index fb45f5ee8df1..454970d2d701 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
@@ -746,7 +746,9 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) | |||
746 | return AE_BAD_PARAMETER; | 746 | return AE_BAD_PARAMETER; |
747 | if (quirks->mailled == 1) { | 747 | if (quirks->mailled == 1) { |
748 | param = value ? 0x92 : 0x93; | 748 | param = value ? 0x92 : 0x93; |
749 | i8042_lock_chip(); | ||
749 | i8042_command(¶m, 0x1059); | 750 | i8042_command(¶m, 0x1059); |
751 | i8042_unlock_chip(); | ||
750 | return 0; | 752 | return 0; |
751 | } | 753 | } |
752 | break; | 754 | break; |
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index c431198bdbc4..82daa3c1dc9c 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/miscdevice.h> | 16 | #include <linux/miscdevice.h> |
17 | #include <linux/utsname.h> | ||
18 | #include <linux/debugfs.h> | 17 | #include <linux/debugfs.h> |
19 | #include <asm/ipl.h> | 18 | #include <asm/ipl.h> |
20 | #include <asm/sclp.h> | 19 | #include <asm/sclp.h> |
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index eb6ddfc20857..6cb29d3df575 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c | |||
@@ -22,7 +22,6 @@ | |||
22 | /* #define VERBOSE_DEBUG */ | 22 | /* #define VERBOSE_DEBUG */ |
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/utsname.h> | ||
26 | #include <linux/device.h> | 25 | #include <linux/device.h> |
27 | 26 | ||
28 | #include "g_zero.h" | 27 | #include "g_zero.h" |
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 46d6266f30ec..b4a3ba654ea5 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c | |||
@@ -24,7 +24,6 @@ | |||
24 | /* #define VERBOSE_DEBUG */ | 24 | /* #define VERBOSE_DEBUG */ |
25 | 25 | ||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/utsname.h> | ||
28 | #include <linux/device.h> | 27 | #include <linux/device.h> |
29 | 28 | ||
30 | #include "u_serial.h" | 29 | #include "u_serial.h" |
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index bffe91d525f9..09cba273d2db 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c | |||
@@ -22,7 +22,6 @@ | |||
22 | /* #define VERBOSE_DEBUG */ | 22 | /* #define VERBOSE_DEBUG */ |
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/utsname.h> | ||
26 | #include <linux/device.h> | 25 | #include <linux/device.h> |
27 | 26 | ||
28 | #include "g_zero.h" | 27 | #include "g_zero.h" |
diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_audio.c index b5200d551458..8252595d619d 100644 --- a/drivers/usb/gadget/u_audio.c +++ b/drivers/usb/gadget/u_audio.c | |||
@@ -10,7 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/utsname.h> | ||
14 | #include <linux/device.h> | 13 | #include <linux/device.h> |
15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
16 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index f8751ff863cd..2fc02bd95848 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c | |||
@@ -23,7 +23,6 @@ | |||
23 | /* #define VERBOSE_DEBUG */ | 23 | /* #define VERBOSE_DEBUG */ |
24 | 24 | ||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/utsname.h> | ||
27 | #include <linux/device.h> | 26 | #include <linux/device.h> |
28 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
29 | #include <linux/etherdevice.h> | 28 | #include <linux/etherdevice.h> |