1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. 4 */ 5 6 #include <linux/iio/common/ssp_sensors.h> 7 #include <linux/iio/iio.h> 8 #include <linux/iio/buffer.h> 9 #include <linux/iio/kfifo_buf.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/slab.h> 13 #include "../common/ssp_sensors/ssp_iio_sensor.h" 14 15 #define SSP_CHANNEL_COUNT 3 16 17 #define SSP_GYROSCOPE_NAME "ssp-gyroscope" 18 static const char ssp_gyro_name[] = SSP_GYROSCOPE_NAME; 19 20 enum ssp_gyro_3d_channel { 21 SSP_CHANNEL_SCAN_INDEX_X, 22 SSP_CHANNEL_SCAN_INDEX_Y, 23 SSP_CHANNEL_SCAN_INDEX_Z, 24 SSP_CHANNEL_SCAN_INDEX_TIME, 25 }; 26 27 static int ssp_gyro_read_raw(struct iio_dev *indio_dev, 28 struct iio_chan_spec const *chan, int *val, 29 int *val2, long mask) 30 { 31 u32 t; 32 struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); 33 34 switch (mask) { 35 case IIO_CHAN_INFO_SAMP_FREQ: 36 t = ssp_get_sensor_delay(data, SSP_GYROSCOPE_SENSOR); 37 ssp_convert_to_freq(t, val, val2); 38 return IIO_VAL_INT_PLUS_MICRO; 39 default: 40 break; 41 } 42 43 return -EINVAL; 44 } 45 46 static int ssp_gyro_write_raw(struct iio_dev *indio_dev, 47 struct iio_chan_spec const *chan, int val, 48 int val2, long mask) 49 { 50 int ret; 51 struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); 52 53 switch (mask) { 54 case IIO_CHAN_INFO_SAMP_FREQ: 55 ret = ssp_convert_to_time(val, val2); 56 ret = ssp_change_delay(data, SSP_GYROSCOPE_SENSOR, ret); 57 if (ret < 0) 58 dev_err(&indio_dev->dev, "gyro sensor enable fail\n"); 59 60 return ret; 61 default: 62 break; 63 } 64 65 return -EINVAL; 66 } 67 68 static const struct iio_info ssp_gyro_iio_info = { 69 .read_raw = &ssp_gyro_read_raw, 70 .write_raw = &ssp_gyro_write_raw, 71 }; 72 73 static const unsigned long ssp_gyro_scan_mask[] = { 0x07, 0, }; 74 75 static const struct iio_chan_spec ssp_gyro_channels[] = { 76 SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X), 77 SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y), 78 SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z), 79 SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME), 80 }; 81 82 static int ssp_process_gyro_data(struct iio_dev *indio_dev, void *buf, 83 int64_t timestamp) 84 { 85 return ssp_common_process_data(indio_dev, buf, SSP_GYROSCOPE_SIZE, 86 timestamp); 87 } 88 89 static const struct iio_buffer_setup_ops ssp_gyro_buffer_ops = { 90 .postenable = &ssp_common_buffer_postenable, 91 .postdisable = &ssp_common_buffer_postdisable, 92 }; 93 94 static int ssp_gyro_probe(struct platform_device *pdev) 95 { 96 int ret; 97 struct iio_dev *indio_dev; 98 struct ssp_sensor_data *spd; 99 struct iio_buffer *buffer; 100 101 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd)); 102 if (!indio_dev) 103 return -ENOMEM; 104 105 spd = iio_priv(indio_dev); 106 107 spd->process_data = ssp_process_gyro_data; 108 spd->type = SSP_GYROSCOPE_SENSOR; 109 110 indio_dev->name = ssp_gyro_name; 111 indio_dev->dev.parent = &pdev->dev; 112 indio_dev->info = &ssp_gyro_iio_info; 113 indio_dev->modes = INDIO_BUFFER_SOFTWARE; 114 indio_dev->channels = ssp_gyro_channels; 115 indio_dev->num_channels = ARRAY_SIZE(ssp_gyro_channels); 116 indio_dev->available_scan_masks = ssp_gyro_scan_mask; 117 118 buffer = devm_iio_kfifo_allocate(&pdev->dev); 119 if (!buffer) 120 return -ENOMEM; 121 122 iio_device_attach_buffer(indio_dev, buffer); 123 124 indio_dev->setup_ops = &ssp_gyro_buffer_ops; 125 126 platform_set_drvdata(pdev, indio_dev); 127 128 ret = devm_iio_device_register(&pdev->dev, indio_dev); 129 if (ret < 0) 130 return ret; 131 132 /* ssp registering should be done after all iio setup */ 133 ssp_register_consumer(indio_dev, SSP_GYROSCOPE_SENSOR); 134 135 return 0; 136 } 137 138 static struct platform_driver ssp_gyro_driver = { 139 .driver = { 140 .name = SSP_GYROSCOPE_NAME, 141 }, 142 .probe = ssp_gyro_probe, 143 }; 144 145 module_platform_driver(ssp_gyro_driver); 146 147 MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>"); 148 MODULE_DESCRIPTION("Samsung sensorhub gyroscopes driver"); 149 MODULE_LICENSE("GPL"); 150