0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/device.h>
0009 #include <linux/iio/events.h>
0010 #include <linux/iio/iio.h>
0011 #include <linux/kernel.h>
0012 #include <linux/mfd/iqs62x.h>
0013 #include <linux/module.h>
0014 #include <linux/mutex.h>
0015 #include <linux/notifier.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regmap.h>
0018
0019 #define IQS624_POS_DEG_OUT 0x16
0020
0021 #define IQS624_POS_SCALE1 (314159 / 180)
0022 #define IQS624_POS_SCALE2 100000
0023
0024 struct iqs624_pos_private {
0025 struct iqs62x_core *iqs62x;
0026 struct iio_dev *indio_dev;
0027 struct notifier_block notifier;
0028 struct mutex lock;
0029 bool angle_en;
0030 u16 angle;
0031 };
0032
0033 static int iqs624_pos_angle_en(struct iqs62x_core *iqs62x, bool angle_en)
0034 {
0035 unsigned int event_mask = IQS624_HALL_UI_WHL_EVENT;
0036
0037
0038
0039
0040
0041
0042
0043 if (iqs62x->dev_desc->prod_num == IQS625_PROD_NUM)
0044 event_mask = IQS624_HALL_UI_INT_EVENT;
0045
0046 return regmap_update_bits(iqs62x->regmap, IQS624_HALL_UI, event_mask,
0047 angle_en ? 0 : 0xFF);
0048 }
0049
0050 static int iqs624_pos_notifier(struct notifier_block *notifier,
0051 unsigned long event_flags, void *context)
0052 {
0053 struct iqs62x_event_data *event_data = context;
0054 struct iqs624_pos_private *iqs624_pos;
0055 struct iqs62x_core *iqs62x;
0056 struct iio_dev *indio_dev;
0057 u16 angle = event_data->ui_data;
0058 s64 timestamp;
0059 int ret;
0060
0061 iqs624_pos = container_of(notifier, struct iqs624_pos_private,
0062 notifier);
0063 indio_dev = iqs624_pos->indio_dev;
0064 timestamp = iio_get_time_ns(indio_dev);
0065
0066 iqs62x = iqs624_pos->iqs62x;
0067 if (iqs62x->dev_desc->prod_num == IQS625_PROD_NUM)
0068 angle = event_data->interval;
0069
0070 mutex_lock(&iqs624_pos->lock);
0071
0072 if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) {
0073 ret = iqs624_pos_angle_en(iqs62x, iqs624_pos->angle_en);
0074 if (ret) {
0075 dev_err(indio_dev->dev.parent,
0076 "Failed to re-initialize device: %d\n", ret);
0077 ret = NOTIFY_BAD;
0078 } else {
0079 ret = NOTIFY_OK;
0080 }
0081 } else if (iqs624_pos->angle_en && (angle != iqs624_pos->angle)) {
0082 iio_push_event(indio_dev,
0083 IIO_UNMOD_EVENT_CODE(IIO_ANGL, 0,
0084 IIO_EV_TYPE_CHANGE,
0085 IIO_EV_DIR_NONE),
0086 timestamp);
0087
0088 iqs624_pos->angle = angle;
0089 ret = NOTIFY_OK;
0090 } else {
0091 ret = NOTIFY_DONE;
0092 }
0093
0094 mutex_unlock(&iqs624_pos->lock);
0095
0096 return ret;
0097 }
0098
0099 static void iqs624_pos_notifier_unregister(void *context)
0100 {
0101 struct iqs624_pos_private *iqs624_pos = context;
0102 struct iio_dev *indio_dev = iqs624_pos->indio_dev;
0103 int ret;
0104
0105 ret = blocking_notifier_chain_unregister(&iqs624_pos->iqs62x->nh,
0106 &iqs624_pos->notifier);
0107 if (ret)
0108 dev_err(indio_dev->dev.parent,
0109 "Failed to unregister notifier: %d\n", ret);
0110 }
0111
0112 static int iqs624_pos_angle_get(struct iqs62x_core *iqs62x, unsigned int *val)
0113 {
0114 int ret;
0115 __le16 val_buf;
0116
0117 if (iqs62x->dev_desc->prod_num == IQS625_PROD_NUM)
0118 return regmap_read(iqs62x->regmap, iqs62x->dev_desc->interval,
0119 val);
0120
0121 ret = regmap_raw_read(iqs62x->regmap, IQS624_POS_DEG_OUT, &val_buf,
0122 sizeof(val_buf));
0123 if (ret)
0124 return ret;
0125
0126 *val = le16_to_cpu(val_buf);
0127
0128 return 0;
0129 }
0130
0131 static int iqs624_pos_read_raw(struct iio_dev *indio_dev,
0132 struct iio_chan_spec const *chan,
0133 int *val, int *val2, long mask)
0134 {
0135 struct iqs624_pos_private *iqs624_pos = iio_priv(indio_dev);
0136 struct iqs62x_core *iqs62x = iqs624_pos->iqs62x;
0137 unsigned int scale = 1;
0138 int ret;
0139
0140 switch (mask) {
0141 case IIO_CHAN_INFO_RAW:
0142 ret = iqs624_pos_angle_get(iqs62x, val);
0143 if (ret)
0144 return ret;
0145
0146 return IIO_VAL_INT;
0147
0148 case IIO_CHAN_INFO_SCALE:
0149 if (iqs62x->dev_desc->prod_num == IQS625_PROD_NUM) {
0150 ret = regmap_read(iqs62x->regmap, IQS624_INTERVAL_DIV,
0151 &scale);
0152 if (ret)
0153 return ret;
0154 }
0155
0156 *val = scale * IQS624_POS_SCALE1;
0157 *val2 = IQS624_POS_SCALE2;
0158 return IIO_VAL_FRACTIONAL;
0159
0160 default:
0161 return -EINVAL;
0162 }
0163 }
0164
0165 static int iqs624_pos_read_event_config(struct iio_dev *indio_dev,
0166 const struct iio_chan_spec *chan,
0167 enum iio_event_type type,
0168 enum iio_event_direction dir)
0169 {
0170 struct iqs624_pos_private *iqs624_pos = iio_priv(indio_dev);
0171 int ret;
0172
0173 mutex_lock(&iqs624_pos->lock);
0174 ret = iqs624_pos->angle_en;
0175 mutex_unlock(&iqs624_pos->lock);
0176
0177 return ret;
0178 }
0179
0180 static int iqs624_pos_write_event_config(struct iio_dev *indio_dev,
0181 const struct iio_chan_spec *chan,
0182 enum iio_event_type type,
0183 enum iio_event_direction dir,
0184 int state)
0185 {
0186 struct iqs624_pos_private *iqs624_pos = iio_priv(indio_dev);
0187 struct iqs62x_core *iqs62x = iqs624_pos->iqs62x;
0188 unsigned int val;
0189 int ret;
0190
0191 mutex_lock(&iqs624_pos->lock);
0192
0193 ret = iqs624_pos_angle_get(iqs62x, &val);
0194 if (ret)
0195 goto err_mutex;
0196
0197 ret = iqs624_pos_angle_en(iqs62x, state);
0198 if (ret)
0199 goto err_mutex;
0200
0201 iqs624_pos->angle = val;
0202 iqs624_pos->angle_en = state;
0203
0204 err_mutex:
0205 mutex_unlock(&iqs624_pos->lock);
0206
0207 return ret;
0208 }
0209
0210 static const struct iio_info iqs624_pos_info = {
0211 .read_raw = &iqs624_pos_read_raw,
0212 .read_event_config = iqs624_pos_read_event_config,
0213 .write_event_config = iqs624_pos_write_event_config,
0214 };
0215
0216 static const struct iio_event_spec iqs624_pos_events[] = {
0217 {
0218 .type = IIO_EV_TYPE_CHANGE,
0219 .dir = IIO_EV_DIR_NONE,
0220 .mask_separate = BIT(IIO_EV_INFO_ENABLE),
0221 },
0222 };
0223
0224 static const struct iio_chan_spec iqs624_pos_channels[] = {
0225 {
0226 .type = IIO_ANGL,
0227 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0228 BIT(IIO_CHAN_INFO_SCALE),
0229 .event_spec = iqs624_pos_events,
0230 .num_event_specs = ARRAY_SIZE(iqs624_pos_events),
0231 },
0232 };
0233
0234 static int iqs624_pos_probe(struct platform_device *pdev)
0235 {
0236 struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent);
0237 struct iqs624_pos_private *iqs624_pos;
0238 struct iio_dev *indio_dev;
0239 int ret;
0240
0241 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*iqs624_pos));
0242 if (!indio_dev)
0243 return -ENOMEM;
0244
0245 iqs624_pos = iio_priv(indio_dev);
0246 iqs624_pos->iqs62x = iqs62x;
0247 iqs624_pos->indio_dev = indio_dev;
0248
0249 indio_dev->modes = INDIO_DIRECT_MODE;
0250 indio_dev->channels = iqs624_pos_channels;
0251 indio_dev->num_channels = ARRAY_SIZE(iqs624_pos_channels);
0252 indio_dev->name = iqs62x->dev_desc->dev_name;
0253 indio_dev->info = &iqs624_pos_info;
0254
0255 mutex_init(&iqs624_pos->lock);
0256
0257 iqs624_pos->notifier.notifier_call = iqs624_pos_notifier;
0258 ret = blocking_notifier_chain_register(&iqs624_pos->iqs62x->nh,
0259 &iqs624_pos->notifier);
0260 if (ret) {
0261 dev_err(&pdev->dev, "Failed to register notifier: %d\n", ret);
0262 return ret;
0263 }
0264
0265 ret = devm_add_action_or_reset(&pdev->dev,
0266 iqs624_pos_notifier_unregister,
0267 iqs624_pos);
0268 if (ret)
0269 return ret;
0270
0271 return devm_iio_device_register(&pdev->dev, indio_dev);
0272 }
0273
0274 static struct platform_driver iqs624_pos_platform_driver = {
0275 .driver = {
0276 .name = "iqs624-pos",
0277 },
0278 .probe = iqs624_pos_probe,
0279 };
0280 module_platform_driver(iqs624_pos_platform_driver);
0281
0282 MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
0283 MODULE_DESCRIPTION("Azoteq IQS624/625 Angular Position Sensors");
0284 MODULE_LICENSE("GPL");
0285 MODULE_ALIAS("platform:iqs624-pos");