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/acpi.h>
14#include <linux/i2c.h>
15#include <linux/iio/iio.h>
16
17#include <linux/iio/common/st_sensors_i2c.h>
18#include "st_accel.h"
19
20static const struct of_device_id st_accel_of_match[] = {
21	{
22		/* An older compatible */
23		.compatible = "st,lis3lv02d",
24		.data = LIS3LV02DL_ACCEL_DEV_NAME,
25	},
26	{
27		.compatible = "st,lis3lv02dl-accel",
28		.data = LIS3LV02DL_ACCEL_DEV_NAME,
29	},
30	{
31		.compatible = "st,lsm303dlh-accel",
32		.data = LSM303DLH_ACCEL_DEV_NAME,
33	},
34	{
35		.compatible = "st,lsm303dlhc-accel",
36		.data = LSM303DLHC_ACCEL_DEV_NAME,
37	},
38	{
39		.compatible = "st,lis3dh-accel",
40		.data = LIS3DH_ACCEL_DEV_NAME,
41	},
42	{
43		.compatible = "st,lsm330d-accel",
44		.data = LSM330D_ACCEL_DEV_NAME,
45	},
46	{
47		.compatible = "st,lsm330dl-accel",
48		.data = LSM330DL_ACCEL_DEV_NAME,
49	},
50	{
51		.compatible = "st,lsm330dlc-accel",
52		.data = LSM330DLC_ACCEL_DEV_NAME,
53	},
54	{
55		.compatible = "st,lis331dl-accel",
56		.data = LIS331DL_ACCEL_DEV_NAME,
57	},
58	{
59		.compatible = "st,lis331dlh-accel",
60		.data = LIS331DLH_ACCEL_DEV_NAME,
61	},
62	{
63		.compatible = "st,lsm303dl-accel",
64		.data = LSM303DL_ACCEL_DEV_NAME,
65	},
66	{
67		.compatible = "st,lsm303dlm-accel",
68		.data = LSM303DLM_ACCEL_DEV_NAME,
69	},
70	{
71		.compatible = "st,lsm330-accel",
72		.data = LSM330_ACCEL_DEV_NAME,
73	},
74	{
75		.compatible = "st,lsm303agr-accel",
76		.data = LSM303AGR_ACCEL_DEV_NAME,
77	},
78	{
79		.compatible = "st,lis2dh12-accel",
80		.data = LIS2DH12_ACCEL_DEV_NAME,
81	},
82	{
83		.compatible = "st,h3lis331dl-accel",
84		.data = H3LIS331DL_ACCEL_DEV_NAME,
85	},
86	{
87		.compatible = "st,lis3l02dq",
88		.data = LIS3L02DQ_ACCEL_DEV_NAME,
89	},
90	{
91		.compatible = "st,lng2dm-accel",
92		.data = LNG2DM_ACCEL_DEV_NAME,
93	},
94	{
95		.compatible = "st,lis2dw12",
96		.data = LIS2DW12_ACCEL_DEV_NAME,
97	},
98	{
99		.compatible = "st,lis3de",
100		.data = LIS3DE_ACCEL_DEV_NAME,
101	},
102	{
103		.compatible = "st,lis2de12",
104		.data = LIS2DE12_ACCEL_DEV_NAME,
105	},
106	{
107		.compatible = "st,lis2hh12",
108		.data = LIS2HH12_ACCEL_DEV_NAME,
109	},
110	{
111		.compatible = "st,lis302dl",
112		.data = LIS302DL_ACCEL_DEV_NAME,
113	},
114	{
115		.compatible = "st,lsm303c-accel",
116		.data = LSM303C_ACCEL_DEV_NAME,
117	},
118	{
119		.compatible = "silan,sc7a20",
120		.data = SC7A20_ACCEL_DEV_NAME,
121	},
122	{
123		.compatible = "st,iis328dq",
124		.data = IIS328DQ_ACCEL_DEV_NAME,
125	},
126	{},
127};
128MODULE_DEVICE_TABLE(of, st_accel_of_match);
129
130#ifdef CONFIG_ACPI
131static const struct acpi_device_id st_accel_acpi_match[] = {
132	{"SMO8840", (kernel_ulong_t)LIS2DH12_ACCEL_DEV_NAME},
133	{"SMO8A90", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME},
134	{ },
135};
136MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match);
137#endif
138
139static const struct i2c_device_id st_accel_id_table[] = {
140	{ LSM303DLH_ACCEL_DEV_NAME },
141	{ LSM303DLHC_ACCEL_DEV_NAME },
142	{ LIS3DH_ACCEL_DEV_NAME },
143	{ LSM330D_ACCEL_DEV_NAME },
144	{ LSM330DL_ACCEL_DEV_NAME },
145	{ LSM330DLC_ACCEL_DEV_NAME },
146	{ LIS331DLH_ACCEL_DEV_NAME },
147	{ LSM303DL_ACCEL_DEV_NAME },
148	{ LSM303DLM_ACCEL_DEV_NAME },
149	{ LSM330_ACCEL_DEV_NAME },
150	{ LSM303AGR_ACCEL_DEV_NAME },
151	{ LIS2DH12_ACCEL_DEV_NAME },
152	{ LIS3L02DQ_ACCEL_DEV_NAME },
153	{ LNG2DM_ACCEL_DEV_NAME },
154	{ H3LIS331DL_ACCEL_DEV_NAME },
155	{ LIS331DL_ACCEL_DEV_NAME },
156	{ LIS3LV02DL_ACCEL_DEV_NAME },
157	{ LIS2DW12_ACCEL_DEV_NAME },
158	{ LIS3DE_ACCEL_DEV_NAME },
159	{ LIS2DE12_ACCEL_DEV_NAME },
160	{ LIS2HH12_ACCEL_DEV_NAME },
161	{ LIS302DL_ACCEL_DEV_NAME },
162	{ LSM303C_ACCEL_DEV_NAME },
163	{ SC7A20_ACCEL_DEV_NAME },
164	{ IIS328DQ_ACCEL_DEV_NAME },
165	{},
166};
167MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
168
169static int st_accel_i2c_probe(struct i2c_client *client)
170{
171	const struct st_sensor_settings *settings;
172	struct st_sensor_data *adata;
173	struct iio_dev *indio_dev;
174	int ret;
175
176	st_sensors_dev_name_probe(&client->dev, client->name, sizeof(client->name));
177
178	settings = st_accel_get_settings(client->name);
179	if (!settings) {
180		dev_err(&client->dev, "device name %s not recognized.\n",
181			client->name);
182		return -ENODEV;
183	}
184
185	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata));
186	if (!indio_dev)
187		return -ENOMEM;
188
189	adata = iio_priv(indio_dev);
190	adata->sensor_settings = (struct st_sensor_settings *)settings;
191
192	ret = st_sensors_i2c_configure(indio_dev, client);
193	if (ret < 0)
194		return ret;
195
196	ret = st_sensors_power_enable(indio_dev);
197	if (ret)
198		return ret;
199
200	return st_accel_common_probe(indio_dev);
201}
202
203static struct i2c_driver st_accel_driver = {
204	.driver = {
205		.name = "st-accel-i2c",
206		.of_match_table = st_accel_of_match,
207		.acpi_match_table = ACPI_PTR(st_accel_acpi_match),
208	},
209	.probe = st_accel_i2c_probe,
210	.id_table = st_accel_id_table,
211};
212module_i2c_driver(st_accel_driver);
213
214MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
215MODULE_DESCRIPTION("STMicroelectronics accelerometers i2c driver");
216MODULE_LICENSE("GPL v2");
217MODULE_IMPORT_NS(IIO_ST_SENSORS);
218