File linux-2.6.34-moorestown-analog-accelerometer-driver.patch of Package kernel

Index: linux-2.6.33/drivers/hwmon/Kconfig
===================================================================
--- linux-2.6.33.orig/drivers/hwmon/Kconfig
+++ linux-2.6.33/drivers/hwmon/Kconfig
@@ -63,6 +63,13 @@ config SENSORS_EMC1403
 	  Threshold values can be configured using sysfs.
 	  Data from the different diode are  accessible via sysfs.
 
+config SENSORS_MRST_ANALOG_ACCEL
+	tristate "Moorestown Analog Accelerometer"
+	depends on LNW_IPC
+	help
+	  If you say yes here you get support for the Analog Accelerometer  Devices
+	  x y Z data can be accessed via sysfs.
+
 config HWMON_DEBUG_CHIP
 	bool "Hardware Monitoring Chip debugging messages"
 	default n
Index: linux-2.6.33/drivers/hwmon/Makefile
===================================================================
--- linux-2.6.33.orig/drivers/hwmon/Makefile
+++ linux-2.6.33/drivers/hwmon/Makefile
@@ -103,6 +103,7 @@ obj-$(CONFIG_SENSORS_ISL29020)	+= isl290
 obj-$(CONFIG_SENSORS_HMC6352)	+= hmc6352.o
 obj-$(CONFIG_SENSORS_LIS331DL)	+= lis331dl.o
 obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
+obj-$(CONFIG_SENSORS_MRST_ANALOG_ACCEL)	+= mrst_analog_accel.o
 
 ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
