summaryrefslogtreecommitdiff
path: root/drivers/hwmon/ams
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/ams')
-rw-r--r--drivers/hwmon/ams/ams-core.c82
-rw-r--r--drivers/hwmon/ams/ams-i2c.c60
-rw-r--r--drivers/hwmon/ams/ams-input.c63
-rw-r--r--drivers/hwmon/ams/ams-pmu.c18
-rw-r--r--drivers/hwmon/ams/ams.h6
5 files changed, 95 insertions, 134 deletions
diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c
index fbefa82a015c..6c9ace1b76f6 100644
--- a/drivers/hwmon/ams/ams-core.c
+++ b/drivers/hwmon/ams/ams-core.c
@@ -99,39 +99,31 @@ static struct pmf_irq_client ams_shock_client = {
*/
static void ams_worker(struct work_struct *work)
{
- mutex_lock(&ams_info.lock);
-
- if (ams_info.has_device) {
- unsigned long flags;
+ unsigned long flags;
+ u8 irqs_to_clear;
- spin_lock_irqsave(&ams_info.irq_lock, flags);
+ mutex_lock(&ams_info.lock);
- if (ams_info.worker_irqs & AMS_IRQ_FREEFALL) {
- if (verbose)
- printk(KERN_INFO "ams: freefall detected!\n");
+ spin_lock_irqsave(&ams_info.irq_lock, flags);
+ irqs_to_clear = ams_info.worker_irqs;
- ams_info.worker_irqs &= ~AMS_IRQ_FREEFALL;
+ if (ams_info.worker_irqs & AMS_IRQ_FREEFALL) {
+ if (verbose)
+ printk(KERN_INFO "ams: freefall detected!\n");
- /* we must call this with interrupts enabled */
- spin_unlock_irqrestore(&ams_info.irq_lock, flags);
- ams_info.clear_irq(AMS_IRQ_FREEFALL);
- spin_lock_irqsave(&ams_info.irq_lock, flags);
- }
+ ams_info.worker_irqs &= ~AMS_IRQ_FREEFALL;
+ }
- if (ams_info.worker_irqs & AMS_IRQ_SHOCK) {
- if (verbose)
- printk(KERN_INFO "ams: shock detected!\n");
+ if (ams_info.worker_irqs & AMS_IRQ_SHOCK) {
+ if (verbose)
+ printk(KERN_INFO "ams: shock detected!\n");
- ams_info.worker_irqs &= ~AMS_IRQ_SHOCK;
+ ams_info.worker_irqs &= ~AMS_IRQ_SHOCK;
+ }
- /* we must call this with interrupts enabled */
- spin_unlock_irqrestore(&ams_info.irq_lock, flags);
- ams_info.clear_irq(AMS_IRQ_SHOCK);
- spin_lock_irqsave(&ams_info.irq_lock, flags);
- }
+ spin_unlock_irqrestore(&ams_info.irq_lock, flags);
- spin_unlock_irqrestore(&ams_info.irq_lock, flags);
- }
+ ams_info.clear_irq(irqs_to_clear);
mutex_unlock(&ams_info.lock);
}
@@ -223,34 +215,28 @@ int __init ams_init(void)
void ams_exit(void)
{
- mutex_lock(&ams_info.lock);
-
- if (ams_info.has_device) {
- /* Remove input device */
- ams_input_exit();
+ /* Remove input device */
+ ams_input_exit();
- /* Shut down implementation */
- ams_info.exit();
-
- /* Flush interrupt worker
- *
- * We do this after ams_info.exit(), because an interrupt might
- * have arrived before disabling them.
- */
- flush_scheduled_work();
+ /* Remove attributes */
+ device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
- /* Remove attributes */
- device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+ /* Shut down implementation */
+ ams_info.exit();
- /* Remove device */
- of_device_unregister(ams_info.of_dev);
+ /* Flush interrupt worker
+ *
+ * We do this after ams_info.exit(), because an interrupt might
+ * have arrived before disabling them.
+ */
+ flush_scheduled_work();
- /* Remove handler */
- pmf_unregister_irq_client(&ams_shock_client);
- pmf_unregister_irq_client(&ams_freefall_client);
- }
+ /* Remove device */
+ of_device_unregister(ams_info.of_dev);
- mutex_unlock(&ams_info.lock);
+ /* Remove handler */
+ pmf_unregister_irq_client(&ams_shock_client);
+ pmf_unregister_irq_client(&ams_freefall_client);
}
MODULE_AUTHOR("Stelian Pop, Michael Hanselmann");
diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c
index 957760536a4c..2cbf8a6506c7 100644
--- a/drivers/hwmon/ams/ams-i2c.c
+++ b/drivers/hwmon/ams/ams-i2c.c
@@ -60,26 +60,34 @@ enum ams_i2c_cmd {
AMS_CMD_START,
};
-static int ams_i2c_attach(struct i2c_adapter *adapter);
-static int ams_i2c_detach(struct i2c_adapter *adapter);
+static int ams_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int ams_i2c_remove(struct i2c_client *client);
+
+static const struct i2c_device_id ams_id[] = {
+ { "ams", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ams_id);
static struct i2c_driver ams_i2c_driver = {
.driver = {
.name = "ams",
.owner = THIS_MODULE,
},
- .attach_adapter = ams_i2c_attach,
- .detach_adapter = ams_i2c_detach,
+ .probe = ams_i2c_probe,
+ .remove = ams_i2c_remove,
+ .id_table = ams_id,
};
static s32 ams_i2c_read(u8 reg)
{
- return i2c_smbus_read_byte_data(&ams_info.i2c_client, reg);
+ return i2c_smbus_read_byte_data(ams_info.i2c_client, reg);
}
static int ams_i2c_write(u8 reg, u8 value)
{
- return i2c_smbus_write_byte_data(&ams_info.i2c_client, reg, value);
+ return i2c_smbus_write_byte_data(ams_info.i2c_client, reg, value);
}
static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
@@ -152,9 +160,9 @@ static void ams_i2c_get_xyz(s8 *x, s8 *y, s8 *z)
*z = ams_i2c_read(AMS_DATAZ);
}
-static int ams_i2c_attach(struct i2c_adapter *adapter)
+static int ams_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- unsigned long bus;
int vmaj, vmin;
int result;
@@ -162,17 +170,7 @@ static int ams_i2c_attach(struct i2c_adapter *adapter)
if (unlikely(ams_info.has_device))
return -ENODEV;
- if (strncmp(adapter->name, "uni-n", 5))
- return -ENODEV;
-
- bus = simple_strtoul(adapter->name + 6, NULL, 10);
- if (bus != ams_info.i2c_bus)
- return -ENODEV;
-
- ams_info.i2c_client.addr = ams_info.i2c_address;
- ams_info.i2c_client.adapter = adapter;
- ams_info.i2c_client.driver = &ams_i2c_driver;
- strcpy(ams_info.i2c_client.name, "Apple Motion Sensor");
+ ams_info.i2c_client = client;
if (ams_i2c_cmd(AMS_CMD_RESET)) {
printk(KERN_INFO "ams: Failed to reset the device\n");
@@ -237,7 +235,7 @@ static int ams_i2c_attach(struct i2c_adapter *adapter)
return 0;
}
-static int ams_i2c_detach(struct i2c_adapter *adapter)
+static int ams_i2c_remove(struct i2c_client *client)
{
if (ams_info.has_device) {
/* Disable interrupts */
@@ -261,11 +259,7 @@ static void ams_i2c_exit(void)
int __init ams_i2c_init(struct device_node *np)
{
- char *tmp_bus;
int result;
- const u32 *prop;
-
- mutex_lock(&ams_info.lock);
/* Set implementation stuff */
ams_info.of_node = np;
@@ -275,25 +269,7 @@ int __init ams_i2c_init(struct device_node *np)
ams_info.clear_irq = ams_i2c_clear_irq;
ams_info.bustype = BUS_I2C;
- /* look for bus either using "reg" or by path */
- prop = of_get_property(ams_info.of_node, "reg", NULL);
- if (!prop) {
- result = -ENODEV;
-
- goto exit;
- }
-
- tmp_bus = strstr(ams_info.of_node->full_name, "/i2c-bus@");
- if (tmp_bus)
- ams_info.i2c_bus = *(tmp_bus + 9) - '0';
- else
- ams_info.i2c_bus = ((*prop) >> 8) & 0x0f;
- ams_info.i2c_address = ((*prop) & 0xff) >> 1;
-
result = i2c_add_driver(&ams_i2c_driver);
-exit:
- mutex_unlock(&ams_info.lock);
-
return result;
}
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
index 7b81e0c2c2d9..8a712392cd38 100644
--- a/drivers/hwmon/ams/ams-input.c
+++ b/drivers/hwmon/ams/ams-input.c
@@ -20,13 +20,15 @@
#include "ams.h"
static unsigned int joystick;
-module_param(joystick, bool, 0644);
+module_param(joystick, bool, S_IRUGO);
MODULE_PARM_DESC(joystick, "Enable the input class device on module load");
static unsigned int invert;
-module_param(invert, bool, 0644);
+module_param(invert, bool, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
+static DEFINE_MUTEX(ams_input_mutex);
+
static void ams_idev_poll(struct input_polled_dev *dev)
{
struct input_dev *idev = dev->input;
@@ -50,13 +52,11 @@ static void ams_idev_poll(struct input_polled_dev *dev)
}
/* Call with ams_info.lock held! */
-static void ams_input_enable(void)
+static int ams_input_enable(void)
{
struct input_dev *input;
s8 x, y, z;
-
- if (ams_info.idev)
- return;
+ int error;
ams_sensors(&x, &y, &z);
ams_info.xcalib = x;
@@ -65,7 +65,7 @@ static void ams_input_enable(void)
ams_info.idev = input_allocate_polled_device();
if (!ams_info.idev)
- return;
+ return -ENOMEM;
ams_info.idev->poll = ams_idev_poll;
ams_info.idev->poll_interval = 25;
@@ -84,14 +84,18 @@ static void ams_input_enable(void)
set_bit(EV_KEY, input->evbit);
set_bit(BTN_TOUCH, input->keybit);
- if (input_register_polled_device(ams_info.idev)) {
+ error = input_register_polled_device(ams_info.idev);
+ if (error) {
input_free_polled_device(ams_info.idev);
ams_info.idev = NULL;
- return;
+ return error;
}
+
+ joystick = 1;
+
+ return 0;
}
-/* Call with ams_info.lock held! */
static void ams_input_disable(void)
{
if (ams_info.idev) {
@@ -99,6 +103,8 @@ static void ams_input_disable(void)
input_free_polled_device(ams_info.idev);
ams_info.idev = NULL;
}
+
+ joystick = 0;
}
static ssize_t ams_input_show_joystick(struct device *dev,
@@ -110,39 +116,42 @@ static ssize_t ams_input_show_joystick(struct device *dev,
static ssize_t ams_input_store_joystick(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- if (sscanf(buf, "%d\n", &joystick) != 1)
+ unsigned long enable;
+ int error = 0;
+
+ if (strict_strtoul(buf, 0, &enable) || enable > 1)
return -EINVAL;
- mutex_lock(&ams_info.lock);
+ mutex_lock(&ams_input_mutex);
- if (joystick)
- ams_input_enable();
- else
- ams_input_disable();
+ if (enable != joystick) {
+ if (enable)
+ error = ams_input_enable();
+ else
+ ams_input_disable();
+ }
- mutex_unlock(&ams_info.lock);
+ mutex_unlock(&ams_input_mutex);
- return count;
+ return error ? error : count;
}
static DEVICE_ATTR(joystick, S_IRUGO | S_IWUSR,
ams_input_show_joystick, ams_input_store_joystick);
-/* Call with ams_info.lock held! */
int ams_input_init(void)
{
- int result;
-
- result = device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick);
-
- if (!result && joystick)
+ if (joystick)
ams_input_enable();
- return result;
+
+ return device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick);
}
-/* Call with ams_info.lock held! */
void ams_input_exit(void)
{
- ams_input_disable();
device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick);
+
+ mutex_lock(&ams_input_mutex);
+ ams_input_disable();
+ mutex_unlock(&ams_input_mutex);
}
diff --git a/drivers/hwmon/ams/ams-pmu.c b/drivers/hwmon/ams/ams-pmu.c
index 9463e9768f6f..fb18b3d3162b 100644
--- a/drivers/hwmon/ams/ams-pmu.c
+++ b/drivers/hwmon/ams/ams-pmu.c
@@ -149,8 +149,6 @@ int __init ams_pmu_init(struct device_node *np)
const u32 *prop;
int result;
- mutex_lock(&ams_info.lock);
-
/* Set implementation stuff */
ams_info.of_node = np;
ams_info.exit = ams_pmu_exit;
@@ -161,10 +159,9 @@ int __init ams_pmu_init(struct device_node *np)
/* Get PMU command, should be 0x4e, but we can never know */
prop = of_get_property(ams_info.of_node, "reg", NULL);
- if (!prop) {
- result = -ENODEV;
- goto exit;
- }
+ if (!prop)
+ return -ENODEV;
+
ams_pmu_cmd = ((*prop) >> 8) & 0xff;
/* Disable interrupts */
@@ -175,7 +172,7 @@ int __init ams_pmu_init(struct device_node *np)
result = ams_sensor_attach();
if (result < 0)
- goto exit;
+ return result;
/* Set default values */
ams_pmu_set_register(AMS_FF_LOW_LIMIT, 0x15);
@@ -198,10 +195,5 @@ int __init ams_pmu_init(struct device_node *np)
printk(KERN_INFO "ams: Found PMU based motion sensor\n");
- result = 0;
-
-exit:
- mutex_unlock(&ams_info.lock);
-
- return result;
+ return 0;
}
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h
index a6221e5dd984..5ed387b0bd9a 100644
--- a/drivers/hwmon/ams/ams.h
+++ b/drivers/hwmon/ams/ams.h
@@ -4,7 +4,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <asm/of_device.h>
+#include <linux/of_device.h>
enum ams_irq {
AMS_IRQ_FREEFALL = 0x01,
@@ -46,9 +46,7 @@ struct ams {
#ifdef CONFIG_SENSORS_AMS_I2C
/* I2C properties */
- int i2c_bus;
- int i2c_address;
- struct i2c_client i2c_client;
+ struct i2c_client *i2c_client;
#endif
/* Joystick emulation */