0001
0002
0003
0004
0005
0006 #include <linux/iio/common/ssp_sensors.h>
0007 #include <linux/iio/iio.h>
0008 #include <linux/iio/buffer.h>
0009 #include <linux/iio/kfifo_buf.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/slab.h>
0013 #include "../common/ssp_sensors/ssp_iio_sensor.h"
0014
0015 #define SSP_CHANNEL_COUNT 3
0016
0017 #define SSP_GYROSCOPE_NAME "ssp-gyroscope"
0018 static const char ssp_gyro_name[] = SSP_GYROSCOPE_NAME;
0019
0020 enum ssp_gyro_3d_channel {
0021 SSP_CHANNEL_SCAN_INDEX_X,
0022 SSP_CHANNEL_SCAN_INDEX_Y,
0023 SSP_CHANNEL_SCAN_INDEX_Z,
0024 SSP_CHANNEL_SCAN_INDEX_TIME,
0025 };
0026
0027 static int ssp_gyro_read_raw(struct iio_dev *indio_dev,
0028 struct iio_chan_spec const *chan, int *val,
0029 int *val2, long mask)
0030 {
0031 u32 t;
0032 struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent);
0033
0034 switch (mask) {
0035 case IIO_CHAN_INFO_SAMP_FREQ:
0036 t = ssp_get_sensor_delay(data, SSP_GYROSCOPE_SENSOR);
0037 ssp_convert_to_freq(t, val, val2);
0038 return IIO_VAL_INT_PLUS_MICRO;
0039 default:
0040 break;
0041 }
0042
0043 return -EINVAL;
0044 }
0045
0046 static int ssp_gyro_write_raw(struct iio_dev *indio_dev,
0047 struct iio_chan_spec const *chan, int val,
0048 int val2, long mask)
0049 {
0050 int ret;
0051 struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent);
0052
0053 switch (mask) {
0054 case IIO_CHAN_INFO_SAMP_FREQ:
0055 ret = ssp_convert_to_time(val, val2);
0056 ret = ssp_change_delay(data, SSP_GYROSCOPE_SENSOR, ret);
0057 if (ret < 0)
0058 dev_err(&indio_dev->dev, "gyro sensor enable fail\n");
0059
0060 return ret;
0061 default:
0062 break;
0063 }
0064
0065 return -EINVAL;
0066 }
0067
0068 static const struct iio_info ssp_gyro_iio_info = {
0069 .read_raw = &ssp_gyro_read_raw,
0070 .write_raw = &ssp_gyro_write_raw,
0071 };
0072
0073 static const unsigned long ssp_gyro_scan_mask[] = { 0x07, 0, };
0074
0075 static const struct iio_chan_spec ssp_gyro_channels[] = {
0076 SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X),
0077 SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y),
0078 SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z),
0079 SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME),
0080 };
0081
0082 static int ssp_process_gyro_data(struct iio_dev *indio_dev, void *buf,
0083 int64_t timestamp)
0084 {
0085 return ssp_common_process_data(indio_dev, buf, SSP_GYROSCOPE_SIZE,
0086 timestamp);
0087 }
0088
0089 static const struct iio_buffer_setup_ops ssp_gyro_buffer_ops = {
0090 .postenable = &ssp_common_buffer_postenable,
0091 .postdisable = &ssp_common_buffer_postdisable,
0092 };
0093
0094 static int ssp_gyro_probe(struct platform_device *pdev)
0095 {
0096 int ret;
0097 struct iio_dev *indio_dev;
0098 struct ssp_sensor_data *spd;
0099
0100 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd));
0101 if (!indio_dev)
0102 return -ENOMEM;
0103
0104 spd = iio_priv(indio_dev);
0105
0106 spd->process_data = ssp_process_gyro_data;
0107 spd->type = SSP_GYROSCOPE_SENSOR;
0108
0109 indio_dev->name = ssp_gyro_name;
0110 indio_dev->info = &ssp_gyro_iio_info;
0111 indio_dev->channels = ssp_gyro_channels;
0112 indio_dev->num_channels = ARRAY_SIZE(ssp_gyro_channels);
0113 indio_dev->available_scan_masks = ssp_gyro_scan_mask;
0114
0115 ret = devm_iio_kfifo_buffer_setup(&pdev->dev, indio_dev,
0116 &ssp_gyro_buffer_ops);
0117 if (ret)
0118 return ret;
0119
0120 platform_set_drvdata(pdev, indio_dev);
0121
0122 ret = devm_iio_device_register(&pdev->dev, indio_dev);
0123 if (ret < 0)
0124 return ret;
0125
0126
0127 ssp_register_consumer(indio_dev, SSP_GYROSCOPE_SENSOR);
0128
0129 return 0;
0130 }
0131
0132 static struct platform_driver ssp_gyro_driver = {
0133 .driver = {
0134 .name = SSP_GYROSCOPE_NAME,
0135 },
0136 .probe = ssp_gyro_probe,
0137 };
0138
0139 module_platform_driver(ssp_gyro_driver);
0140
0141 MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>");
0142 MODULE_DESCRIPTION("Samsung sensorhub gyroscopes driver");
0143 MODULE_LICENSE("GPL");
0144 MODULE_IMPORT_NS(IIO_SSP_SENSORS);