dmard06.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * IIO driver for Domintech DMARD06 accelerometer
  3. *
  4. * Copyright (C) 2016 Aleksei Mamlin <mamlinav@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2, as published by the Free Software Foundation.
  9. */
  10. #include <linux/module.h>
  11. #include <linux/i2c.h>
  12. #include <linux/iio/iio.h>
  13. #define DMARD06_DRV_NAME "dmard06"
  14. /* Device data registers */
  15. #define DMARD06_CHIP_ID_REG 0x0f
  16. #define DMARD06_TOUT_REG 0x40
  17. #define DMARD06_XOUT_REG 0x41
  18. #define DMARD06_YOUT_REG 0x42
  19. #define DMARD06_ZOUT_REG 0x43
  20. #define DMARD06_CTRL1_REG 0x44
  21. /* Device ID value */
  22. #define DMARD05_CHIP_ID 0x05
  23. #define DMARD06_CHIP_ID 0x06
  24. #define DMARD07_CHIP_ID 0x07
  25. /* Device values */
  26. #define DMARD05_AXIS_SCALE_VAL 15625
  27. #define DMARD06_AXIS_SCALE_VAL 31250
  28. #define DMARD06_TEMP_CENTER_VAL 25
  29. #define DMARD06_SIGN_BIT 7
  30. /* Device power modes */
  31. #define DMARD06_MODE_NORMAL 0x27
  32. #define DMARD06_MODE_POWERDOWN 0x00
  33. /* Device channels */
  34. #define DMARD06_ACCEL_CHANNEL(_axis, _reg) { \
  35. .type = IIO_ACCEL, \
  36. .address = _reg, \
  37. .channel2 = IIO_MOD_##_axis, \
  38. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
  39. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
  40. .modified = 1, \
  41. }
  42. #define DMARD06_TEMP_CHANNEL(_reg) { \
  43. .type = IIO_TEMP, \
  44. .address = _reg, \
  45. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
  46. BIT(IIO_CHAN_INFO_OFFSET), \
  47. }
  48. struct dmard06_data {
  49. struct i2c_client *client;
  50. u8 chip_id;
  51. };
  52. static const struct iio_chan_spec dmard06_channels[] = {
  53. DMARD06_ACCEL_CHANNEL(X, DMARD06_XOUT_REG),
  54. DMARD06_ACCEL_CHANNEL(Y, DMARD06_YOUT_REG),
  55. DMARD06_ACCEL_CHANNEL(Z, DMARD06_ZOUT_REG),
  56. DMARD06_TEMP_CHANNEL(DMARD06_TOUT_REG),
  57. };
  58. static int dmard06_read_raw(struct iio_dev *indio_dev,
  59. struct iio_chan_spec const *chan,
  60. int *val, int *val2, long mask)
  61. {
  62. struct dmard06_data *dmard06 = iio_priv(indio_dev);
  63. int ret;
  64. switch (mask) {
  65. case IIO_CHAN_INFO_RAW:
  66. ret = i2c_smbus_read_byte_data(dmard06->client,
  67. chan->address);
  68. if (ret < 0) {
  69. dev_err(&dmard06->client->dev,
  70. "Error reading data: %d\n", ret);
  71. return ret;
  72. }
  73. *val = sign_extend32(ret, DMARD06_SIGN_BIT);
  74. if (dmard06->chip_id == DMARD06_CHIP_ID)
  75. *val = *val >> 1;
  76. switch (chan->type) {
  77. case IIO_ACCEL:
  78. return IIO_VAL_INT;
  79. case IIO_TEMP:
  80. if (dmard06->chip_id != DMARD06_CHIP_ID)
  81. *val = *val / 2;
  82. return IIO_VAL_INT;
  83. default:
  84. return -EINVAL;
  85. }
  86. case IIO_CHAN_INFO_OFFSET:
  87. switch (chan->type) {
  88. case IIO_TEMP:
  89. *val = DMARD06_TEMP_CENTER_VAL;
  90. return IIO_VAL_INT;
  91. default:
  92. return -EINVAL;
  93. }
  94. case IIO_CHAN_INFO_SCALE:
  95. switch (chan->type) {
  96. case IIO_ACCEL:
  97. *val = 0;
  98. if (dmard06->chip_id == DMARD06_CHIP_ID)
  99. *val2 = DMARD06_AXIS_SCALE_VAL;
  100. else
  101. *val2 = DMARD05_AXIS_SCALE_VAL;
  102. return IIO_VAL_INT_PLUS_MICRO;
  103. default:
  104. return -EINVAL;
  105. }
  106. default:
  107. return -EINVAL;
  108. }
  109. }
  110. static const struct iio_info dmard06_info = {
  111. .driver_module = THIS_MODULE,
  112. .read_raw = dmard06_read_raw,
  113. };
  114. static int dmard06_probe(struct i2c_client *client,
  115. const struct i2c_device_id *id)
  116. {
  117. int ret;
  118. struct iio_dev *indio_dev;
  119. struct dmard06_data *dmard06;
  120. if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  121. dev_err(&client->dev, "I2C check functionality failed\n");
  122. return -ENXIO;
  123. }
  124. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*dmard06));
  125. if (!indio_dev) {
  126. dev_err(&client->dev, "Failed to allocate iio device\n");
  127. return -ENOMEM;
  128. }
  129. dmard06 = iio_priv(indio_dev);
  130. dmard06->client = client;
  131. ret = i2c_smbus_read_byte_data(dmard06->client, DMARD06_CHIP_ID_REG);
  132. if (ret < 0) {
  133. dev_err(&client->dev, "Error reading chip id: %d\n", ret);
  134. return ret;
  135. }
  136. if (ret != DMARD05_CHIP_ID && ret != DMARD06_CHIP_ID &&
  137. ret != DMARD07_CHIP_ID) {
  138. dev_err(&client->dev, "Invalid chip id: %02d\n", ret);
  139. return -ENODEV;
  140. }
  141. dmard06->chip_id = ret;
  142. i2c_set_clientdata(client, indio_dev);
  143. indio_dev->dev.parent = &client->dev;
  144. indio_dev->name = DMARD06_DRV_NAME;
  145. indio_dev->modes = INDIO_DIRECT_MODE;
  146. indio_dev->channels = dmard06_channels;
  147. indio_dev->num_channels = ARRAY_SIZE(dmard06_channels);
  148. indio_dev->info = &dmard06_info;
  149. return devm_iio_device_register(&client->dev, indio_dev);
  150. }
  151. #ifdef CONFIG_PM_SLEEP
  152. static int dmard06_suspend(struct device *dev)
  153. {
  154. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  155. struct dmard06_data *dmard06 = iio_priv(indio_dev);
  156. int ret;
  157. ret = i2c_smbus_write_byte_data(dmard06->client, DMARD06_CTRL1_REG,
  158. DMARD06_MODE_POWERDOWN);
  159. if (ret < 0)
  160. return ret;
  161. return 0;
  162. }
  163. static int dmard06_resume(struct device *dev)
  164. {
  165. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  166. struct dmard06_data *dmard06 = iio_priv(indio_dev);
  167. int ret;
  168. ret = i2c_smbus_write_byte_data(dmard06->client, DMARD06_CTRL1_REG,
  169. DMARD06_MODE_NORMAL);
  170. if (ret < 0)
  171. return ret;
  172. return 0;
  173. }
  174. static SIMPLE_DEV_PM_OPS(dmard06_pm_ops, dmard06_suspend, dmard06_resume);
  175. #define DMARD06_PM_OPS (&dmard06_pm_ops)
  176. #else
  177. #define DMARD06_PM_OPS NULL
  178. #endif
  179. static const struct i2c_device_id dmard06_id[] = {
  180. { "dmard05", 0 },
  181. { "dmard06", 0 },
  182. { "dmard07", 0 },
  183. { }
  184. };
  185. MODULE_DEVICE_TABLE(i2c, dmard06_id);
  186. static const struct of_device_id dmard06_of_match[] = {
  187. { .compatible = "domintech,dmard05" },
  188. { .compatible = "domintech,dmard06" },
  189. { .compatible = "domintech,dmard07" },
  190. { }
  191. };
  192. MODULE_DEVICE_TABLE(of, dmard06_of_match);
  193. static struct i2c_driver dmard06_driver = {
  194. .probe = dmard06_probe,
  195. .id_table = dmard06_id,
  196. .driver = {
  197. .name = DMARD06_DRV_NAME,
  198. .of_match_table = of_match_ptr(dmard06_of_match),
  199. .pm = DMARD06_PM_OPS,
  200. },
  201. };
  202. module_i2c_driver(dmard06_driver);
  203. MODULE_AUTHOR("Aleksei Mamlin <mamlinav@gmail.com>");
  204. MODULE_DESCRIPTION("Domintech DMARD06 accelerometer driver");
  205. MODULE_LICENSE("GPL v2");