adxl34x-i2c.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. #include <linux/input.h> /* BUS_I2C */
  10. #include <linux/i2c.h>
  11. #include <linux/module.h>
  12. #include <linux/of.h>
  13. #include <linux/types.h>
  14. #include <linux/pm.h>
  15. #include "adxl34x.h"
  16. static int adxl34x_smbus_read(struct device *dev, unsigned char reg)
  17. {
  18. struct i2c_client *client = to_i2c_client(dev);
  19. return i2c_smbus_read_byte_data(client, reg);
  20. }
  21. static int adxl34x_smbus_write(struct device *dev,
  22. unsigned char reg, unsigned char val)
  23. {
  24. struct i2c_client *client = to_i2c_client(dev);
  25. return i2c_smbus_write_byte_data(client, reg, val);
  26. }
  27. static int adxl34x_smbus_read_block(struct device *dev,
  28. unsigned char reg, int count,
  29. void *buf)
  30. {
  31. struct i2c_client *client = to_i2c_client(dev);
  32. return i2c_smbus_read_i2c_block_data(client, reg, count, buf);
  33. }
  34. static int adxl34x_i2c_read_block(struct device *dev,
  35. unsigned char reg, int count,
  36. void *buf)
  37. {
  38. struct i2c_client *client = to_i2c_client(dev);
  39. int ret;
  40. ret = i2c_master_send(client, &reg, 1);
  41. if (ret < 0)
  42. return ret;
  43. ret = i2c_master_recv(client, buf, count);
  44. if (ret < 0)
  45. return ret;
  46. if (ret != count)
  47. return -EIO;
  48. return 0;
  49. }
  50. static const struct adxl34x_bus_ops adxl34x_smbus_bops = {
  51. .bustype = BUS_I2C,
  52. .write = adxl34x_smbus_write,
  53. .read = adxl34x_smbus_read,
  54. .read_block = adxl34x_smbus_read_block,
  55. };
  56. static const struct adxl34x_bus_ops adxl34x_i2c_bops = {
  57. .bustype = BUS_I2C,
  58. .write = adxl34x_smbus_write,
  59. .read = adxl34x_smbus_read,
  60. .read_block = adxl34x_i2c_read_block,
  61. };
  62. static int adxl34x_i2c_probe(struct i2c_client *client,
  63. const struct i2c_device_id *id)
  64. {
  65. struct adxl34x *ac;
  66. int error;
  67. error = i2c_check_functionality(client->adapter,
  68. I2C_FUNC_SMBUS_BYTE_DATA);
  69. if (!error) {
  70. dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
  71. return -EIO;
  72. }
  73. ac = adxl34x_probe(&client->dev, client->irq, false,
  74. i2c_check_functionality(client->adapter,
  75. I2C_FUNC_SMBUS_READ_I2C_BLOCK) ?
  76. &adxl34x_smbus_bops : &adxl34x_i2c_bops);
  77. if (IS_ERR(ac))
  78. return PTR_ERR(ac);
  79. i2c_set_clientdata(client, ac);
  80. return 0;
  81. }
  82. static int adxl34x_i2c_remove(struct i2c_client *client)
  83. {
  84. struct adxl34x *ac = i2c_get_clientdata(client);
  85. return adxl34x_remove(ac);
  86. }
  87. static int __maybe_unused adxl34x_i2c_suspend(struct device *dev)
  88. {
  89. struct i2c_client *client = to_i2c_client(dev);
  90. struct adxl34x *ac = i2c_get_clientdata(client);
  91. adxl34x_suspend(ac);
  92. return 0;
  93. }
  94. static int __maybe_unused adxl34x_i2c_resume(struct device *dev)
  95. {
  96. struct i2c_client *client = to_i2c_client(dev);
  97. struct adxl34x *ac = i2c_get_clientdata(client);
  98. adxl34x_resume(ac);
  99. return 0;
  100. }
  101. static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend,
  102. adxl34x_i2c_resume);
  103. static const struct i2c_device_id adxl34x_id[] = {
  104. { "adxl34x", 0 },
  105. { }
  106. };
  107. MODULE_DEVICE_TABLE(i2c, adxl34x_id);
  108. #ifdef CONFIG_OF
  109. static const struct of_device_id adxl34x_of_id[] = {
  110. /*
  111. * The ADXL346 is backward-compatible with the ADXL345. Differences are
  112. * handled by runtime detection of the device model, there's thus no
  113. * need for listing the "adi,adxl346" compatible value explicitly.
  114. */
  115. { .compatible = "adi,adxl345", },
  116. /*
  117. * Deprecated, DT nodes should use one or more of the device-specific
  118. * compatible values "adi,adxl345" and "adi,adxl346".
  119. */
  120. { .compatible = "adi,adxl34x", },
  121. { }
  122. };
  123. MODULE_DEVICE_TABLE(of, adxl34x_of_id);
  124. #endif
  125. static struct i2c_driver adxl34x_driver = {
  126. .driver = {
  127. .name = "adxl34x",
  128. .pm = &adxl34x_i2c_pm,
  129. .of_match_table = of_match_ptr(adxl34x_of_id),
  130. },
  131. .probe = adxl34x_i2c_probe,
  132. .remove = adxl34x_i2c_remove,
  133. .id_table = adxl34x_id,
  134. };
  135. module_i2c_driver(adxl34x_driver);
  136. MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
  137. MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver");
  138. MODULE_LICENSE("GPL");