st_lis3dhh.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * STMicroelectronics st_lis3dhh sensor driver
  4. *
  5. * MEMS Software Solutions Team
  6. *
  7. * Copyright 2016 STMicroelectronics Inc.
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/device.h>
  12. #include <linux/iio/sysfs.h>
  13. #include <linux/iio/buffer.h>
  14. #include <linux/delay.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/spi/spi.h>
  17. #include <asm/unaligned.h>
  18. #include <linux/platform_data/st_sensors_pdata.h>
  19. #include "st_lis3dhh.h"
  20. #define LIS3DHH_DEV_NAME "lis3dhh"
  21. #define IIS3DHHC_DEV_NAME "iis3dhhc"
  22. #define REG_WHOAMI_ADDR 0x0f
  23. #define REG_WHOAMI_VAL 0x11
  24. #define REG_CTRL1_ADDR 0x20
  25. #define REG_CTRL1_BDU_MASK BIT(0)
  26. #define REG_CTRL1_SW_RESET_MASK BIT(2)
  27. #define REG_CTRL1_EN_MASK BIT(7)
  28. #define REG_INT1_CTRL_ADDR 0x21
  29. #define REG_INT2_CTRL_ADDR 0x22
  30. #define REG_INT_FTM_MASK BIT(3)
  31. #define ST_LIS3DHH_FS IIO_G_TO_M_S_2(76)
  32. #define ST_LIS3DHH_DATA_CHANNEL(addr, modx, scan_idx) \
  33. { \
  34. .type = IIO_ACCEL, \
  35. .address = addr, \
  36. .modified = 1, \
  37. .channel2 = modx, \
  38. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
  39. BIT(IIO_CHAN_INFO_SCALE), \
  40. .scan_index = scan_idx, \
  41. .scan_type = { \
  42. .sign = 's', \
  43. .realbits = 16, \
  44. .storagebits = 16, \
  45. .endianness = IIO_LE, \
  46. }, \
  47. }
  48. #define ST_LIS3DHH_FLUSH_CHANNEL() \
  49. { \
  50. .type = IIO_ACCEL, \
  51. .modified = 0, \
  52. .scan_index = -1, \
  53. .indexed = -1, \
  54. .event_spec = &st_lis3dhh_fifo_flush_event, \
  55. .num_event_specs = 1, \
  56. }
  57. const struct iio_event_spec st_lis3dhh_fifo_flush_event = {
  58. .type = STM_IIO_EV_TYPE_FIFO_FLUSH,
  59. .dir = IIO_EV_DIR_EITHER,
  60. };
  61. static const struct iio_chan_spec st_lis3dhh_channels[] = {
  62. ST_LIS3DHH_DATA_CHANNEL(0x28, IIO_MOD_X, 0),
  63. ST_LIS3DHH_DATA_CHANNEL(0x2a, IIO_MOD_Y, 1),
  64. ST_LIS3DHH_DATA_CHANNEL(0x2c, IIO_MOD_Z, 2),
  65. ST_LIS3DHH_FLUSH_CHANNEL(),
  66. IIO_CHAN_SOFT_TIMESTAMP(3),
  67. };
  68. #define SENSORS_SPI_READ BIT(7)
  69. int st_lis3dhh_spi_read(struct st_lis3dhh_hw *hw, u8 addr, int len, u8 *data)
  70. {
  71. struct spi_device *spi = to_spi_device(hw->dev);
  72. int err;
  73. struct spi_transfer xfers[] = {
  74. {
  75. .tx_buf = hw->tb.tx_buf,
  76. .bits_per_word = 8,
  77. .len = 1,
  78. },
  79. {
  80. .rx_buf = hw->tb.rx_buf,
  81. .bits_per_word = 8,
  82. .len = len,
  83. }
  84. };
  85. hw->tb.tx_buf[0] = addr | SENSORS_SPI_READ;
  86. err = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
  87. if (err < 0)
  88. return err;
  89. memcpy(data, hw->tb.rx_buf, len * sizeof(u8));
  90. return len;
  91. }
  92. static int st_lis3dhh_spi_write(struct st_lis3dhh_hw *hw, u8 addr,
  93. int len, u8 *data)
  94. {
  95. struct spi_device *spi = to_spi_device(hw->dev);
  96. if (len >= ST_LIS3DHH_TX_MAX_LENGTH)
  97. return -ENOMEM;
  98. hw->tb.tx_buf[0] = addr;
  99. memcpy(&hw->tb.tx_buf[1], data, len);
  100. return spi_write(spi, hw->tb.tx_buf, len + 1);
  101. }
  102. int st_lis3dhh_write_with_mask(struct st_lis3dhh_hw *hw, u8 addr, u8 mask,
  103. u8 val)
  104. {
  105. u8 data;
  106. int err;
  107. mutex_lock(&hw->lock);
  108. err = st_lis3dhh_spi_read(hw, addr, 1, &data);
  109. if (err < 0) {
  110. dev_err(hw->dev, "failed to read %02x register\n", addr);
  111. mutex_unlock(&hw->lock);
  112. return err;
  113. }
  114. data = (data & ~mask) | ((val << __ffs(mask)) & mask);
  115. err = st_lis3dhh_spi_write(hw, addr, 1, &data);
  116. if (err < 0) {
  117. dev_err(hw->dev, "failed to write %02x register\n", addr);
  118. mutex_unlock(&hw->lock);
  119. return err;
  120. }
  121. mutex_unlock(&hw->lock);
  122. return 0;
  123. }
  124. int st_lis3dhh_set_enable(struct st_lis3dhh_hw *hw, bool enable)
  125. {
  126. return st_lis3dhh_write_with_mask(hw, REG_CTRL1_ADDR,
  127. REG_CTRL1_EN_MASK, enable);
  128. }
  129. static int st_lis3dhh_read_raw(struct iio_dev *iio_dev,
  130. struct iio_chan_spec const *ch,
  131. int *val, int *val2, long mask)
  132. {
  133. struct st_lis3dhh_hw *hw = iio_priv(iio_dev);
  134. int ret;
  135. switch (mask) {
  136. case IIO_CHAN_INFO_RAW: {
  137. int err, delay;
  138. u8 data[2];
  139. mutex_lock(&iio_dev->mlock);
  140. if (iio_buffer_enabled(iio_dev)) {
  141. mutex_unlock(&iio_dev->mlock);
  142. return -EBUSY;
  143. }
  144. err = st_lis3dhh_set_enable(hw, true);
  145. if (err < 0) {
  146. mutex_unlock(&iio_dev->mlock);
  147. return err;
  148. }
  149. /* sample to discard, 3 * odr us */
  150. delay = 3000000 / ST_LIS3DHH_ODR;
  151. usleep_range(delay, delay + 1);
  152. err = st_lis3dhh_spi_read(hw, ch->address, 2, data);
  153. if (err < 0) {
  154. mutex_unlock(&iio_dev->mlock);
  155. return err;
  156. }
  157. err = st_lis3dhh_set_enable(hw, false);
  158. if (err < 0) {
  159. mutex_unlock(&iio_dev->mlock);
  160. return err;
  161. }
  162. *val = (s16)get_unaligned_le16(data);
  163. *val = *val >> ch->scan_type.shift;
  164. mutex_unlock(&iio_dev->mlock);
  165. ret = IIO_VAL_INT;
  166. break;
  167. }
  168. case IIO_CHAN_INFO_SCALE:
  169. *val = 0;
  170. *val2 = ST_LIS3DHH_FS;
  171. ret = IIO_VAL_INT_PLUS_MICRO;
  172. break;
  173. case IIO_CHAN_INFO_SAMP_FREQ:
  174. *val = ST_LIS3DHH_ODR;
  175. ret = IIO_VAL_INT;
  176. break;
  177. default:
  178. ret = -EINVAL;
  179. break;
  180. }
  181. return ret;
  182. }
  183. static ssize_t
  184. st_lis3dhh_get_sampling_frequency_avail(struct device *device,
  185. struct device_attribute *attr,
  186. char *buf)
  187. {
  188. return scnprintf(buf, PAGE_SIZE, "%d\n", ST_LIS3DHH_ODR);
  189. }
  190. static ssize_t st_lis3dhh_get_scale_avail(struct device *device,
  191. struct device_attribute *attr,
  192. char *buf)
  193. {
  194. return scnprintf(buf, PAGE_SIZE, "0.%06d\n", (int)ST_LIS3DHH_FS);
  195. }
  196. static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lis3dhh_get_sampling_frequency_avail);
  197. static IIO_DEVICE_ATTR(in_accel_scale_available, 0444,
  198. st_lis3dhh_get_scale_avail, NULL, 0);
  199. static IIO_DEVICE_ATTR(hwfifo_watermark, 0644,
  200. st_lis3dhh_get_hwfifo_watermark,
  201. st_lis3dhh_set_hwfifo_watermark, 0);
  202. static IIO_DEVICE_ATTR(hwfifo_watermark_max, 0444,
  203. st_lis3dhh_get_max_hwfifo_watermark, NULL, 0);
  204. static IIO_DEVICE_ATTR(hwfifo_flush, 0200, NULL, st_lis3dhh_flush_hwfifo, 0);
  205. static struct attribute *st_lis3dhh_attributes[] = {
  206. &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
  207. &iio_dev_attr_in_accel_scale_available.dev_attr.attr,
  208. &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
  209. &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
  210. &iio_dev_attr_hwfifo_flush.dev_attr.attr,
  211. NULL,
  212. };
  213. static const struct attribute_group st_lis3dhh_attribute_group = {
  214. .attrs = st_lis3dhh_attributes,
  215. };
  216. static const struct iio_info st_lis3dhh_info = {
  217. .attrs = &st_lis3dhh_attribute_group,
  218. .read_raw = st_lis3dhh_read_raw,
  219. };
  220. static int st_lis3dhh_check_whoami(struct st_lis3dhh_hw *hw)
  221. {
  222. u8 data;
  223. int err;
  224. err = st_lis3dhh_spi_read(hw, REG_WHOAMI_ADDR, sizeof(data), &data);
  225. if (err < 0) {
  226. dev_err(hw->dev, "failed to read whoami register\n");
  227. return err;
  228. }
  229. if (data != REG_WHOAMI_VAL) {
  230. dev_err(hw->dev, "wrong whoami {%02x-%02x}\n",
  231. data, REG_WHOAMI_VAL);
  232. return -ENODEV;
  233. }
  234. return 0;
  235. }
  236. static int st_lis3dhh_of_get_drdy_pin(struct st_lis3dhh_hw *hw, int *drdy_pin)
  237. {
  238. struct device_node *np = hw->dev->of_node;
  239. if (!np)
  240. return -EINVAL;
  241. return of_property_read_u32(np, "st,drdy-int-pin", drdy_pin);
  242. }
  243. static int st_lis3dhh_set_drdy_reg(struct st_lis3dhh_hw *hw)
  244. {
  245. int drdy_pin;
  246. u8 drdy_reg;
  247. if (st_lis3dhh_of_get_drdy_pin(hw, &drdy_pin) < 0) {
  248. struct st_sensors_platform_data *pdata;
  249. struct device *dev = hw->dev;
  250. pdata = (struct st_sensors_platform_data *)dev->platform_data;
  251. drdy_pin = pdata ? pdata->drdy_int_pin : 1;
  252. }
  253. switch (drdy_pin) {
  254. case 1:
  255. drdy_reg = REG_INT1_CTRL_ADDR;
  256. break;
  257. case 2:
  258. drdy_reg = REG_INT2_CTRL_ADDR;
  259. break;
  260. default:
  261. dev_err(hw->dev, "unsupported data ready pin\n");
  262. return -EINVAL;
  263. }
  264. return st_lis3dhh_write_with_mask(hw, drdy_reg, REG_INT_FTM_MASK, 1);
  265. }
  266. static int st_lis3dhh_init_device(struct st_lis3dhh_hw *hw)
  267. {
  268. int err;
  269. err = st_lis3dhh_write_with_mask(hw, REG_CTRL1_ADDR,
  270. REG_CTRL1_SW_RESET_MASK, 1);
  271. if (err < 0)
  272. return err;
  273. msleep(200);
  274. err = st_lis3dhh_write_with_mask(hw, REG_CTRL1_ADDR,
  275. REG_CTRL1_BDU_MASK, 1);
  276. if (err < 0)
  277. return err;
  278. err = st_lis3dhh_update_watermark(hw, hw->watermark);
  279. if (err < 0)
  280. return err;
  281. return st_lis3dhh_set_drdy_reg(hw);
  282. }
  283. static int st_lis3dhh_spi_probe(struct spi_device *spi)
  284. {
  285. struct st_lis3dhh_hw *hw;
  286. struct iio_dev *iio_dev;
  287. int err;
  288. iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*hw));
  289. if (!iio_dev)
  290. return -ENOMEM;
  291. spi_set_drvdata(spi, iio_dev);
  292. iio_dev->channels = st_lis3dhh_channels;
  293. iio_dev->num_channels = ARRAY_SIZE(st_lis3dhh_channels);
  294. iio_dev->modes = INDIO_DIRECT_MODE;
  295. iio_dev->info = &st_lis3dhh_info;
  296. iio_dev->dev.parent = &spi->dev;
  297. iio_dev->name = spi->modalias;
  298. hw = iio_priv(iio_dev);
  299. mutex_init(&hw->fifo_lock);
  300. mutex_init(&hw->lock);
  301. hw->watermark = 1;
  302. hw->dev = &spi->dev;
  303. hw->name = spi->modalias;
  304. hw->irq = spi->irq;
  305. hw->iio_dev = iio_dev;
  306. err = st_lis3dhh_check_whoami(hw);
  307. if (err < 0)
  308. return err;
  309. err = st_lis3dhh_init_device(hw);
  310. if (err < 0)
  311. return err;
  312. if (hw->irq > 0) {
  313. err = st_lis3dhh_fifo_setup(hw);
  314. if (err < 0)
  315. return err;
  316. }
  317. return devm_iio_device_register(hw->dev, iio_dev);
  318. }
  319. static const struct of_device_id st_lis3dhh_spi_of_match[] = {
  320. {
  321. .compatible = "st,lis3dhh",
  322. .data = LIS3DHH_DEV_NAME,
  323. },
  324. {
  325. .compatible = "st,iis3dhhc",
  326. .data = IIS3DHHC_DEV_NAME,
  327. },
  328. {},
  329. };
  330. MODULE_DEVICE_TABLE(of, st_lis3dhh_spi_of_match);
  331. static const struct spi_device_id st_lis3dhh_spi_id_table[] = {
  332. { LIS3DHH_DEV_NAME },
  333. { IIS3DHHC_DEV_NAME },
  334. {},
  335. };
  336. MODULE_DEVICE_TABLE(spi, st_lis3dhh_spi_id_table);
  337. static struct spi_driver st_lis3dhh_driver = {
  338. .driver = {
  339. .name = "st_lis3dhh",
  340. .of_match_table = of_match_ptr(st_lis3dhh_spi_of_match),
  341. },
  342. .probe = st_lis3dhh_spi_probe,
  343. .id_table = st_lis3dhh_spi_id_table,
  344. };
  345. module_spi_driver(st_lis3dhh_driver);
  346. MODULE_AUTHOR("MEMS Software Solutions Team");
  347. MODULE_DESCRIPTION("STMicroelectronics st_lis3dhh sensor driver");
  348. MODULE_LICENSE("GPL v2");