180503b23SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e27c7292SMichael Hennerich /*
3e27c7292SMichael Hennerich * ADLX345/346 Three-Axis Digital Accelerometers (I2C Interface)
4e27c7292SMichael Hennerich *
5e27c7292SMichael Hennerich * Enter bugs at http://blackfin.uclinux.org/
6e27c7292SMichael Hennerich *
7e27c7292SMichael Hennerich * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc.
8e27c7292SMichael Hennerich */
9e27c7292SMichael Hennerich
10e27c7292SMichael Hennerich #include <linux/input.h> /* BUS_I2C */
11e27c7292SMichael Hennerich #include <linux/i2c.h>
12e27c7292SMichael Hennerich #include <linux/module.h>
133a38958dSLaurent Pinchart #include <linux/of.h>
14e27c7292SMichael Hennerich #include <linux/types.h>
15fbb89935SMark Brown #include <linux/pm.h>
16e27c7292SMichael Hennerich #include "adxl34x.h"
17e27c7292SMichael Hennerich
adxl34x_smbus_read(struct device * dev,unsigned char reg)18e27c7292SMichael Hennerich static int adxl34x_smbus_read(struct device *dev, unsigned char reg)
19e27c7292SMichael Hennerich {
20e27c7292SMichael Hennerich struct i2c_client *client = to_i2c_client(dev);
21e27c7292SMichael Hennerich
22e27c7292SMichael Hennerich return i2c_smbus_read_byte_data(client, reg);
23e27c7292SMichael Hennerich }
24e27c7292SMichael Hennerich
adxl34x_smbus_write(struct device * dev,unsigned char reg,unsigned char val)25e27c7292SMichael Hennerich static int adxl34x_smbus_write(struct device *dev,
26e27c7292SMichael Hennerich unsigned char reg, unsigned char val)
27e27c7292SMichael Hennerich {
28e27c7292SMichael Hennerich struct i2c_client *client = to_i2c_client(dev);
29e27c7292SMichael Hennerich
30e27c7292SMichael Hennerich return i2c_smbus_write_byte_data(client, reg, val);
31e27c7292SMichael Hennerich }
32e27c7292SMichael Hennerich
adxl34x_smbus_read_block(struct device * dev,unsigned char reg,int count,void * buf)33e27c7292SMichael Hennerich static int adxl34x_smbus_read_block(struct device *dev,
34e27c7292SMichael Hennerich unsigned char reg, int count,
35e27c7292SMichael Hennerich void *buf)
36e27c7292SMichael Hennerich {
37e27c7292SMichael Hennerich struct i2c_client *client = to_i2c_client(dev);
38e27c7292SMichael Hennerich
39e27c7292SMichael Hennerich return i2c_smbus_read_i2c_block_data(client, reg, count, buf);
40e27c7292SMichael Hennerich }
41e27c7292SMichael Hennerich
adxl34x_i2c_read_block(struct device * dev,unsigned char reg,int count,void * buf)42e27c7292SMichael Hennerich static int adxl34x_i2c_read_block(struct device *dev,
43e27c7292SMichael Hennerich unsigned char reg, int count,
44e27c7292SMichael Hennerich void *buf)
45e27c7292SMichael Hennerich {
46e27c7292SMichael Hennerich struct i2c_client *client = to_i2c_client(dev);
47e27c7292SMichael Hennerich int ret;
48e27c7292SMichael Hennerich
49e27c7292SMichael Hennerich ret = i2c_master_send(client, ®, 1);
50e27c7292SMichael Hennerich if (ret < 0)
51e27c7292SMichael Hennerich return ret;
52e27c7292SMichael Hennerich
53e27c7292SMichael Hennerich ret = i2c_master_recv(client, buf, count);
54e27c7292SMichael Hennerich if (ret < 0)
55e27c7292SMichael Hennerich return ret;
56e27c7292SMichael Hennerich
57e27c7292SMichael Hennerich if (ret != count)
58e27c7292SMichael Hennerich return -EIO;
59e27c7292SMichael Hennerich
60e27c7292SMichael Hennerich return 0;
61e27c7292SMichael Hennerich }
62e27c7292SMichael Hennerich
63af6e1d99SDmitry Torokhov static const struct adxl34x_bus_ops adxl34x_smbus_bops = {
64e27c7292SMichael Hennerich .bustype = BUS_I2C,
65e27c7292SMichael Hennerich .write = adxl34x_smbus_write,
66e27c7292SMichael Hennerich .read = adxl34x_smbus_read,
67e27c7292SMichael Hennerich .read_block = adxl34x_smbus_read_block,
68e27c7292SMichael Hennerich };
69e27c7292SMichael Hennerich
70af6e1d99SDmitry Torokhov static const struct adxl34x_bus_ops adxl34x_i2c_bops = {
71e27c7292SMichael Hennerich .bustype = BUS_I2C,
72e27c7292SMichael Hennerich .write = adxl34x_smbus_write,
73e27c7292SMichael Hennerich .read = adxl34x_smbus_read,
74e27c7292SMichael Hennerich .read_block = adxl34x_i2c_read_block,
75e27c7292SMichael Hennerich };
76e27c7292SMichael Hennerich
adxl34x_i2c_probe(struct i2c_client * client)77e186e84eSUwe Kleine-König static int adxl34x_i2c_probe(struct i2c_client *client)
78e27c7292SMichael Hennerich {
79e27c7292SMichael Hennerich struct adxl34x *ac;
80e27c7292SMichael Hennerich int error;
81e27c7292SMichael Hennerich
82e27c7292SMichael Hennerich error = i2c_check_functionality(client->adapter,
83e27c7292SMichael Hennerich I2C_FUNC_SMBUS_BYTE_DATA);
84e27c7292SMichael Hennerich if (!error) {
85e27c7292SMichael Hennerich dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
86e27c7292SMichael Hennerich return -EIO;
87e27c7292SMichael Hennerich }
88e27c7292SMichael Hennerich
89e27c7292SMichael Hennerich ac = adxl34x_probe(&client->dev, client->irq, false,
90e27c7292SMichael Hennerich i2c_check_functionality(client->adapter,
91e27c7292SMichael Hennerich I2C_FUNC_SMBUS_READ_I2C_BLOCK) ?
92af6e1d99SDmitry Torokhov &adxl34x_smbus_bops : &adxl34x_i2c_bops);
93e27c7292SMichael Hennerich if (IS_ERR(ac))
94e27c7292SMichael Hennerich return PTR_ERR(ac);
95e27c7292SMichael Hennerich
96e27c7292SMichael Hennerich i2c_set_clientdata(client, ac);
97e27c7292SMichael Hennerich
98e27c7292SMichael Hennerich return 0;
99e27c7292SMichael Hennerich }
100e27c7292SMichael Hennerich
adxl34x_i2c_remove(struct i2c_client * client)101ed5c2f5fSUwe Kleine-König static void adxl34x_i2c_remove(struct i2c_client *client)
102e27c7292SMichael Hennerich {
103e27c7292SMichael Hennerich struct adxl34x *ac = i2c_get_clientdata(client);
104e27c7292SMichael Hennerich
105af98ff04SUwe Kleine-König adxl34x_remove(ac);
106e27c7292SMichael Hennerich }
107e27c7292SMichael Hennerich
108e27c7292SMichael Hennerich static const struct i2c_device_id adxl34x_id[] = {
109e27c7292SMichael Hennerich { "adxl34x", 0 },
110e27c7292SMichael Hennerich { }
111e27c7292SMichael Hennerich };
112e27c7292SMichael Hennerich
113e27c7292SMichael Hennerich MODULE_DEVICE_TABLE(i2c, adxl34x_id);
114e27c7292SMichael Hennerich
1153a38958dSLaurent Pinchart static const struct of_device_id adxl34x_of_id[] = {
1163a38958dSLaurent Pinchart /*
1173a38958dSLaurent Pinchart * The ADXL346 is backward-compatible with the ADXL345. Differences are
1183a38958dSLaurent Pinchart * handled by runtime detection of the device model, there's thus no
1193a38958dSLaurent Pinchart * need for listing the "adi,adxl346" compatible value explicitly.
1203a38958dSLaurent Pinchart */
1213a38958dSLaurent Pinchart { .compatible = "adi,adxl345", },
1223a38958dSLaurent Pinchart /*
1233a38958dSLaurent Pinchart * Deprecated, DT nodes should use one or more of the device-specific
1243a38958dSLaurent Pinchart * compatible values "adi,adxl345" and "adi,adxl346".
1253a38958dSLaurent Pinchart */
1263a38958dSLaurent Pinchart { .compatible = "adi,adxl34x", },
1273a38958dSLaurent Pinchart { }
1283a38958dSLaurent Pinchart };
1293a38958dSLaurent Pinchart
1303a38958dSLaurent Pinchart MODULE_DEVICE_TABLE(of, adxl34x_of_id);
1313a38958dSLaurent Pinchart
132e27c7292SMichael Hennerich static struct i2c_driver adxl34x_driver = {
133e27c7292SMichael Hennerich .driver = {
134e27c7292SMichael Hennerich .name = "adxl34x",
13540be0646SJonathan Cameron .pm = pm_sleep_ptr(&adxl34x_pm),
13601427fe7SAndy Shevchenko .of_match_table = adxl34x_of_id,
137e27c7292SMichael Hennerich },
138*d8bde56dSUwe Kleine-König .probe = adxl34x_i2c_probe,
1391cb0aa88SBill Pemberton .remove = adxl34x_i2c_remove,
140e27c7292SMichael Hennerich .id_table = adxl34x_id,
141e27c7292SMichael Hennerich };
142e27c7292SMichael Hennerich
1431b92c1cfSAxel Lin module_i2c_driver(adxl34x_driver);
144e27c7292SMichael Hennerich
145e27c7292SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
146e27c7292SMichael Hennerich MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver");
147e27c7292SMichael Hennerich MODULE_LICENSE("GPL");
148