aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-16 22:50:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-16 22:50:13 -0400
commit517d08699b250021303f9a7cf0d758b6dc0748ed (patch)
tree5e5b0134c3fffb78fe9d8b1641a64ff28fdd7bbc /drivers/hwmon
parent8eeee4e2f04fc551f50c9d9847da2d73d7d33728 (diff)
parenta34601c5d84134055782ee031d58d82f5440e918 (diff)
Merge branch 'akpm'
* akpm: (182 commits) fbdev: bf54x-lq043fb: use kzalloc over kmalloc/memset fbdev: *bfin*: fix __dev{init,exit} markings fbdev: *bfin*: drop unnecessary calls to memset fbdev: bfin-t350mcqb-fb: drop unused local variables fbdev: blackfin has __raw I/O accessors, so use them in fb.h fbdev: s1d13xxxfb: add accelerated bitblt functions tcx: use standard fields for framebuffer physical address and length fbdev: add support for handoff from firmware to hw framebuffers intelfb: fix a bug when changing video timing fbdev: use framebuffer_release() for freeing fb_info structures radeon: P2G2CLK_ALWAYS_ONb tested twice, should 2nd be P2G2CLK_DAC_ALWAYS_ONb? s3c-fb: CPUFREQ frequency scaling support s3c-fb: fix resource releasing on error during probing carminefb: fix possible access beyond end of carmine_modedb[] acornfb: remove fb_mmap function mb862xxfb: use CONFIG_OF instead of CONFIG_PPC_OF mb862xxfb: restrict compliation of platform driver to PPC Samsung SoC Framebuffer driver: add Alpha Channel support atmel-lcdc: fix pixclock upper bound detection offb: use framebuffer_alloc() to allocate fb_info struct ... Manually fix up conflicts due to kmemcheck in mm/slab.c
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig2
-rw-r--r--drivers/hwmon/hp_accel.c20
-rw-r--r--drivers/hwmon/lis3lv02d.c187
-rw-r--r--drivers/hwmon/lis3lv02d.h29
-rw-r--r--drivers/hwmon/lis3lv02d_spi.c1
5 files changed, 106 insertions, 133 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f8090e137fef..2d5016691d40 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -950,6 +950,7 @@ config SENSORS_HDAPS
950config SENSORS_LIS3LV02D 950config SENSORS_LIS3LV02D
951 tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer" 951 tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
952 depends on ACPI && INPUT 952 depends on ACPI && INPUT
953 select INPUT_POLLDEV
953 select NEW_LEDS 954 select NEW_LEDS
954 select LEDS_CLASS 955 select LEDS_CLASS
955 default n 956 default n
@@ -977,6 +978,7 @@ config SENSORS_LIS3LV02D
977config SENSORS_LIS3_SPI 978config SENSORS_LIS3_SPI
978 tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)" 979 tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
979 depends on !ACPI && SPI_MASTER && INPUT 980 depends on !ACPI && SPI_MASTER && INPUT
981 select INPUT_POLLDEV
980 default n 982 default n
981 help 983 help
982 This driver provides support for the LIS3LV02Dx accelerometer connected 984 This driver provides support for the LIS3LV02Dx accelerometer connected
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index abca7e9f953b..6679854c85b0 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -27,9 +27,6 @@
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/input.h>
31#include <linux/kthread.h>
32#include <linux/semaphore.h>
33#include <linux/delay.h> 30#include <linux/delay.h>
34#include <linux/wait.h> 31#include <linux/wait.h>
35#include <linux/poll.h> 32#include <linux/poll.h>
@@ -161,6 +158,7 @@ static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3};
161static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3}; 158static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
162static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3}; 159static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
163static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3}; 160static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
161static struct axis_conversion lis3lv02d_axis_xy_swap = {2, 1, 3};
164static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3}; 162static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
165static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3}; 163static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
166static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3}; 164static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
@@ -194,13 +192,16 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
194 AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted), 192 AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
195 AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted), 193 AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
196 AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), 194 AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
195 AXIS_DMI_MATCH("NC2710", "HP Compaq 2710", xy_swap),
197 AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), 196 AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
198 AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), 197 AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
199 AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted), 198 AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
200 AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), 199 AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
201 AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), 200 AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
202 AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), 201 AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
203 AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted), 202 AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
203 AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
204 AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
204 /* Intel-based HP Pavilion dv5 */ 205 /* Intel-based HP Pavilion dv5 */
205 AXIS_DMI_MATCH2("HPDV5_I", 206 AXIS_DMI_MATCH2("HPDV5_I",
206 PRODUCT_NAME, "HP Pavilion dv5", 207 PRODUCT_NAME, "HP Pavilion dv5",
@@ -216,7 +217,6 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
216 { NULL, } 217 { NULL, }
217/* Laptop models without axis info (yet): 218/* Laptop models without axis info (yet):
218 * "NC6910" "HP Compaq 6910" 219 * "NC6910" "HP Compaq 6910"
219 * HP Compaq 8710x Notebook PC / Mobile Workstation
220 * "NC2400" "HP Compaq nc2400" 220 * "NC2400" "HP Compaq nc2400"
221 * "NX74x0" "HP Compaq nx74" 221 * "NX74x0" "HP Compaq nx74"
222 * "NX6325" "HP Compaq nx6325" 222 * "NX6325" "HP Compaq nx6325"
@@ -324,7 +324,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
324 flush_work(&hpled_led.work); 324 flush_work(&hpled_led.work);
325 led_classdev_unregister(&hpled_led.led_classdev); 325 led_classdev_unregister(&hpled_led.led_classdev);
326 326
327 return lis3lv02d_remove_fs(); 327 return lis3lv02d_remove_fs(&lis3_dev);
328} 328}
329 329
330 330
@@ -338,13 +338,7 @@ static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
338 338
339static int lis3lv02d_resume(struct acpi_device *device) 339static int lis3lv02d_resume(struct acpi_device *device)
340{ 340{
341 /* put back the device in the right state (ACPI might turn it on) */ 341 lis3lv02d_poweron(&lis3_dev);
342 mutex_lock(&lis3_dev.lock);
343 if (lis3_dev.usage > 0)
344 lis3lv02d_poweron(&lis3_dev);
345 else
346 lis3lv02d_poweroff(&lis3_dev);
347 mutex_unlock(&lis3_dev.lock);
348 return 0; 342 return 0;
349} 343}
350#else 344#else
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 778eb7795983..271338bdb6be 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -27,9 +27,7 @@
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/input.h> 30#include <linux/input-polldev.h>
31#include <linux/kthread.h>
32#include <linux/semaphore.h>
33#include <linux/delay.h> 31#include <linux/delay.h>
34#include <linux/wait.h> 32#include <linux/wait.h>
35#include <linux/poll.h> 33#include <linux/poll.h>
@@ -105,56 +103,39 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
105{ 103{
106 int position[3]; 104 int position[3];
107 105
108 position[0] = lis3_dev.read_data(lis3, OUTX); 106 position[0] = lis3->read_data(lis3, OUTX);
109 position[1] = lis3_dev.read_data(lis3, OUTY); 107 position[1] = lis3->read_data(lis3, OUTY);
110 position[2] = lis3_dev.read_data(lis3, OUTZ); 108 position[2] = lis3->read_data(lis3, OUTZ);
111 109
112 *x = lis3lv02d_get_axis(lis3_dev.ac.x, position); 110 *x = lis3lv02d_get_axis(lis3->ac.x, position);
113 *y = lis3lv02d_get_axis(lis3_dev.ac.y, position); 111 *y = lis3lv02d_get_axis(lis3->ac.y, position);
114 *z = lis3lv02d_get_axis(lis3_dev.ac.z, position); 112 *z = lis3lv02d_get_axis(lis3->ac.z, position);
115} 113}
116 114
117void lis3lv02d_poweroff(struct lis3lv02d *lis3) 115void lis3lv02d_poweroff(struct lis3lv02d *lis3)
118{ 116{
119 lis3_dev.is_on = 0; 117 /* disable X,Y,Z axis and power down */
118 lis3->write(lis3, CTRL_REG1, 0x00);
120} 119}
121EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); 120EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
122 121
123void lis3lv02d_poweron(struct lis3lv02d *lis3) 122void lis3lv02d_poweron(struct lis3lv02d *lis3)
124{ 123{
125 lis3_dev.is_on = 1; 124 u8 reg;
126 lis3_dev.init(lis3);
127}
128EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
129 125
130/* 126 lis3->init(lis3);
131 * To be called before starting to use the device. It makes sure that the
132 * device will always be on until a call to lis3lv02d_decrease_use(). Not to be
133 * used from interrupt context.
134 */
135static void lis3lv02d_increase_use(struct lis3lv02d *dev)
136{
137 mutex_lock(&dev->lock);
138 dev->usage++;
139 if (dev->usage == 1) {
140 if (!dev->is_on)
141 lis3lv02d_poweron(dev);
142 }
143 mutex_unlock(&dev->lock);
144}
145 127
146/* 128 /*
147 * To be called whenever a usage of the device is stopped. 129 * Common configuration
148 * It will make sure to turn off the device when there is not usage. 130 * BDU: LSB and MSB values are not updated until both have been read.
149 */ 131 * So the value read will always be correct.
150static void lis3lv02d_decrease_use(struct lis3lv02d *dev) 132 */
151{ 133 lis3->read(lis3, CTRL_REG2, &reg);
152 mutex_lock(&dev->lock); 134 reg |= CTRL2_BDU;
153 dev->usage--; 135 lis3->write(lis3, CTRL_REG2, reg);
154 if (dev->usage == 0)
155 lis3lv02d_poweroff(dev);
156 mutex_unlock(&dev->lock);
157} 136}
137EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
138
158 139
159static irqreturn_t lis302dl_interrupt(int irq, void *dummy) 140static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
160{ 141{
@@ -198,15 +179,12 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
198 printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq); 179 printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq);
199 return -EBUSY; 180 return -EBUSY;
200 } 181 }
201 lis3lv02d_increase_use(&lis3_dev);
202 printk("lis3: registered interrupt %d\n", lis3_dev.irq);
203 return 0; 182 return 0;
204} 183}
205 184
206static int lis3lv02d_misc_release(struct inode *inode, struct file *file) 185static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
207{ 186{
208 fasync_helper(-1, file, 0, &lis3_dev.async_queue); 187 fasync_helper(-1, file, 0, &lis3_dev.async_queue);
209 lis3lv02d_decrease_use(&lis3_dev);
210 free_irq(lis3_dev.irq, &lis3_dev); 188 free_irq(lis3_dev.irq, &lis3_dev);
211 clear_bit(0, &lis3_dev.misc_opened); /* release the device */ 189 clear_bit(0, &lis3_dev.misc_opened); /* release the device */
212 return 0; 190 return 0;
@@ -290,46 +268,16 @@ static struct miscdevice lis3lv02d_misc_device = {
290 .fops = &lis3lv02d_misc_fops, 268 .fops = &lis3lv02d_misc_fops,
291}; 269};
292 270
293/** 271static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
294 * lis3lv02d_joystick_kthread - Kthread polling function
295 * @data: unused - here to conform to threadfn prototype
296 */
297static int lis3lv02d_joystick_kthread(void *data)
298{ 272{
299 int x, y, z; 273 int x, y, z;
300 274
301 while (!kthread_should_stop()) { 275 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
302 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); 276 input_report_abs(pidev->input, ABS_X, x - lis3_dev.xcalib);
303 input_report_abs(lis3_dev.idev, ABS_X, x - lis3_dev.xcalib); 277 input_report_abs(pidev->input, ABS_Y, y - lis3_dev.ycalib);
304 input_report_abs(lis3_dev.idev, ABS_Y, y - lis3_dev.ycalib); 278 input_report_abs(pidev->input, ABS_Z, z - lis3_dev.zcalib);
305 input_report_abs(lis3_dev.idev, ABS_Z, z - lis3_dev.zcalib);
306
307 input_sync(lis3_dev.idev);
308
309 try_to_freeze();
310 msleep_interruptible(MDPS_POLL_INTERVAL);
311 }
312
313 return 0;
314}
315
316static int lis3lv02d_joystick_open(struct input_dev *input)
317{
318 lis3lv02d_increase_use(&lis3_dev);
319 lis3_dev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d");
320 if (IS_ERR(lis3_dev.kthread)) {
321 lis3lv02d_decrease_use(&lis3_dev);
322 return PTR_ERR(lis3_dev.kthread);
323 }
324
325 return 0;
326} 279}
327 280
328static void lis3lv02d_joystick_close(struct input_dev *input)
329{
330 kthread_stop(lis3_dev.kthread);
331 lis3lv02d_decrease_use(&lis3_dev);
332}
333 281
334static inline void lis3lv02d_calibrate_joystick(void) 282static inline void lis3lv02d_calibrate_joystick(void)
335{ 283{
@@ -339,33 +287,36 @@ static inline void lis3lv02d_calibrate_joystick(void)
339 287
340int lis3lv02d_joystick_enable(void) 288int lis3lv02d_joystick_enable(void)
341{ 289{
290 struct input_dev *input_dev;
342 int err; 291 int err;
343 292
344 if (lis3_dev.idev) 293 if (lis3_dev.idev)
345 return -EINVAL; 294 return -EINVAL;
346 295
347 lis3_dev.idev = input_allocate_device(); 296 lis3_dev.idev = input_allocate_polled_device();
348 if (!lis3_dev.idev) 297 if (!lis3_dev.idev)
349 return -ENOMEM; 298 return -ENOMEM;
350 299
300 lis3_dev.idev->poll = lis3lv02d_joystick_poll;
301 lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
302 input_dev = lis3_dev.idev->input;
303
351 lis3lv02d_calibrate_joystick(); 304 lis3lv02d_calibrate_joystick();
352 305
353 lis3_dev.idev->name = "ST LIS3LV02DL Accelerometer"; 306 input_dev->name = "ST LIS3LV02DL Accelerometer";
354 lis3_dev.idev->phys = DRIVER_NAME "/input0"; 307 input_dev->phys = DRIVER_NAME "/input0";
355 lis3_dev.idev->id.bustype = BUS_HOST; 308 input_dev->id.bustype = BUS_HOST;
356 lis3_dev.idev->id.vendor = 0; 309 input_dev->id.vendor = 0;
357 lis3_dev.idev->dev.parent = &lis3_dev.pdev->dev; 310 input_dev->dev.parent = &lis3_dev.pdev->dev;
358 lis3_dev.idev->open = lis3lv02d_joystick_open;
359 lis3_dev.idev->close = lis3lv02d_joystick_close;
360 311
361 set_bit(EV_ABS, lis3_dev.idev->evbit); 312 set_bit(EV_ABS, input_dev->evbit);
362 input_set_abs_params(lis3_dev.idev, ABS_X, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); 313 input_set_abs_params(input_dev, ABS_X, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
363 input_set_abs_params(lis3_dev.idev, ABS_Y, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); 314 input_set_abs_params(input_dev, ABS_Y, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
364 input_set_abs_params(lis3_dev.idev, ABS_Z, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); 315 input_set_abs_params(input_dev, ABS_Z, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
365 316
366 err = input_register_device(lis3_dev.idev); 317 err = input_register_polled_device(lis3_dev.idev);
367 if (err) { 318 if (err) {
368 input_free_device(lis3_dev.idev); 319 input_free_polled_device(lis3_dev.idev);
369 lis3_dev.idev = NULL; 320 lis3_dev.idev = NULL;
370 } 321 }
371 322
@@ -378,8 +329,9 @@ void lis3lv02d_joystick_disable(void)
378 if (!lis3_dev.idev) 329 if (!lis3_dev.idev)
379 return; 330 return;
380 331
381 misc_deregister(&lis3lv02d_misc_device); 332 if (lis3_dev.irq)
382 input_unregister_device(lis3_dev.idev); 333 misc_deregister(&lis3lv02d_misc_device);
334 input_unregister_polled_device(lis3_dev.idev);
383 lis3_dev.idev = NULL; 335 lis3_dev.idev = NULL;
384} 336}
385EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); 337EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
@@ -390,9 +342,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
390{ 342{
391 int x, y, z; 343 int x, y, z;
392 344
393 lis3lv02d_increase_use(&lis3_dev);
394 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); 345 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
395 lis3lv02d_decrease_use(&lis3_dev);
396 return sprintf(buf, "(%d,%d,%d)\n", x, y, z); 346 return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
397} 347}
398 348
@@ -406,9 +356,7 @@ static ssize_t lis3lv02d_calibrate_store(struct device *dev,
406 struct device_attribute *attr, 356 struct device_attribute *attr,
407 const char *buf, size_t count) 357 const char *buf, size_t count)
408{ 358{
409 lis3lv02d_increase_use(&lis3_dev);
410 lis3lv02d_calibrate_joystick(); 359 lis3lv02d_calibrate_joystick();
411 lis3lv02d_decrease_use(&lis3_dev);
412 return count; 360 return count;
413} 361}
414 362
@@ -420,9 +368,7 @@ static ssize_t lis3lv02d_rate_show(struct device *dev,
420 u8 ctrl; 368 u8 ctrl;
421 int val; 369 int val;
422 370
423 lis3lv02d_increase_use(&lis3_dev);
424 lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); 371 lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
425 lis3lv02d_decrease_use(&lis3_dev);
426 val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; 372 val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4;
427 return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); 373 return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]);
428} 374}
@@ -446,17 +392,17 @@ static struct attribute_group lis3lv02d_attribute_group = {
446 392
447static int lis3lv02d_add_fs(struct lis3lv02d *lis3) 393static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
448{ 394{
449 lis3_dev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); 395 lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
450 if (IS_ERR(lis3_dev.pdev)) 396 if (IS_ERR(lis3->pdev))
451 return PTR_ERR(lis3_dev.pdev); 397 return PTR_ERR(lis3->pdev);
452 398
453 return sysfs_create_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group); 399 return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
454} 400}
455 401
456int lis3lv02d_remove_fs(void) 402int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
457{ 403{
458 sysfs_remove_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group); 404 sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
459 platform_device_unregister(lis3_dev.pdev); 405 platform_device_unregister(lis3->pdev);
460 return 0; 406 return 0;
461} 407}
462EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); 408EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
@@ -482,18 +428,35 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
482 break; 428 break;
483 default: 429 default:
484 printk(KERN_ERR DRIVER_NAME 430 printk(KERN_ERR DRIVER_NAME
485 ": unknown sensor type 0x%X\n", lis3_dev.whoami); 431 ": unknown sensor type 0x%X\n", dev->whoami);
486 return -EINVAL; 432 return -EINVAL;
487 } 433 }
488 434
489 mutex_init(&dev->lock);
490 lis3lv02d_add_fs(dev); 435 lis3lv02d_add_fs(dev);
491 lis3lv02d_increase_use(dev); 436 lis3lv02d_poweron(dev);
492 437
493 if (lis3lv02d_joystick_enable()) 438 if (lis3lv02d_joystick_enable())
494 printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); 439 printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
495 440
496 printk("lis3_init_device: irq %d\n", dev->irq); 441 /* passing in platform specific data is purely optional and only
442 * used by the SPI transport layer at the moment */
443 if (dev->pdata) {
444 struct lis3lv02d_platform_data *p = dev->pdata;
445
446 if (p->click_flags && (dev->whoami == LIS_SINGLE_ID)) {
447 dev->write(dev, CLICK_CFG, p->click_flags);
448 dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
449 dev->write(dev, CLICK_LATENCY, p->click_latency);
450 dev->write(dev, CLICK_WINDOW, p->click_window);
451 dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
452 dev->write(dev, CLICK_THSY_X,
453 (p->click_thresh_x & 0xf) |
454 (p->click_thresh_y << 4));
455 }
456
457 if (p->irq_cfg)
458 dev->write(dev, CTRL_REG3, p->irq_cfg);
459 }
497 460
498 /* bail if we did not get an IRQ from the bus layer */ 461 /* bail if we did not get an IRQ from the bus layer */
499 if (!dev->irq) { 462 if (!dev->irq) {
@@ -502,11 +465,9 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
502 goto out; 465 goto out;
503 } 466 }
504 467
505 printk("lis3: registering device\n");
506 if (misc_register(&lis3lv02d_misc_device)) 468 if (misc_register(&lis3lv02d_misc_device))
507 printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); 469 printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
508out: 470out:
509 lis3lv02d_decrease_use(dev);
510 return 0; 471 return 0;
511} 472}
512EXPORT_SYMBOL_GPL(lis3lv02d_init_device); 473EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index 745ec96806d4..e320e2f511f1 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -18,6 +18,8 @@
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21#include <linux/platform_device.h>
22#include <linux/input-polldev.h>
21 23
22/* 24/*
23 * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to 25 * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to
@@ -27,12 +29,14 @@
27 * They can also be connected via I²C. 29 * They can also be connected via I²C.
28 */ 30 */
29 31
32#include <linux/lis3lv02d.h>
33
30/* 2-byte registers */ 34/* 2-byte registers */
31#define LIS_DOUBLE_ID 0x3A /* LIS3LV02D[LQ] */ 35#define LIS_DOUBLE_ID 0x3A /* LIS3LV02D[LQ] */
32/* 1-byte registers */ 36/* 1-byte registers */
33#define LIS_SINGLE_ID 0x3B /* LIS[32]02DL and others */ 37#define LIS_SINGLE_ID 0x3B /* LIS[32]02DL and others */
34 38
35enum lis3lv02d_reg { 39enum lis3_reg {
36 WHO_AM_I = 0x0F, 40 WHO_AM_I = 0x0F,
37 OFFSET_X = 0x16, 41 OFFSET_X = 0x16,
38 OFFSET_Y = 0x17, 42 OFFSET_Y = 0x17,
@@ -60,6 +64,19 @@ enum lis3lv02d_reg {
60 FF_WU_THS_L = 0x34, 64 FF_WU_THS_L = 0x34,
61 FF_WU_THS_H = 0x35, 65 FF_WU_THS_H = 0x35,
62 FF_WU_DURATION = 0x36, 66 FF_WU_DURATION = 0x36,
67};
68
69enum lis302d_reg {
70 CLICK_CFG = 0x38,
71 CLICK_SRC = 0x39,
72 CLICK_THSY_X = 0x3B,
73 CLICK_THSZ = 0x3C,
74 CLICK_TIMELIMIT = 0x3D,
75 CLICK_LATENCY = 0x3E,
76 CLICK_WINDOW = 0x3F,
77};
78
79enum lis3lv02d_reg {
63 DD_CFG = 0x38, 80 DD_CFG = 0x38,
64 DD_SRC = 0x39, 81 DD_SRC = 0x39,
65 DD_ACK = 0x3A, 82 DD_ACK = 0x3A,
@@ -169,22 +186,20 @@ struct lis3lv02d {
169 s16 (*read_data) (struct lis3lv02d *lis3, int reg); 186 s16 (*read_data) (struct lis3lv02d *lis3, int reg);
170 int mdps_max_val; 187 int mdps_max_val;
171 188
172 struct input_dev *idev; /* input device */ 189 struct input_polled_dev *idev; /* input device */
173 struct task_struct *kthread; /* kthread for input */
174 struct mutex lock;
175 struct platform_device *pdev; /* platform device */ 190 struct platform_device *pdev; /* platform device */
176 atomic_t count; /* interrupt count after last read */ 191 atomic_t count; /* interrupt count after last read */
177 int xcalib; /* calibrated null value for x */ 192 int xcalib; /* calibrated null value for x */
178 int ycalib; /* calibrated null value for y */ 193 int ycalib; /* calibrated null value for y */
179 int zcalib; /* calibrated null value for z */ 194 int zcalib; /* calibrated null value for z */
180 unsigned char is_on; /* whether the device is on or off */
181 unsigned char usage; /* usage counter */
182 struct axis_conversion ac; /* hw -> logical axis */ 195 struct axis_conversion ac; /* hw -> logical axis */
183 196
184 u32 irq; /* IRQ number */ 197 u32 irq; /* IRQ number */
185 struct fasync_struct *async_queue; /* queue for the misc device */ 198 struct fasync_struct *async_queue; /* queue for the misc device */
186 wait_queue_head_t misc_wait; /* Wait queue for the misc device */ 199 wait_queue_head_t misc_wait; /* Wait queue for the misc device */
187 unsigned long misc_opened; /* bit0: whether the device is open */ 200 unsigned long misc_opened; /* bit0: whether the device is open */
201
202 struct lis3lv02d_platform_data *pdata; /* for passing board config */
188}; 203};
189 204
190int lis3lv02d_init_device(struct lis3lv02d *lis3); 205int lis3lv02d_init_device(struct lis3lv02d *lis3);
@@ -192,6 +207,6 @@ int lis3lv02d_joystick_enable(void);
192void lis3lv02d_joystick_disable(void); 207void lis3lv02d_joystick_disable(void);
193void lis3lv02d_poweroff(struct lis3lv02d *lis3); 208void lis3lv02d_poweroff(struct lis3lv02d *lis3);
194void lis3lv02d_poweron(struct lis3lv02d *lis3); 209void lis3lv02d_poweron(struct lis3lv02d *lis3);
195int lis3lv02d_remove_fs(void); 210int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
196 211
197extern struct lis3lv02d lis3_dev; 212extern struct lis3lv02d lis3_dev;
diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c
index 07ae74b0e191..3827ff04485f 100644
--- a/drivers/hwmon/lis3lv02d_spi.c
+++ b/drivers/hwmon/lis3lv02d_spi.c
@@ -72,6 +72,7 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi)
72 lis3_dev.write = lis3_spi_write; 72 lis3_dev.write = lis3_spi_write;
73 lis3_dev.irq = spi->irq; 73 lis3_dev.irq = spi->irq;
74 lis3_dev.ac = lis3lv02d_axis_normal; 74 lis3_dev.ac = lis3lv02d_axis_normal;
75 lis3_dev.pdata = spi->dev.platform_data;
75 spi_set_drvdata(spi, &lis3_dev); 76 spi_set_drvdata(spi, &lis3_dev);
76 77
77 ret = lis3lv02d_init_device(&lis3_dev); 78 ret = lis3lv02d_init_device(&lis3_dev);