^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * lis3lv02d.c - ST LIS3LV02DL accelerometer driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2007-2008 Yan Burman
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2008 Eric Piel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2008-2009 Pavel Machek
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/freezer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "lis3lv02d.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DRIVER_NAME "lis3lv02d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* joystick device poll interval in milliseconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define MDPS_POLL_INTERVAL 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define MDPS_POLL_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define MDPS_POLL_MAX 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SELFTEST_OK 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define SELFTEST_FAIL -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SELFTEST_IRQ -2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define IRQ_LINE0 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define IRQ_LINE1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * The sensor can also generate interrupts (DRDY) but it's pretty pointless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * because they are generated even if the data do not change. So it's better
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * to keep the interrupt for the free-fall event. The values are updated at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * some low processor, we poll the sensor only at 20Hz... enough for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * joystick.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define LIS3_PWRON_DELAY_WAI_12B (5000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define LIS3_PWRON_DELAY_WAI_8B (3000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * LIS302D spec says: 18 mG / digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * LIS3_ACCURACY is used to increase accuracy of the intermediate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * calculation results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define LIS3_ACCURACY 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* Sensitivity values for -2G +2G scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * LIS331DLH spec says 1LSBs corresponds 4G/4096 -> 1LSB is 1000/1024 mG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * Below macros defines sensitivity values for +/-2G. Dataout bits for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * +/-2G range is 12 bits so 4 bits adjustment must be done to get 12bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * data from 16bit value. Currently this driver supports only 2G range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define LIS3DLH_SENSITIVITY_2G ((LIS3_ACCURACY * 1000) / 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define SHIFT_ADJ_2G 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define LIS3_DEFAULT_FUZZ_12B 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define LIS3_DEFAULT_FLAT_12B 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define LIS3_DEFAULT_FUZZ_8B 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define LIS3_DEFAULT_FLAT_8B 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct lis3lv02d lis3_dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) EXPORT_SYMBOL_GPL(lis3_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* just like param_set_int() but does sanity-check so that it won't point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * over the axis array size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int param_set_axis(const char *val, const struct kernel_param *kp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ret = param_set_int(val, kp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int val = *(int *)kp->arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) val = -val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (!val || val > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static const struct kernel_param_ops param_ops_axis = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .set = param_set_axis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .get = param_get_int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define param_check_axis(name, p) param_check_int(name, p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) s8 lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (lis3->read(lis3, reg, &lo) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u8 lo, hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) lis3->read(lis3, reg - 1, &lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) lis3->read(lis3, reg, &hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return (s16)((hi << 8) | lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* 12bits for 2G range, 13 bits for 4G range and 14 bits for 8G range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static s16 lis331dlh_read_data(struct lis3lv02d *lis3, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u8 lo, hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) lis3->read(lis3, reg - 1, &lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) lis3->read(lis3, reg, &hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) v = (int) ((hi << 8) | lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return (s16) v >> lis3->shift_adj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * lis3lv02d_get_axis - For the given axis, give the value converted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * @axis: 1,2,3 - can also be negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * @hw_values: raw values returned by the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Returns the converted value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (axis > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return hw_values[axis - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -hw_values[-axis - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * @lis3: pointer to the device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * @x: where to store the X axis value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * @y: where to store the Y axis value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @z: where to store the Z axis value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int position[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (lis3->blkread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (lis3->whoami == WAI_12B) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u16 data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) position[i] = (s16)le16_to_cpu(data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u8 data[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* Data: x, dummy, y, dummy, z */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) lis3->blkread(lis3, OUTX, 5, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) position[i] = (s8)data[i * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) position[0] = lis3->read_data(lis3, OUTX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) position[1] = lis3->read_data(lis3, OUTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) position[2] = lis3->read_data(lis3, OUTZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) *x = lis3lv02d_get_axis(lis3->ac.x, position);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) *y = lis3lv02d_get_axis(lis3->ac.y, position);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *z = lis3lv02d_get_axis(lis3->ac.z, position);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* conversion btw sampling rate and the register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int lis3_12_rates[4] = {40, 160, 640, 2560};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int lis3_8_rates[2] = {100, 400};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int lis3_3dlh_rates[4] = {50, 100, 400, 1000};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* ODR is Output Data Rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int lis3lv02d_get_odr_index(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) u8 ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) lis3->read(lis3, CTRL_REG1, &ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ctrl &= lis3->odr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) shift = ffs(lis3->odr_mask) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return (ctrl >> shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int odr_idx = lis3lv02d_get_odr_index(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int div = lis3->odrs[odr_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (div == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (odr_idx == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Power-down mode, not sampling no need to sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) dev_err(&lis3->pdev->dev, "Error unknown odrs-index: %d\n", odr_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* LIS3 power on delay is quite long */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) msleep(lis3->pwron_delay / div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static int lis3lv02d_set_odr(struct lis3lv02d *lis3, int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u8 ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int i, len, shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) lis3->read(lis3, CTRL_REG1, &ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ctrl &= ~lis3->odr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) len = 1 << hweight_long(lis3->odr_mask); /* # of possible values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) shift = ffs(lis3->odr_mask) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (lis3->odrs[i] == rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) lis3->write(lis3, CTRL_REG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ctrl | (i << shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) u8 ctlreg, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) s16 x, y, z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) u8 selftest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u8 ctrl_reg_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) unsigned char irq_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mutex_lock(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) irq_cfg = lis3->irq_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (lis3->whoami == WAI_8B) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) lis3->data_ready_count[IRQ_LINE0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) lis3->data_ready_count[IRQ_LINE1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* Change interrupt cfg to data ready for selftest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) atomic_inc(&lis3->wake_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if ((lis3->whoami == WAI_3DC) || (lis3->whoami == WAI_3DLH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ctlreg = CTRL_REG4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) selftest = CTRL4_ST0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ctlreg = CTRL_REG1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (lis3->whoami == WAI_12B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) selftest = CTRL1_ST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) selftest = CTRL1_STP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) lis3->read(lis3, ctlreg, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) lis3->write(lis3, ctlreg, (reg | selftest));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ret = lis3lv02d_get_pwron_wait(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* Read directly to avoid axis remap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) x = lis3->read_data(lis3, OUTX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) y = lis3->read_data(lis3, OUTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) z = lis3->read_data(lis3, OUTZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* back to normal settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) lis3->write(lis3, ctlreg, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = lis3lv02d_get_pwron_wait(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) results[0] = x - lis3->read_data(lis3, OUTX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) results[1] = y - lis3->read_data(lis3, OUTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) results[2] = z - lis3->read_data(lis3, OUTZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (lis3->whoami == WAI_8B) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* Restore original interrupt configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) atomic_dec(&lis3->wake_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) lis3->irq_cfg = irq_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if ((irq_cfg & LIS3_IRQ1_MASK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) lis3->data_ready_count[IRQ_LINE0] < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ret = SELFTEST_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if ((irq_cfg & LIS3_IRQ2_MASK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) lis3->data_ready_count[IRQ_LINE1] < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret = SELFTEST_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (lis3->pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* Check against selftest acceptance limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if ((results[i] < lis3->pdata->st_min_limits[i]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) (results[i] > lis3->pdata->st_max_limits[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ret = SELFTEST_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* test passed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) mutex_unlock(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * Order of registers in the list affects to order of the restore process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * Perhaps it is a good idea to set interrupt enable register as a last one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * after all other configurations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) CTRL_REG1, CTRL_REG2, CTRL_REG3};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) DD_THSE_L, DD_THSE_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) CTRL_REG1, CTRL_REG3, CTRL_REG2};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static inline void lis3_context_save(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) for (i = 0; i < lis3->regs_size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) lis3->regs_stored = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static inline void lis3_context_restore(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (lis3->regs_stored)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) for (i = 0; i < lis3->regs_size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) void lis3lv02d_poweroff(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (lis3->reg_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) lis3_context_save(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* disable X,Y,Z axis and power down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) lis3->write(lis3, CTRL_REG1, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (lis3->reg_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) lis3->reg_ctrl(lis3, LIS3_REG_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int lis3lv02d_poweron(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) lis3->init(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * Common configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * BDU: (12 bits sensors only) LSB and MSB values are not updated until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * both have been read. So the value read will always be correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * Set BOOT bit to refresh factory tuning values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (lis3->pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) lis3->read(lis3, CTRL_REG2, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (lis3->whoami == WAI_12B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) reg |= CTRL2_BDU | CTRL2_BOOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) else if (lis3->whoami == WAI_3DLH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) reg |= CTRL2_BOOT_3DLH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) reg |= CTRL2_BOOT_8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) lis3->write(lis3, CTRL_REG2, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (lis3->whoami == WAI_3DLH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) lis3->read(lis3, CTRL_REG4, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) reg |= CTRL4_BDU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) lis3->write(lis3, CTRL_REG4, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) err = lis3lv02d_get_pwron_wait(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (lis3->reg_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) lis3_context_restore(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static void lis3lv02d_joystick_poll(struct input_dev *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct lis3lv02d *lis3 = input_get_drvdata(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int x, y, z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) mutex_lock(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) lis3lv02d_get_xyz(lis3, &x, &y, &z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) input_report_abs(input, ABS_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) input_report_abs(input, ABS_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) input_report_abs(input, ABS_Z, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) input_sync(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) mutex_unlock(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static int lis3lv02d_joystick_open(struct input_dev *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct lis3lv02d *lis3 = input_get_drvdata(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (lis3->pm_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) pm_runtime_get_sync(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (lis3->pdata && lis3->whoami == WAI_8B && lis3->idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) atomic_set(&lis3->wake_thread, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * Update coordinates for the case where poll interval is 0 and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * the chip in running purely under interrupt control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) lis3lv02d_joystick_poll(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static void lis3lv02d_joystick_close(struct input_dev *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct lis3lv02d *lis3 = input_get_drvdata(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) atomic_set(&lis3->wake_thread, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (lis3->pm_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) pm_runtime_put(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static irqreturn_t lis302dl_interrupt(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct lis3lv02d *lis3 = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!test_bit(0, &lis3->misc_opened))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * Be careful: on some HP laptops the bios force DD when on battery and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * the lid is closed. This leads to interrupts as soon as a little move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * is done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) atomic_inc(&lis3->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) wake_up_interruptible(&lis3->misc_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) kill_fasync(&lis3->async_queue, SIGIO, POLL_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (atomic_read(&lis3->wake_thread))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return IRQ_WAKE_THREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct input_dev *dev = lis3->idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) u8 click_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) mutex_lock(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) lis3->read(lis3, CLICK_SRC, &click_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (click_src & CLICK_SINGLE_X) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) input_report_key(dev, lis3->mapped_btns[0], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) input_report_key(dev, lis3->mapped_btns[0], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (click_src & CLICK_SINGLE_Y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) input_report_key(dev, lis3->mapped_btns[1], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) input_report_key(dev, lis3->mapped_btns[1], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (click_src & CLICK_SINGLE_Z) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) input_report_key(dev, lis3->mapped_btns[2], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) input_report_key(dev, lis3->mapped_btns[2], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) mutex_unlock(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* Dummy read to ack interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) lis3->data_ready_count[index]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct lis3lv02d *lis3 = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (irq_cfg == LIS3_IRQ1_CLICK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) lis302dl_interrupt_handle_click(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) lis302dl_data_ready(lis3, IRQ_LINE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) lis3lv02d_joystick_poll(lis3->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct lis3lv02d *lis3 = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (irq_cfg == LIS3_IRQ2_CLICK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) lis302dl_interrupt_handle_click(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) lis302dl_data_ready(lis3, IRQ_LINE1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) lis3lv02d_joystick_poll(lis3->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct lis3lv02d *lis3 = container_of(file->private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct lis3lv02d, miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (test_and_set_bit(0, &lis3->misc_opened))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return -EBUSY; /* already open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (lis3->pm_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) pm_runtime_get_sync(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) atomic_set(&lis3->count, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct lis3lv02d *lis3 = container_of(file->private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct lis3lv02d, miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) clear_bit(0, &lis3->misc_opened); /* release the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (lis3->pm_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) pm_runtime_put(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) size_t count, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct lis3lv02d *lis3 = container_of(file->private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct lis3lv02d, miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) unsigned char byte_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ssize_t retval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (count < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) add_wait_queue(&lis3->misc_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) data = atomic_xchg(&lis3->count, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (file->f_flags & O_NONBLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) retval = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (signal_pending(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) retval = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (data < 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) byte_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) byte_data = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /* make sure we are not going into copy_to_user() with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * TASK_INTERRUPTIBLE state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) retval = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) remove_wait_queue(&lis3->misc_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static __poll_t lis3lv02d_misc_poll(struct file *file, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct lis3lv02d *lis3 = container_of(file->private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) struct lis3lv02d, miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) poll_wait(file, &lis3->misc_wait, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (atomic_read(&lis3->count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct lis3lv02d *lis3 = container_of(file->private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct lis3lv02d, miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return fasync_helper(fd, file, on, &lis3->async_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static const struct file_operations lis3lv02d_misc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) .read = lis3lv02d_misc_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) .open = lis3lv02d_misc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) .release = lis3lv02d_misc_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) .poll = lis3lv02d_misc_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) .fasync = lis3lv02d_misc_fasync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int lis3lv02d_joystick_enable(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int max_val, fuzz, flat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int btns[] = {BTN_X, BTN_Y, BTN_Z};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (lis3->idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (!input_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) input_dev->name = "ST LIS3LV02DL Accelerometer";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) input_dev->phys = DRIVER_NAME "/input0";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) input_dev->id.bustype = BUS_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) input_dev->id.vendor = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) input_dev->dev.parent = &lis3->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) input_dev->open = lis3lv02d_joystick_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) input_dev->close = lis3lv02d_joystick_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) max_val = (lis3->mdps_max_val * lis3->scale) / LIS3_ACCURACY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (lis3->whoami == WAI_12B) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) fuzz = LIS3_DEFAULT_FUZZ_12B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) flat = LIS3_DEFAULT_FLAT_12B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) fuzz = LIS3_DEFAULT_FUZZ_8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) flat = LIS3_DEFAULT_FLAT_8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) fuzz = (fuzz * lis3->scale) / LIS3_ACCURACY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) flat = (flat * lis3->scale) / LIS3_ACCURACY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) input_set_drvdata(input_dev, lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) lis3->idev = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) err = input_setup_polling(input_dev, lis3lv02d_joystick_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) goto err_free_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) input_set_poll_interval(input_dev, MDPS_POLL_INTERVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) input_set_min_poll_interval(input_dev, MDPS_POLL_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) input_set_max_poll_interval(input_dev, MDPS_POLL_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) lis3->mapped_btns[0] = lis3lv02d_get_axis(abs(lis3->ac.x), btns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) lis3->mapped_btns[1] = lis3lv02d_get_axis(abs(lis3->ac.y), btns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) lis3->mapped_btns[2] = lis3lv02d_get_axis(abs(lis3->ac.z), btns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) err = input_register_device(lis3->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) goto err_free_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) err_free_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) input_free_device(input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) lis3->idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) void lis3lv02d_joystick_disable(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (lis3->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) free_irq(lis3->irq, lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (lis3->pdata && lis3->pdata->irq2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) free_irq(lis3->pdata->irq2, lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (!lis3->idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (lis3->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) misc_deregister(&lis3->miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) input_unregister_device(lis3->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) lis3->idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* Sysfs stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * SYSFS functions are fast visitors so put-call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * immediately after the get-call. However, keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * chip running for a while and schedule delayed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * suspend. This way periodic sysfs calls doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * suffer from relatively long power up time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (lis3->pm_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) pm_runtime_get_sync(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pm_runtime_put_noidle(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static ssize_t lis3lv02d_selftest_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct lis3lv02d *lis3 = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) s16 values[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static const char ok[] = "OK";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static const char fail[] = "FAIL";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static const char irq[] = "FAIL_IRQ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) const char *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) lis3lv02d_sysfs_poweron(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) switch (lis3lv02d_selftest(lis3, values)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) case SELFTEST_FAIL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) res = fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) case SELFTEST_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) res = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) case SELFTEST_OK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) res = ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return sprintf(buf, "%s %d %d %d\n", res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) values[0], values[1], values[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static ssize_t lis3lv02d_position_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct lis3lv02d *lis3 = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) int x, y, z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) lis3lv02d_sysfs_poweron(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mutex_lock(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) lis3lv02d_get_xyz(lis3, &x, &y, &z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) mutex_unlock(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static ssize_t lis3lv02d_rate_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct lis3lv02d *lis3 = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) int odr_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) lis3lv02d_sysfs_poweron(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) odr_idx = lis3lv02d_get_odr_index(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return sprintf(buf, "%d\n", lis3->odrs[odr_idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static ssize_t lis3lv02d_rate_set(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) struct device_attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct lis3lv02d *lis3 = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ret = kstrtoul(buf, 0, &rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) lis3lv02d_sysfs_poweron(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (lis3lv02d_set_odr(lis3, rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) lis3lv02d_rate_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static struct attribute *lis3lv02d_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) &dev_attr_selftest.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) &dev_attr_position.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) &dev_attr_rate.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static const struct attribute_group lis3lv02d_attribute_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) .attrs = lis3lv02d_attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (IS_ERR(lis3->pdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return PTR_ERR(lis3->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) platform_set_drvdata(lis3->pdev, lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) platform_device_unregister(lis3->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (lis3->pm_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* Barrier after the sysfs remove */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) pm_runtime_barrier(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* SYSFS may have left chip running. Turn off if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (!pm_runtime_suspended(lis3->pm_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) lis3lv02d_poweroff(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) pm_runtime_disable(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) pm_runtime_set_suspended(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) kfree(lis3->reg_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static void lis3lv02d_8b_configure(struct lis3lv02d *lis3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct lis3lv02d_platform_data *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int ctrl2 = p->hipass_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (p->click_flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) lis3->write(lis3, CLICK_CFG, p->click_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) lis3->write(lis3, CLICK_TIMELIMIT, p->click_time_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) lis3->write(lis3, CLICK_LATENCY, p->click_latency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) lis3->write(lis3, CLICK_WINDOW, p->click_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) lis3->write(lis3, CLICK_THSZ, p->click_thresh_z & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) lis3->write(lis3, CLICK_THSY_X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) (p->click_thresh_x & 0xf) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) (p->click_thresh_y << 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (lis3->idev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) input_set_capability(lis3->idev, EV_KEY, BTN_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) input_set_capability(lis3->idev, EV_KEY, BTN_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) input_set_capability(lis3->idev, EV_KEY, BTN_Z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (p->wakeup_flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) lis3->write(lis3, FF_WU_CFG_1, p->wakeup_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) lis3->write(lis3, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* pdata value + 1 to keep this backward compatible*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) lis3->write(lis3, FF_WU_DURATION_1, p->duration1 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (p->wakeup_flags2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) lis3->write(lis3, FF_WU_CFG_2, p->wakeup_flags2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) lis3->write(lis3, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* pdata value + 1 to keep this backward compatible*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) lis3->write(lis3, FF_WU_DURATION_2, p->duration2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* Configure hipass filters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) lis3->write(lis3, CTRL_REG2, ctrl2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (p->irq2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) err = request_threaded_irq(p->irq2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) lis302dl_interrupt_thread2_8b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) IRQF_TRIGGER_RISING | IRQF_ONESHOT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) (p->irq_flags2 & IRQF_TRIGGER_MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) DRIVER_NAME, lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) pr_err("No second IRQ. Limited functionality\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) int lis3lv02d_init_dt(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct lis3lv02d_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct device_node *np = lis3->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) s32 sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (!lis3->of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (of_get_property(np, "st,click-single-x", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) pdata->click_flags |= LIS3_CLICK_SINGLE_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (of_get_property(np, "st,click-double-x", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) pdata->click_flags |= LIS3_CLICK_DOUBLE_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (of_get_property(np, "st,click-single-y", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) pdata->click_flags |= LIS3_CLICK_SINGLE_Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (of_get_property(np, "st,click-double-y", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) pdata->click_flags |= LIS3_CLICK_DOUBLE_Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (of_get_property(np, "st,click-single-z", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) pdata->click_flags |= LIS3_CLICK_SINGLE_Z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (of_get_property(np, "st,click-double-z", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) pdata->click_flags |= LIS3_CLICK_DOUBLE_Z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!of_property_read_u32(np, "st,click-threshold-x", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) pdata->click_thresh_x = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (!of_property_read_u32(np, "st,click-threshold-y", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) pdata->click_thresh_y = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (!of_property_read_u32(np, "st,click-threshold-z", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) pdata->click_thresh_z = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (!of_property_read_u32(np, "st,click-time-limit", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) pdata->click_time_limit = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (!of_property_read_u32(np, "st,click-latency", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) pdata->click_latency = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (!of_property_read_u32(np, "st,click-window", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) pdata->click_window = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (of_get_property(np, "st,irq1-disable", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) pdata->irq_cfg |= LIS3_IRQ1_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (of_get_property(np, "st,irq1-ff-wu-1", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) pdata->irq_cfg |= LIS3_IRQ1_FF_WU_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (of_get_property(np, "st,irq1-ff-wu-2", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) pdata->irq_cfg |= LIS3_IRQ1_FF_WU_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (of_get_property(np, "st,irq1-data-ready", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) pdata->irq_cfg |= LIS3_IRQ1_DATA_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (of_get_property(np, "st,irq1-click", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) pdata->irq_cfg |= LIS3_IRQ1_CLICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (of_get_property(np, "st,irq2-disable", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) pdata->irq_cfg |= LIS3_IRQ2_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (of_get_property(np, "st,irq2-ff-wu-1", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) pdata->irq_cfg |= LIS3_IRQ2_FF_WU_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (of_get_property(np, "st,irq2-ff-wu-2", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) pdata->irq_cfg |= LIS3_IRQ2_FF_WU_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (of_get_property(np, "st,irq2-data-ready", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) pdata->irq_cfg |= LIS3_IRQ2_DATA_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (of_get_property(np, "st,irq2-click", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) pdata->irq_cfg |= LIS3_IRQ2_CLICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (of_get_property(np, "st,irq-open-drain", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) pdata->irq_cfg |= LIS3_IRQ_OPEN_DRAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (of_get_property(np, "st,irq-active-low", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) pdata->irq_cfg |= LIS3_IRQ_ACTIVE_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (!of_property_read_u32(np, "st,wu-duration-1", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) pdata->duration1 = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (!of_property_read_u32(np, "st,wu-duration-2", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) pdata->duration2 = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (of_get_property(np, "st,wakeup-x-lo", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) pdata->wakeup_flags |= LIS3_WAKEUP_X_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (of_get_property(np, "st,wakeup-x-hi", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) pdata->wakeup_flags |= LIS3_WAKEUP_X_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (of_get_property(np, "st,wakeup-y-lo", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) pdata->wakeup_flags |= LIS3_WAKEUP_Y_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (of_get_property(np, "st,wakeup-y-hi", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) pdata->wakeup_flags |= LIS3_WAKEUP_Y_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (of_get_property(np, "st,wakeup-z-lo", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) pdata->wakeup_flags |= LIS3_WAKEUP_Z_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (of_get_property(np, "st,wakeup-z-hi", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) pdata->wakeup_flags |= LIS3_WAKEUP_Z_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (of_get_property(np, "st,wakeup-threshold", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) pdata->wakeup_thresh = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (of_get_property(np, "st,wakeup2-x-lo", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) pdata->wakeup_flags2 |= LIS3_WAKEUP_X_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (of_get_property(np, "st,wakeup2-x-hi", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) pdata->wakeup_flags2 |= LIS3_WAKEUP_X_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (of_get_property(np, "st,wakeup2-y-lo", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) pdata->wakeup_flags2 |= LIS3_WAKEUP_Y_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (of_get_property(np, "st,wakeup2-y-hi", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) pdata->wakeup_flags2 |= LIS3_WAKEUP_Y_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (of_get_property(np, "st,wakeup2-z-lo", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) pdata->wakeup_flags2 |= LIS3_WAKEUP_Z_LO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (of_get_property(np, "st,wakeup2-z-hi", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) pdata->wakeup_flags2 |= LIS3_WAKEUP_Z_HI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (of_get_property(np, "st,wakeup2-threshold", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) pdata->wakeup_thresh2 = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (!of_property_read_u32(np, "st,highpass-cutoff-hz", &val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_1HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_2HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_4HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_8HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (of_get_property(np, "st,hipass1-disable", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) pdata->hipass_ctrl |= LIS3_HIPASS1_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (of_get_property(np, "st,hipass2-disable", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) pdata->hipass_ctrl |= LIS3_HIPASS2_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (of_property_read_s32(np, "st,axis-x", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) pdata->axis_x = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (of_property_read_s32(np, "st,axis-y", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) pdata->axis_y = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (of_property_read_s32(np, "st,axis-z", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) pdata->axis_z = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (of_get_property(np, "st,default-rate", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) pdata->default_rate = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (of_property_read_s32(np, "st,min-limit-x", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) pdata->st_min_limits[0] = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (of_property_read_s32(np, "st,min-limit-y", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) pdata->st_min_limits[1] = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (of_property_read_s32(np, "st,min-limit-z", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) pdata->st_min_limits[2] = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (of_property_read_s32(np, "st,max-limit-x", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) pdata->st_max_limits[0] = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (of_property_read_s32(np, "st,max-limit-y", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) pdata->st_max_limits[1] = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (of_property_read_s32(np, "st,max-limit-z", &sval) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) pdata->st_max_limits[2] = sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) lis3->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) int lis3lv02d_init_dt(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) EXPORT_SYMBOL_GPL(lis3lv02d_init_dt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * Initialise the accelerometer and the various subsystems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) * Should be rather independent of the bus system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) int lis3lv02d_init_device(struct lis3lv02d *lis3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) irq_handler_t thread_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) int irq_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) lis3->whoami = lis3lv02d_read_8(lis3, WHO_AM_I);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) switch (lis3->whoami) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) case WAI_12B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) pr_info("12 bits sensor found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) lis3->read_data = lis3lv02d_read_12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) lis3->mdps_max_val = 2048;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) lis3->odrs = lis3_12_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) lis3->odr_mask = CTRL1_DF0 | CTRL1_DF1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) lis3->scale = LIS3_SENSITIVITY_12B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) lis3->regs = lis3_wai12_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) lis3->regs_size = ARRAY_SIZE(lis3_wai12_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) case WAI_8B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) pr_info("8 bits sensor found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) lis3->read_data = lis3lv02d_read_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) lis3->mdps_max_val = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) lis3->odrs = lis3_8_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) lis3->odr_mask = CTRL1_DR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) lis3->scale = LIS3_SENSITIVITY_8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) lis3->regs = lis3_wai8_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) lis3->regs_size = ARRAY_SIZE(lis3_wai8_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) case WAI_3DC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) pr_info("8 bits 3DC sensor found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) lis3->read_data = lis3lv02d_read_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) lis3->mdps_max_val = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) lis3->odrs = lis3_3dc_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) lis3->scale = LIS3_SENSITIVITY_8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) case WAI_3DLH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) pr_info("16 bits lis331dlh sensor found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) lis3->read_data = lis331dlh_read_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) lis3->mdps_max_val = 2048; /* 12 bits for 2G */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) lis3->shift_adj = SHIFT_ADJ_2G;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) lis3->odrs = lis3_3dlh_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) lis3->odr_mask = CTRL1_DR0 | CTRL1_DR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) lis3->scale = LIS3DLH_SENSITIVITY_2G;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) pr_err("unknown sensor type 0x%X\n", lis3->whoami);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) lis3->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) sizeof(lis3_wai12_regs)), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (lis3->reg_cache == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) printk(KERN_ERR DRIVER_NAME "out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) mutex_init(&lis3->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) atomic_set(&lis3->wake_thread, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) lis3lv02d_add_fs(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) err = lis3lv02d_poweron(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) lis3lv02d_remove_fs(lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (lis3->pm_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) pm_runtime_set_active(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) pm_runtime_enable(lis3->pm_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (lis3lv02d_joystick_enable(lis3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) pr_err("joystick initialization failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /* passing in platform specific data is purely optional and only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * used by the SPI transport layer at the moment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (lis3->pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) struct lis3lv02d_platform_data *p = lis3->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (lis3->whoami == WAI_8B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) lis3lv02d_8b_configure(lis3, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) lis3->irq_cfg = p->irq_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (p->irq_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) lis3->write(lis3, CTRL_REG3, p->irq_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (p->default_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) lis3lv02d_set_odr(lis3, p->default_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /* bail if we did not get an IRQ from the bus layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (!lis3->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) pr_debug("No IRQ. Disabling /dev/freefall\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) * The sensor can generate interrupts for free-fall and direction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * the things simple and _fast_ we activate it only for free-fall, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * no need to read register (very slow with ACPI). For the same reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) * we forbid shared interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * io-apic is not configurable (and generates a warning) but I keep it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) * in case of support for other hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (lis3->pdata && lis3->whoami == WAI_8B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) thread_fn = lis302dl_interrupt_thread1_8b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) thread_fn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) err = request_threaded_irq(lis3->irq, lis302dl_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) thread_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) IRQF_TRIGGER_RISING | IRQF_ONESHOT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) irq_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) DRIVER_NAME, lis3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) pr_err("Cannot get IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) lis3->miscdev.minor = MISC_DYNAMIC_MINOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) lis3->miscdev.name = "freefall";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) lis3->miscdev.fops = &lis3lv02d_misc_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (misc_register(&lis3->miscdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) pr_err("misc_register failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) MODULE_LICENSE("GPL");