]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/hwmon/lis3lv02d.c
hwmon: (lis3) add axes module parameter for custom axis-mapping
[karo-tx-linux.git] / drivers / hwmon / lis3lv02d.c
index fc591ae53107da8481a2ab5e02f53117ac6e2471..25f3850109538b079fadec2fe22eb1220ff35f10 100644 (file)
@@ -75,6 +75,30 @@ struct lis3lv02d lis3_dev = {
 
 EXPORT_SYMBOL_GPL(lis3_dev);
 
+/* just like param_set_int() but does sanity-check so that it won't point
+ * over the axis array size
+ */
+static int param_set_axis(const char *val, const struct kernel_param *kp)
+{
+       int ret = param_set_int(val, kp);
+       if (!ret) {
+               int val = *(int *)kp->arg;
+               if (val < 0)
+                       val = -val;
+               if (!val || val > 3)
+                       return -EINVAL;
+       }
+       return ret;
+}
+
+static struct kernel_param_ops param_ops_axis = {
+       .set = param_set_axis,
+       .get = param_get_int,
+};
+
+module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
+MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
+
 static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
 {
        s8 lo;
@@ -138,6 +162,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
 /* conversion btw sampling rate and the register values */
 static int lis3_12_rates[4] = {40, 160, 640, 2560};
 static int lis3_8_rates[2] = {100, 400};
+static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
 
 /* ODR is Output Data Rate */
 static int lis3lv02d_get_odr(void)
@@ -156,6 +181,9 @@ static int lis3lv02d_set_odr(int rate)
        u8 ctrl;
        int i, len, shift;
 
+       if (!rate)
+               return -EINVAL;
+
        lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
        ctrl &= ~lis3_dev.odr_mask;
        len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
@@ -172,19 +200,25 @@ static int lis3lv02d_set_odr(int rate)
 
 static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
 {
-       u8 reg;
+       u8 ctlreg, reg;
        s16 x, y, z;
        u8 selftest;
        int ret;
 
        mutex_lock(&lis3->mutex);
-       if (lis3_dev.whoami == WAI_12B)
-               selftest = CTRL1_ST;
-       else
-               selftest = CTRL1_STP;
+       if (lis3_dev.whoami == WAI_3DC) {
+               ctlreg = CTRL_REG4;
+               selftest = CTRL4_ST0;
+       } else {
+               ctlreg = CTRL_REG1;
+               if (lis3_dev.whoami == WAI_12B)
+                       selftest = CTRL1_ST;
+               else
+                       selftest = CTRL1_STP;
+       }
 
-       lis3->read(lis3, CTRL_REG1, &reg);
-       lis3->write(lis3, CTRL_REG1, (reg | selftest));
+       lis3->read(lis3, ctlreg, &reg);
+       lis3->write(lis3, ctlreg, (reg | selftest));
        msleep(lis3->pwron_delay / lis3lv02d_get_odr());
 
        /* Read directly to avoid axis remap */
@@ -193,7 +227,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
        z = lis3->read_data(lis3, OUTZ);
 
        /* back to normal settings */
-       lis3->write(lis3, CTRL_REG1, reg);
+       lis3->write(lis3, ctlreg, reg);
        msleep(lis3->pwron_delay / lis3lv02d_get_odr());
 
        results[0] = x - lis3->read_data(lis3, OUTX);
@@ -674,6 +708,15 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                dev->odr_mask = CTRL1_DR;
                dev->scale = LIS3_SENSITIVITY_8B;
                break;
+       case WAI_3DC:
+               printk(KERN_INFO DRIVER_NAME ": 8 bits 3DC sensor found\n");
+               dev->read_data = lis3lv02d_read_8;
+               dev->mdps_max_val = 128;
+               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+               dev->odrs = lis3_3dc_rates;
+               dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+               dev->scale = LIS3_SENSITIVITY_8B;
+               break;
        default:
                printk(KERN_ERR DRIVER_NAME
                        ": unknown sensor type 0x%X\n", dev->whoami);