diff options
author | Daniel Mack <zonque@gmail.com> | 2012-09-26 16:58:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-26 17:15:55 -0400 |
commit | cbac1a8b89452f378a17cc2c673aca0e53af684d (patch) | |
tree | c52184fb2ef4129bbf4ca8a8b9c280ee4e0fd8a7 | |
parent | e2b2ed8365e040b274dd23bdabd34ec3b0e43137 (diff) |
drivers/misc/lis3lv02d: add generic DT matching code
Adds logic to parse lis3 properties from a device tree node and store them
in a freshly allocated lis3lv02d_platform_data.
Note that the actual match tables are left out here. This part should
happen in the drivers that bind to the individual busses (SPI/I2C/PCI).
Also adds some DT bindinds documentation.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Cc: Rob Herring <robherring2@gmail.com>
Cc: "AnilKumar, Chimata" <anilkumar@ti.com>
Reviewed-by: Éric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | Documentation/devicetree/bindings/misc/lis302.txt | 76 | ||||
-rw-r--r-- | drivers/misc/lis3lv02d/lis3lv02d.c | 153 | ||||
-rw-r--r-- | drivers/misc/lis3lv02d/lis3lv02d.h | 4 |
3 files changed, 233 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/misc/lis302.txt b/Documentation/devicetree/bindings/misc/lis302.txt new file mode 100644 index 000000000000..e18af9d19793 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/lis302.txt | |||
@@ -0,0 +1,76 @@ | |||
1 | LIS302 accelerometer devicetree bindings | ||
2 | |||
3 | This device is matched via its bus drivers, and has a number of properties | ||
4 | that apply in on the generic device (independent from the bus). | ||
5 | |||
6 | |||
7 | Required properties for the SPI bindings: | ||
8 | - compatible: should be set to "st,lis3lv02d_spi" | ||
9 | - reg: the chipselect index | ||
10 | - spi-max-frequency: maximal bus speed, should be set to 1000000 unless | ||
11 | constrained by external circuitry | ||
12 | - interrupts: the interrupt generated by the device | ||
13 | |||
14 | |||
15 | Optional properties for all bus drivers: | ||
16 | |||
17 | - st,click-single-{x,y,z}: if present, tells the device to issue an | ||
18 | interrupt on single click events on the | ||
19 | x/y/z axis. | ||
20 | - st,click-double-{x,y,z}: if present, tells the device to issue an | ||
21 | interrupt on double click events on the | ||
22 | x/y/z axis. | ||
23 | - st,click-thresh-{x,y,z}: set the x/y/z axis threshold | ||
24 | - st,click-click-time-limit: click time limit, from 0 to 127.5msec | ||
25 | with step of 0.5 msec | ||
26 | - st,click-latency: click latency, from 0 to 255 msec with | ||
27 | step of 1 msec. | ||
28 | - st,click-window: click window, from 0 to 255 msec with | ||
29 | step of 1 msec. | ||
30 | - st,irq{1,2}-disable: disable IRQ 1/2 | ||
31 | - st,irq{1,2}-ff-wu-1: raise IRQ 1/2 on FF_WU_1 condition | ||
32 | - st,irq{1,2}-ff-wu-2: raise IRQ 1/2 on FF_WU_2 condition | ||
33 | - st,irq{1,2}-data-ready: raise IRQ 1/2 on data ready contition | ||
34 | - st,irq{1,2}-click: raise IRQ 1/2 on click condition | ||
35 | - st,irq-open-drain: consider IRQ lines open-drain | ||
36 | - st,irq-active-low: make IRQ lines active low | ||
37 | - st,wu-duration-1: duration register for Free-Fall/Wake-Up | ||
38 | interrupt 1 | ||
39 | - st,wu-duration-2: duration register for Free-Fall/Wake-Up | ||
40 | interrupt 2 | ||
41 | - st,wakeup-{x,y,z}-{lo,hi}: set wakeup condition on x/y/z axis for | ||
42 | upper/lower limit | ||
43 | - st,highpass-cutoff-hz=: 1, 2, 4 or 8 for 1Hz, 2Hz, 4Hz or 8Hz of | ||
44 | highpass cut-off frequency | ||
45 | - st,hipass{1,2}-disable: disable highpass 1/2. | ||
46 | - st,default-rate=: set the default rate | ||
47 | - st,axis-{x,y,z}=: set the axis to map to the three coordinates | ||
48 | - st,{min,max}-limit-{x,y,z} set the min/max limits for x/y/z axis | ||
49 | (used by self-test) | ||
50 | |||
51 | |||
52 | Example for a SPI device node: | ||
53 | |||
54 | lis302@0 { | ||
55 | compatible = "st,lis302dl-spi"; | ||
56 | reg = <0>; | ||
57 | spi-max-frequency = <1000000>; | ||
58 | interrupt-parent = <&gpio>; | ||
59 | interrupts = <104 0>; | ||
60 | |||
61 | st,click-single-x; | ||
62 | st,click-single-y; | ||
63 | st,click-single-z; | ||
64 | st,click-thresh-x = <10>; | ||
65 | st,click-thresh-y = <10>; | ||
66 | st,click-thresh-z = <10>; | ||
67 | st,irq1-click; | ||
68 | st,irq2-click; | ||
69 | st,wakeup-x-lo; | ||
70 | st,wakeup-x-hi; | ||
71 | st,wakeup-y-lo; | ||
72 | st,wakeup-y-hi; | ||
73 | st,wakeup-z-lo; | ||
74 | st,wakeup-z-hi; | ||
75 | }; | ||
76 | |||
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index e670072fe24c..6877f1179875 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/miscdevice.h> | 39 | #include <linux/miscdevice.h> |
40 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
41 | #include <linux/atomic.h> | 41 | #include <linux/atomic.h> |
42 | #include <linux/of_device.h> | ||
42 | #include "lis3lv02d.h" | 43 | #include "lis3lv02d.h" |
43 | 44 | ||
44 | #define DRIVER_NAME "lis3lv02d" | 45 | #define DRIVER_NAME "lis3lv02d" |
@@ -943,6 +944,154 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *lis3, | |||
943 | } | 944 | } |
944 | } | 945 | } |
945 | 946 | ||
947 | #ifdef CONFIG_OF | ||
948 | static int lis3lv02d_init_dt(struct lis3lv02d *lis3) | ||
949 | { | ||
950 | struct lis3lv02d_platform_data *pdata; | ||
951 | struct device_node *np = lis3->of_node; | ||
952 | u32 val; | ||
953 | |||
954 | if (!lis3->of_node) | ||
955 | return 0; | ||
956 | |||
957 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
958 | if (!pdata) | ||
959 | return -ENOMEM; | ||
960 | |||
961 | if (of_get_property(np, "st,click-single-x", NULL)) | ||
962 | pdata->click_flags |= LIS3_CLICK_SINGLE_X; | ||
963 | if (of_get_property(np, "st,click-double-x", NULL)) | ||
964 | pdata->click_flags |= LIS3_CLICK_DOUBLE_X; | ||
965 | |||
966 | if (of_get_property(np, "st,click-single-y", NULL)) | ||
967 | pdata->click_flags |= LIS3_CLICK_SINGLE_Y; | ||
968 | if (of_get_property(np, "st,click-double-y", NULL)) | ||
969 | pdata->click_flags |= LIS3_CLICK_DOUBLE_Y; | ||
970 | |||
971 | if (of_get_property(np, "st,click-single-z", NULL)) | ||
972 | pdata->click_flags |= LIS3_CLICK_SINGLE_Z; | ||
973 | if (of_get_property(np, "st,click-double-z", NULL)) | ||
974 | pdata->click_flags |= LIS3_CLICK_DOUBLE_Z; | ||
975 | |||
976 | if (!of_property_read_u32(np, "st,click-threshold-x", &val)) | ||
977 | pdata->click_thresh_x = val; | ||
978 | if (!of_property_read_u32(np, "st,click-threshold-y", &val)) | ||
979 | pdata->click_thresh_y = val; | ||
980 | if (!of_property_read_u32(np, "st,click-threshold-z", &val)) | ||
981 | pdata->click_thresh_z = val; | ||
982 | |||
983 | if (!of_property_read_u32(np, "st,click-time-limit", &val)) | ||
984 | pdata->click_time_limit = val; | ||
985 | if (!of_property_read_u32(np, "st,click-latency", &val)) | ||
986 | pdata->click_latency = val; | ||
987 | if (!of_property_read_u32(np, "st,click-window", &val)) | ||
988 | pdata->click_window = val; | ||
989 | |||
990 | if (of_get_property(np, "st,irq1-disable", NULL)) | ||
991 | pdata->irq_cfg |= LIS3_IRQ1_DISABLE; | ||
992 | if (of_get_property(np, "st,irq1-ff-wu-1", NULL)) | ||
993 | pdata->irq_cfg |= LIS3_IRQ1_FF_WU_1; | ||
994 | if (of_get_property(np, "st,irq1-ff-wu-2", NULL)) | ||
995 | pdata->irq_cfg |= LIS3_IRQ1_FF_WU_2; | ||
996 | if (of_get_property(np, "st,irq1-data-ready", NULL)) | ||
997 | pdata->irq_cfg |= LIS3_IRQ1_DATA_READY; | ||
998 | if (of_get_property(np, "st,irq1-click", NULL)) | ||
999 | pdata->irq_cfg |= LIS3_IRQ1_CLICK; | ||
1000 | |||
1001 | if (of_get_property(np, "st,irq2-disable", NULL)) | ||
1002 | pdata->irq_cfg |= LIS3_IRQ2_DISABLE; | ||
1003 | if (of_get_property(np, "st,irq2-ff-wu-1", NULL)) | ||
1004 | pdata->irq_cfg |= LIS3_IRQ2_FF_WU_1; | ||
1005 | if (of_get_property(np, "st,irq2-ff-wu-2", NULL)) | ||
1006 | pdata->irq_cfg |= LIS3_IRQ2_FF_WU_2; | ||
1007 | if (of_get_property(np, "st,irq2-data-ready", NULL)) | ||
1008 | pdata->irq_cfg |= LIS3_IRQ2_DATA_READY; | ||
1009 | if (of_get_property(np, "st,irq2-click", NULL)) | ||
1010 | pdata->irq_cfg |= LIS3_IRQ2_CLICK; | ||
1011 | |||
1012 | if (of_get_property(np, "st,irq-open-drain", NULL)) | ||
1013 | pdata->irq_cfg |= LIS3_IRQ_OPEN_DRAIN; | ||
1014 | if (of_get_property(np, "st,irq-active-low", NULL)) | ||
1015 | pdata->irq_cfg |= LIS3_IRQ_ACTIVE_LOW; | ||
1016 | |||
1017 | if (!of_property_read_u32(np, "st,wu-duration-1", &val)) | ||
1018 | pdata->duration1 = val; | ||
1019 | if (!of_property_read_u32(np, "st,wu-duration-2", &val)) | ||
1020 | pdata->duration2 = val; | ||
1021 | |||
1022 | if (of_get_property(np, "st,wakeup-x-lo", NULL)) | ||
1023 | pdata->wakeup_flags |= LIS3_WAKEUP_X_LO; | ||
1024 | if (of_get_property(np, "st,wakeup-x-hi", NULL)) | ||
1025 | pdata->wakeup_flags |= LIS3_WAKEUP_X_HI; | ||
1026 | if (of_get_property(np, "st,wakeup-y-lo", NULL)) | ||
1027 | pdata->wakeup_flags |= LIS3_WAKEUP_Y_LO; | ||
1028 | if (of_get_property(np, "st,wakeup-y-hi", NULL)) | ||
1029 | pdata->wakeup_flags |= LIS3_WAKEUP_Y_HI; | ||
1030 | if (of_get_property(np, "st,wakeup-z-lo", NULL)) | ||
1031 | pdata->wakeup_flags |= LIS3_WAKEUP_Z_LO; | ||
1032 | if (of_get_property(np, "st,wakeup-z-hi", NULL)) | ||
1033 | pdata->wakeup_flags |= LIS3_WAKEUP_Z_HI; | ||
1034 | |||
1035 | if (!of_property_read_u32(np, "st,highpass-cutoff-hz", &val)) { | ||
1036 | switch (val) { | ||
1037 | case 1: | ||
1038 | pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_1HZ; | ||
1039 | break; | ||
1040 | case 2: | ||
1041 | pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_2HZ; | ||
1042 | break; | ||
1043 | case 4: | ||
1044 | pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_4HZ; | ||
1045 | break; | ||
1046 | case 8: | ||
1047 | pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_8HZ; | ||
1048 | break; | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | if (of_get_property(np, "st,hipass1-disable", NULL)) | ||
1053 | pdata->hipass_ctrl |= LIS3_HIPASS1_DISABLE; | ||
1054 | if (of_get_property(np, "st,hipass2-disable", NULL)) | ||
1055 | pdata->hipass_ctrl |= LIS3_HIPASS2_DISABLE; | ||
1056 | |||
1057 | if (of_get_property(np, "st,axis-x", &val)) | ||
1058 | pdata->axis_x = val; | ||
1059 | if (of_get_property(np, "st,axis-y", &val)) | ||
1060 | pdata->axis_y = val; | ||
1061 | if (of_get_property(np, "st,axis-z", &val)) | ||
1062 | pdata->axis_z = val; | ||
1063 | |||
1064 | if (of_get_property(np, "st,default-rate", NULL)) | ||
1065 | pdata->default_rate = val; | ||
1066 | |||
1067 | if (of_get_property(np, "st,min-limit-x", &val)) | ||
1068 | pdata->st_min_limits[0] = val; | ||
1069 | if (of_get_property(np, "st,min-limit-y", &val)) | ||
1070 | pdata->st_min_limits[1] = val; | ||
1071 | if (of_get_property(np, "st,min-limit-z", &val)) | ||
1072 | pdata->st_min_limits[2] = val; | ||
1073 | |||
1074 | if (of_get_property(np, "st,max-limit-x", &val)) | ||
1075 | pdata->st_max_limits[0] = val; | ||
1076 | if (of_get_property(np, "st,max-limit-y", &val)) | ||
1077 | pdata->st_max_limits[1] = val; | ||
1078 | if (of_get_property(np, "st,max-limit-z", &val)) | ||
1079 | pdata->st_max_limits[2] = val; | ||
1080 | |||
1081 | |||
1082 | lis3->pdata = pdata; | ||
1083 | |||
1084 | return 0; | ||
1085 | } | ||
1086 | |||
1087 | #else | ||
1088 | static int lis3lv02d_init_dt(struct lis3lv02d *lis3) | ||
1089 | { | ||
1090 | return 0; | ||
1091 | } | ||
1092 | #endif | ||
1093 | EXPORT_SYMBOL_GPL(lis3lv02d_init_dt); | ||
1094 | |||
946 | /* | 1095 | /* |
947 | * Initialise the accelerometer and the various subsystems. | 1096 | * Initialise the accelerometer and the various subsystems. |
948 | * Should be rather independent of the bus system. | 1097 | * Should be rather independent of the bus system. |
@@ -953,6 +1102,10 @@ int lis3lv02d_init_device(struct lis3lv02d *lis3) | |||
953 | irq_handler_t thread_fn; | 1102 | irq_handler_t thread_fn; |
954 | int irq_flags = 0; | 1103 | int irq_flags = 0; |
955 | 1104 | ||
1105 | err = lis3lv02d_init_dt(lis3); | ||
1106 | if (err < 0) | ||
1107 | return err; | ||
1108 | |||
956 | lis3->whoami = lis3lv02d_read_8(lis3, WHO_AM_I); | 1109 | lis3->whoami = lis3lv02d_read_8(lis3, WHO_AM_I); |
957 | 1110 | ||
958 | switch (lis3->whoami) { | 1111 | switch (lis3->whoami) { |
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h index 387504a37937..2e0700baa584 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.h +++ b/drivers/misc/lis3lv02d/lis3lv02d.h | |||
@@ -314,6 +314,10 @@ struct lis3lv02d { | |||
314 | 314 | ||
315 | struct lis3lv02d_platform_data *pdata; /* for passing board config */ | 315 | struct lis3lv02d_platform_data *pdata; /* for passing board config */ |
316 | struct mutex mutex; /* Serialize poll and selftest */ | 316 | struct mutex mutex; /* Serialize poll and selftest */ |
317 | |||
318 | #ifdef CONFIG_OF | ||
319 | struct device_node *of_node; | ||
320 | #endif | ||
317 | }; | 321 | }; |
318 | 322 | ||
319 | int lis3lv02d_init_device(struct lis3lv02d *lis3); | 323 | int lis3lv02d_init_device(struct lis3lv02d *lis3); |