0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/module.h>
0014 #include <linux/types.h>
0015 #include <linux/errno.h>
0016 #include <linux/init.h>
0017 #include <linux/delay.h>
0018
0019 #include "ams.h"
0020
0021
0022 #define AMS_COMMAND 0x00
0023 #define AMS_STATUS 0x01
0024 #define AMS_CTRL1 0x02
0025 #define AMS_CTRL2 0x03
0026 #define AMS_CTRL3 0x04
0027 #define AMS_DATA1 0x05
0028 #define AMS_DATA2 0x06
0029 #define AMS_DATA3 0x07
0030 #define AMS_DATA4 0x08
0031 #define AMS_DATAX 0x20
0032 #define AMS_DATAY 0x21
0033 #define AMS_DATAZ 0x22
0034 #define AMS_FREEFALL 0x24
0035 #define AMS_SHOCK 0x25
0036 #define AMS_SENSLOW 0x26
0037 #define AMS_SENSHIGH 0x27
0038 #define AMS_CTRLX 0x28
0039 #define AMS_CTRLY 0x29
0040 #define AMS_CTRLZ 0x2A
0041 #define AMS_UNKNOWN1 0x2B
0042 #define AMS_UNKNOWN2 0x2C
0043 #define AMS_UNKNOWN3 0x2D
0044 #define AMS_VENDOR 0x2E
0045
0046
0047 enum ams_i2c_cmd {
0048 AMS_CMD_NOOP = 0,
0049 AMS_CMD_VERSION,
0050 AMS_CMD_READMEM,
0051 AMS_CMD_WRITEMEM,
0052 AMS_CMD_ERASEMEM,
0053 AMS_CMD_READEE,
0054 AMS_CMD_WRITEEE,
0055 AMS_CMD_RESET,
0056 AMS_CMD_START,
0057 };
0058
0059 static int ams_i2c_probe(struct i2c_client *client,
0060 const struct i2c_device_id *id);
0061 static int ams_i2c_remove(struct i2c_client *client);
0062
0063 static const struct i2c_device_id ams_id[] = {
0064 { "MAC,accelerometer_1", 0 },
0065 { }
0066 };
0067 MODULE_DEVICE_TABLE(i2c, ams_id);
0068
0069 static struct i2c_driver ams_i2c_driver = {
0070 .driver = {
0071 .name = "ams",
0072 },
0073 .probe = ams_i2c_probe,
0074 .remove = ams_i2c_remove,
0075 .id_table = ams_id,
0076 };
0077
0078 static s32 ams_i2c_read(u8 reg)
0079 {
0080 return i2c_smbus_read_byte_data(ams_info.i2c_client, reg);
0081 }
0082
0083 static int ams_i2c_write(u8 reg, u8 value)
0084 {
0085 return i2c_smbus_write_byte_data(ams_info.i2c_client, reg, value);
0086 }
0087
0088 static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
0089 {
0090 s32 result;
0091 int count = 3;
0092
0093 ams_i2c_write(AMS_COMMAND, cmd);
0094 msleep(5);
0095
0096 while (count--) {
0097 result = ams_i2c_read(AMS_COMMAND);
0098 if (result == 0 || result & 0x80)
0099 return 0;
0100
0101 schedule_timeout_uninterruptible(HZ / 20);
0102 }
0103
0104 return -1;
0105 }
0106
0107 static void ams_i2c_set_irq(enum ams_irq reg, char enable)
0108 {
0109 if (reg & AMS_IRQ_FREEFALL) {
0110 u8 val = ams_i2c_read(AMS_CTRLX);
0111 if (enable)
0112 val |= 0x80;
0113 else
0114 val &= ~0x80;
0115 ams_i2c_write(AMS_CTRLX, val);
0116 }
0117
0118 if (reg & AMS_IRQ_SHOCK) {
0119 u8 val = ams_i2c_read(AMS_CTRLY);
0120 if (enable)
0121 val |= 0x80;
0122 else
0123 val &= ~0x80;
0124 ams_i2c_write(AMS_CTRLY, val);
0125 }
0126
0127 if (reg & AMS_IRQ_GLOBAL) {
0128 u8 val = ams_i2c_read(AMS_CTRLZ);
0129 if (enable)
0130 val |= 0x80;
0131 else
0132 val &= ~0x80;
0133 ams_i2c_write(AMS_CTRLZ, val);
0134 }
0135 }
0136
0137 static void ams_i2c_clear_irq(enum ams_irq reg)
0138 {
0139 if (reg & AMS_IRQ_FREEFALL)
0140 ams_i2c_write(AMS_FREEFALL, 0);
0141
0142 if (reg & AMS_IRQ_SHOCK)
0143 ams_i2c_write(AMS_SHOCK, 0);
0144 }
0145
0146 static u8 ams_i2c_get_vendor(void)
0147 {
0148 return ams_i2c_read(AMS_VENDOR);
0149 }
0150
0151 static void ams_i2c_get_xyz(s8 *x, s8 *y, s8 *z)
0152 {
0153 *x = ams_i2c_read(AMS_DATAX);
0154 *y = ams_i2c_read(AMS_DATAY);
0155 *z = ams_i2c_read(AMS_DATAZ);
0156 }
0157
0158 static int ams_i2c_probe(struct i2c_client *client,
0159 const struct i2c_device_id *id)
0160 {
0161 int vmaj, vmin;
0162 int result;
0163
0164
0165 if (unlikely(ams_info.has_device))
0166 return -ENODEV;
0167
0168 ams_info.i2c_client = client;
0169
0170 if (ams_i2c_cmd(AMS_CMD_RESET)) {
0171 printk(KERN_INFO "ams: Failed to reset the device\n");
0172 return -ENODEV;
0173 }
0174
0175 if (ams_i2c_cmd(AMS_CMD_START)) {
0176 printk(KERN_INFO "ams: Failed to start the device\n");
0177 return -ENODEV;
0178 }
0179
0180
0181 ams_i2c_write(AMS_CTRL1, 0x02);
0182 ams_i2c_write(AMS_CTRL2, 0x85);
0183 ams_i2c_write(AMS_CTRL3, 0x01);
0184
0185 ams_i2c_cmd(AMS_CMD_READMEM);
0186
0187 vmaj = ams_i2c_read(AMS_DATA1);
0188 vmin = ams_i2c_read(AMS_DATA2);
0189 if (vmaj != 1 || vmin != 52) {
0190 printk(KERN_INFO "ams: Incorrect device version (%d.%d)\n",
0191 vmaj, vmin);
0192 return -ENODEV;
0193 }
0194
0195 ams_i2c_cmd(AMS_CMD_VERSION);
0196
0197 vmaj = ams_i2c_read(AMS_DATA1);
0198 vmin = ams_i2c_read(AMS_DATA2);
0199 if (vmaj != 0 || vmin != 1) {
0200 printk(KERN_INFO "ams: Incorrect firmware version (%d.%d)\n",
0201 vmaj, vmin);
0202 return -ENODEV;
0203 }
0204
0205
0206 ams_i2c_set_irq(AMS_IRQ_ALL, 0);
0207
0208 result = ams_sensor_attach();
0209 if (result < 0)
0210 return result;
0211
0212
0213 ams_i2c_write(AMS_SENSLOW, 0x15);
0214 ams_i2c_write(AMS_SENSHIGH, 0x60);
0215 ams_i2c_write(AMS_CTRLX, 0x08);
0216 ams_i2c_write(AMS_CTRLY, 0x0F);
0217 ams_i2c_write(AMS_CTRLZ, 0x4F);
0218 ams_i2c_write(AMS_UNKNOWN1, 0x14);
0219
0220
0221 ams_i2c_clear_irq(AMS_IRQ_ALL);
0222
0223 ams_info.has_device = 1;
0224
0225
0226 ams_i2c_set_irq(AMS_IRQ_ALL, 1);
0227
0228 printk(KERN_INFO "ams: Found I2C based motion sensor\n");
0229
0230 return 0;
0231 }
0232
0233 static int ams_i2c_remove(struct i2c_client *client)
0234 {
0235 if (ams_info.has_device) {
0236 ams_sensor_detach();
0237
0238
0239 ams_i2c_set_irq(AMS_IRQ_ALL, 0);
0240
0241
0242 ams_i2c_clear_irq(AMS_IRQ_ALL);
0243
0244 printk(KERN_INFO "ams: Unloading\n");
0245
0246 ams_info.has_device = 0;
0247 }
0248
0249 return 0;
0250 }
0251
0252 static void ams_i2c_exit(void)
0253 {
0254 i2c_del_driver(&ams_i2c_driver);
0255 }
0256
0257 int __init ams_i2c_init(struct device_node *np)
0258 {
0259
0260 ams_info.of_node = np;
0261 ams_info.exit = ams_i2c_exit;
0262 ams_info.get_vendor = ams_i2c_get_vendor;
0263 ams_info.get_xyz = ams_i2c_get_xyz;
0264 ams_info.clear_irq = ams_i2c_clear_irq;
0265 ams_info.bustype = BUS_I2C;
0266
0267 return i2c_add_driver(&ams_i2c_driver);
0268 }