From 5e8c7c54a9b297dae0081dd19a7bb94e23040a3d Mon Sep 17 00:00:00 2001 From: Joshua Lock Date: Tue, 18 May 2010 14:51:13 +0100 Subject: linux-moblin: add 2.6.33.2 kernel from MeeGo 1.0 Signed-off-by: Joshua Lock --- ...linux-2.6.34-moorestown-sensor-driver-1.1.patch | 1836 ++++++++++++++++++++ 1 file changed, 1836 insertions(+) create mode 100644 meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-sensor-driver-1.1.patch (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-sensor-driver-1.1.patch') diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-sensor-driver-1.1.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-sensor-driver-1.1.patch new file mode 100644 index 000000000..fce452451 --- /dev/null +++ b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-sensor-driver-1.1.patch @@ -0,0 +1,1836 @@ +From cffaf6b15ff40cfbeafd0d4728ba3a5a5fb6155f Mon Sep 17 00:00:00 2001 +From: Alan Olsen +Date: Thu, 15 Oct 2009 14:26:47 -0700 +Subject: [PATCH 062/104] Moorestown Sensor drivers v1.1 consolidated patch + +This patch contains the following patches: + +Alpha2-1.1-1-5-mrst-Sensors-ALS-Driver-for-Moorestown.patch + + [PATCH] ALS Driver for Moorestown Sensors + + This patch single patch for Alpha2:2.0. ALS driver will read + the latest Lux measurement based on the light brightness and + will report the LUX output through sysfs interface. + + Signed-off-by: Kalhan Trisal + +Alpha2-1.1-2-5-mrst-Sensors-Compass-Driver-for-Moorestown.patch + + [PATCH] Compass Driver for Moorestown Sensors + This patch single patch for Alpha2:2.0.This driver will report + the heading values in degrees to the sysfs interface.The vlaues + returned are head . e.g. 245.6 + + Signed-off-by: Kalhan Trisal + +Alpha2-1.1-3-5-mrst-Sensors-Accelerometer-Driver-for-Moorestown.patch + + [PATCH] Accelerometer Driver for Moorestown Sensors + + This patch single patch for Alpha2:2.0.Accelerometer driver will + read the x,y,z coordinate registers and provide the information to + user through sysfs interface. + + Signed-off-by: Kalhan Trisal + +Alpha2-1.1-4-5-mrst-Sensors-Vibrator-Driver-for-Moorestown.patch + + [PATCH] Vibrator Driver for Moorestown Sensors + + This patch single patch for Alpha2:2.0.Vibrator can be switched + on/off using sysfs interface. + + Signed-off-by: Kalhan Trisal + +Alpha2-1.1-5-5-mrst-Sensors-Thermal-Driver-for-Moorestown.patch + + [PATCH] Thermal Driver for Moorestown Sensors + + Moorestown Platform has EMC1403 chip which support three thermal + devices, one thermal zone is used by the EMC1403 chip itself and + second is used by processor and third one is used for platform + (skin temperature).Driver support poll and interrupt + mode,min/max/crit configuration can be done using sysfs interface. + + The driver also support interrupt mode when the temperature crosses the + threshold configured value the min/max/crit. ALERT/THERM interrupt will + be triggered and driver register its callback with GPE driver, and send + the events to OSPM power management to take action. OSPM will take + action and set the new threshold values till it doesnot get ALERT/THERM + events.temp1 is used for configuring internal EMC1403 chip diode, temp2 + is used to configure processor diode and temp3 is used to configure the + platform diode. + + The interrupt mode code has dependency MRST PMIC_GPIO/MAX7315/OSPM.Flag + is added to differentiate the generic functionality of the driver with + moorestown specific. + + Signed-off-by: Kalhan Trisal + +Signed-off-by: Alan Olsen +--- + drivers/hwmon/Kconfig | 35 ++ + drivers/hwmon/Makefile | 4 + drivers/hwmon/emc1403.c | 731 +++++++++++++++++++++++++++++++++++++++++++++++ + drivers/hwmon/hmc6352.c | 250 ++++++++++++++++ + drivers/hwmon/isl29020.c | 248 +++++++++++++++ + drivers/hwmon/lis331dl.c | 322 ++++++++++++++++++++ + drivers/misc/Kconfig | 7 + drivers/misc/Makefile | 1 + drivers/misc/mrst_vib.c | 99 ++++++ + 9 files changed, 1697 insertions(+) + create mode 100644 drivers/hwmon/emc1403.c + create mode 100644 drivers/hwmon/hmc6352.c + create mode 100644 drivers/hwmon/isl29020.c + create mode 100644 drivers/hwmon/lis331dl.c + create mode 100644 drivers/misc/mrst_vib.c + +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -28,6 +28,41 @@ config HWMON_VID + tristate + default n + ++config SENSORS_ISL29020 ++ tristate "Intersil ISL29020 ALS" ++ depends on I2C_MRST ++ help ++ If you say yes here you get support for the ALS Devices ++ Ambient Light Sensor monitoring chip. ++ Range values can be configured using sysfs. ++ Lux Data are accessible via sysfs. ++ ++config SENSORS_HMC6352 ++ tristate "Honeywell HMC6352 compass" ++ depends on I2C_MRST ++ help ++ If you say yes here you get support for the Compass Devices ++ Device can be configured using sysfs. ++ heading data can be accessible via sysfs. ++ ++config SENSORS_LIS331DL ++ tristate "STMicroeletronics LIS331DL three-axis digital accelerometer" ++ depends on I2C_MRST ++ help ++ If you say yes here you get support for the Accelerometer Devices ++ Device can be configured using sysfs. ++ x y Z data can be accessible via sysfs. ++ ++config SENSORS_EMC1403 ++ tristate "SMSC EMC1403 Thermal" ++ depends on I2C_MRST && GPE && GPIO_MAX7315 && MSTWN_POWER_MGMT ++ help ++ If you say yes here you get support for the SMSC Devices ++ EMC1403 temperature monitoring chip. ++ ++ Threshold values can be configured using sysfs. ++ Data from the different diode are accessible via sysfs. ++ + config HWMON_DEBUG_CHIP + bool "Hardware Monitoring Chip debugging messages" + default n +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -99,6 +99,10 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l7 + obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o + obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o + obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o ++obj-$(CONFIG_SENSORS_ISL29020) += isl29020.o ++obj-$(CONFIG_SENSORS_HMC6352) += hmc6352.o ++obj-$(CONFIG_SENSORS_LIS331DL) += lis331dl.o ++obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o + + ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) + EXTRA_CFLAGS += -DDEBUG +--- /dev/null ++++ b/drivers/hwmon/emc1403.c +@@ -0,0 +1,731 @@ ++/* ++ * emc1403.c - SMSC Thermal Driver ++ * ++ * Copyright (C) 2008 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++MODULE_AUTHOR("Kalhan Trisal > 1) & 1)) { ++ set_mask = (ret_val & 0x05); ++ alert = 1; ++ } ++ } else if (offset == 4 || offset == 5) { ++ if (((ret_val >> 2) & 1)) { ++ set_mask = (ret_val & 0x03); ++ alert = 1; ++ } ++ } else if (offset == 0 || offset == 1) { ++ if (ret_val & 1) { ++ set_mask = (ret_val & 0x06); ++ alert = 1; ++ } ++ } ++ /* only rest set the mask for alert events */ ++ if (alert == 1) { ++ status_reg_read(client); ++ i2c_write_current_data(client, 0x1F, set_mask); ++ } ++} ++#endif ++ ++static ssize_t show_temp_auto_offset(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr); ++ int temp_index = s_attr->index; ++ int temp_ofs = s_attr->nr; ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret_val = 0; ++ int ret_offset = 0; ++ ++ ret_offset = calculate_offset(temp_index, temp_ofs); ++ if (ret_offset != -1) { ++ ret_val = i2c_read_current_data(client, ++ THM_LIMIT_REG_TEMP[ret_offset]); ++ return sprintf(buf, "%d\n", ret_val); ++ } else { ++ return -EINVAL; ++ } ++} ++ ++static ssize_t store_temp_auto_offset(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr); ++ int temp_index = s_attr->index; ++ int temp_ofs = s_attr->nr; ++ struct i2c_client *client = to_i2c_client(dev); ++ unsigned long val; ++ int ret_offset = 0; ++ ++ if (strict_strtoul(buf, 10, &val)) ++ return -EINVAL; ++ ret_offset = calculate_offset(temp_index, temp_ofs); ++ if (ret_offset != -1) { ++ i2c_write_current_data(client, ++ THM_LIMIT_REG_TEMP[ret_offset], val); ++#ifdef MOORESTOWN_INTERRUPT_ENABLE ++ reg_unmask_intr(client, ret_offset, val); ++#endif ++ return count; ++ } else { ++ return -EINVAL; ++ } ++} ++ ++static ssize_t show_temp_hyst(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret_val; ++ ++ ret_val = i2c_read_current_data(client, THM_LIMIT_REG_TEMP[9]); ++ return sprintf(buf, "%d\n", ret_val); ++} ++ ++static ssize_t store_temp_hyst(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ unsigned long val = 0; ++ ++ if (strict_strtoul(buf, 10, &val)) ++ return -EINVAL; ++ i2c_write_current_data(client, THM_LIMIT_REG_TEMP[9], val); ++ return count; ++} ++ ++static ssize_t show_temp1_curr_temp(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret_val; ++ ++ ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[0]); ++ return sprintf(buf, "%d\n", ret_val); ++} ++ ++static ssize_t show_temp2_curr_temp(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret_val; ++ ++ ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[1]); ++ return sprintf(buf, "%d\n", ret_val); ++} ++ ++static ssize_t show_temp3_curr_temp(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret_val; ++ ++ ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[2]); ++ return sprintf(buf, "%d\n", ret_val); ++} ++ ++static ssize_t show_status_reg(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret_val1, ret_val2, ret_val3, ret_val4; ++ ++ ret_val1 = i2c_read_current_data(client, 0x1F); ++ ret_val2 = i2c_read_current_data(client, 0x35); ++ ret_val3 = i2c_read_current_data(client, 0x36); ++ ret_val4 = i2c_read_current_data(client, 0x37); ++ return sprintf(buf, "alarm=%x,High=%x,Low=%x,Therm=%x \n", ++ ret_val1, ret_val2, ret_val3, ret_val4); ++} ++ ++static ssize_t show_power_state(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret_val; ++ ++ ret_val = i2c_read_current_data(client, 0x03); ++ ret_val = ret_val & 0x40; ++ if (ret_val == 0x40) ++ ret_val = 1; ++ return sprintf(buf, "%x", ret_val); ++} ++ ++static ssize_t store_power_state(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ unsigned long val = 0; ++ char curr_val; ++ ++ if (strict_strtoul(buf, 10, &val)) ++ return -EINVAL; ++ ++ curr_val = i2c_read_current_data(client, 0x03); ++ if (val == POWER_STA_ENABLE) ++ curr_val = curr_val & 0xBF; ++ else if (val == POWER_STA_DISABLE) ++ curr_val = curr_val | 0x40; ++ else ++ return -EINVAL; ++ i2c_write_current_data(client, 0x03, curr_val); ++ return count; ++} ++ ++static ssize_t show_mode(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret_val; ++ ++ ret_val = i2c_read_current_data(client, 0x03); ++ ret_val = ret_val & 0x80; ++ if (ret_val == 0x80) ++ ret_val = 1; ++ return sprintf(buf, "%x", ret_val); ++} ++ ++static ssize_t store_mode(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ unsigned long val = 0; ++ char curr_val; ++ ++ if (strict_strtoul(buf, 10, &val)) ++ return -EINVAL; ++ ++ curr_val = i2c_read_current_data(client, 0x03); ++ if (val == INTERRUPT_MODE_ENABLE) ++ curr_val = curr_val & 0x7F; ++ else if (val == INTERRUPT_MODE_DISABLE) ++ curr_val = curr_val | 0x80; ++ else ++ return -EINVAL; ++ i2c_write_current_data(client, 0x03, curr_val); ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 0, 1); ++static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 1, 1); ++static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 2, 1); ++static DEVICE_ATTR(temp1_curr, S_IRUGO, show_temp1_curr_temp, NULL); ++ ++static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 0, 2); ++static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 1, 2); ++static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 2, 2); ++static DEVICE_ATTR(temp2_curr, S_IRUGO, show_temp2_curr_temp, NULL); ++ ++static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 0, 4); ++static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 1, 4); ++static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, ++ show_temp_auto_offset, store_temp_auto_offset, 2, 4); ++static DEVICE_ATTR(temp3_curr, S_IRUGO, show_temp3_curr_temp, NULL); ++ ++static DEVICE_ATTR(hyster, S_IRUGO | S_IWUSR, show_temp_hyst, store_temp_hyst); ++static DEVICE_ATTR(status, S_IRUGO, show_status_reg, NULL); ++ ++static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, ++ show_power_state, store_power_state); ++static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode); ++ ++static struct attribute *mid_att_thermal[] = { ++ &sensor_dev_attr_temp1_min.dev_attr.attr, ++ &sensor_dev_attr_temp1_max.dev_attr.attr, ++ &sensor_dev_attr_temp1_crit.dev_attr.attr, ++ &dev_attr_temp1_curr.attr, ++ &sensor_dev_attr_temp2_min.dev_attr.attr, ++ &sensor_dev_attr_temp2_max.dev_attr.attr, ++ &sensor_dev_attr_temp2_crit.dev_attr.attr, ++ &dev_attr_temp2_curr.attr, ++ &sensor_dev_attr_temp3_min.dev_attr.attr, ++ &sensor_dev_attr_temp3_max.dev_attr.attr, ++ &sensor_dev_attr_temp3_crit.dev_attr.attr, ++ &dev_attr_temp3_curr.attr, ++ &dev_attr_hyster.attr, ++ &dev_attr_status.attr, ++ &dev_attr_power_state.attr, ++ &dev_attr_mode.attr, ++ NULL ++}; ++ ++static struct attribute_group m_thermal_gr = { ++ .name = "emc1403", ++ .attrs = mid_att_thermal ++}; ++ ++static void emc1403_set_default_config(struct i2c_client *client) ++{ ++ i2c_smbus_write_byte_data(client, 0x03, 0x00); ++ i2c_smbus_write_byte_data(client, 0x04, 0x02); ++ i2c_smbus_write_byte_data(client, 0x22, 0x00); ++} ++ ++#ifdef MOORESTOWN_INTERRUPT_ENABLE ++static irqreturn_t therm_interrupt_handler(int id, void *dev) ++{ ++ struct thermal_data *data = (struct thermal_data *)dev; ++ schedule_work(&data->therm_handler); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t alert_interrupt_handler(int id, void *dev) ++{ ++ struct thermal_data *data = (struct thermal_data *)dev; ++ schedule_work(&data->alert_handler); ++ ++ return IRQ_HANDLED; ++} ++ ++/* when the device raise the interrupt we mask the interrupt ++ * bit for that device as the status register is R-C ++ * so that till thermal governor doesnot take action we need ++ * not to send continuous events */ ++ ++static int interrupt_status(struct i2c_client *client, u8 diode_reg_val, ++ u8 *status, u8 event) ++{ ++ u8 crit_st = 0, set_mask = 0; ++ ++ set_mask = i2c_read_current_data(client, 0x1F); ++ if (diode_reg_val & THM_CHAN_TEMP[3]) { ++ set_mask = (set_mask | 0x02); ++ crit_st = (crit_st | 2); ++ } ++ if (diode_reg_val & THM_CHAN_TEMP[2]) { ++ set_mask = (set_mask | 0x04); ++ crit_st = (crit_st | 4); ++ } ++ if (diode_reg_val & THM_CHAN_TEMP[4]) { ++ set_mask = (set_mask | 0x01); ++ crit_st = (crit_st | 1); ++ } ++ if (event == ALERT_EVENT) ++ i2c_smbus_write_byte_data(client, 0x1F, set_mask); ++ *status = crit_st; ++ return 0; ++} ++ ++static void ospm_event(int event_id, int sensor_id, int curr_temp) ++{ ++ if (event_id == THERM_EVENT) { ++ printk(KERN_ALERT "emc1403: Sensor Id = %d crit event \ ++ temp = %d \n", sensor_id, curr_temp); ++ ospm_generate_netlink_event(sensor_id, ++ OSPM_EVENT_THERMAL_CRITICAL); ++ } ++ if (event_id == HIGH_EVENT) { ++ printk(KERN_ALERT "emc1403: Sensor Id = %d AUX1 event \ ++ temp = %d \n", sensor_id, curr_temp); ++ ospm_generate_netlink_event(sensor_id, ++ OSPM_EVENT_THERMAL_AUX1); ++ } ++ if (event_id == LOW_EVENT) { ++ printk(KERN_ALERT "emc1403: Sensor Id = %d AUX0 event \ ++ temp = %d \n", sensor_id, curr_temp); ++ ospm_generate_netlink_event(sensor_id, ++ OSPM_EVENT_THERMAL_AUX0); ++ } ++ if (event_id == FAULT_EVENT) { ++ printk(KERN_ALERT "emc1403: Sensor Id = %d Fault event \ ++ temp = %d \n", sensor_id, curr_temp); ++ ospm_generate_netlink_event(sensor_id, ++ OSPM_EVENT_THERMAL_DEV_FAULT); ++ } ++} ++ ++static void send_event(struct i2c_client *client, int status, int event_id) ++{ ++ int ret_val; ++ ++ if (status & TEMP1) { ++ ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[0]); ++ ospm_event(event_id, TEMP_DEV_ID1, ret_val); ++ } ++ if (status & TEMP2) { ++ ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[1]); ++ ospm_event(event_id, TEMP_DEV_ID2, ret_val); ++ } ++ if (status & TEMP3) { ++ ret_val = i2c_read_current_data(client, THM_REG_CURR_TEMP[2]); ++ ospm_event(event_id, TEMP_DEV_ID3, ret_val); ++ } ++} ++ ++static void therm_handle_intrpt(struct work_struct *work) ++{ ++ u8 status, reg_val; ++ struct thermal_data *data = container_of(work, ++ struct thermal_data, therm_handler); ++ ++ /* check if therm_module_info is initialized */ ++ if (!data) ++ return; ++ /* Which DIODE has raised the interrupt 0x1B ++ internal/External1/External2 */ ++ reg_val = i2c_smbus_read_byte_data(data->client, ++ THM_STAT_REG_TEMP[0]); ++ interrupt_status(data->client, reg_val, &status, THERM_EVENT); ++ send_event(data->client, status, THERM_EVENT); ++} ++ ++static void alert_handle_intrpt(struct work_struct *work) ++{ ++ int sta_reg_val, reg_val; ++ u8 status; ++ struct thermal_data *data = container_of(work, ++ struct thermal_data, alert_handler); ++ if (!data) ++ return; ++ /* HIGH/ LOW / FAULT Alert has occured for */ ++ reg_val = i2c_smbus_read_byte_data(data->client, THM_STAT_REG_TEMP[4]); ++ /* High status bit is set */ ++ if (reg_val & THM_CHAN_TEMP[0]) { ++ /* Which DIODE has raised the interrupt 0x1B ++ internal/External1/External2 */ ++ sta_reg_val = i2c_smbus_read_byte_data(data->client, ++ THM_STAT_REG_TEMP[1]); ++ interrupt_status(data->client, sta_reg_val, &status, ++ ALERT_EVENT); ++ send_event(data->client, status, HIGH_EVENT); ++ } ++ /* Low status bit is set */ ++ if (reg_val & THM_CHAN_TEMP[1]) { ++ sta_reg_val = i2c_smbus_read_byte_data(data->client, ++ THM_STAT_REG_TEMP[2]); ++ interrupt_status(data->client, sta_reg_val, &status, ++ ALERT_EVENT); ++ send_event(data->client, status, LOW_EVENT); ++ } ++ /* Fault status bit is set */ ++ if (reg_val & THM_CHAN_TEMP[2]) { ++ sta_reg_val = i2c_smbus_read_byte_data(data->client, ++ THM_STAT_REG_TEMP[3]); ++ interrupt_status(data->client, sta_reg_val, &status, ++ ALERT_EVENT); ++ send_event(data->client, status, FAULT_EVENT); ++ } ++} ++#endif ++ ++static int emc1403_probe(struct i2c_client *new_client, ++ const struct i2c_device_id *id) ++{ ++ int res = 0; ++ struct thermal_data *data; ++ u16 pid, smsc_id, revision; ++ ++#ifdef MOORESTOWN_INTERRUPT_ENABLE ++ u16 t_irq, a_irq; ++#endif ++ data = kzalloc(sizeof(struct thermal_data), GFP_KERNEL); ++ ++ if (data == NULL) { ++ printk(KERN_WARNING "emc1403: Memory allocation failed"); ++ return -ENOMEM; ++ } ++ data->client = new_client; ++ i2c_set_clientdata(new_client, data); ++ ++ /* Check if thermal chip is SMSC and EMC1403 */ ++ smsc_id = i2c_read_current_data(new_client, ++ THERMAL_SMSC_ID_REG); ++ if (smsc_id != 0x5d) { ++ printk(KERN_WARNING "emc1403: vendor id mismatch \n"); ++ goto thermal_error1; ++ } ++ pid = i2c_read_current_data(new_client, THERMAL_PID_REG); ++ if (pid != 0x21) { ++ printk(KERN_WARNING "emc1403: Prod id mismatch \n"); ++ goto thermal_error1; ++ } ++ revision = i2c_read_current_data(new_client, ++ THERMAL_REVISION_REG); ++ if (revision != 0x01) { ++ printk(KERN_WARNING "emc1403: Rev id mismatch is \n"); ++ goto thermal_error1; ++ } ++ res = sysfs_create_group(&new_client->dev.kobj, &m_thermal_gr); ++ if (res) { ++ printk(KERN_WARNING "emc1403: create group failed! \n"); ++ hwmon_device_unregister(data->hwmon_dev); ++ goto thermal_error1; ++ } ++ data->hwmon_dev = hwmon_device_register(&new_client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ res = PTR_ERR(data->hwmon_dev); ++ data->hwmon_dev = NULL; ++ printk(KERN_WARNING "emc1403:Register hwmon dev Failed\n"); ++ goto thermal_error1; ++ } ++#ifdef MOORESTOWN_INTERRUPT_ENABLE ++ INIT_WORK(&data->therm_handler, (void *)therm_handle_intrpt); ++ INIT_WORK(&data->alert_handler, (void *)alert_handle_intrpt); ++ t_irq = new_client->irq; ++ a_irq = *(short *)new_client->dev.platform_data; ++ data->therm_irq = t_irq & ~IRQ_TYPE_MASK; ++ data->alert_irq = a_irq & ~IRQ_TYPE_MASK; ++ /* interpret irq field */ ++ if (data->therm_irq == 0x113) { ++ if (t_irq & IRQ_TYPE_MASK) { ++ /* irq -> GPE_ID */ ++ res = request_gpe(data->therm_irq, ++ (gpio_function_t)therm_interrupt_handler, ++ data, DETECT_LEVEL_LOW); ++ if (res) ++ dev_crit(&new_client->dev, "%s(): cannot \ ++ register therm gpe \n", __func__); ++ } else { ++ res = request_irq(data->therm_irq, ++ therm_interrupt_handler, ++ DETECT_LEVEL_LOW, "emc1403", data); ++ if (res) ++ dev_crit(&new_client->dev, "%s(): \ ++ cannot get therm IRQ\n", __func__); ++ } ++ } else { ++ printk(KERN_WARNING"emc1403: IRQ mismatch \ ++ sent for therm registration"); ++ } ++ if (data->alert_irq == 0x114) { ++ if (a_irq & IRQ_TYPE_MASK) { ++ /* irq -> GPE_ID */ ++ res = request_gpe(data->alert_irq, ++ (gpio_function_t)alert_interrupt_handler, ++ data, DETECT_LEVEL_LOW); ++ if (res) ++ dev_crit(&new_client->dev, "%s(): \ ++ cannot register alert gpe \n", __func__); ++ } else { ++ res = request_irq(data->alert_irq, ++ alert_interrupt_handler, DETECT_LEVEL_LOW, ++ "emc1403", data); ++ if (res) ++ dev_crit(&new_client->dev, "%s(): cannot \ ++ get alert IRQ\n", __func__); ++ } ++ } else { ++ printk(KERN_WARNING"emc1403: IRQ mismatch \ ++ sent for alert registration"); ++ } ++#endif ++ emc1403_set_default_config(new_client); ++ dev_info(&new_client->dev, "%s EMC1403 Thermal chip found \n", ++ new_client->name); ++ return res; ++thermal_error1: ++ i2c_set_clientdata(new_client, NULL); ++ kfree(data); ++ return res; ++} ++ ++static int emc1403_remove(struct i2c_client *client) ++{ ++ struct thermal_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &m_thermal_gr); ++ kfree(data); ++ return 0; ++} ++ ++static struct i2c_device_id emc1403_idtable[] = { ++ { "i2c_thermal", 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, emc1403_idtable); ++ ++static struct i2c_driver sensor_emc1403 = { ++ .driver = { ++ .name = "emc1403", ++ }, ++ .probe = emc1403_probe, ++ .remove = emc1403_remove, ++ .id_table = emc1403_idtable, ++}; ++ ++static int __init sensor_emc1403_init(void) ++{ ++ return i2c_add_driver(&sensor_emc1403); ++} ++ ++static void __exit sensor_emc1403_exit(void) ++{ ++ i2c_del_driver(&sensor_emc1403); ++} ++ ++module_init(sensor_emc1403_init); ++module_exit(sensor_emc1403_exit); +--- /dev/null ++++ b/drivers/hwmon/hmc6352.c +@@ -0,0 +1,250 @@ ++/* ++ * hmc6352.c - Honeywell Compass Driver ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++MODULE_AUTHOR("Kalhan Trisal addr, 0, 1, cmd }, ++ }; ++ struct i2c_msg msg1[] = { ++ { client->addr, 0, 1, cmd1 }, ++ }; ++ ++ if (strict_strtoul(buf, 10, &val)) ++ return -EINVAL; ++ if (val == COMP_CALIB_START) { ++ client->addr = 0x21; ++ ret = i2c_transfer(client->adapter, msg, 1); ++ if (ret != 1) { ++ printk(KERN_WARNING "hmc6352_comp : i2c callib start \ ++ cmd failed \n"); ++ return ret; ++ } ++ } else if (val == COMP_CALIB_STOP) { ++ client->addr = 0x21; ++ ret = i2c_transfer(client->adapter, msg1, 1); ++ if (ret != 1) { ++ printk(KERN_WARNING " hmc6352_comp : i2c callib stop \ ++ cmd failed \n"); ++ return ret; ++ } ++ } else ++ return -EINVAL; ++ ++ return count; ++} ++ ++static ssize_t compass_heading_data_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ char cmd[] = {0x41}; ++ unsigned char i2c_data[2] = {0, 0}; ++ unsigned int ret, ret_val; ++ struct i2c_msg msg[] = { ++ { client->addr, 0, 1, cmd }, ++ }; ++ struct i2c_msg msg1[] = { ++ { client->addr, I2C_M_RD, 2, i2c_data }, ++ }; ++ ++ client->addr = 0x21; ++ ret = i2c_transfer(client->adapter, msg, 1); ++ if (ret != 1) { ++ printk(KERN_WARNING "hmc6352 : i2c cmd 0x41 failed \n"); ++ return ret; ++ } ++ msleep(10); /* sending 0x41 cmd we need to wait for 7-10 milli second*/ ++ ret = i2c_transfer(client->adapter, msg1, 1); ++ if (ret != 1) { ++ printk(KERN_WARNING "hmc6352 : i2c read data cmd failed \n"); ++ return ret; ++ } ++ ret_val = i2c_data[0]; ++ ret_val = ((ret_val << 8) | i2c_data[1]); ++ return sprintf(buf, "%d.%d\n", ret_val/10, ret_val%10); ++} ++ ++static ssize_t compass_power_mode_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ unsigned long val; ++ unsigned int ret; ++ char cmd[] = {0x53}; ++ char cmd1[] = {0x57}; ++ struct i2c_msg msg[] = { ++ { client->addr, 0, 1, cmd }, ++ }; ++ struct i2c_msg msg1[] = { ++ { client->addr, 0, 1, cmd1 }, ++ }; ++ ++ if (strict_strtoul(buf, 10, &val)) ++ return -EINVAL; ++ ++ if (val == COMP_SLEEP_MODE) { ++ ret = i2c_transfer(client->adapter, msg, 1); ++ if (ret != 1) ++ printk(KERN_WARNING "hmc6352: i2c cmd sleep mode \ ++ failed \n"); ++ } else if (val == COMP_ACTIVE_MODE) { ++ ret = i2c_transfer(client->adapter, msg1, 1); ++ if (ret != 1) ++ printk(KERN_WARNING "hmc6352: i2c cmd active mode \ ++ failed \n"); ++ } else ++ return -EINVAL; ++ ++ return count; ++} ++ ++static DEVICE_ATTR(heading, S_IRUGO, compass_heading_data_show, NULL); ++static DEVICE_ATTR(calibration, S_IWUSR, NULL, compass_calibration_store); ++static DEVICE_ATTR(power_state, S_IWUSR, NULL, compass_power_mode_store); ++ ++static struct attribute *mid_att_compass[] = { ++ &dev_attr_heading.attr, ++ &dev_attr_calibration.attr, ++ &dev_attr_power_state.attr, ++ NULL ++}; ++ ++static struct attribute_group m_compass_gr = { ++ .name = "hmc6352", ++ .attrs = mid_att_compass ++}; ++ ++static int hmc6352_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int res; ++ struct compass_data *data; ++ ++ data = kzalloc(sizeof(struct compass_data), GFP_KERNEL); ++ if (data == NULL) { ++ printk(KERN_WARNING "hmc6352: Memory initialization failed"); ++ return -ENOMEM; ++ } ++ i2c_set_clientdata(client, data); ++ ++ res = sysfs_create_group(&client->dev.kobj, &m_compass_gr); ++ if (res) { ++ printk(KERN_WARNING "hmc6352: device_create_file failed!!\n"); ++ goto compass_error1; ++ } ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ res = PTR_ERR(data->hwmon_dev); ++ data->hwmon_dev = NULL; ++ printk(KERN_WARNING "hmc6352: fail to register hwmon device\n"); ++ sysfs_remove_group(&client->dev.kobj, &m_compass_gr); ++ goto compass_error1; ++ } ++ dev_info(&client->dev, "%s HMC6352 compass chip found \n", ++ client->name); ++ return res; ++ ++compass_error1: ++ i2c_set_clientdata(client, NULL); ++ kfree(data); ++ return res; ++} ++ ++static int hmc6352_remove(struct i2c_client *client) ++{ ++ struct compass_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &m_compass_gr); ++ kfree(data); ++ return 0; ++} ++ ++static struct i2c_device_id hmc6352_id[] = { ++ { "i2c_compass", 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, hmc6352_id); ++ ++static struct i2c_driver hmc6352_driver = { ++ .driver = { ++ .name = "hmc6352", ++ }, ++ .probe = hmc6352_probe, ++ .remove = hmc6352_remove, ++ .id_table = hmc6352_id, ++}; ++ ++static int __init sensor_hmc6352_init(void) ++{ ++ int res; ++ ++ res = i2c_add_driver(&hmc6352_driver); ++ return res; ++} ++ ++static void __exit sensor_hmc6352_exit(void) ++{ ++ i2c_del_driver(&hmc6352_driver); ++} ++ ++module_init(sensor_hmc6352_init); ++module_exit(sensor_hmc6352_exit); +--- /dev/null ++++ b/drivers/hwmon/isl29020.c +@@ -0,0 +1,248 @@ ++/* ++ * isl29020.c - Intersil ALS Driver ++ * ++ * Copyright (C) 2008 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++MODULE_AUTHOR("Kalhan Trisal dev.kobj, &m_als_gr); ++ if (res) { ++ printk(KERN_WARNING "isl29020: device create file failed!!\n"); ++ goto als_error1; ++ } ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ res = PTR_ERR(data->hwmon_dev); ++ data->hwmon_dev = NULL; ++ sysfs_remove_group(&client->dev.kobj, &m_als_gr); ++ printk(KERN_ALERT "isl29020:unable to register hwmon device\n"); ++ goto als_error1; ++ } ++ dev_info(&client->dev, "%s isl29020: ALS chip found \n", client->name); ++ als_set_default_config(client); ++ return res; ++ ++als_error1: ++ i2c_set_clientdata(client, NULL); ++ kfree(data); ++ return res; ++} ++ ++static int isl29020_remove(struct i2c_client *client) ++{ ++ struct als_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &m_als_gr); ++ kfree(data); ++ return 0; ++} ++ ++static struct i2c_device_id isl29020_id[] = { ++ { "i2c_als", 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, isl29020_id); ++ ++static struct i2c_driver isl29020_driver = { ++ .driver = { ++ .name = "isl29020", ++ }, ++ .probe = isl29020_probe, ++ .remove = isl29020_remove, ++ .id_table = isl29020_id, ++}; ++ ++static int __init sensor_isl29020_init(void) ++{ ++ int res; ++ ++ res = i2c_add_driver(&isl29020_driver); ++ return res; ++} ++ ++static void __exit sensor_isl29020_exit(void) ++{ ++ i2c_del_driver(&isl29020_driver); ++} ++ ++module_init(sensor_isl29020_init); ++module_exit(sensor_isl29020_exit); +--- /dev/null ++++ b/drivers/hwmon/lis331dl.c +@@ -0,0 +1,322 @@ ++/* ++ * lis331dl.c - ST LIS331DL Accelerometer Driver ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++MODULE_AUTHOR("Kalhan Trisal update_lock); ++ if (val == ACCEL_DATA_RATE_100HZ) ++ set_val = (ret_val & 0x7F); /* setting the 8th bit to 0 */ ++ else if (val == ACCEL_DATA_RATE_400HZ) ++ set_val = (ret_val | (1 << 7)); ++ else ++ goto invarg; ++ ++ i2c_write_current_data(client, 0x20, set_val); ++ mutex_unlock(&data->update_lock); ++ return count; ++invarg: ++ mutex_unlock(&data->update_lock); ++ return -EINVAL; ++} ++ ++static ssize_t power_mode_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, 0x20); ++ ++ mutex_lock(&data->update_lock); ++ if (val == ACCEL_POWER_MODE_DOWN) ++ set_val = ret_val & 0xBF; /* if value id 0 */ ++ else if (val == ACCEL_POWER_MODE_ACTIVE) ++ set_val = (ret_val | (1<<6)); /* if value is 1 */ ++ else ++ goto invarg; ++ ++ i2c_write_current_data(client, 0x20, set_val); ++ mutex_unlock(&data->update_lock); ++ return count; ++invarg: ++ mutex_unlock(&data->update_lock); ++ 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); ++static DEVICE_ATTR(curr_pos, S_IRUGO, xyz_pos_show, NULL); ++ ++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, ++ &dev_attr_curr_pos.attr, ++ NULL ++}; ++ ++static struct attribute_group m_acclero_gr = { ++ .name = "lis331dl", ++ .attrs = mid_att_acclero ++}; ++ ++static void accel_set_default_config(struct i2c_client *client) ++{ ++ i2c_write_current_data(client, 0x20, 0x47); ++} ++ ++static int lis331dl_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int res; ++ struct acclero_data *data; ++ ++ data = kzalloc(sizeof(struct acclero_data), GFP_KERNEL); ++ if (data == NULL) { ++ printk(KERN_WARNING "lis331dl: Memory initi failed \n"); ++ return -ENOMEM; ++ } ++ mutex_init(&data->update_lock); ++ i2c_set_clientdata(client, data); ++ ++ res = sysfs_create_group(&client->dev.kobj, &m_acclero_gr); ++ if (res) { ++ printk(KERN_WARNING "lis331dl: Sysfs group failed!!\n"); ++ goto acclero_error1; ++ } ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ res = PTR_ERR(data->hwmon_dev); ++ data->hwmon_dev = NULL; ++ sysfs_remove_group(&client->dev.kobj, &m_acclero_gr); ++ printk(KERN_WARNING "lis331dl: unable to register \ ++ hwmon device\n"); ++ goto acclero_error1; ++ } ++ accel_set_default_config(client); ++ ++ dev_info(&client->dev, "%s lis331dl: Accelerometer chip \ ++ foundn", client->name); ++ return res; ++ ++acclero_error1: ++ i2c_set_clientdata(client, NULL); ++ kfree(data); ++ return res; ++} ++ ++static int lis331dl_remove(struct i2c_client *client) ++{ ++ struct acclero_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &m_acclero_gr); ++ kfree(data); ++ return 0; ++} ++ ++static struct i2c_device_id lis331dl_id[] = { ++ { "i2c_accel", 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, lis331dl_id); ++ ++static struct i2c_driver lis331dl_driver = { ++ .driver = { ++ .name = "lis331dl", ++ }, ++ .probe = lis331dl_probe, ++ .remove = lis331dl_remove, ++ .id_table = lis331dl_id, ++}; ++ ++static int __init sensor_lis331dl_init(void) ++{ ++ int res; ++ ++ res = i2c_add_driver(&lis331dl_driver); ++ return res; ++} ++ ++static void __exit sensor_lis331dl_exit(void) ++{ ++ i2c_del_driver(&lis331dl_driver); ++} ++ ++module_init(sensor_lis331dl_init); ++module_exit(sensor_lis331dl_exit); +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -249,6 +249,13 @@ config SGI_GRU_DEBUG + This option enables addition debugging code for the SGI GRU driver. If + you are unsure, say N. + ++config MRST_VIB ++ tristate "vibrator driver for Intel Moorestown platform" ++ help ++ Vibrator for Intel Moorestown platform. ++ ++ If unsure, say N. ++ + config ISL29003 + tristate "Intersil ISL29003 ambient light sensor" + depends on I2C && SYSFS +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfg + obj-$(CONFIG_HP_ILO) += hpilo.o + obj-$(CONFIG_MRST) += intel_mrst.o + obj-$(CONFIG_ISL29003) += isl29003.o ++obj-$(CONFIG_MRST_VIB) += mrst_vib.o + obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o + obj-$(CONFIG_DS1682) += ds1682.o + obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o +--- /dev/null ++++ b/drivers/misc/mrst_vib.c +@@ -0,0 +1,99 @@ ++/* ++ * mrst_vib.c - Intel vibrator Driver ++ * ++ * Copyright (C) 2008 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 ++#include ++#include ++#include ++ ++ ++MODULE_AUTHOR("Kalhan Trisal"); ++MODULE_DESCRIPTION("Intel Moorestown Thermal Driver"); ++MODULE_LICENSE("GPL v2"); ++ ++#define VIB_START 1 ++#define VIB_STOP 2 ++static struct platform_device *vib_pdev; ++ ++static ssize_t vib_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct ipc_pmic_reg_data vib_power_reg_write = {0}; ++ unsigned long val; ++ ++ if (strict_strtoul(buf, 10, &val)) ++ return -EINVAL; ++ if (val == VIB_START) { ++ vib_power_reg_write.ioc = TRUE; ++ vib_power_reg_write.pmic_reg_data[0].register_address = 0x49; ++ vib_power_reg_write.pmic_reg_data[0].value = 0xAD; ++ vib_power_reg_write.num_entries = 1; ++ if (ipc_pmic_register_write(&vib_power_reg_write, TRUE)) { ++ printk(KERN_WARNING "mrst_vib: failed to turn ON \ ++ vib \n"); ++ return -EINVAL; ++ } ++ } else if (val == VIB_STOP) { ++ vib_power_reg_write.ioc = TRUE; ++ vib_power_reg_write.pmic_reg_data[0].register_address = 0x49; ++ vib_power_reg_write.pmic_reg_data[0].value = 0x14; ++ vib_power_reg_write.num_entries = 1; ++ if (ipc_pmic_register_write(&vib_power_reg_write, TRUE)) { ++ printk(KERN_WARNING "mrst_vib: failed to turn OFF \ ++ Vibrator \n"); ++ return -EINVAL; ++ } ++ } else ++ return -EINVAL; ++ ++ return count; ++} ++ ++static struct device_attribute dev_attr_vib = ++ __ATTR(vib, S_IWUSR, NULL, vib_store); ++ ++static int __init mrst_vib_init(void) ++{ ++ int res = 0; ++ ++ vib_pdev = platform_device_register_simple("mrst_vib", -1, NULL, 0); ++ if (IS_ERR(vib_pdev)) { ++ res = PTR_ERR(vib_pdev); ++ vib_pdev = NULL; ++ printk(KERN_WARNING "mrst_vib: unable to register platform \ ++ device\n"); ++ return res; ++ } ++ res = device_create_file(&vib_pdev->dev, &dev_attr_vib); ++ return res; ++} ++ ++static void __exit mrst_vib_exit(void) ++{ ++ device_remove_file(&vib_pdev->dev, &dev_attr_vib); ++ platform_device_unregister(vib_pdev); ++} ++ ++module_init(mrst_vib_init); ++module_exit(mrst_vib_exit); -- cgit v1.2.3