xref: /OK3568_Linux_fs/kernel/drivers/input/misc/adxl34x-i2c.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * ADLX345/346 Three-Axis Digital Accelerometers (I2C Interface)
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Enter bugs at http://blackfin.uclinux.org/
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc.
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/input.h>	/* BUS_I2C */
11*4882a593Smuzhiyun #include <linux/i2c.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/of.h>
14*4882a593Smuzhiyun #include <linux/types.h>
15*4882a593Smuzhiyun #include <linux/pm.h>
16*4882a593Smuzhiyun #include "adxl34x.h"
17*4882a593Smuzhiyun 
adxl34x_smbus_read(struct device * dev,unsigned char reg)18*4882a593Smuzhiyun static int adxl34x_smbus_read(struct device *dev, unsigned char reg)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun 	return i2c_smbus_read_byte_data(client, reg);
23*4882a593Smuzhiyun }
24*4882a593Smuzhiyun 
adxl34x_smbus_write(struct device * dev,unsigned char reg,unsigned char val)25*4882a593Smuzhiyun static int adxl34x_smbus_write(struct device *dev,
26*4882a593Smuzhiyun 			       unsigned char reg, unsigned char val)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	return i2c_smbus_write_byte_data(client, reg, val);
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
adxl34x_smbus_read_block(struct device * dev,unsigned char reg,int count,void * buf)33*4882a593Smuzhiyun static int adxl34x_smbus_read_block(struct device *dev,
34*4882a593Smuzhiyun 				    unsigned char reg, int count,
35*4882a593Smuzhiyun 				    void *buf)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	return i2c_smbus_read_i2c_block_data(client, reg, count, buf);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
adxl34x_i2c_read_block(struct device * dev,unsigned char reg,int count,void * buf)42*4882a593Smuzhiyun static int adxl34x_i2c_read_block(struct device *dev,
43*4882a593Smuzhiyun 				  unsigned char reg, int count,
44*4882a593Smuzhiyun 				  void *buf)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
47*4882a593Smuzhiyun 	int ret;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	ret = i2c_master_send(client, &reg, 1);
50*4882a593Smuzhiyun 	if (ret < 0)
51*4882a593Smuzhiyun 		return ret;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	ret = i2c_master_recv(client, buf, count);
54*4882a593Smuzhiyun 	if (ret < 0)
55*4882a593Smuzhiyun 		return ret;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	if (ret != count)
58*4882a593Smuzhiyun 		return -EIO;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	return 0;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun static const struct adxl34x_bus_ops adxl34x_smbus_bops = {
64*4882a593Smuzhiyun 	.bustype	= BUS_I2C,
65*4882a593Smuzhiyun 	.write		= adxl34x_smbus_write,
66*4882a593Smuzhiyun 	.read		= adxl34x_smbus_read,
67*4882a593Smuzhiyun 	.read_block	= adxl34x_smbus_read_block,
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static const struct adxl34x_bus_ops adxl34x_i2c_bops = {
71*4882a593Smuzhiyun 	.bustype	= BUS_I2C,
72*4882a593Smuzhiyun 	.write		= adxl34x_smbus_write,
73*4882a593Smuzhiyun 	.read		= adxl34x_smbus_read,
74*4882a593Smuzhiyun 	.read_block	= adxl34x_i2c_read_block,
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun 
adxl34x_i2c_probe(struct i2c_client * client,const struct i2c_device_id * id)77*4882a593Smuzhiyun static int adxl34x_i2c_probe(struct i2c_client *client,
78*4882a593Smuzhiyun 				       const struct i2c_device_id *id)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	struct adxl34x *ac;
81*4882a593Smuzhiyun 	int error;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	error = i2c_check_functionality(client->adapter,
84*4882a593Smuzhiyun 			I2C_FUNC_SMBUS_BYTE_DATA);
85*4882a593Smuzhiyun 	if (!error) {
86*4882a593Smuzhiyun 		dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
87*4882a593Smuzhiyun 		return -EIO;
88*4882a593Smuzhiyun 	}
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	ac = adxl34x_probe(&client->dev, client->irq, false,
91*4882a593Smuzhiyun 			   i2c_check_functionality(client->adapter,
92*4882a593Smuzhiyun 						   I2C_FUNC_SMBUS_READ_I2C_BLOCK) ?
93*4882a593Smuzhiyun 				&adxl34x_smbus_bops : &adxl34x_i2c_bops);
94*4882a593Smuzhiyun 	if (IS_ERR(ac))
95*4882a593Smuzhiyun 		return PTR_ERR(ac);
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	i2c_set_clientdata(client, ac);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	return 0;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
adxl34x_i2c_remove(struct i2c_client * client)102*4882a593Smuzhiyun static int adxl34x_i2c_remove(struct i2c_client *client)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	struct adxl34x *ac = i2c_get_clientdata(client);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	return adxl34x_remove(ac);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
adxl34x_i2c_suspend(struct device * dev)109*4882a593Smuzhiyun static int __maybe_unused adxl34x_i2c_suspend(struct device *dev)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
112*4882a593Smuzhiyun 	struct adxl34x *ac = i2c_get_clientdata(client);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	adxl34x_suspend(ac);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return 0;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
adxl34x_i2c_resume(struct device * dev)119*4882a593Smuzhiyun static int __maybe_unused adxl34x_i2c_resume(struct device *dev)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
122*4882a593Smuzhiyun 	struct adxl34x *ac = i2c_get_clientdata(client);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	adxl34x_resume(ac);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	return 0;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend,
130*4882a593Smuzhiyun 			 adxl34x_i2c_resume);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun static const struct i2c_device_id adxl34x_id[] = {
133*4882a593Smuzhiyun 	{ "adxl34x", 0 },
134*4882a593Smuzhiyun 	{ }
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, adxl34x_id);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static const struct of_device_id adxl34x_of_id[] = {
140*4882a593Smuzhiyun 	/*
141*4882a593Smuzhiyun 	 * The ADXL346 is backward-compatible with the ADXL345. Differences are
142*4882a593Smuzhiyun 	 * handled by runtime detection of the device model, there's thus no
143*4882a593Smuzhiyun 	 * need for listing the "adi,adxl346" compatible value explicitly.
144*4882a593Smuzhiyun 	 */
145*4882a593Smuzhiyun 	{ .compatible = "adi,adxl345", },
146*4882a593Smuzhiyun 	/*
147*4882a593Smuzhiyun 	 * Deprecated, DT nodes should use one or more of the device-specific
148*4882a593Smuzhiyun 	 * compatible values "adi,adxl345" and "adi,adxl346".
149*4882a593Smuzhiyun 	 */
150*4882a593Smuzhiyun 	{ .compatible = "adi,adxl34x", },
151*4882a593Smuzhiyun 	{ }
152*4882a593Smuzhiyun };
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, adxl34x_of_id);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun static struct i2c_driver adxl34x_driver = {
157*4882a593Smuzhiyun 	.driver = {
158*4882a593Smuzhiyun 		.name = "adxl34x",
159*4882a593Smuzhiyun 		.pm = &adxl34x_i2c_pm,
160*4882a593Smuzhiyun 		.of_match_table = adxl34x_of_id,
161*4882a593Smuzhiyun 	},
162*4882a593Smuzhiyun 	.probe    = adxl34x_i2c_probe,
163*4882a593Smuzhiyun 	.remove   = adxl34x_i2c_remove,
164*4882a593Smuzhiyun 	.id_table = adxl34x_id,
165*4882a593Smuzhiyun };
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun module_i2c_driver(adxl34x_driver);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
170*4882a593Smuzhiyun MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver");
171*4882a593Smuzhiyun MODULE_LICENSE("GPL");
172