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);
+}