Initial commit of ADS7924 driver
Change-Id: If74b8c4f6bbc0aec67e2dca6c0162c3d15e08ae8
diff --git a/qcom-adc/adc-averaging.c b/qcom-adc/adc-averaging.c
new file mode 100644
index 0000000..7c0c6f6
--- /dev/null
+++ b/qcom-adc/adc-averaging.c
@@ -0,0 +1,83 @@
+/*
+ * ./kernel_modules/qcom-adc/adc-averaging.c
+ *
+ * This file does some basic FIR averaging on a fifo; it is intended to be used
+ * with the ADS7924 device driver
+ *
+ * Author: Cradlepoint Technology, Inc. <source@cradlepoint.com>
+ * Kyle Swenson <kswenson@cradlepoint.com>
+ *
+ * Copyright 2017 Cradlepoint Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include "adc-averaging.h"
+
+
+void free_adc_channel(struct adc_channel *ch)
+{
+ if (ch->samples) {
+ kfree(ch->samples);
+ }
+ kfree(ch);
+}
+
+struct adc_channel *create_adc_channel(uint16_t fifo_length)
+{
+ struct adc_channel *ch;
+ if (fifo_length >= MAX_SAMPLE_LENGTH) {
+ printk(KERN_ALERT "Requested a ADC buffer length (%u) exceedes max (%u)\n", fifo_length, MAX_SAMPLE_LENGTH);
+ return NULL;
+
+ }
+ ch = (struct adc_channel *) kzalloc(sizeof(struct adc_channel), GFP_KERNEL);
+ if (!ch) {
+ printk(KERN_ALERT "Failed to allocate new ADC channel\n");
+ return NULL;
+ }
+ ch->samples = (uint16_t *) kzalloc(sizeof(uint16_t) * fifo_length, GFP_KERNEL);
+ if (!ch->samples) {
+ kfree(ch);
+ printk(KERN_ALERT "Failled to allocate new ADC channel buffer\n");
+ return NULL;
+ }
+ ch->total_length = fifo_length;
+ ch->index = 0;
+ mutex_init(&ch->lock);
+ return ch;
+}
+
+uint16_t compute_average(struct adc_channel *ch)
+{
+ uint32_t sum=0;
+ uint16_t average;
+ int i = 0;
+ mutex_lock(&ch->lock);
+ for (i = 0; i < ch->total_length; i++) {
+ sum += ch->samples[i];
+ }
+ average = DIV_ROUND_CLOSEST(sum, ch->total_length);
+ mutex_unlock(&ch->lock);
+ return average;
+}
+
+void add_sample(struct adc_channel *ch, uint16_t sample)
+{
+ mutex_lock(&ch->lock);
+ ch->samples[ch->index++] = sample;
+ if (ch->index >= ch->total_length)
+ ch->index = 0;
+ mutex_unlock(&ch->lock);
+}