1 /* 2 * ADLX345/346 Three-Axis Digital Accelerometers (I2C Interface) 3 * 4 * Enter bugs at http://blackfin.uclinux.org/ 5 * 6 * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc. 7 * Licensed under the GPL-2 or later. 8 */ 9 10 #include <linux/input.h> /* BUS_I2C */ 11 #include <linux/i2c.h> 12 #include <linux/module.h> 13 #include <linux/types.h> 14 #include "adxl34x.h" 15 16 static int adxl34x_smbus_read(struct device *dev, unsigned char reg) 17 { 18 struct i2c_client *client = to_i2c_client(dev); 19 20 return i2c_smbus_read_byte_data(client, reg); 21 } 22 23 static int adxl34x_smbus_write(struct device *dev, 24 unsigned char reg, unsigned char val) 25 { 26 struct i2c_client *client = to_i2c_client(dev); 27 28 return i2c_smbus_write_byte_data(client, reg, val); 29 } 30 31 static int adxl34x_smbus_read_block(struct device *dev, 32 unsigned char reg, int count, 33 void *buf) 34 { 35 struct i2c_client *client = to_i2c_client(dev); 36 37 return i2c_smbus_read_i2c_block_data(client, reg, count, buf); 38 } 39 40 static int adxl34x_i2c_read_block(struct device *dev, 41 unsigned char reg, int count, 42 void *buf) 43 { 44 struct i2c_client *client = to_i2c_client(dev); 45 int ret; 46 47 ret = i2c_master_send(client, ®, 1); 48 if (ret < 0) 49 return ret; 50 51 ret = i2c_master_recv(client, buf, count); 52 if (ret < 0) 53 return ret; 54 55 if (ret != count) 56 return -EIO; 57 58 return 0; 59 } 60 61 static const struct adxl34x_bus_ops adxl34x_smbus_bops = { 62 .bustype = BUS_I2C, 63 .write = adxl34x_smbus_write, 64 .read = adxl34x_smbus_read, 65 .read_block = adxl34x_smbus_read_block, 66 }; 67 68 static const struct adxl34x_bus_ops adxl34x_i2c_bops = { 69 .bustype = BUS_I2C, 70 .write = adxl34x_smbus_write, 71 .read = adxl34x_smbus_read, 72 .read_block = adxl34x_i2c_read_block, 73 }; 74 75 static int __devinit adxl34x_i2c_probe(struct i2c_client *client, 76 const struct i2c_device_id *id) 77 { 78 struct adxl34x *ac; 79 int error; 80 81 error = i2c_check_functionality(client->adapter, 82 I2C_FUNC_SMBUS_BYTE_DATA); 83 if (!error) { 84 dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); 85 return -EIO; 86 } 87 88 ac = adxl34x_probe(&client->dev, client->irq, false, 89 i2c_check_functionality(client->adapter, 90 I2C_FUNC_SMBUS_READ_I2C_BLOCK) ? 91 &adxl34x_smbus_bops : &adxl34x_i2c_bops); 92 if (IS_ERR(ac)) 93 return PTR_ERR(ac); 94 95 i2c_set_clientdata(client, ac); 96 97 return 0; 98 } 99 100 static int __devexit adxl34x_i2c_remove(struct i2c_client *client) 101 { 102 struct adxl34x *ac = i2c_get_clientdata(client); 103 104 return adxl34x_remove(ac); 105 } 106 107 #ifdef CONFIG_PM 108 static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message) 109 { 110 struct adxl34x *ac = i2c_get_clientdata(client); 111 112 adxl34x_suspend(ac); 113 114 return 0; 115 } 116 117 static int adxl34x_i2c_resume(struct i2c_client *client) 118 { 119 struct adxl34x *ac = i2c_get_clientdata(client); 120 121 adxl34x_resume(ac); 122 123 return 0; 124 } 125 #else 126 # define adxl34x_i2c_suspend NULL 127 # define adxl34x_i2c_resume NULL 128 #endif 129 130 static const struct i2c_device_id adxl34x_id[] = { 131 { "adxl34x", 0 }, 132 { } 133 }; 134 135 MODULE_DEVICE_TABLE(i2c, adxl34x_id); 136 137 static struct i2c_driver adxl34x_driver = { 138 .driver = { 139 .name = "adxl34x", 140 .owner = THIS_MODULE, 141 }, 142 .probe = adxl34x_i2c_probe, 143 .remove = __devexit_p(adxl34x_i2c_remove), 144 .suspend = adxl34x_i2c_suspend, 145 .resume = adxl34x_i2c_resume, 146 .id_table = adxl34x_id, 147 }; 148 149 static int __init adxl34x_i2c_init(void) 150 { 151 return i2c_add_driver(&adxl34x_driver); 152 } 153 module_init(adxl34x_i2c_init); 154 155 static void __exit adxl34x_i2c_exit(void) 156 { 157 i2c_del_driver(&adxl34x_driver); 158 } 159 module_exit(adxl34x_i2c_exit); 160 161 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 162 MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver"); 163 MODULE_LICENSE("GPL"); 164