adxl34x-i2c.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * ADLX345/346 Three-Axis Digital Accelerometers (I2C Interface)
  4. *
  5. * Enter bugs at http://blackfin.uclinux.org/
  6. *
  7. * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc.
  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. {
  64. struct adxl34x *ac;
  65. int error;
  66. error = i2c_check_functionality(client->adapter,
  67. I2C_FUNC_SMBUS_BYTE_DATA);
  68. if (!error) {
  69. dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
  70. return -EIO;
  71. }
  72. ac = adxl34x_probe(&client->dev, client->irq, false,
  73. i2c_check_functionality(client->adapter,
  74. I2C_FUNC_SMBUS_READ_I2C_BLOCK) ?
  75. &adxl34x_smbus_bops : &adxl34x_i2c_bops);
  76. if (IS_ERR(ac))
  77. return PTR_ERR(ac);
  78. i2c_set_clientdata(client, ac);
  79. return 0;
  80. }
  81. static const struct i2c_device_id adxl34x_id[] = {
  82. { "adxl34x" },
  83. { }
  84. };
  85. MODULE_DEVICE_TABLE(i2c, adxl34x_id);
  86. static const struct of_device_id adxl34x_of_id[] = {
  87. /*
  88. * The ADXL346 is backward-compatible with the ADXL345. Differences are
  89. * handled by runtime detection of the device model, there's thus no
  90. * need for listing the "adi,adxl346" compatible value explicitly.
  91. */
  92. { .compatible = "adi,adxl345", },
  93. /*
  94. * Deprecated, DT nodes should use one or more of the device-specific
  95. * compatible values "adi,adxl345" and "adi,adxl346".
  96. */
  97. { .compatible = "adi,adxl34x", },
  98. { }
  99. };
  100. MODULE_DEVICE_TABLE(of, adxl34x_of_id);
  101. static struct i2c_driver adxl34x_driver = {
  102. .driver = {
  103. .name = "adxl34x",
  104. .dev_groups = adxl34x_groups,
  105. .pm = pm_sleep_ptr(&adxl34x_pm),
  106. .of_match_table = adxl34x_of_id,
  107. },
  108. .probe = adxl34x_i2c_probe,
  109. .id_table = adxl34x_id,
  110. };
  111. module_i2c_driver(adxl34x_driver);
  112. MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
  113. MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver");
  114. MODULE_LICENSE("GPL");