Index: linux-2.6.33/drivers/hwmon/mrst_analog_accel.c
===================================================================
--- /dev/null
+++ linux-2.6.33/drivers/hwmon/mrst_analog_accel.c
@@ -0,0 +1,381 @@
+/*
+ * mrst_analog_accel.c - Intel analog accelerometer driver for Moorestown
+ *
+ * Copyright (C) 2009 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <asm/ipc_defs.h>
+
+MODULE_AUTHOR("Ramesh Agarwal");
+MODULE_DESCRIPTION("Intel Moorestown Analog Accelerometer Driver");
+MODULE_LICENSE("GPL v2");
+
+/* PMIC ADC INTERRUPT REGISTERS */
+#define PMIC_ADC_ACC_REG_ADCINT		0x5F	/*ADC interrupt register */
+#define PMIC_ADC_ACC_REG_MADCINT	0x60	/*ADC interrupt mask register */
+
+/* PMIC ADC CONTROL REGISTERS */
+#define PMIC_ADC_ACC_REG_ADCCNTL1	0x61	/*ADC control register */
+#define PMIC_ADC_ACC_REG_ADCCNTL2	0x62	/*ADC gain regs channel 10-17 */
+#define PMIC_ADC_ACC_REG_ADCCNTL3	0x63	/*ADC gain regs channel 18-21 */
+
+/* PMIC Data Register base */
+#define PMIC_ADC_DATA_REG_BASE		0x64
+
+/* PMIC Channel Mapping Register base */
+#define PMIC_ADC_MAPPING_BASE		0xA4
+
+/* Number of PMIC sample registers */
+#define PMIC_ADC_REG_MAX	32	/* Max no of available channel */
+
+#define PMIC_ADC_X_REG_HIGH(index)	(PMIC_ADC_DATA_REG_BASE \
+						+ (index * 2))
+#define PMIC_ADC_X_REG_LOW(index)	(PMIC_ADC_DATA_REG_BASE \
+						+ (index * 2) + 1)
+#define PMIC_ADC_Y_REG_HIGH(index)	(PMIC_ADC_DATA_REG_BASE \
+						+ (index * 2) + 2)
+#define PMIC_ADC_Y_REG_LOW(index)	(PMIC_ADC_DATA_REG_BASE \
+						+ (index * 2) + 3)
+#define PMIC_ADC_Z_REG_HIGH(index)	(PMIC_ADC_DATA_REG_BASE \
+						+ (index * 2) + 4)
+#define PMIC_ADC_Z_REG_LOW(index)	(PMIC_ADC_DATA_REG_BASE \
+						+ (index * 2) + 5)
+
+/* Number of registers to read at a time */
+#define REG_READ_PER_IPC	4	/* Read 4 at a time although the */
+					/* IPC will support max 5 */
+
+#define END_OF_CHANNEL_VALUE	0x1F	/* Used to indicate the last */
+					/* channel being used */
+
+/* PMIC ADC channels for Accelero Meter */
+#define PMIC_ADC_ACC_ADC_ACC_CH14  0xE
+#define PMIC_ADC_ACC_ADC_ACC_CH15  0xF
+#define PMIC_ADC_ACC_ADC_ACC_CH16  0x10
+
+static unsigned int mrst_analog_reg_idx;
+
+/* Use IPC to read the value of the register and display
+ * X value
+ */
+static ssize_t
+mrst_analog_accel_x_axis_data_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	unsigned int ret_val;
+	struct ipc_pmic_reg_data ipc_data;
+
+	ipc_data.ioc = FALSE;	/* No need to generate MSI */
+	ipc_data.num_entries = 2;
+	ipc_data.pmic_reg_data[0].register_address =
+		PMIC_ADC_X_REG_HIGH(mrst_analog_reg_idx); /* X Higher 8 bits */
+	ipc_data.pmic_reg_data[1].register_address =
+		PMIC_ADC_X_REG_LOW(mrst_analog_reg_idx); /* X lower 3 bits */
+	if (ipc_pmic_register_read(&ipc_data) != 0) {
+		printk(KERN_ALERT
+			"\nmrst_analog_accel:PMIC reg read using IPC failed\n");
+		return -1;
+	}
+	ret_val = ipc_data.pmic_reg_data[0].value << 3;	/* X higher 8 bits */
+	/* lower 3 bits */
+	ret_val = ret_val | (ipc_data.pmic_reg_data[1].value & 0x07);
+	return sprintf(buf, "%d\n", ret_val);
+}
+
+/* Use IPC to read the value of the register and display
+ * Y value */
+static ssize_t
+mrst_analog_accel_y_axis_data_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	unsigned int ret_val;
+	struct ipc_pmic_reg_data ipc_data;
+
+	ipc_data.ioc = FALSE;	/* No need to generate MSI */
+	ipc_data.num_entries = 2;
+	ipc_data.pmic_reg_data[0].register_address =
+		PMIC_ADC_Y_REG_HIGH(mrst_analog_reg_idx); /* Y higher 8 bits */
+	ipc_data.pmic_reg_data[1].register_address =
+		PMIC_ADC_Y_REG_LOW(mrst_analog_reg_idx); /* Y lower 3 bits */
+	if (ipc_pmic_register_read(&ipc_data) != 0) {
+		printk(KERN_ALERT
+		"\nmrst_analog_accel:PMIC reg read using IPC failed\n");
+		return -1;
+	}
+	ret_val = ipc_data.pmic_reg_data[0].value << 3;	/* Y higher 8 bits */
+	/* Y lower 3 bits */
+	ret_val = ret_val | (ipc_data.pmic_reg_data[1].value & 0x07);
+	return sprintf(buf, "%d\n", ret_val);
+}
+
+/* Use IPC to read the value of the register and display
+ * Z value */
+static ssize_t
+mrst_analog_accel_z_axis_data_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	unsigned int ret_val;
+	struct ipc_pmic_reg_data ipc_data;
+
+	ipc_data.ioc = FALSE;	/* No need to generate MSI */
+	ipc_data.num_entries = 2;
+	ipc_data.pmic_reg_data[0].register_address =
+		PMIC_ADC_Z_REG_HIGH(mrst_analog_reg_idx);
+	ipc_data.pmic_reg_data[1].register_address =
+		PMIC_ADC_Z_REG_LOW(mrst_analog_reg_idx); /* Z lower 3 bits */
+	if (ipc_pmic_register_read(&ipc_data) != 0) {
+		printk(KERN_ALERT
+		"\nmrst_analog_accel:PMIC reg read using IPC failed\n");
+		return -1;
+	}
+	ret_val = ipc_data.pmic_reg_data[0].value << 3;	/* Z higher 8 bits */
+	/* Z lower 3 bits */
+	ret_val = ret_val | (ipc_data.pmic_reg_data[1].value & 0x07);
+	return sprintf(buf, "%d\n", ret_val);
+}
+
+
+static DEVICE_ATTR(acc_x_axis, S_IRUGO,
+			mrst_analog_accel_x_axis_data_show, NULL);
+static DEVICE_ATTR(acc_y_axis, S_IRUGO,
+			mrst_analog_accel_y_axis_data_show, NULL);
+static DEVICE_ATTR(acc_z_axis, S_IRUGO,
+			mrst_analog_accel_z_axis_data_show, NULL);
+
+static struct attribute *mid_att_acc[] = {
+	&dev_attr_acc_x_axis.attr,
+	&dev_attr_acc_y_axis.attr,
+	&dev_attr_acc_z_axis.attr,
+	NULL
+};
+
+static struct attribute_group m_analog_gr = {
+	.name = "mrst_analog_accel",
+	.attrs = mid_att_acc
+};
+
+static int
+mrst_analog_accel_initialize(void)
+{
+	struct ipc_pmic_mod_reg_data ipc_mod_data;
+	struct ipc_pmic_reg_data ipc_data;
+	u8 retval = 0;
+	u8 mad_cntrl = 0;	/* MADCINT register value */
+	u8 adc_cntrl2 = 0;	/* ADCCNTL2 register value */
+	int i, j;
+
+	/* Initialize the register index to use to be zero */
+	mrst_analog_reg_idx = 0;
+
+	/* check if the ADC is enabled or not
+	 * Read ADCCNTL1 registers */
+	ipc_data.ioc = FALSE;	/* No need to generate MSI */
+	ipc_data.num_entries = 1;
+	ipc_data.pmic_reg_data[0].register_address =
+		PMIC_ADC_ACC_REG_ADCCNTL1;
+	ipc_data.pmic_reg_data[0].value = 0;
+
+	retval = ipc_pmic_register_read(&ipc_data);
+	if (retval != 0) {
+		printk(KERN_ALERT
+			"\nmrst_analog_accel:PMIC register read failed\n");
+		return retval;
+	}
+
+	adc_cntrl2 = ipc_data.pmic_reg_data[0].value;
+
+	if ((adc_cntrl2 >> 7) & 0x1) {
+		/* If the ADC is enabled find the set of registers to use
+		** Loop through the channel mapping register to find out the
+		** first free one
+		*/
+		for (i = 0;
+			(i < PMIC_ADC_REG_MAX) && (mrst_analog_reg_idx == 0);
+			i += REG_READ_PER_IPC) {
+
+			ipc_data.num_entries = REG_READ_PER_IPC;
+			ipc_data.ioc = FALSE;	/* No need to generate MSI */
+
+			/* Reading 4 regs at a time instead of reading each
+			 * reg one by one since IPC is an expensive operation
+			 */
+			for (j = 0; j < REG_READ_PER_IPC; j++) {
+				ipc_data.pmic_reg_data[j].register_address =
+					PMIC_ADC_MAPPING_BASE + i + j;
+				ipc_data.pmic_reg_data[j].value = 0;
+			}
+			retval = ipc_pmic_register_read(&ipc_data);
+			if (retval != 0) {
+				printk(KERN_ALERT
+				"\nmrst_analog_accel:PMIC regs read failed\n");
+				return retval;
+			}
+			for (j = 0; j < REG_READ_PER_IPC; j++) {
+				if (ipc_data.pmic_reg_data[j].value
+					== END_OF_CHANNEL_VALUE) {
+					mrst_analog_reg_idx = i + j;
+					break;
+				}
+			}
+		}
+	}
+	/* Check to see if there are enough registers to map the channel */
+	if ((mrst_analog_reg_idx + 3) >= PMIC_ADC_REG_MAX) {
+		printk(KERN_ALERT
+		"\nmrst_analog_accel:Not enough regs to map the channels\n");
+		return -1;
+	}
+
+	/* Update the mapping registers for the accelerometer*/
+	ipc_data.num_entries = 4;
+	ipc_data.ioc = FALSE;	/* No need to generate MSI */
+	ipc_data.pmic_reg_data[0].register_address =
+			PMIC_ADC_MAPPING_BASE + mrst_analog_reg_idx;
+	ipc_data.pmic_reg_data[0].value = PMIC_ADC_ACC_ADC_ACC_CH14;
+
+	ipc_data.pmic_reg_data[1].register_address =
+			PMIC_ADC_MAPPING_BASE + mrst_analog_reg_idx + 1;
+	ipc_data.pmic_reg_data[1].value = PMIC_ADC_ACC_ADC_ACC_CH15;
+
+	ipc_data.pmic_reg_data[2].register_address =
+			PMIC_ADC_MAPPING_BASE + mrst_analog_reg_idx + 2;
+	ipc_data.pmic_reg_data[2].value = PMIC_ADC_ACC_ADC_ACC_CH16;
+
+	ipc_data.pmic_reg_data[3].register_address =
+			PMIC_ADC_MAPPING_BASE + mrst_analog_reg_idx + 3 ;
+	ipc_data.pmic_reg_data[3].value = END_OF_CHANNEL_VALUE;
+
+	retval = ipc_pmic_register_write(&ipc_data, FALSE);
+	if (retval != 0) {
+		printk(KERN_ALERT
+			"\nmrst_analog_accel:PMIC reg write failed\n");
+		return retval;
+	}
+
+	/* If the ADC was not enabled, enable it now */
+	if (!(adc_cntrl2 >> 7) & 0x1) {
+		/* Mask the round robin completion interrupt */
+		ipc_mod_data.ioc = FALSE;	/* No need to generate MSI */
+		ipc_mod_data.num_entries = 1;
+		mad_cntrl = 0x01;
+		ipc_mod_data.pmic_mod_reg_data[0].register_address =
+			PMIC_ADC_ACC_REG_MADCINT;
+		ipc_mod_data.pmic_mod_reg_data[0].value = mad_cntrl;
+		ipc_mod_data.pmic_mod_reg_data[0].bit_map = 0x01;
+
+		retval = ipc_pmic_register_read_modify(&ipc_mod_data);
+		if (retval != 0) {
+			printk(KERN_ALERT
+			"\nmrst_analog_accel:PMIC reg modify failed\n");
+			return retval;
+		}
+
+		adc_cntrl2 = 0xc6;	/*27ms delay,start round robin,
+					   enable full power */
+		ipc_data.ioc = FALSE;	/* No need to generate MSI */
+		ipc_data.num_entries = 1;
+		ipc_data.pmic_reg_data[0].register_address =
+			PMIC_ADC_ACC_REG_ADCCNTL1;
+		ipc_data.pmic_reg_data[0].value = adc_cntrl2;
+		retval = ipc_pmic_register_write(&ipc_data, FALSE);
+		if (retval != 0)
+			return retval;
+	}
+	return retval;
+}
+
+static struct platform_device *mrst_analog_accel_pdev;
+static struct device *mrst_analog_accel_hwmon;
+
+static int
+mrst_analog_accel_unregister(void)
+{
+
+	printk(KERN_ALERT "\nStart Exit\n\n");
+	sysfs_remove_group(&mrst_analog_accel_hwmon->kobj, &m_analog_gr);
+	hwmon_device_unregister(mrst_analog_accel_hwmon);
+	platform_device_unregister(mrst_analog_accel_pdev);
+	printk(KERN_ALERT "\n\nEnd Exit\n");
+	return 0;
+}
+
+
+static int __init
+mrst_analog_accel_module_init(void)
+{
+	int retval = 0;
+
+	mrst_analog_accel_pdev =
+		platform_device_register_simple("mrst_analog_accel",
+			0, NULL, 0);
+	if (IS_ERR(mrst_analog_accel_pdev)) {
+		retval = PTR_ERR(mrst_analog_accel_pdev);
+		printk(KERN_ALERT
+		"\nmrst_analog_accel:Registration with the platform failed\n");
+		goto accelero_reg_failed;
+	}
+	printk(KERN_ALERT
+		"\nmrst_analog_accel:Registered with the platform\n");
+
+	retval = mrst_analog_accel_initialize();
+	if (retval == 0) {
+		retval = sysfs_create_group(&mrst_analog_accel_pdev->dev.kobj,
+			&m_analog_gr);
+		if (retval) {
+			printk(KERN_ALERT
+			"\nmrst_analog_accel:device_create_file 1 failed\n");
+			goto accelero_reg_failed;
+		}
+		mrst_analog_accel_hwmon =
+			hwmon_device_register(&mrst_analog_accel_pdev->dev);
+		if (IS_ERR(mrst_analog_accel_hwmon)) {
+			retval = PTR_ERR(mrst_analog_accel_hwmon);
+			mrst_analog_accel_hwmon = NULL;
+			printk(KERN_ALERT
+			"\nmrst_analog_accel:Registration with hwmon failed\n");
+		}
+	} else {
+		printk(KERN_ALERT
+		"\nmrst_analog_accel:Initialization failed: %d\n", retval);
+	}
+
+accelero_reg_failed:
+	return retval;
+}
+
+static void __exit
+mrst_analog_accel_module_exit(void)
+{
+
+	mrst_analog_accel_unregister();
+}
+
+module_init(mrst_analog_accel_module_init);
+module_exit(mrst_analog_accel_module_exit);
Index: linux-2.6.33/drivers/hwmon/lis331dl.c
===================================================================
--- linux-2.6.33.orig/drivers/hwmon/lis331dl.c
+++ linux-2.6.33/drivers/hwmon/lis331dl.c
@@ -186,33 +186,10 @@ invarg:
 	return -EINVAL;
 }
 
