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 16static 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 23static 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 31static 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 40static 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 61static 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 68static 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 75static 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 100static 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 108static 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 117static 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 130static const struct i2c_device_id adxl34x_id[] = { 131 { "adxl34x", 0 }, 132 { } 133}; 134 135MODULE_DEVICE_TABLE(i2c, adxl34x_id); 136 137static 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 149static int __init adxl34x_i2c_init(void) 150{ 151 return i2c_add_driver(&adxl34x_driver); 152} 153module_init(adxl34x_i2c_init); 154 155static void __exit adxl34x_i2c_exit(void) 156{ 157 i2c_del_driver(&adxl34x_driver); 158} 159module_exit(adxl34x_i2c_exit); 160 161MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 162MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver"); 163MODULE_LICENSE("GPL"); 164