1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for Freescale's 3-Axis Accelerometer MMA8450 4 * 5 * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/slab.h> 11 #include <linux/delay.h> 12 #include <linux/i2c.h> 13 #include <linux/input.h> 14 15 #define MMA8450_DRV_NAME "mma8450" 16 17 #define MODE_CHANGE_DELAY_MS 100 18 #define POLL_INTERVAL 100 19 #define POLL_INTERVAL_MAX 500 20 21 /* register definitions */ 22 #define MMA8450_STATUS 0x00 23 #define MMA8450_STATUS_ZXYDR 0x08 24 25 #define MMA8450_OUT_X8 0x01 26 #define MMA8450_OUT_Y8 0x02 27 #define MMA8450_OUT_Z8 0x03 28 29 #define MMA8450_OUT_X_LSB 0x05 30 #define MMA8450_OUT_X_MSB 0x06 31 #define MMA8450_OUT_Y_LSB 0x07 32 #define MMA8450_OUT_Y_MSB 0x08 33 #define MMA8450_OUT_Z_LSB 0x09 34 #define MMA8450_OUT_Z_MSB 0x0a 35 36 #define MMA8450_XYZ_DATA_CFG 0x16 37 38 #define MMA8450_CTRL_REG1 0x38 39 #define MMA8450_CTRL_REG2 0x39 40 #define MMA8450_ID 0xc6 41 #define MMA8450_WHO_AM_I 0x0f 42 43 static int mma8450_read(struct i2c_client *c, unsigned int off) 44 { 45 int ret; 46 47 ret = i2c_smbus_read_byte_data(c, off); 48 if (ret < 0) 49 dev_err(&c->dev, 50 "failed to read register 0x%02x, error %d\n", 51 off, ret); 52 53 return ret; 54 } 55 56 static int mma8450_write(struct i2c_client *c, unsigned int off, u8 v) 57 { 58 int error; 59 60 error = i2c_smbus_write_byte_data(c, off, v); 61 if (error < 0) { 62 dev_err(&c->dev, 63 "failed to write to register 0x%02x, error %d\n", 64 off, error); 65 return error; 66 } 67 68 return 0; 69 } 70 71 static int mma8450_read_block(struct i2c_client *c, unsigned int off, 72 u8 *buf, size_t size) 73 { 74 int err; 75 76 err = i2c_smbus_read_i2c_block_data(c, off, size, buf); 77 if (err < 0) { 78 dev_err(&c->dev, 79 "failed to read block data at 0x%02x, error %d\n", 80 MMA8450_OUT_X_LSB, err); 81 return err; 82 } 83 84 return 0; 85 } 86 87 static void mma8450_poll(struct input_dev *input) 88 { 89 struct i2c_client *c = input_get_drvdata(input); 90 int x, y, z; 91 int ret; 92 u8 buf[6]; 93 94 ret = mma8450_read(c, MMA8450_STATUS); 95 if (ret < 0) 96 return; 97 98 if (!(ret & MMA8450_STATUS_ZXYDR)) 99 return; 100 101 ret = mma8450_read_block(c, MMA8450_OUT_X_LSB, buf, sizeof(buf)); 102 if (ret < 0) 103 return; 104 105 x = ((int)(s8)buf[1] << 4) | (buf[0] & 0xf); 106 y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf); 107 z = ((int)(s8)buf[5] << 4) | (buf[4] & 0xf); 108 109 input_report_abs(input, ABS_X, x); 110 input_report_abs(input, ABS_Y, y); 111 input_report_abs(input, ABS_Z, z); 112 input_sync(input); 113 } 114 115 /* Initialize the MMA8450 chip */ 116 static int mma8450_open(struct input_dev *input) 117 { 118 struct i2c_client *c = input_get_drvdata(input); 119 int err; 120 121 /* enable all events from X/Y/Z, no FIFO */ 122 err = mma8450_write(c, MMA8450_XYZ_DATA_CFG, 0x07); 123 if (err) 124 return err; 125 126 /* 127 * Sleep mode poll rate - 50Hz 128 * System output data rate - 400Hz 129 * Full scale selection - Active, +/- 2G 130 */ 131 err = mma8450_write(c, MMA8450_CTRL_REG1, 0x01); 132 if (err) 133 return err; 134 135 msleep(MODE_CHANGE_DELAY_MS); 136 return 0; 137 } 138 139 static void mma8450_close(struct input_dev *input) 140 { 141 struct i2c_client *c = input_get_drvdata(input); 142 143 mma8450_write(c, MMA8450_CTRL_REG1, 0x00); 144 mma8450_write(c, MMA8450_CTRL_REG2, 0x01); 145 } 146 147 /* 148 * I2C init/probing/exit functions 149 */ 150 static int mma8450_probe(struct i2c_client *c) 151 { 152 struct i2c_adapter *adapter = c->adapter; 153 struct input_dev *input; 154 int err, client_id; 155 156 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE | 157 I2C_FUNC_SMBUS_BYTE_DATA)) 158 return dev_err_probe(&c->dev, -EINVAL, 159 "I2C adapter doesn't support SMBUS BYTE"); 160 161 client_id = i2c_smbus_read_byte_data(c, MMA8450_WHO_AM_I); 162 if (client_id != MMA8450_ID) 163 return dev_err_probe(&c->dev, -EINVAL, 164 "unexpected chip ID 0x%x (vs 0x%x)\n", 165 client_id, MMA8450_ID); 166 167 input = devm_input_allocate_device(&c->dev); 168 if (!input) 169 return -ENOMEM; 170 171 input_set_drvdata(input, c); 172 173 input->name = MMA8450_DRV_NAME; 174 input->id.bustype = BUS_I2C; 175 176 input->open = mma8450_open; 177 input->close = mma8450_close; 178 179 input_set_abs_params(input, ABS_X, -2048, 2047, 32, 32); 180 input_set_abs_params(input, ABS_Y, -2048, 2047, 32, 32); 181 input_set_abs_params(input, ABS_Z, -2048, 2047, 32, 32); 182 183 err = input_setup_polling(input, mma8450_poll); 184 if (err) { 185 dev_err(&c->dev, "failed to set up polling\n"); 186 return err; 187 } 188 189 input_set_poll_interval(input, POLL_INTERVAL); 190 input_set_max_poll_interval(input, POLL_INTERVAL_MAX); 191 192 err = input_register_device(input); 193 if (err) { 194 dev_err(&c->dev, "failed to register input device\n"); 195 return err; 196 } 197 198 return 0; 199 } 200 201 static const struct i2c_device_id mma8450_id[] = { 202 { .name = MMA8450_DRV_NAME }, 203 { } 204 }; 205 MODULE_DEVICE_TABLE(i2c, mma8450_id); 206 207 static const struct of_device_id mma8450_dt_ids[] = { 208 { .compatible = "fsl,mma8450", }, 209 { /* sentinel */ } 210 }; 211 MODULE_DEVICE_TABLE(of, mma8450_dt_ids); 212 213 static struct i2c_driver mma8450_driver = { 214 .driver = { 215 .name = MMA8450_DRV_NAME, 216 .of_match_table = mma8450_dt_ids, 217 }, 218 .probe = mma8450_probe, 219 .id_table = mma8450_id, 220 }; 221 222 module_i2c_driver(mma8450_driver); 223 224 MODULE_AUTHOR("Freescale Semiconductor, Inc."); 225 MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver"); 226 MODULE_LICENSE("GPL"); 227