-static ssize_t reboot_mem_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct acclero_data *data = i2c_get_clientdata(client);
-	unsigned int ret_val, set_val;
-	unsigned long val;
-
-	if (strict_strtoul(buf, 10, &val))
-		return -EINVAL;
-	ret_val = i2c_smbus_read_byte_data(client, 0x21);
-	if (val == ACCEL_MEMORY_REBOOT) {
-		mutex_lock(&data->update_lock);
-		set_val = (ret_val | (1 << 6)); /* setting the 6th  bit */
-		i2c_write_current_data(client, 0x21, set_val);
-		mutex_unlock(&data->update_lock);
-	} else
-		return -EINVAL;
-	return count;
-}
-
 static DEVICE_ATTR(data_rate, S_IRUGO | S_IWUSR,
 	data_rate_show, data_rate_store);
 static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
 	power_mode_show, power_mode_store);
-static DEVICE_ATTR(reboot_mem, S_IWUSR, NULL,
-			reboot_mem_store);
 static DEVICE_ATTR(x, S_IRUGO, x_pos_show, NULL);
 static DEVICE_ATTR(y, S_IRUGO, y_pos_show, NULL);
 static DEVICE_ATTR(z, S_IRUGO, z_pos_show, NULL);
@@ -221,7 +198,6 @@ static DEVICE_ATTR(curr_pos, S_IRUGO, xy
 static struct attribute *mid_att_acclero[] = {
 	&dev_attr_data_rate.attr,
 	&dev_attr_power_state.attr,
-	&dev_attr_reboot_mem.attr,
 	&dev_attr_x.attr,
 	&dev_attr_y.attr,
 	&dev_attr_z.attr,
openSUSE Build Service is sponsored by