diff options
author | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2009-03-27 16:14:38 +0100 |
---|---|---|
committer | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2009-03-27 16:14:38 +0100 |
commit | b92efa9abffc4a634cd2e7a0f81f8aa6310d67c9 (patch) | |
tree | 9847508d9b8d4e585f90db4a453bfbc3700c997e /drivers/hwmon | |
parent | a16fffdd8eb95ebab7dc22414896fe6493951e0e (diff) | |
parent | be0ea69674ed95e1e98cb3687a241badc756d228 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into avr32-arch
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/Kconfig | 4 | ||||
-rw-r--r-- | drivers/hwmon/abituguru3.c | 7 | ||||
-rw-r--r-- | drivers/hwmon/applesmc.c | 30 | ||||
-rw-r--r-- | drivers/hwmon/f71882fg.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/f75375s.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/hp_accel.c | 94 | ||||
-rw-r--r-- | drivers/hwmon/it87.c | 8 | ||||
-rw-r--r-- | drivers/hwmon/lis3lv02d.c | 195 | ||||
-rw-r--r-- | drivers/hwmon/lis3lv02d.h | 21 | ||||
-rw-r--r-- | drivers/hwmon/lm85.c | 8 | ||||
-rw-r--r-- | drivers/hwmon/lm90.c | 8 | ||||
-rw-r--r-- | drivers/hwmon/vt1211.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 2 |
13 files changed, 321 insertions, 64 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index b84bf066879..b4eea0292c1 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -543,8 +543,8 @@ config SENSORS_LM90 help If you say yes here you get support for National Semiconductor LM90, LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim - MAX6646, MAX6647, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680 and - MAX6681 sensor chips. + MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, + MAX6680, MAX6681 and MAX6692 sensor chips. This driver can also be built as a module. If so, the module will be called lm90. diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index e52b38806d0..ad2b3431b72 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -760,8 +760,11 @@ static int abituguru3_read_increment_offset(struct abituguru3_data *data, for (i = 0; i < offset_count; i++) if ((x = abituguru3_read(data, bank, offset + i, count, - buf + i * count)) != count) - return i * count + (i && (x < 0)) ? 0 : x; + buf + i * count)) != count) { + if (x < 0) + return x; + return i * count + x; + } return i * count; } diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index e3018623658..678e34b01e5 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -83,7 +83,7 @@ /* * Temperature sensors keys (sp78 - 2 bytes). */ -static const char* temperature_sensors_sets[][36] = { +static const char *temperature_sensors_sets[][41] = { /* Set 0: Macbook Pro */ { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H", "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL }, @@ -135,6 +135,13 @@ static const char* temperature_sensors_sets[][36] = { { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TN0D", "TTF0", "TV0P", "TVFP", "TW0P", "Th0P", "Tp0P", "Tp1P", "TpFP", "Ts0P", "Ts0S", NULL }, +/* Set 16: Mac Pro 3,1 (2 x Quad-Core) */ + { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P", + "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "TH0P", "TH1P", + "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", "TM1P", + "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S", + "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S", + NULL }, }; /* List of keys used to read/write fan speeds */ @@ -1153,6 +1160,16 @@ static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO, applesmc_show_temperature, NULL, 33); static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO, applesmc_show_temperature, NULL, 34); +static SENSOR_DEVICE_ATTR(temp36_input, S_IRUGO, + applesmc_show_temperature, NULL, 35); +static SENSOR_DEVICE_ATTR(temp37_input, S_IRUGO, + applesmc_show_temperature, NULL, 36); +static SENSOR_DEVICE_ATTR(temp38_input, S_IRUGO, + applesmc_show_temperature, NULL, 37); +static SENSOR_DEVICE_ATTR(temp39_input, S_IRUGO, + applesmc_show_temperature, NULL, 38); +static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO, + applesmc_show_temperature, NULL, 39); static struct attribute *temperature_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -1190,6 +1207,11 @@ static struct attribute *temperature_attributes[] = { &sensor_dev_attr_temp33_input.dev_attr.attr, &sensor_dev_attr_temp34_input.dev_attr.attr, &sensor_dev_attr_temp35_input.dev_attr.attr, + &sensor_dev_attr_temp36_input.dev_attr.attr, + &sensor_dev_attr_temp37_input.dev_attr.attr, + &sensor_dev_attr_temp38_input.dev_attr.attr, + &sensor_dev_attr_temp39_input.dev_attr.attr, + &sensor_dev_attr_temp40_input.dev_attr.attr, NULL }; @@ -1312,6 +1334,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 0, .light = 0, .temperature_set = 14 }, /* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */ { .accelerometer = 1, .light = 1, .temperature_set = 15 }, +/* MacPro3,1: temperature set 16 */ + { .accelerometer = 0, .light = 0, .temperature_set = 16 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1369,6 +1393,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, &applesmc_dmi_data[4]}, + { applesmc_dmi_match, "Apple MacPro3", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacPro3") }, + &applesmc_dmi_data[16]}, { applesmc_dmi_match, "Apple MacPro", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 609cafff86b..5f81ddf7150 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -1872,7 +1872,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { - printk(KERN_INFO DRVNAME ": Not a Fintek device\n"); + pr_debug(DRVNAME ": Not a Fintek device\n"); goto exit; } @@ -1932,7 +1932,7 @@ static int __init f71882fg_device_add(unsigned short address, res.name = f71882fg_pdev->name; err = acpi_check_resource_conflict(&res); if (err) - return err; + goto exit_device_put; err = platform_device_add_resources(f71882fg_pdev, &res, 1); if (err) { diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 1692de36996..18a1ba88816 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -617,7 +617,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data, static int f75375_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct f75375_data *data = i2c_get_clientdata(client); + struct f75375_data *data; struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data; int err; diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 03705240000..29c83b5b969 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -153,7 +153,10 @@ static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3}; static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3}; static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3}; static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3}; +static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3}; static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3}; +static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3}; +static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3}; #define AXIS_DMI_MATCH(_ident, _name, _axis) { \ .ident = _ident, \ @@ -163,6 +166,18 @@ static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3}; }, \ .driver_data = &lis3lv02d_axis_##_axis \ } + +#define AXIS_DMI_MATCH2(_ident, _class1, _name1, \ + _class2, _name2, \ + _axis) { \ + .ident = _ident, \ + .callback = lis3lv02d_dmi_matched, \ + .matches = { \ + DMI_MATCH(DMI_##_class1, _name1), \ + DMI_MATCH(DMI_##_class2, _name2), \ + }, \ + .driver_data = &lis3lv02d_axis_##_axis \ +} static struct dmi_system_id lis3lv02d_dmi_ids[] = { /* product names are truncated to match all kinds of a same model */ AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), @@ -172,10 +187,22 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), + AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), + AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), + AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), + AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted), + /* Intel-based HP Pavilion dv5 */ + AXIS_DMI_MATCH2("HPDV5_I", + PRODUCT_NAME, "HP Pavilion dv5", + BOARD_NAME, "3603", + x_inverted), + /* AMD-based HP Pavilion dv5 */ + AXIS_DMI_MATCH2("HPDV5_A", + PRODUCT_NAME, "HP Pavilion dv5", + BOARD_NAME, "3600", + y_inverted), { NULL, } /* Laptop models without axis info (yet): - * "NC651xx" "HP Compaq 651" - * "NC671xx" "HP Compaq 671" * "NC6910" "HP Compaq 6910" * HP Compaq 8710x Notebook PC / Mobile Workstation * "NC2400" "HP Compaq nc2400" @@ -208,9 +235,49 @@ static struct delayed_led_classdev hpled_led = { .set_brightness = hpled_set, }; +static acpi_status +lis3lv02d_get_resource(struct acpi_resource *resource, void *context) +{ + if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { + struct acpi_resource_extended_irq *irq; + u32 *device_irq = context; + + irq = &resource->data.extended_irq; + *device_irq = irq->interrupts[0]; + } + + return AE_OK; +} + +static void lis3lv02d_enum_resources(struct acpi_device *device) +{ + acpi_status status; + + status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + lis3lv02d_get_resource, &adev.irq); + if (ACPI_FAILURE(status)) + printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); +} + +static s16 lis3lv02d_read_16(acpi_handle handle, int reg) +{ + u8 lo, hi; + + adev.read(handle, reg - 1, &lo); + adev.read(handle, reg, &hi); + /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ + return (s16)((hi << 8) | lo); +} + +static s16 lis3lv02d_read_8(acpi_handle handle, int reg) +{ + s8 lo; + adev.read(handle, reg, &lo); + return lo; +} + static int lis3lv02d_add(struct acpi_device *device) { - u8 val; int ret; if (!device) @@ -224,10 +291,22 @@ static int lis3lv02d_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); device->driver_data = &adev; - lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val); - if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) { + lis3lv02d_acpi_read(device->handle, WHO_AM_I, &adev.whoami); + switch (adev.whoami) { + case LIS_DOUBLE_ID: + printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n"); + adev.read_data = lis3lv02d_read_16; + adev.mdps_max_val = 2048; + break; + case LIS_SINGLE_ID: + printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n"); + adev.read_data = lis3lv02d_read_8; + adev.mdps_max_val = 128; + break; + default: printk(KERN_ERR DRIVER_NAME - ": Accelerometer chip not LIS3LV02D{L,Q}\n"); + ": unknown sensor type 0x%X\n", adev.whoami); + return -EINVAL; } /* If possible use a "standard" axes order */ @@ -242,6 +321,9 @@ static int lis3lv02d_add(struct acpi_device *device) if (ret) return ret; + /* obtain IRQ number of our device from ACPI */ + lis3lv02d_enum_resources(adev.device); + ret = lis3lv02d_init_device(&adev); if (ret) { flush_work(&hpled_led.work); diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 95a99c590da..9157247fed8 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -213,7 +213,7 @@ static inline u16 FAN16_TO_REG(long rpm) #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ ((val)+500)/1000),-128,127)) -#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000) +#define TEMP_FROM_REG(val) ((val) * 1000) #define PWM_TO_REG(val) ((val) >> 1) #define PWM_FROM_REG(val) (((val)&0x7f) << 1) @@ -267,9 +267,9 @@ struct it87_data { u8 has_fan; /* Bitfield, fans enabled */ u16 fan[5]; /* Register values, possibly combined */ u16 fan_min[5]; /* Register values, possibly combined */ - u8 temp[3]; /* Register value */ - u8 temp_high[3]; /* Register value */ - u8 temp_low[3]; /* Register value */ + s8 temp[3]; /* Register value */ + s8 temp_high[3]; /* Register value */ + s8 temp_low[3]; /* Register value */ u8 sensor; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 219d2d0d5a6..8bb2158f045 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c @@ -3,7 +3,7 @@ * * Copyright (C) 2007-2008 Yan Burman * Copyright (C) 2008 Eric Piel - * Copyright (C) 2008 Pavel Machek + * Copyright (C) 2008-2009 Pavel Machek * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +35,7 @@ #include <linux/poll.h> #include <linux/freezer.h> #include <linux/uaccess.h> +#include <linux/miscdevice.h> #include <acpi/acpi_drivers.h> #include <asm/atomic.h> #include "lis3lv02d.h" @@ -52,24 +53,14 @@ * joystick. */ -/* Maximum value our axis may get for the input device (signed 12 bits) */ -#define MDPS_MAX_VAL 2048 +struct acpi_lis3lv02d adev = { + .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(adev.misc_wait), +}; -struct acpi_lis3lv02d adev; EXPORT_SYMBOL_GPL(adev); static int lis3lv02d_add_fs(struct acpi_device *device); -static s16 lis3lv02d_read_16(acpi_handle handle, int reg) -{ - u8 lo, hi; - - adev.read(handle, reg, &lo); - adev.read(handle, reg + 1, &hi); - /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ - return (s16)((hi << 8) | lo); -} - /** * lis3lv02d_get_axis - For the given axis, give the value converted * @axis: 1,2,3 - can also be negative @@ -98,9 +89,9 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z) { int position[3]; - position[0] = lis3lv02d_read_16(handle, OUTX_L); - position[1] = lis3lv02d_read_16(handle, OUTY_L); - position[2] = lis3lv02d_read_16(handle, OUTZ_L); + position[0] = adev.read_data(handle, OUTX); + position[1] = adev.read_data(handle, OUTY); + position[2] = adev.read_data(handle, OUTZ); *x = lis3lv02d_get_axis(adev.ac.x, position); *y = lis3lv02d_get_axis(adev.ac.y, position); @@ -110,26 +101,13 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z) void lis3lv02d_poweroff(acpi_handle handle) { adev.is_on = 0; - /* disable X,Y,Z axis and power down */ - adev.write(handle, CTRL_REG1, 0x00); } EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); void lis3lv02d_poweron(acpi_handle handle) { - u8 val; - adev.is_on = 1; adev.init(handle); - adev.write(handle, FF_WU_CFG, 0); - /* - * BDU: LSB and MSB values are not updated until both have been read. - * So the value read will always be correct. - * IEN: Interrupt for free-fall and DD, not for data-ready. - */ - adev.read(handle, CTRL_REG2, &val); - val |= CTRL2_BDU | CTRL2_IEN; - adev.write(handle, CTRL_REG2, val); } EXPORT_SYMBOL_GPL(lis3lv02d_poweron); @@ -162,6 +140,140 @@ static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev) mutex_unlock(&dev->lock); } +static irqreturn_t lis302dl_interrupt(int irq, void *dummy) +{ + /* + * Be careful: on some HP laptops the bios force DD when on battery and + * the lid is closed. This leads to interrupts as soon as a little move + * is done. + */ + atomic_inc(&adev.count); + + wake_up_interruptible(&adev.misc_wait); + kill_fasync(&adev.async_queue, SIGIO, POLL_IN); + return IRQ_HANDLED; +} + +static int lis3lv02d_misc_open(struct inode *inode, struct file *file) +{ + int ret; + + if (test_and_set_bit(0, &adev.misc_opened)) + return -EBUSY; /* already open */ + + atomic_set(&adev.count, 0); + + /* + * The sensor can generate interrupts for free-fall and direction + * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep + * the things simple and _fast_ we activate it only for free-fall, so + * no need to read register (very slow with ACPI). For the same reason, + * we forbid shared interrupts. + * + * IRQF_TRIGGER_RISING seems pointless on HP laptops because the + * io-apic is not configurable (and generates a warning) but I keep it + * in case of support for other hardware. + */ + ret = request_irq(adev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING, + DRIVER_NAME, &adev); + + if (ret) { + clear_bit(0, &adev.misc_opened); + printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", adev.irq); + return -EBUSY; + } + lis3lv02d_increase_use(&adev); + printk("lis3: registered interrupt %d\n", adev.irq); + return 0; +} + +static int lis3lv02d_misc_release(struct inode *inode, struct file *file) +{ + fasync_helper(-1, file, 0, &adev.async_queue); + lis3lv02d_decrease_use(&adev); + free_irq(adev.irq, &adev); + clear_bit(0, &adev.misc_opened); /* release the device */ + return 0; +} + +static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + DECLARE_WAITQUEUE(wait, current); + u32 data; + unsigned char byte_data; + ssize_t retval = 1; + + if (count < 1) + return -EINVAL; + + add_wait_queue(&adev.misc_wait, &wait); + while (true) { + set_current_state(TASK_INTERRUPTIBLE); + data = atomic_xchg(&adev.count, 0); + if (data) + break; + + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + + schedule(); + } + + if (data < 255) + byte_data = data; + else + byte_data = 255; + + /* make sure we are not going into copy_to_user() with + * TASK_INTERRUPTIBLE state */ + set_current_state(TASK_RUNNING); + if (copy_to_user(buf, &byte_data, sizeof(byte_data))) + retval = -EFAULT; + +out: + __set_current_state(TASK_RUNNING); + remove_wait_queue(&adev.misc_wait, &wait); + + return retval; +} + +static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &adev.misc_wait, wait); + if (atomic_read(&adev.count)) + return POLLIN | POLLRDNORM; + return 0; +} + +static int lis3lv02d_misc_fasync(int fd, struct file *file, int on) +{ + return fasync_helper(fd, file, on, &adev.async_queue); +} + +static const struct file_operations lis3lv02d_misc_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = lis3lv02d_misc_read, + .open = lis3lv02d_misc_open, + .release = lis3lv02d_misc_release, + .poll = lis3lv02d_misc_poll, + .fasync = lis3lv02d_misc_fasync, +}; + +static struct miscdevice lis3lv02d_misc_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "freefall", + .fops = &lis3lv02d_misc_fops, +}; + /** * lis3lv02d_joystick_kthread - Kthread polling function * @data: unused - here to conform to threadfn prototype @@ -203,7 +315,6 @@ static void lis3lv02d_joystick_close(struct input_dev *input) lis3lv02d_decrease_use(&adev); } - static inline void lis3lv02d_calibrate_joystick(void) { lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib); @@ -231,9 +342,9 @@ int lis3lv02d_joystick_enable(void) adev.idev->close = lis3lv02d_joystick_close; set_bit(EV_ABS, adev.idev->evbit); - input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); - input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); - input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); + input_set_abs_params(adev.idev, ABS_X, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); + input_set_abs_params(adev.idev, ABS_Y, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); + input_set_abs_params(adev.idev, ABS_Z, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); err = input_register_device(adev.idev); if (err) { @@ -250,6 +361,7 @@ void lis3lv02d_joystick_disable(void) if (!adev.idev) return; + misc_deregister(&lis3lv02d_misc_device); input_unregister_device(adev.idev); adev.idev = NULL; } @@ -268,6 +380,19 @@ int lis3lv02d_init_device(struct acpi_lis3lv02d *dev) if (lis3lv02d_joystick_enable()) printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); + printk("lis3_init_device: irq %d\n", dev->irq); + + /* if we did not get an IRQ from ACPI - we have nothing more to do */ + if (!dev->irq) { + printk(KERN_ERR DRIVER_NAME + ": No IRQ in ACPI. Disabling /dev/freefall\n"); + goto out; + } + + printk("lis3: registering device\n"); + if (misc_register(&lis3lv02d_misc_device)) + printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); +out: lis3lv02d_decrease_use(dev); return 0; } @@ -351,6 +476,6 @@ int lis3lv02d_remove_fs(void) EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); -MODULE_AUTHOR("Yan Burman and Eric Piel"); +MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h index 223f1c0763b..75972bf372f 100644 --- a/drivers/hwmon/lis3lv02d.h +++ b/drivers/hwmon/lis3lv02d.h @@ -22,12 +22,15 @@ /* * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to * be connected via SPI. There exists also several similar chips (such as LIS302DL or - * LIS3L02DQ) but not in the HP laptops and they have slightly different registers. + * LIS3L02DQ) and they have slightly different registers, but we can provide a + * common interface for all of them. * They can also be connected via I²C. */ -#define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */ -#define LIS302DL_ID 0x3B /* Also the LIS202DL! */ +/* 2-byte registers */ +#define LIS_DOUBLE_ID 0x3A /* LIS3LV02D[LQ] */ +/* 1-byte registers */ +#define LIS_SINGLE_ID 0x3B /* LIS[32]02DL and others */ enum lis3lv02d_reg { WHO_AM_I = 0x0F, @@ -44,10 +47,13 @@ enum lis3lv02d_reg { STATUS_REG = 0x27, OUTX_L = 0x28, OUTX_H = 0x29, + OUTX = 0x29, OUTY_L = 0x2A, OUTY_H = 0x2B, + OUTY = 0x2B, OUTZ_L = 0x2C, OUTZ_H = 0x2D, + OUTZ = 0x2D, FF_WU_CFG = 0x30, FF_WU_SRC = 0x31, FF_WU_ACK = 0x32, @@ -159,6 +165,10 @@ struct acpi_lis3lv02d { acpi_status (*write) (acpi_handle handle, int reg, u8 val); acpi_status (*read) (acpi_handle handle, int reg, u8 *ret); + u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */ + s16 (*read_data) (acpi_handle handle, int reg); + int mdps_max_val; + struct input_dev *idev; /* input device */ struct task_struct *kthread; /* kthread for input */ struct mutex lock; @@ -170,6 +180,11 @@ struct acpi_lis3lv02d { unsigned char is_on; /* whether the device is on or off */ unsigned char usage; /* usage counter */ struct axis_conversion ac; /* hw -> logical axis */ + + u32 irq; /* IRQ number */ + struct fasync_struct *async_queue; /* queue for the misc device */ + wait_queue_head_t misc_wait; /* Wait queue for the misc device */ + unsigned long misc_opened; /* bit0: whether the device is open */ }; int lis3lv02d_init_device(struct acpi_lis3lv02d *dev); diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index cfc1ee90f5a..b251d8674b4 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -72,6 +72,7 @@ I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100, #define LM85_COMPANY_SMSC 0x5c #define LM85_VERSTEP_VMASK 0xf0 #define LM85_VERSTEP_GENERIC 0x60 +#define LM85_VERSTEP_GENERIC2 0x70 #define LM85_VERSTEP_LM85C 0x60 #define LM85_VERSTEP_LM85B 0x62 #define LM85_VERSTEP_ADM1027 0x60 @@ -334,6 +335,7 @@ static struct lm85_data *lm85_update_device(struct device *dev); static const struct i2c_device_id lm85_id[] = { { "adm1027", adm1027 }, { "adt7463", adt7463 }, + { "adt7468", adt7468 }, { "lm85", any_chip }, { "lm85b", lm85b }, { "lm85c", lm85c }, @@ -408,7 +410,8 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, struct lm85_data *data = lm85_update_device(dev); int vid; - if (data->type == adt7463 && (data->vid & 0x80)) { + if ((data->type == adt7463 || data->type == adt7468) && + (data->vid & 0x80)) { /* 6-pin VID (VRM 10) */ vid = vid_from_reg(data->vid & 0x3f, data->vrm); } else { @@ -1153,7 +1156,8 @@ static int lm85_detect(struct i2c_client *client, int kind, address, company, verstep); /* All supported chips have the version in common */ - if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC) { + if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC && + (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) { dev_dbg(&adapter->dev, "Autodetection failed: " "unsupported version\n"); return -ENODEV; diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 96a70186672..1aff7575799 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -32,10 +32,10 @@ * supported by this driver. These chips lack the remote temperature * offset feature. * - * This driver also supports the MAX6646, MAX6647 and MAX6649 chips - * made by Maxim. These are again similar to the LM86, but they use - * unsigned temperature values and can report temperatures from 0 to - * 145 degrees. + * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and + * MAX6692 chips made by Maxim. These are again similar to the LM86, + * but they use unsigned temperature values and can report temperatures + * from 0 to 145 degrees. * * This driver also supports the MAX6680 and MAX6681, two other sensor * chips made by Maxim. These are quite similar to the other Maxim diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index b0ce3785228..73f77a9b8b1 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -1262,7 +1262,7 @@ static int __init vt1211_device_add(unsigned short address) res.name = pdev->name; err = acpi_check_resource_conflict(&res); if (err) - goto EXIT; + goto EXIT_DEV_PUT; err = platform_device_add_resources(pdev, &res, 1); if (err) { diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index cb808d01536..feae743ba99 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -1548,7 +1548,7 @@ static int __init sensors_w83627ehf_init(void) err = acpi_check_resource_conflict(&res); if (err) - goto exit; + goto exit_device_put; err = platform_device_add_resources(pdev, &res, 1); if (err) { |