cros_ec_accel_legacy.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * Driver for older Chrome OS EC accelerometer
  3. *
  4. * Copyright 2017 Google, Inc
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * This driver uses the memory mapper cros-ec interface to communicate
  16. * with the Chrome OS EC about accelerometer data.
  17. * Accelerometer access is presented through iio sysfs.
  18. */
  19. #include <linux/delay.h>
  20. #include <linux/device.h>
  21. #include <linux/iio/buffer.h>
  22. #include <linux/iio/iio.h>
  23. #include <linux/iio/kfifo_buf.h>
  24. #include <linux/iio/trigger_consumer.h>
  25. #include <linux/iio/triggered_buffer.h>
  26. #include <linux/kernel.h>
  27. #include <linux/mfd/cros_ec.h>
  28. #include <linux/mfd/cros_ec_commands.h>
  29. #include <linux/module.h>
  30. #include <linux/slab.h>
  31. #include <linux/sysfs.h>
  32. #include <linux/platform_device.h>
  33. #define DRV_NAME "cros-ec-accel-legacy"
  34. /*
  35. * Sensor scale hard coded at 10 bits per g, computed as:
  36. * g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2
  37. */
  38. #define ACCEL_LEGACY_NSCALE 9586168
  39. /* Indices for EC sensor values. */
  40. enum {
  41. X,
  42. Y,
  43. Z,
  44. MAX_AXIS,
  45. };
  46. /* State data for cros_ec_accel_legacy iio driver. */
  47. struct cros_ec_accel_legacy_state {
  48. struct cros_ec_device *ec;
  49. /*
  50. * Array holding data from a single capture. 2 bytes per channel
  51. * for the 3 channels plus the timestamp which is always last and
  52. * 8-bytes aligned.
  53. */
  54. s16 capture_data[8];
  55. s8 sign[MAX_AXIS];
  56. u8 sensor_num;
  57. };
  58. static int ec_cmd_read_u8(struct cros_ec_device *ec, unsigned int offset,
  59. u8 *dest)
  60. {
  61. return ec->cmd_readmem(ec, offset, 1, dest);
  62. }
  63. static int ec_cmd_read_u16(struct cros_ec_device *ec, unsigned int offset,
  64. u16 *dest)
  65. {
  66. __le16 tmp;
  67. int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
  68. *dest = le16_to_cpu(tmp);
  69. return ret;
  70. }
  71. /**
  72. * read_ec_until_not_busy() - Read from EC status byte until it reads not busy.
  73. * @st: Pointer to state information for device.
  74. *
  75. * This function reads EC status until its busy bit gets cleared. It does not
  76. * wait indefinitely and returns -EIO if the EC status is still busy after a
  77. * few hundreds milliseconds.
  78. *
  79. * Return: 8-bit status if ok, -EIO on error
  80. */
  81. static int read_ec_until_not_busy(struct cros_ec_accel_legacy_state *st)
  82. {
  83. struct cros_ec_device *ec = st->ec;
  84. u8 status;
  85. int attempts = 0;
  86. ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
  87. while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
  88. /* Give up after enough attempts, return error. */
  89. if (attempts++ >= 50)
  90. return -EIO;
  91. /* Small delay every so often. */
  92. if (attempts % 5 == 0)
  93. msleep(25);
  94. ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
  95. }
  96. return status;
  97. }
  98. /**
  99. * read_ec_accel_data_unsafe() - Read acceleration data from EC shared memory.
  100. * @st: Pointer to state information for device.
  101. * @scan_mask: Bitmap of the sensor indices to scan.
  102. * @data: Location to store data.
  103. *
  104. * This is the unsafe function for reading the EC data. It does not guarantee
  105. * that the EC will not modify the data as it is being read in.
  106. */
  107. static void read_ec_accel_data_unsafe(struct cros_ec_accel_legacy_state *st,
  108. unsigned long scan_mask, s16 *data)
  109. {
  110. int i = 0;
  111. int num_enabled = bitmap_weight(&scan_mask, MAX_AXIS);
  112. /* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
  113. while (num_enabled--) {
  114. i = find_next_bit(&scan_mask, MAX_AXIS, i);
  115. ec_cmd_read_u16(st->ec,
  116. EC_MEMMAP_ACC_DATA +
  117. sizeof(s16) *
  118. (1 + i + st->sensor_num * MAX_AXIS),
  119. data);
  120. *data *= st->sign[i];
  121. i++;
  122. data++;
  123. }
  124. }
  125. /**
  126. * read_ec_accel_data() - Read acceleration data from EC shared memory.
  127. * @st: Pointer to state information for device.
  128. * @scan_mask: Bitmap of the sensor indices to scan.
  129. * @data: Location to store data.
  130. *
  131. * This is the safe function for reading the EC data. It guarantees that
  132. * the data sampled was not modified by the EC while being read.
  133. *
  134. * Return: 0 if ok, -ve on error
  135. */
  136. static int read_ec_accel_data(struct cros_ec_accel_legacy_state *st,
  137. unsigned long scan_mask, s16 *data)
  138. {
  139. u8 samp_id = 0xff;
  140. u8 status = 0;
  141. int ret;
  142. int attempts = 0;
  143. /*
  144. * Continually read all data from EC until the status byte after
  145. * all reads reflects that the EC is not busy and the sample id
  146. * matches the sample id from before all reads. This guarantees
  147. * that data read in was not modified by the EC while reading.
  148. */
  149. while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
  150. EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
  151. /* If we have tried to read too many times, return error. */
  152. if (attempts++ >= 5)
  153. return -EIO;
  154. /* Read status byte until EC is not busy. */
  155. ret = read_ec_until_not_busy(st);
  156. if (ret < 0)
  157. return ret;
  158. status = ret;
  159. /*
  160. * Store the current sample id so that we can compare to the
  161. * sample id after reading the data.
  162. */
  163. samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
  164. /* Read all EC data, format it, and store it into data. */
  165. read_ec_accel_data_unsafe(st, scan_mask, data);
  166. /* Read status byte. */
  167. ec_cmd_read_u8(st->ec, EC_MEMMAP_ACC_STATUS, &status);
  168. }
  169. return 0;
  170. }
  171. static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev,
  172. struct iio_chan_spec const *chan,
  173. int *val, int *val2, long mask)
  174. {
  175. struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev);
  176. s16 data = 0;
  177. int ret = IIO_VAL_INT;
  178. switch (mask) {
  179. case IIO_CHAN_INFO_RAW:
  180. ret = read_ec_accel_data(st, (1 << chan->scan_index), &data);
  181. if (ret)
  182. return ret;
  183. *val = data;
  184. return IIO_VAL_INT;
  185. case IIO_CHAN_INFO_SCALE:
  186. *val = 0;
  187. *val2 = ACCEL_LEGACY_NSCALE;
  188. return IIO_VAL_INT_PLUS_NANO;
  189. case IIO_CHAN_INFO_CALIBBIAS:
  190. /* Calibration not supported. */
  191. *val = 0;
  192. return IIO_VAL_INT;
  193. default:
  194. return -EINVAL;
  195. }
  196. }
  197. static int cros_ec_accel_legacy_write(struct iio_dev *indio_dev,
  198. struct iio_chan_spec const *chan,
  199. int val, int val2, long mask)
  200. {
  201. /*
  202. * Do nothing but don't return an error code to allow calibration
  203. * script to work.
  204. */
  205. if (mask == IIO_CHAN_INFO_CALIBBIAS)
  206. return 0;
  207. return -EINVAL;
  208. }
  209. static const struct iio_info cros_ec_accel_legacy_info = {
  210. .read_raw = &cros_ec_accel_legacy_read,
  211. .write_raw = &cros_ec_accel_legacy_write,
  212. };
  213. /**
  214. * cros_ec_accel_legacy_capture() - The trigger handler function
  215. * @irq: The interrupt number.
  216. * @p: Private data - always a pointer to the poll func.
  217. *
  218. * On a trigger event occurring, if the pollfunc is attached then this
  219. * handler is called as a threaded interrupt (and hence may sleep). It
  220. * is responsible for grabbing data from the device and pushing it into
  221. * the associated buffer.
  222. *
  223. * Return: IRQ_HANDLED
  224. */
  225. static irqreturn_t cros_ec_accel_legacy_capture(int irq, void *p)
  226. {
  227. struct iio_poll_func *pf = p;
  228. struct iio_dev *indio_dev = pf->indio_dev;
  229. struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev);
  230. /* Clear capture data. */
  231. memset(st->capture_data, 0, sizeof(st->capture_data));
  232. /*
  233. * Read data based on which channels are enabled in scan mask. Note
  234. * that on a capture we are always reading the calibrated data.
  235. */
  236. read_ec_accel_data(st, *indio_dev->active_scan_mask, st->capture_data);
  237. iio_push_to_buffers_with_timestamp(indio_dev, (void *)st->capture_data,
  238. iio_get_time_ns(indio_dev));
  239. /*
  240. * Tell the core we are done with this trigger and ready for the
  241. * next one.
  242. */
  243. iio_trigger_notify_done(indio_dev->trig);
  244. return IRQ_HANDLED;
  245. }
  246. static char *cros_ec_accel_legacy_loc_strings[] = {
  247. [MOTIONSENSE_LOC_BASE] = "base",
  248. [MOTIONSENSE_LOC_LID] = "lid",
  249. [MOTIONSENSE_LOC_MAX] = "unknown",
  250. };
  251. static ssize_t cros_ec_accel_legacy_loc(struct iio_dev *indio_dev,
  252. uintptr_t private,
  253. const struct iio_chan_spec *chan,
  254. char *buf)
  255. {
  256. struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev);
  257. return sprintf(buf, "%s\n",
  258. cros_ec_accel_legacy_loc_strings[st->sensor_num +
  259. MOTIONSENSE_LOC_BASE]);
  260. }
  261. static ssize_t cros_ec_accel_legacy_id(struct iio_dev *indio_dev,
  262. uintptr_t private,
  263. const struct iio_chan_spec *chan,
  264. char *buf)
  265. {
  266. struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev);
  267. return sprintf(buf, "%d\n", st->sensor_num);
  268. }
  269. static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = {
  270. {
  271. .name = "id",
  272. .shared = IIO_SHARED_BY_ALL,
  273. .read = cros_ec_accel_legacy_id,
  274. },
  275. {
  276. .name = "location",
  277. .shared = IIO_SHARED_BY_ALL,
  278. .read = cros_ec_accel_legacy_loc,
  279. },
  280. { }
  281. };
  282. #define CROS_EC_ACCEL_LEGACY_CHAN(_axis) \
  283. { \
  284. .type = IIO_ACCEL, \
  285. .channel2 = IIO_MOD_X + (_axis), \
  286. .modified = 1, \
  287. .info_mask_separate = \
  288. BIT(IIO_CHAN_INFO_RAW) | \
  289. BIT(IIO_CHAN_INFO_CALIBBIAS), \
  290. .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \
  291. .ext_info = cros_ec_accel_legacy_ext_info, \
  292. .scan_type = { \
  293. .sign = 's', \
  294. .realbits = 16, \
  295. .storagebits = 16, \
  296. }, \
  297. } \
  298. static struct iio_chan_spec ec_accel_channels[] = {
  299. CROS_EC_ACCEL_LEGACY_CHAN(X),
  300. CROS_EC_ACCEL_LEGACY_CHAN(Y),
  301. CROS_EC_ACCEL_LEGACY_CHAN(Z),
  302. IIO_CHAN_SOFT_TIMESTAMP(MAX_AXIS)
  303. };
  304. static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
  305. {
  306. struct device *dev = &pdev->dev;
  307. struct cros_ec_dev *ec = dev_get_drvdata(dev->parent);
  308. struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
  309. struct iio_dev *indio_dev;
  310. struct cros_ec_accel_legacy_state *state;
  311. int ret, i;
  312. if (!ec || !ec->ec_dev) {
  313. dev_warn(&pdev->dev, "No EC device found.\n");
  314. return -EINVAL;
  315. }
  316. if (!ec->ec_dev->cmd_readmem) {
  317. dev_warn(&pdev->dev, "EC does not support direct reads.\n");
  318. return -EINVAL;
  319. }
  320. indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
  321. if (!indio_dev)
  322. return -ENOMEM;
  323. platform_set_drvdata(pdev, indio_dev);
  324. state = iio_priv(indio_dev);
  325. state->ec = ec->ec_dev;
  326. state->sensor_num = sensor_platform->sensor_num;
  327. indio_dev->dev.parent = dev;
  328. indio_dev->name = pdev->name;
  329. indio_dev->channels = ec_accel_channels;
  330. /*
  331. * Present the channel using HTML5 standard:
  332. * need to invert X and Y and invert some lid axis.
  333. */
  334. for (i = X ; i < MAX_AXIS; i++) {
  335. switch (i) {
  336. case X:
  337. ec_accel_channels[X].scan_index = Y;
  338. case Y:
  339. ec_accel_channels[Y].scan_index = X;
  340. case Z:
  341. ec_accel_channels[Z].scan_index = Z;
  342. }
  343. if (state->sensor_num == MOTIONSENSE_LOC_LID && i != Y)
  344. state->sign[i] = -1;
  345. else
  346. state->sign[i] = 1;
  347. }
  348. indio_dev->num_channels = ARRAY_SIZE(ec_accel_channels);
  349. indio_dev->dev.parent = &pdev->dev;
  350. indio_dev->info = &cros_ec_accel_legacy_info;
  351. indio_dev->modes = INDIO_DIRECT_MODE;
  352. ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
  353. cros_ec_accel_legacy_capture,
  354. NULL);
  355. if (ret)
  356. return ret;
  357. return devm_iio_device_register(dev, indio_dev);
  358. }
  359. static struct platform_driver cros_ec_accel_platform_driver = {
  360. .driver = {
  361. .name = DRV_NAME,
  362. },
  363. .probe = cros_ec_accel_legacy_probe,
  364. };
  365. module_platform_driver(cros_ec_accel_platform_driver);
  366. MODULE_DESCRIPTION("ChromeOS EC legacy accelerometer driver");
  367. MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
  368. MODULE_LICENSE("GPL");
  369. MODULE_ALIAS("platform:" DRV_NAME);