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