Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved.
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_ACCEL_NAME "ssp-accelerometer"
0018 static const char ssp_accel_device_name[] = SSP_ACCEL_NAME;
0019 
0020 enum ssp_accel_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_accel_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_ACCELEROMETER_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_accel_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_ACCELEROMETER_SENSOR, ret);
0057         if (ret < 0)
0058             dev_err(&indio_dev->dev, "accel 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_accel_iio_info = {
0069     .read_raw = &ssp_accel_read_raw,
0070     .write_raw = &ssp_accel_write_raw,
0071 };
0072 
0073 static const unsigned long ssp_accel_scan_mask[] = { 0x7, 0, };
0074 
0075 static const struct iio_chan_spec ssp_acc_channels[] = {
0076     SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X),
0077     SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y),
0078     SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z),
0079     SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME),
0080 };
0081 
0082 static int ssp_process_accel_data(struct iio_dev *indio_dev, void *buf,
0083                   int64_t timestamp)
0084 {
0085     return ssp_common_process_data(indio_dev, buf, SSP_ACCELEROMETER_SIZE,
0086                        timestamp);
0087 }
0088 
0089 static const struct iio_buffer_setup_ops ssp_accel_buffer_ops = {
0090     .postenable = &ssp_common_buffer_postenable,
0091     .postdisable = &ssp_common_buffer_postdisable,
0092 };
0093 
0094 static int ssp_accel_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_accel_data;
0107     spd->type = SSP_ACCELEROMETER_SENSOR;
0108 
0109     indio_dev->name = ssp_accel_device_name;
0110     indio_dev->info = &ssp_accel_iio_info;
0111     indio_dev->channels = ssp_acc_channels;
0112     indio_dev->num_channels = ARRAY_SIZE(ssp_acc_channels);
0113     indio_dev->available_scan_masks = ssp_accel_scan_mask;
0114 
0115     ret = devm_iio_kfifo_buffer_setup(&pdev->dev, indio_dev,
0116                       &ssp_accel_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     /* ssp registering should be done after all iio setup */
0127     ssp_register_consumer(indio_dev, SSP_ACCELEROMETER_SENSOR);
0128 
0129     return 0;
0130 }
0131 
0132 static struct platform_driver ssp_accel_driver = {
0133     .driver = {
0134         .name = SSP_ACCEL_NAME,
0135     },
0136     .probe = ssp_accel_probe,
0137 };
0138 
0139 module_platform_driver(ssp_accel_driver);
0140 
0141 MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>");
0142 MODULE_DESCRIPTION("Samsung sensorhub accelerometers driver");
0143 MODULE_LICENSE("GPL");
0144 MODULE_IMPORT_NS(IIO_SSP_SENSORS);