diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-14 20:31:54 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-14 20:31:54 -0400 |
commit | 6dc6472581f693b5fc95aebedf67b4960fb85cf0 (patch) | |
tree | 06a5a9a08519950575505273eabced331ed51405 /drivers/hwmon | |
parent | ee673eaa72d8d185012b1027a05e25aba18c267f (diff) | |
parent | 8acd3a60bcca17c6d89c73cee3ad6057eb83ba1e (diff) |
Merge commit 'origin'
Manual fixup of conflicts on:
arch/powerpc/include/asm/dcr-regs.h
drivers/net/ibm_newemac/core.h
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/Kconfig | 16 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 2 | ||||
-rw-r--r-- | drivers/hwmon/abituguru3.c | 3 | ||||
-rw-r--r-- | drivers/hwmon/ad7414.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/atxp1.c | 18 | ||||
-rw-r--r-- | drivers/hwmon/it87.c | 74 | ||||
-rw-r--r-- | drivers/hwmon/max1111.c | 244 | ||||
-rw-r--r-- | drivers/hwmon/ultra45_env.c | 320 |
8 files changed, 647 insertions, 32 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index d402e8d813ce..ebacc0af40fe 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -540,6 +540,15 @@ config SENSORS_LM93 | |||
540 | This driver can also be built as a module. If so, the module | 540 | This driver can also be built as a module. If so, the module |
541 | will be called lm93. | 541 | will be called lm93. |
542 | 542 | ||
543 | config SENSORS_MAX1111 | ||
544 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" | ||
545 | depends on SPI_MASTER | ||
546 | help | ||
547 | Say y here to support Maxim's MAX1111 ADC chips. | ||
548 | |||
549 | This driver can also be built as a module. If so, the module | ||
550 | will be called max1111. | ||
551 | |||
543 | config SENSORS_MAX1619 | 552 | config SENSORS_MAX1619 |
544 | tristate "Maxim MAX1619 sensor chip" | 553 | tristate "Maxim MAX1619 sensor chip" |
545 | depends on I2C | 554 | depends on I2C |
@@ -791,6 +800,13 @@ config SENSORS_W83627EHF | |||
791 | This driver can also be built as a module. If so, the module | 800 | This driver can also be built as a module. If so, the module |
792 | will be called w83627ehf. | 801 | will be called w83627ehf. |
793 | 802 | ||
803 | config SENSORS_ULTRA45 | ||
804 | tristate "Sun Ultra45 PIC16F747" | ||
805 | depends on SPARC64 | ||
806 | help | ||
807 | This driver provides support for the Ultra45 workstation environmental | ||
808 | sensors. | ||
809 | |||
794 | config SENSORS_HDAPS | 810 | config SENSORS_HDAPS |
795 | tristate "IBM Hard Drive Active Protection System (hdaps)" | 811 | tristate "IBM Hard Drive Active Protection System (hdaps)" |
796 | depends on INPUT && X86 | 812 | depends on INPUT && X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 950134ab8426..042d5a78622e 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o | |||
41 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o | 41 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o |
42 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o | 42 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o |
43 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o | 43 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o |
44 | obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o | ||
44 | obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o | 45 | obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o |
45 | obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o | 46 | obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o |
46 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o | 47 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o |
@@ -59,6 +60,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o | |||
59 | obj-$(CONFIG_SENSORS_LM90) += lm90.o | 60 | obj-$(CONFIG_SENSORS_LM90) += lm90.o |
60 | obj-$(CONFIG_SENSORS_LM92) += lm92.o | 61 | obj-$(CONFIG_SENSORS_LM92) += lm92.o |
61 | obj-$(CONFIG_SENSORS_LM93) += lm93.o | 62 | obj-$(CONFIG_SENSORS_LM93) += lm93.o |
63 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o | ||
62 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o | 64 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o |
63 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o | 65 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o |
64 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o | 66 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o |
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index d568c65c1370..d9e7a49d6cbf 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c | |||
@@ -279,7 +279,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
279 | { "OTES1 Fan", 36, 2, 60, 1, 0 }, | 279 | { "OTES1 Fan", 36, 2, 60, 1, 0 }, |
280 | { NULL, 0, 0, 0, 0, 0 } } | 280 | { NULL, 0, 0, 0, 0, 0 } } |
281 | }, | 281 | }, |
282 | { 0x0011, NULL /* Abit AT8 32X, need DMI string */, { | 282 | { 0x0011, "AT8 32X(ATI RD580-ULI M1575)", { |
283 | { "CPU Core", 0, 0, 10, 1, 0 }, | 283 | { "CPU Core", 0, 0, 10, 1, 0 }, |
284 | { "DDR", 1, 0, 20, 1, 0 }, | 284 | { "DDR", 1, 0, 20, 1, 0 }, |
285 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 285 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
@@ -303,6 +303,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
303 | { "SYS Fan", 34, 2, 60, 1, 0 }, | 303 | { "SYS Fan", 34, 2, 60, 1, 0 }, |
304 | { "AUX1 Fan", 35, 2, 60, 1, 0 }, | 304 | { "AUX1 Fan", 35, 2, 60, 1, 0 }, |
305 | { "AUX2 Fan", 36, 2, 60, 1, 0 }, | 305 | { "AUX2 Fan", 36, 2, 60, 1, 0 }, |
306 | { "AUX3 Fan", 37, 2, 60, 1, 0 }, | ||
306 | { NULL, 0, 0, 0, 0, 0 } } | 307 | { NULL, 0, 0, 0, 0, 0 } } |
307 | }, | 308 | }, |
308 | { 0x0012, NULL /* Abit AN8 32X, need DMI string */, { | 309 | { 0x0012, NULL /* Abit AN8 32X, need DMI string */, { |
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index ce8d94fbfd7e..bfda8c80ef24 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c | |||
@@ -69,7 +69,7 @@ static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value) | |||
69 | return i2c_smbus_write_byte_data(client, reg, value); | 69 | return i2c_smbus_write_byte_data(client, reg, value); |
70 | } | 70 | } |
71 | 71 | ||
72 | struct ad7414_data *ad7414_update_device(struct device *dev) | 72 | static struct ad7414_data *ad7414_update_device(struct device *dev) |
73 | { | 73 | { |
74 | struct i2c_client *client = to_i2c_client(dev); | 74 | struct i2c_client *client = to_i2c_client(dev); |
75 | struct ad7414_data *data = i2c_get_clientdata(client); | 75 | struct ad7414_data *data = i2c_get_clientdata(client); |
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index d191118ba0cb..d6b490d3e36f 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
33 | MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); | 33 | MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); |
34 | MODULE_VERSION("0.6.2"); | 34 | MODULE_VERSION("0.6.3"); |
35 | MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>"); | 35 | MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>"); |
36 | 36 | ||
37 | #define ATXP1_VID 0x00 | 37 | #define ATXP1_VID 0x00 |
@@ -289,16 +289,16 @@ static int atxp1_detect(struct i2c_client *new_client, int kind, | |||
289 | if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && | 289 | if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && |
290 | (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) && | 290 | (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) && |
291 | (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) && | 291 | (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) && |
292 | (i2c_smbus_read_byte_data(new_client, 0xff) == 0) )) { | 292 | (i2c_smbus_read_byte_data(new_client, 0xff) == 0))) |
293 | return -ENODEV; | ||
293 | 294 | ||
294 | /* No vendor ID, now checking if registers 0x10,0x11 (non-existent) | 295 | /* No vendor ID, now checking if registers 0x10,0x11 (non-existent) |
295 | * showing the same as register 0x00 */ | 296 | * showing the same as register 0x00 */ |
296 | temp = i2c_smbus_read_byte_data(new_client, 0x00); | 297 | temp = i2c_smbus_read_byte_data(new_client, 0x00); |
297 | 298 | ||
298 | if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && | 299 | if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && |
299 | (i2c_smbus_read_byte_data(new_client, 0x11) == temp) )) | 300 | (i2c_smbus_read_byte_data(new_client, 0x11) == temp))) |
300 | return -ENODEV; | 301 | return -ENODEV; |
301 | } | ||
302 | 302 | ||
303 | /* Get VRM */ | 303 | /* Get VRM */ |
304 | temp = vid_which_vrm(); | 304 | temp = vid_which_vrm(); |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 30cdb0956779..d793cc011990 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -46,6 +46,8 @@ | |||
46 | #include <linux/err.h> | 46 | #include <linux/err.h> |
47 | #include <linux/mutex.h> | 47 | #include <linux/mutex.h> |
48 | #include <linux/sysfs.h> | 48 | #include <linux/sysfs.h> |
49 | #include <linux/string.h> | ||
50 | #include <linux/dmi.h> | ||
49 | #include <asm/io.h> | 51 | #include <asm/io.h> |
50 | 52 | ||
51 | #define DRVNAME "it87" | 53 | #define DRVNAME "it87" |
@@ -236,6 +238,8 @@ struct it87_sio_data { | |||
236 | /* Values read from Super-I/O config space */ | 238 | /* Values read from Super-I/O config space */ |
237 | u8 revision; | 239 | u8 revision; |
238 | u8 vid_value; | 240 | u8 vid_value; |
241 | /* Values set based on DMI strings */ | ||
242 | u8 skip_pwm; | ||
239 | }; | 243 | }; |
240 | 244 | ||
241 | /* For each registered chip, we need to keep some data in memory. | 245 | /* For each registered chip, we need to keep some data in memory. |
@@ -273,10 +277,10 @@ struct it87_data { | |||
273 | static inline int has_16bit_fans(const struct it87_data *data) | 277 | static inline int has_16bit_fans(const struct it87_data *data) |
274 | { | 278 | { |
275 | /* IT8705F Datasheet 0.4.1, 3h == Version G. | 279 | /* IT8705F Datasheet 0.4.1, 3h == Version G. |
276 | IT8712F Datasheet 0.9.1, section 8.3.5 indicates 7h == Version I. | 280 | IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. |
277 | These are the first revisions with 16bit tachometer support. */ | 281 | These are the first revisions with 16bit tachometer support. */ |
278 | return (data->type == it87 && data->revision >= 0x03) | 282 | return (data->type == it87 && data->revision >= 0x03) |
279 | || (data->type == it8712 && data->revision >= 0x07) | 283 | || (data->type == it8712 && data->revision >= 0x08) |
280 | || data->type == it8716 | 284 | || data->type == it8716 |
281 | || data->type == it8718; | 285 | || data->type == it8718; |
282 | } | 286 | } |
@@ -964,6 +968,7 @@ static int __init it87_find(unsigned short *address, | |||
964 | { | 968 | { |
965 | int err = -ENODEV; | 969 | int err = -ENODEV; |
966 | u16 chip_type; | 970 | u16 chip_type; |
971 | const char *board_vendor, *board_name; | ||
967 | 972 | ||
968 | superio_enter(); | 973 | superio_enter(); |
969 | chip_type = force_id ? force_id : superio_inw(DEVID); | 974 | chip_type = force_id ? force_id : superio_inw(DEVID); |
@@ -1022,6 +1027,24 @@ static int __init it87_find(unsigned short *address, | |||
1022 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | 1027 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); |
1023 | } | 1028 | } |
1024 | 1029 | ||
1030 | /* Disable specific features based on DMI strings */ | ||
1031 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | ||
1032 | board_name = dmi_get_system_info(DMI_BOARD_NAME); | ||
1033 | if (board_vendor && board_name) { | ||
1034 | if (strcmp(board_vendor, "nVIDIA") == 0 | ||
1035 | && strcmp(board_name, "FN68PT") == 0) { | ||
1036 | /* On the Shuttle SN68PT, FAN_CTL2 is apparently not | ||
1037 | connected to a fan, but to something else. One user | ||
1038 | has reported instant system power-off when changing | ||
1039 | the PWM2 duty cycle, so we disable it. | ||
1040 | I use the board name string as the trigger in case | ||
1041 | the same board is ever used in other systems. */ | ||
1042 | pr_info("it87: Disabling pwm2 due to " | ||
1043 | "hardware constraints\n"); | ||
1044 | sio_data->skip_pwm = (1 << 1); | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1025 | exit: | 1048 | exit: |
1026 | superio_exit(); | 1049 | superio_exit(); |
1027 | return err; | 1050 | return err; |
@@ -1168,25 +1191,33 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1168 | } | 1191 | } |
1169 | 1192 | ||
1170 | if (enable_pwm_interface) { | 1193 | if (enable_pwm_interface) { |
1171 | if ((err = device_create_file(dev, | 1194 | if (!(sio_data->skip_pwm & (1 << 0))) { |
1172 | &sensor_dev_attr_pwm1_enable.dev_attr)) | 1195 | if ((err = device_create_file(dev, |
1173 | || (err = device_create_file(dev, | 1196 | &sensor_dev_attr_pwm1_enable.dev_attr)) |
1174 | &sensor_dev_attr_pwm2_enable.dev_attr)) | 1197 | || (err = device_create_file(dev, |
1175 | || (err = device_create_file(dev, | 1198 | &sensor_dev_attr_pwm1.dev_attr)) |
1176 | &sensor_dev_attr_pwm3_enable.dev_attr)) | 1199 | || (err = device_create_file(dev, |
1177 | || (err = device_create_file(dev, | 1200 | &dev_attr_pwm1_freq))) |
1178 | &sensor_dev_attr_pwm1.dev_attr)) | 1201 | goto ERROR4; |
1179 | || (err = device_create_file(dev, | 1202 | } |
1180 | &sensor_dev_attr_pwm2.dev_attr)) | 1203 | if (!(sio_data->skip_pwm & (1 << 1))) { |
1181 | || (err = device_create_file(dev, | 1204 | if ((err = device_create_file(dev, |
1182 | &sensor_dev_attr_pwm3.dev_attr)) | 1205 | &sensor_dev_attr_pwm2_enable.dev_attr)) |
1183 | || (err = device_create_file(dev, | 1206 | || (err = device_create_file(dev, |
1184 | &dev_attr_pwm1_freq)) | 1207 | &sensor_dev_attr_pwm2.dev_attr)) |
1185 | || (err = device_create_file(dev, | 1208 | || (err = device_create_file(dev, |
1186 | &dev_attr_pwm2_freq)) | 1209 | &dev_attr_pwm2_freq))) |
1187 | || (err = device_create_file(dev, | 1210 | goto ERROR4; |
1188 | &dev_attr_pwm3_freq))) | 1211 | } |
1189 | goto ERROR4; | 1212 | if (!(sio_data->skip_pwm & (1 << 2))) { |
1213 | if ((err = device_create_file(dev, | ||
1214 | &sensor_dev_attr_pwm3_enable.dev_attr)) | ||
1215 | || (err = device_create_file(dev, | ||
1216 | &sensor_dev_attr_pwm3.dev_attr)) | ||
1217 | || (err = device_create_file(dev, | ||
1218 | &dev_attr_pwm3_freq))) | ||
1219 | goto ERROR4; | ||
1220 | } | ||
1190 | } | 1221 | } |
1191 | 1222 | ||
1192 | if (data->type == it8712 || data->type == it8716 | 1223 | if (data->type == it8712 || data->type == it8716 |
@@ -1546,6 +1577,7 @@ static int __init sm_it87_init(void) | |||
1546 | unsigned short isa_address=0; | 1577 | unsigned short isa_address=0; |
1547 | struct it87_sio_data sio_data; | 1578 | struct it87_sio_data sio_data; |
1548 | 1579 | ||
1580 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); | ||
1549 | err = it87_find(&isa_address, &sio_data); | 1581 | err = it87_find(&isa_address, &sio_data); |
1550 | if (err) | 1582 | if (err) |
1551 | return err; | 1583 | return err; |
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c new file mode 100644 index 000000000000..bfaa665ccf32 --- /dev/null +++ b/drivers/hwmon/max1111.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * max1111.c - +2.7V, Low-Power, Multichannel, Serial 8-bit ADCs | ||
3 | * | ||
4 | * Based on arch/arm/mach-pxa/corgi_ssp.c | ||
5 | * | ||
6 | * Copyright (C) 2004-2005 Richard Purdie | ||
7 | * | ||
8 | * Copyright (C) 2008 Marvell International Ltd. | ||
9 | * Eric Miao <eric.miao@marvell.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * publishhed by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/hwmon.h> | ||
21 | #include <linux/hwmon-sysfs.h> | ||
22 | #include <linux/spi/spi.h> | ||
23 | |||
24 | #define MAX1111_TX_BUF_SIZE 1 | ||
25 | #define MAX1111_RX_BUF_SIZE 2 | ||
26 | |||
27 | /* MAX1111 Commands */ | ||
28 | #define MAX1111_CTRL_PD0 (1u << 0) | ||
29 | #define MAX1111_CTRL_PD1 (1u << 1) | ||
30 | #define MAX1111_CTRL_SGL (1u << 2) | ||
31 | #define MAX1111_CTRL_UNI (1u << 3) | ||
32 | #define MAX1111_CTRL_SEL_SH (5) /* NOTE: bit 4 is ignored */ | ||
33 | #define MAX1111_CTRL_STR (1u << 7) | ||
34 | |||
35 | struct max1111_data { | ||
36 | struct spi_device *spi; | ||
37 | struct device *hwmon_dev; | ||
38 | struct spi_message msg; | ||
39 | struct spi_transfer xfer[2]; | ||
40 | uint8_t *tx_buf; | ||
41 | uint8_t *rx_buf; | ||
42 | }; | ||
43 | |||
44 | static int max1111_read(struct device *dev, int channel) | ||
45 | { | ||
46 | struct max1111_data *data = dev_get_drvdata(dev); | ||
47 | uint8_t v1, v2; | ||
48 | int err; | ||
49 | |||
50 | data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) | | ||
51 | MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 | | ||
52 | MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR; | ||
53 | |||
54 | err = spi_sync(data->spi, &data->msg); | ||
55 | if (err < 0) { | ||
56 | dev_err(dev, "spi_sync failed with %d\n", err); | ||
57 | return err; | ||
58 | } | ||
59 | |||
60 | v1 = data->rx_buf[0]; | ||
61 | v2 = data->rx_buf[1]; | ||
62 | |||
63 | if ((v1 & 0xc0) || (v2 & 0x3f)) | ||
64 | return -EINVAL; | ||
65 | |||
66 | return (v1 << 2) | (v2 >> 6); | ||
67 | } | ||
68 | |||
69 | #ifdef CONFIG_SHARPSL_PM | ||
70 | static struct max1111_data *the_max1111; | ||
71 | |||
72 | int max1111_read_channel(int channel) | ||
73 | { | ||
74 | return max1111_read(&the_max1111->spi->dev, channel); | ||
75 | } | ||
76 | EXPORT_SYMBOL(max1111_read_channel); | ||
77 | #endif | ||
78 | |||
79 | /* | ||
80 | * NOTE: SPI devices do not have a default 'name' attribute, which is | ||
81 | * likely to be used by hwmon applications to distinguish between | ||
82 | * different devices, explicitly add a name attribute here. | ||
83 | */ | ||
84 | static ssize_t show_name(struct device *dev, | ||
85 | struct device_attribute *attr, char *buf) | ||
86 | { | ||
87 | return sprintf(buf, "max1111\n"); | ||
88 | } | ||
89 | |||
90 | static ssize_t show_adc(struct device *dev, | ||
91 | struct device_attribute *attr, char *buf) | ||
92 | { | ||
93 | int channel = to_sensor_dev_attr(attr)->index; | ||
94 | int ret; | ||
95 | |||
96 | ret = max1111_read(dev, channel); | ||
97 | if (ret < 0) | ||
98 | return ret; | ||
99 | |||
100 | return sprintf(buf, "%d\n", ret); | ||
101 | } | ||
102 | |||
103 | #define MAX1111_ADC_ATTR(_id) \ | ||
104 | SENSOR_DEVICE_ATTR(adc##_id##_in, S_IRUGO, show_adc, NULL, _id) | ||
105 | |||
106 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
107 | static MAX1111_ADC_ATTR(0); | ||
108 | static MAX1111_ADC_ATTR(1); | ||
109 | static MAX1111_ADC_ATTR(2); | ||
110 | static MAX1111_ADC_ATTR(3); | ||
111 | |||
112 | static struct attribute *max1111_attributes[] = { | ||
113 | &dev_attr_name.attr, | ||
114 | &sensor_dev_attr_adc0_in.dev_attr.attr, | ||
115 | &sensor_dev_attr_adc1_in.dev_attr.attr, | ||
116 | &sensor_dev_attr_adc2_in.dev_attr.attr, | ||
117 | &sensor_dev_attr_adc3_in.dev_attr.attr, | ||
118 | NULL, | ||
119 | }; | ||
120 | |||
121 | static const struct attribute_group max1111_attr_group = { | ||
122 | .attrs = max1111_attributes, | ||
123 | }; | ||
124 | |||
125 | static int setup_transfer(struct max1111_data *data) | ||
126 | { | ||
127 | struct spi_message *m; | ||
128 | struct spi_transfer *x; | ||
129 | |||
130 | data->tx_buf = kmalloc(MAX1111_TX_BUF_SIZE, GFP_KERNEL); | ||
131 | if (!data->tx_buf) | ||
132 | return -ENOMEM; | ||
133 | |||
134 | data->rx_buf = kmalloc(MAX1111_RX_BUF_SIZE, GFP_KERNEL); | ||
135 | if (!data->rx_buf) { | ||
136 | kfree(data->tx_buf); | ||
137 | return -ENOMEM; | ||
138 | } | ||
139 | |||
140 | m = &data->msg; | ||
141 | x = &data->xfer[0]; | ||
142 | |||
143 | spi_message_init(m); | ||
144 | |||
145 | x->tx_buf = &data->tx_buf[0]; | ||
146 | x->len = 1; | ||
147 | spi_message_add_tail(x, m); | ||
148 | |||
149 | x++; | ||
150 | x->rx_buf = &data->rx_buf[0]; | ||
151 | x->len = 2; | ||
152 | spi_message_add_tail(x, m); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int __devinit max1111_probe(struct spi_device *spi) | ||
158 | { | ||
159 | struct max1111_data *data; | ||
160 | int err; | ||
161 | |||
162 | spi->bits_per_word = 8; | ||
163 | spi->mode = SPI_MODE_0; | ||
164 | err = spi_setup(spi); | ||
165 | if (err < 0) | ||
166 | return err; | ||
167 | |||
168 | data = kzalloc(sizeof(struct max1111_data), GFP_KERNEL); | ||
169 | if (data == NULL) { | ||
170 | dev_err(&spi->dev, "failed to allocate memory\n"); | ||
171 | return -ENOMEM; | ||
172 | } | ||
173 | |||
174 | err = setup_transfer(data); | ||
175 | if (err) | ||
176 | goto err_free_data; | ||
177 | |||
178 | data->spi = spi; | ||
179 | spi_set_drvdata(spi, data); | ||
180 | |||
181 | err = sysfs_create_group(&spi->dev.kobj, &max1111_attr_group); | ||
182 | if (err) { | ||
183 | dev_err(&spi->dev, "failed to create attribute group\n"); | ||
184 | goto err_free_all; | ||
185 | } | ||
186 | |||
187 | data->hwmon_dev = hwmon_device_register(&spi->dev); | ||
188 | if (IS_ERR(data->hwmon_dev)) { | ||
189 | dev_err(&spi->dev, "failed to create hwmon device\n"); | ||
190 | err = PTR_ERR(data->hwmon_dev); | ||
191 | goto err_remove; | ||
192 | } | ||
193 | |||
194 | #ifdef CONFIG_SHARPSL_PM | ||
195 | the_max1111 = data; | ||
196 | #endif | ||
197 | return 0; | ||
198 | |||
199 | err_remove: | ||
200 | sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); | ||
201 | err_free_all: | ||
202 | kfree(data->rx_buf); | ||
203 | kfree(data->tx_buf); | ||
204 | err_free_data: | ||
205 | kfree(data); | ||
206 | return err; | ||
207 | } | ||
208 | |||
209 | static int __devexit max1111_remove(struct spi_device *spi) | ||
210 | { | ||
211 | struct max1111_data *data = spi_get_drvdata(spi); | ||
212 | |||
213 | hwmon_device_unregister(data->hwmon_dev); | ||
214 | sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); | ||
215 | kfree(data->rx_buf); | ||
216 | kfree(data->tx_buf); | ||
217 | kfree(data); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static struct spi_driver max1111_driver = { | ||
222 | .driver = { | ||
223 | .name = "max1111", | ||
224 | .owner = THIS_MODULE, | ||
225 | }, | ||
226 | .probe = max1111_probe, | ||
227 | .remove = __devexit_p(max1111_remove), | ||
228 | }; | ||
229 | |||
230 | static int __init max1111_init(void) | ||
231 | { | ||
232 | return spi_register_driver(&max1111_driver); | ||
233 | } | ||
234 | module_init(max1111_init); | ||
235 | |||
236 | static void __exit max1111_exit(void) | ||
237 | { | ||
238 | spi_unregister_driver(&max1111_driver); | ||
239 | } | ||
240 | module_exit(max1111_exit); | ||
241 | |||
242 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); | ||
243 | MODULE_DESCRIPTION("MAX1111 ADC Driver"); | ||
244 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c new file mode 100644 index 000000000000..68e90abeba96 --- /dev/null +++ b/drivers/hwmon/ultra45_env.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* ultra45_env.c: Driver for Ultra45 PIC16F747 environmental monitor. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/of_device.h> | ||
10 | #include <linux/io.h> | ||
11 | #include <linux/hwmon.h> | ||
12 | #include <linux/hwmon-sysfs.h> | ||
13 | |||
14 | #define DRV_MODULE_VERSION "0.1" | ||
15 | |||
16 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
17 | MODULE_DESCRIPTION("Ultra45 environmental monitor driver"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | MODULE_VERSION(DRV_MODULE_VERSION); | ||
20 | |||
21 | /* PIC device registers */ | ||
22 | #define REG_CMD 0x00UL | ||
23 | #define REG_CMD_RESET 0x80 | ||
24 | #define REG_CMD_ESTAR 0x01 | ||
25 | #define REG_STAT 0x01UL | ||
26 | #define REG_STAT_FWVER 0xf0 | ||
27 | #define REG_STAT_TGOOD 0x08 | ||
28 | #define REG_STAT_STALE 0x04 | ||
29 | #define REG_STAT_BUSY 0x02 | ||
30 | #define REG_STAT_FAULT 0x01 | ||
31 | #define REG_DATA 0x40UL | ||
32 | #define REG_ADDR 0x41UL | ||
33 | #define REG_SIZE 0x42UL | ||
34 | |||
35 | /* Registers accessed indirectly via REG_DATA/REG_ADDR */ | ||
36 | #define IREG_FAN0 0x00 | ||
37 | #define IREG_FAN1 0x01 | ||
38 | #define IREG_FAN2 0x02 | ||
39 | #define IREG_FAN3 0x03 | ||
40 | #define IREG_FAN4 0x04 | ||
41 | #define IREG_FAN5 0x05 | ||
42 | #define IREG_LCL_TEMP 0x06 | ||
43 | #define IREG_RMT1_TEMP 0x07 | ||
44 | #define IREG_RMT2_TEMP 0x08 | ||
45 | #define IREG_RMT3_TEMP 0x09 | ||
46 | #define IREG_LM95221_TEMP 0x0a | ||
47 | #define IREG_FIRE_TEMP 0x0b | ||
48 | #define IREG_LSI1064_TEMP 0x0c | ||
49 | #define IREG_FRONT_TEMP 0x0d | ||
50 | #define IREG_FAN_STAT 0x0e | ||
51 | #define IREG_VCORE0 0x0f | ||
52 | #define IREG_VCORE1 0x10 | ||
53 | #define IREG_VMEM0 0x11 | ||
54 | #define IREG_VMEM1 0x12 | ||
55 | #define IREG_PSU_TEMP 0x13 | ||
56 | |||
57 | struct env { | ||
58 | void __iomem *regs; | ||
59 | spinlock_t lock; | ||
60 | |||
61 | struct device *hwmon_dev; | ||
62 | }; | ||
63 | |||
64 | static u8 env_read(struct env *p, u8 ireg) | ||
65 | { | ||
66 | u8 ret; | ||
67 | |||
68 | spin_lock(&p->lock); | ||
69 | writeb(ireg, p->regs + REG_ADDR); | ||
70 | ret = readb(p->regs + REG_DATA); | ||
71 | spin_unlock(&p->lock); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | static void env_write(struct env *p, u8 ireg, u8 val) | ||
77 | { | ||
78 | spin_lock(&p->lock); | ||
79 | writeb(ireg, p->regs + REG_ADDR); | ||
80 | writeb(val, p->regs + REG_DATA); | ||
81 | spin_unlock(&p->lock); | ||
82 | } | ||
83 | |||
84 | /* There seems to be a adr7462 providing these values, thus a lot | ||
85 | * of these calculations are borrowed from the adt7470 driver. | ||
86 | */ | ||
87 | #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) | ||
88 | #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM | ||
89 | #define FAN_PERIOD_INVALID (0xff << 8) | ||
90 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | ||
91 | |||
92 | static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, char *buf) | ||
93 | { | ||
94 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
95 | struct env *p = dev_get_drvdata(dev); | ||
96 | int rpm, period; | ||
97 | u8 val; | ||
98 | |||
99 | val = env_read(p, IREG_FAN0 + fan_nr); | ||
100 | period = (int) val << 8; | ||
101 | if (FAN_DATA_VALID(period)) | ||
102 | rpm = FAN_PERIOD_TO_RPM(period); | ||
103 | else | ||
104 | rpm = 0; | ||
105 | |||
106 | return sprintf(buf, "%d\n", rpm); | ||
107 | } | ||
108 | |||
109 | static ssize_t set_fan_speed(struct device *dev, struct device_attribute *attr, | ||
110 | const char *buf, size_t count) | ||
111 | { | ||
112 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
113 | int rpm = simple_strtol(buf, NULL, 10); | ||
114 | struct env *p = dev_get_drvdata(dev); | ||
115 | int period; | ||
116 | u8 val; | ||
117 | |||
118 | if (!rpm) | ||
119 | return -EINVAL; | ||
120 | |||
121 | period = FAN_RPM_TO_PERIOD(rpm); | ||
122 | val = period >> 8; | ||
123 | env_write(p, IREG_FAN0 + fan_nr, val); | ||
124 | |||
125 | return count; | ||
126 | } | ||
127 | |||
128 | static ssize_t show_fan_fault(struct device *dev, struct device_attribute *attr, char *buf) | ||
129 | { | ||
130 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
131 | struct env *p = dev_get_drvdata(dev); | ||
132 | u8 val = env_read(p, IREG_FAN_STAT); | ||
133 | return sprintf(buf, "%d\n", (val & (1 << fan_nr)) ? 1 : 0); | ||
134 | } | ||
135 | |||
136 | #define fan(index) \ | ||
137 | static SENSOR_DEVICE_ATTR(fan##index##_speed, S_IRUGO | S_IWUSR, \ | ||
138 | show_fan_speed, set_fan_speed, index); \ | ||
139 | static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, \ | ||
140 | show_fan_fault, NULL, index) | ||
141 | |||
142 | fan(0); | ||
143 | fan(1); | ||
144 | fan(2); | ||
145 | fan(3); | ||
146 | fan(4); | ||
147 | |||
148 | static SENSOR_DEVICE_ATTR(psu_fan_fault, S_IRUGO, show_fan_fault, NULL, 6); | ||
149 | |||
150 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) | ||
151 | { | ||
152 | int temp_nr = to_sensor_dev_attr(attr)->index; | ||
153 | struct env *p = dev_get_drvdata(dev); | ||
154 | s8 val; | ||
155 | |||
156 | val = env_read(p, IREG_LCL_TEMP + temp_nr); | ||
157 | return sprintf(buf, "%d\n", ((int) val) - 64); | ||
158 | } | ||
159 | |||
160 | static SENSOR_DEVICE_ATTR(adt7462_local_temp, S_IRUGO, show_temp, NULL, 0); | ||
161 | static SENSOR_DEVICE_ATTR(cpu0_temp, S_IRUGO, show_temp, NULL, 1); | ||
162 | static SENSOR_DEVICE_ATTR(cpu1_temp, S_IRUGO, show_temp, NULL, 2); | ||
163 | static SENSOR_DEVICE_ATTR(motherboard_temp, S_IRUGO, show_temp, NULL, 3); | ||
164 | static SENSOR_DEVICE_ATTR(lm95221_local_temp, S_IRUGO, show_temp, NULL, 4); | ||
165 | static SENSOR_DEVICE_ATTR(fire_temp, S_IRUGO, show_temp, NULL, 5); | ||
166 | static SENSOR_DEVICE_ATTR(lsi1064_local_temp, S_IRUGO, show_temp, NULL, 6); | ||
167 | static SENSOR_DEVICE_ATTR(front_panel_temp, S_IRUGO, show_temp, NULL, 7); | ||
168 | static SENSOR_DEVICE_ATTR(psu_temp, S_IRUGO, show_temp, NULL, 13); | ||
169 | |||
170 | static ssize_t show_stat_bit(struct device *dev, struct device_attribute *attr, char *buf) | ||
171 | { | ||
172 | int index = to_sensor_dev_attr(attr)->index; | ||
173 | struct env *p = dev_get_drvdata(dev); | ||
174 | u8 val; | ||
175 | |||
176 | val = readb(p->regs + REG_STAT); | ||
177 | return sprintf(buf, "%d\n", (val & (1 << index)) ? 1 : 0); | ||
178 | } | ||
179 | |||
180 | static SENSOR_DEVICE_ATTR(fan_failure, S_IRUGO, show_stat_bit, NULL, 0); | ||
181 | static SENSOR_DEVICE_ATTR(env_bus_busy, S_IRUGO, show_stat_bit, NULL, 1); | ||
182 | static SENSOR_DEVICE_ATTR(env_data_stale, S_IRUGO, show_stat_bit, NULL, 2); | ||
183 | static SENSOR_DEVICE_ATTR(tpm_self_test_passed, S_IRUGO, show_stat_bit, NULL, 3); | ||
184 | |||
185 | static ssize_t show_fwver(struct device *dev, struct device_attribute *attr, char *buf) | ||
186 | { | ||
187 | struct env *p = dev_get_drvdata(dev); | ||
188 | u8 val; | ||
189 | |||
190 | val = readb(p->regs + REG_STAT); | ||
191 | return sprintf(buf, "%d\n", val >> 4); | ||
192 | } | ||
193 | |||
194 | static SENSOR_DEVICE_ATTR(firmware_version, S_IRUGO, show_fwver, NULL, 0); | ||
195 | |||
196 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
197 | { | ||
198 | return sprintf(buf, "ultra45\n"); | ||
199 | } | ||
200 | |||
201 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); | ||
202 | |||
203 | static struct attribute *env_attributes[] = { | ||
204 | &sensor_dev_attr_fan0_speed.dev_attr.attr, | ||
205 | &sensor_dev_attr_fan0_fault.dev_attr.attr, | ||
206 | &sensor_dev_attr_fan1_speed.dev_attr.attr, | ||
207 | &sensor_dev_attr_fan1_fault.dev_attr.attr, | ||
208 | &sensor_dev_attr_fan2_speed.dev_attr.attr, | ||
209 | &sensor_dev_attr_fan2_fault.dev_attr.attr, | ||
210 | &sensor_dev_attr_fan3_speed.dev_attr.attr, | ||
211 | &sensor_dev_attr_fan3_fault.dev_attr.attr, | ||
212 | &sensor_dev_attr_fan4_speed.dev_attr.attr, | ||
213 | &sensor_dev_attr_fan4_fault.dev_attr.attr, | ||
214 | &sensor_dev_attr_psu_fan_fault.dev_attr.attr, | ||
215 | &sensor_dev_attr_adt7462_local_temp.dev_attr.attr, | ||
216 | &sensor_dev_attr_cpu0_temp.dev_attr.attr, | ||
217 | &sensor_dev_attr_cpu1_temp.dev_attr.attr, | ||
218 | &sensor_dev_attr_motherboard_temp.dev_attr.attr, | ||
219 | &sensor_dev_attr_lm95221_local_temp.dev_attr.attr, | ||
220 | &sensor_dev_attr_fire_temp.dev_attr.attr, | ||
221 | &sensor_dev_attr_lsi1064_local_temp.dev_attr.attr, | ||
222 | &sensor_dev_attr_front_panel_temp.dev_attr.attr, | ||
223 | &sensor_dev_attr_psu_temp.dev_attr.attr, | ||
224 | &sensor_dev_attr_fan_failure.dev_attr.attr, | ||
225 | &sensor_dev_attr_env_bus_busy.dev_attr.attr, | ||
226 | &sensor_dev_attr_env_data_stale.dev_attr.attr, | ||
227 | &sensor_dev_attr_tpm_self_test_passed.dev_attr.attr, | ||
228 | &sensor_dev_attr_firmware_version.dev_attr.attr, | ||
229 | &sensor_dev_attr_name.dev_attr.attr, | ||
230 | NULL, | ||
231 | }; | ||
232 | |||
233 | static const struct attribute_group env_group = { | ||
234 | .attrs = env_attributes, | ||
235 | }; | ||
236 | |||
237 | static int __devinit env_probe(struct of_device *op, | ||
238 | const struct of_device_id *match) | ||
239 | { | ||
240 | struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
241 | int err = -ENOMEM; | ||
242 | |||
243 | if (!p) | ||
244 | goto out; | ||
245 | |||
246 | spin_lock_init(&p->lock); | ||
247 | |||
248 | p->regs = of_ioremap(&op->resource[0], 0, REG_SIZE, "pic16f747"); | ||
249 | if (!p->regs) | ||
250 | goto out_free; | ||
251 | |||
252 | err = sysfs_create_group(&op->dev.kobj, &env_group); | ||
253 | if (err) | ||
254 | goto out_iounmap; | ||
255 | |||
256 | p->hwmon_dev = hwmon_device_register(&op->dev); | ||
257 | if (IS_ERR(p->hwmon_dev)) { | ||
258 | err = PTR_ERR(p->hwmon_dev); | ||
259 | goto out_sysfs_remove_group; | ||
260 | } | ||
261 | |||
262 | dev_set_drvdata(&op->dev, p); | ||
263 | err = 0; | ||
264 | |||
265 | out: | ||
266 | return err; | ||
267 | |||
268 | out_sysfs_remove_group: | ||
269 | sysfs_remove_group(&op->dev.kobj, &env_group); | ||
270 | |||
271 | out_iounmap: | ||
272 | of_iounmap(&op->resource[0], p->regs, REG_SIZE); | ||
273 | |||
274 | out_free: | ||
275 | kfree(p); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | static int __devexit env_remove(struct of_device *op) | ||
280 | { | ||
281 | struct env *p = dev_get_drvdata(&op->dev); | ||
282 | |||
283 | if (p) { | ||
284 | sysfs_remove_group(&op->dev.kobj, &env_group); | ||
285 | hwmon_device_unregister(p->hwmon_dev); | ||
286 | of_iounmap(&op->resource[0], p->regs, REG_SIZE); | ||
287 | kfree(p); | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static const struct of_device_id env_match[] = { | ||
294 | { | ||
295 | .name = "env-monitor", | ||
296 | .compatible = "SUNW,ebus-pic16f747-env", | ||
297 | }, | ||
298 | {}, | ||
299 | }; | ||
300 | MODULE_DEVICE_TABLE(of, env_match); | ||
301 | |||
302 | static struct of_platform_driver env_driver = { | ||
303 | .name = "ultra45_env", | ||
304 | .match_table = env_match, | ||
305 | .probe = env_probe, | ||
306 | .remove = __devexit_p(env_remove), | ||
307 | }; | ||
308 | |||
309 | static int __init env_init(void) | ||
310 | { | ||
311 | return of_register_driver(&env_driver, &of_bus_type); | ||
312 | } | ||
313 | |||
314 | static void __exit env_exit(void) | ||
315 | { | ||
316 | of_unregister_driver(&env_driver); | ||
317 | } | ||
318 | |||
319 | module_init(env_init); | ||
320 | module_exit(env_exit); | ||