1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * STMicroelectronics accelerometers driver |
4 | * |
5 | * Copyright 2012-2013 STMicroelectronics Inc. |
6 | * |
7 | * Denis Ciocca <denis.ciocca@st.com> |
8 | */ |
9 | |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/mod_devicetable.h> |
13 | #include <linux/spi/spi.h> |
14 | #include <linux/iio/iio.h> |
15 | |
16 | #include <linux/iio/common/st_sensors.h> |
17 | #include <linux/iio/common/st_sensors_spi.h> |
18 | #include "st_accel.h" |
19 | |
20 | /* |
21 | * For new single-chip sensors use <device_name> as compatible string. |
22 | * For old single-chip devices keep <device_name>-accel to maintain |
23 | * compatibility |
24 | */ |
25 | static const struct of_device_id st_accel_of_match[] = { |
26 | { |
27 | /* An older compatible */ |
28 | .compatible = "st,lis302dl-spi" , |
29 | .data = LIS3LV02DL_ACCEL_DEV_NAME, |
30 | }, |
31 | { |
32 | .compatible = "st,lis3lv02dl-accel" , |
33 | .data = LIS3LV02DL_ACCEL_DEV_NAME, |
34 | }, |
35 | { |
36 | .compatible = "st,lis3dh-accel" , |
37 | .data = LIS3DH_ACCEL_DEV_NAME, |
38 | }, |
39 | { |
40 | .compatible = "st,lsm330d-accel" , |
41 | .data = LSM330D_ACCEL_DEV_NAME, |
42 | }, |
43 | { |
44 | .compatible = "st,lsm330dl-accel" , |
45 | .data = LSM330DL_ACCEL_DEV_NAME, |
46 | }, |
47 | { |
48 | .compatible = "st,lsm330dlc-accel" , |
49 | .data = LSM330DLC_ACCEL_DEV_NAME, |
50 | }, |
51 | { |
52 | .compatible = "st,lis331dlh-accel" , |
53 | .data = LIS331DLH_ACCEL_DEV_NAME, |
54 | }, |
55 | { |
56 | .compatible = "st,lsm330-accel" , |
57 | .data = LSM330_ACCEL_DEV_NAME, |
58 | }, |
59 | { |
60 | .compatible = "st,lsm303agr-accel" , |
61 | .data = LSM303AGR_ACCEL_DEV_NAME, |
62 | }, |
63 | { |
64 | .compatible = "st,lis2dh12-accel" , |
65 | .data = LIS2DH12_ACCEL_DEV_NAME, |
66 | }, |
67 | { |
68 | .compatible = "st,lis3l02dq" , |
69 | .data = LIS3L02DQ_ACCEL_DEV_NAME, |
70 | }, |
71 | { |
72 | .compatible = "st,lng2dm-accel" , |
73 | .data = LNG2DM_ACCEL_DEV_NAME, |
74 | }, |
75 | { |
76 | .compatible = "st,h3lis331dl-accel" , |
77 | .data = H3LIS331DL_ACCEL_DEV_NAME, |
78 | }, |
79 | { |
80 | .compatible = "st,lis331dl-accel" , |
81 | .data = LIS331DL_ACCEL_DEV_NAME, |
82 | }, |
83 | { |
84 | .compatible = "st,lis2dw12" , |
85 | .data = LIS2DW12_ACCEL_DEV_NAME, |
86 | }, |
87 | { |
88 | .compatible = "st,lis3dhh" , |
89 | .data = LIS3DHH_ACCEL_DEV_NAME, |
90 | }, |
91 | { |
92 | .compatible = "st,lis3de" , |
93 | .data = LIS3DE_ACCEL_DEV_NAME, |
94 | }, |
95 | { |
96 | .compatible = "st,lis302dl" , |
97 | .data = LIS302DL_ACCEL_DEV_NAME, |
98 | }, |
99 | { |
100 | .compatible = "st,lsm303c-accel" , |
101 | .data = LSM303C_ACCEL_DEV_NAME, |
102 | }, |
103 | { |
104 | .compatible = "st,iis328dq" , |
105 | .data = IIS328DQ_ACCEL_DEV_NAME, |
106 | }, |
107 | {} |
108 | }; |
109 | MODULE_DEVICE_TABLE(of, st_accel_of_match); |
110 | |
111 | static int st_accel_spi_probe(struct spi_device *spi) |
112 | { |
113 | const struct st_sensor_settings *settings; |
114 | struct st_sensor_data *adata; |
115 | struct iio_dev *indio_dev; |
116 | int err; |
117 | |
118 | st_sensors_dev_name_probe(dev: &spi->dev, name: spi->modalias, len: sizeof(spi->modalias)); |
119 | |
120 | settings = st_accel_get_settings(name: spi->modalias); |
121 | if (!settings) { |
122 | dev_err(&spi->dev, "device name %s not recognized.\n" , |
123 | spi->modalias); |
124 | return -ENODEV; |
125 | } |
126 | |
127 | indio_dev = devm_iio_device_alloc(parent: &spi->dev, sizeof_priv: sizeof(*adata)); |
128 | if (!indio_dev) |
129 | return -ENOMEM; |
130 | |
131 | adata = iio_priv(indio_dev); |
132 | adata->sensor_settings = (struct st_sensor_settings *)settings; |
133 | |
134 | err = st_sensors_spi_configure(indio_dev, spi); |
135 | if (err < 0) |
136 | return err; |
137 | |
138 | err = st_sensors_power_enable(indio_dev); |
139 | if (err) |
140 | return err; |
141 | |
142 | return st_accel_common_probe(indio_dev); |
143 | } |
144 | |
145 | static const struct spi_device_id st_accel_id_table[] = { |
146 | { LIS3DH_ACCEL_DEV_NAME }, |
147 | { LSM330D_ACCEL_DEV_NAME }, |
148 | { LSM330DL_ACCEL_DEV_NAME }, |
149 | { LSM330DLC_ACCEL_DEV_NAME }, |
150 | { LIS331DLH_ACCEL_DEV_NAME }, |
151 | { LSM330_ACCEL_DEV_NAME }, |
152 | { LSM303AGR_ACCEL_DEV_NAME }, |
153 | { LIS2DH12_ACCEL_DEV_NAME }, |
154 | { LIS3L02DQ_ACCEL_DEV_NAME }, |
155 | { LNG2DM_ACCEL_DEV_NAME }, |
156 | { H3LIS331DL_ACCEL_DEV_NAME }, |
157 | { LIS331DL_ACCEL_DEV_NAME }, |
158 | { LIS3LV02DL_ACCEL_DEV_NAME }, |
159 | { LIS2DW12_ACCEL_DEV_NAME }, |
160 | { LIS3DHH_ACCEL_DEV_NAME }, |
161 | { LIS3DE_ACCEL_DEV_NAME }, |
162 | { LIS302DL_ACCEL_DEV_NAME }, |
163 | { LSM303C_ACCEL_DEV_NAME }, |
164 | { IIS328DQ_ACCEL_DEV_NAME }, |
165 | {}, |
166 | }; |
167 | MODULE_DEVICE_TABLE(spi, st_accel_id_table); |
168 | |
169 | static struct spi_driver st_accel_driver = { |
170 | .driver = { |
171 | .name = "st-accel-spi" , |
172 | .of_match_table = st_accel_of_match, |
173 | }, |
174 | .probe = st_accel_spi_probe, |
175 | .id_table = st_accel_id_table, |
176 | }; |
177 | module_spi_driver(st_accel_driver); |
178 | |
179 | MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>" ); |
180 | MODULE_DESCRIPTION("STMicroelectronics accelerometers spi driver" ); |
181 | MODULE_LICENSE("GPL v2" ); |
182 | MODULE_IMPORT_NS(IIO_ST_SENSORS); |
183 | |