xref: /openbmc/linux/drivers/input/misc/mma8450.c (revision 3ead8b5d)
1 /*
2  *  Driver for Freescale's 3-Axis Accelerometer MMA8450
3  *
4  *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/delay.h>
25 #include <linux/i2c.h>
26 #include <linux/input-polldev.h>
27 
28 #define MMA8450_DRV_NAME	"mma8450"
29 
30 #define MODE_CHANGE_DELAY_MS	100
31 #define POLL_INTERVAL		100
32 #define POLL_INTERVAL_MAX	500
33 
34 /* register definitions */
35 #define MMA8450_STATUS		0x00
36 #define MMA8450_STATUS_ZXYDR	0x08
37 
38 #define MMA8450_OUT_X8		0x01
39 #define MMA8450_OUT_Y8		0x02
40 #define MMA8450_OUT_Z8		0x03
41 
42 #define MMA8450_OUT_X_LSB	0x05
43 #define MMA8450_OUT_X_MSB	0x06
44 #define MMA8450_OUT_Y_LSB	0x07
45 #define MMA8450_OUT_Y_MSB	0x08
46 #define MMA8450_OUT_Z_LSB	0x09
47 #define MMA8450_OUT_Z_MSB	0x0a
48 
49 #define MMA8450_XYZ_DATA_CFG	0x16
50 
51 #define MMA8450_CTRL_REG1	0x38
52 #define MMA8450_CTRL_REG2	0x39
53 
54 /* mma8450 status */
55 struct mma8450 {
56 	struct i2c_client	*client;
57 	struct input_polled_dev	*idev;
58 };
59 
60 static int mma8450_read(struct mma8450 *m, unsigned off)
61 {
62 	struct i2c_client *c = m->client;
63 	int ret;
64 
65 	ret = i2c_smbus_read_byte_data(c, off);
66 	if (ret < 0)
67 		dev_err(&c->dev,
68 			"failed to read register 0x%02x, error %d\n",
69 			off, ret);
70 
71 	return ret;
72 }
73 
74 static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
75 {
76 	struct i2c_client *c = m->client;
77 	int error;
78 
79 	error = i2c_smbus_write_byte_data(c, off, v);
80 	if (error < 0) {
81 		dev_err(&c->dev,
82 			"failed to write to register 0x%02x, error %d\n",
83 			off, error);
84 		return error;
85 	}
86 
87 	return 0;
88 }
89 
90 static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
91 {
92 	struct i2c_client *c = m->client;
93 	u8 buff[6];
94 	int err;
95 
96 	err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
97 	if (err < 0) {
98 		dev_err(&c->dev,
99 			"failed to read block data at 0x%02x, error %d\n",
100 			MMA8450_OUT_X_LSB, err);
101 		return err;
102 	}
103 
104 	*x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
105 	*y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
106 	*z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);
107 
108 	return 0;
109 }
110 
111 static void mma8450_poll(struct input_polled_dev *dev)
112 {
113 	struct mma8450 *m = dev->private;
114 	int x, y, z;
115 	int ret;
116 	int err;
117 
118 	ret = mma8450_read(m, MMA8450_STATUS);
119 	if (ret < 0)
120 		return;
121 
122 	if (!(ret & MMA8450_STATUS_ZXYDR))
123 		return;
124 
125 	err = mma8450_read_xyz(m, &x, &y, &z);
126 	if (err)
127 		return;
128 
129 	input_report_abs(dev->input, ABS_X, x);
130 	input_report_abs(dev->input, ABS_Y, y);
131 	input_report_abs(dev->input, ABS_Z, z);
132 	input_sync(dev->input);
133 }
134 
135 /* Initialize the MMA8450 chip */
136 static void mma8450_open(struct input_polled_dev *dev)
137 {
138 	struct mma8450 *m = dev->private;
139 	int err;
140 
141 	/* enable all events from X/Y/Z, no FIFO */
142 	err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
143 	if (err)
144 		return;
145 
146 	/*
147 	 * Sleep mode poll rate - 50Hz
148 	 * System output data rate - 400Hz
149 	 * Full scale selection - Active, +/- 2G
150 	 */
151 	err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
152 	if (err < 0)
153 		return;
154 
155 	msleep(MODE_CHANGE_DELAY_MS);
156 }
157 
158 static void mma8450_close(struct input_polled_dev *dev)
159 {
160 	struct mma8450 *m = dev->private;
161 
162 	mma8450_write(m, MMA8450_CTRL_REG1, 0x00);
163 	mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
164 }
165 
166 /*
167  * I2C init/probing/exit functions
168  */
169 static int __devinit mma8450_probe(struct i2c_client *c,
170 				   const struct i2c_device_id *id)
171 {
172 	struct input_polled_dev *idev;
173 	struct mma8450 *m;
174 	int err;
175 
176 	m = kzalloc(sizeof(struct mma8450), GFP_KERNEL);
177 	idev = input_allocate_polled_device();
178 	if (!m || !idev) {
179 		err = -ENOMEM;
180 		goto err_free_mem;
181 	}
182 
183 	m->client = c;
184 	m->idev = idev;
185 
186 	idev->private		= m;
187 	idev->input->name	= MMA8450_DRV_NAME;
188 	idev->input->id.bustype	= BUS_I2C;
189 	idev->poll		= mma8450_poll;
190 	idev->poll_interval	= POLL_INTERVAL;
191 	idev->poll_interval_max	= POLL_INTERVAL_MAX;
192 	idev->open		= mma8450_open;
193 	idev->close		= mma8450_close;
194 
195 	__set_bit(EV_ABS, idev->input->evbit);
196 	input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
197 	input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32);
198 	input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);
199 
200 	err = input_register_polled_device(idev);
201 	if (err) {
202 		dev_err(&c->dev, "failed to register polled input device\n");
203 		goto err_free_mem;
204 	}
205 
206 	return 0;
207 
208 err_free_mem:
209 	input_free_polled_device(idev);
210 	kfree(m);
211 	return err;
212 }
213 
214 static int __devexit mma8450_remove(struct i2c_client *c)
215 {
216 	struct mma8450 *m = i2c_get_clientdata(c);
217 	struct input_polled_dev *idev = m->idev;
218 
219 	input_unregister_polled_device(idev);
220 	input_free_polled_device(idev);
221 	kfree(m);
222 
223 	return 0;
224 }
225 
226 static const struct i2c_device_id mma8450_id[] = {
227 	{ MMA8450_DRV_NAME, 0 },
228 	{ },
229 };
230 MODULE_DEVICE_TABLE(i2c, mma8450_id);
231 
232 static struct i2c_driver mma8450_driver = {
233 	.driver = {
234 		.name	= MMA8450_DRV_NAME,
235 		.owner	= THIS_MODULE,
236 	},
237 	.probe		= mma8450_probe,
238 	.remove		= __devexit_p(mma8450_remove),
239 	.id_table	= mma8450_id,
240 };
241 
242 static int __init mma8450_init(void)
243 {
244 	return i2c_add_driver(&mma8450_driver);
245 }
246 module_init(mma8450_init);
247 
248 static void __exit mma8450_exit(void)
249 {
250 	i2c_del_driver(&mma8450_driver);
251 }
252 module_exit(mma8450_exit);
253 
254 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
255 MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver");
256 MODULE_LICENSE("GPL");
257