diff options
author | NeilBrown <neilb@suse.de> | 2012-08-04 22:09:47 +1000 |
---|---|---|
committer | Denis 'GNUtoo' Carikli <GNUtoo@no-log.org> | 2013-03-09 14:48:03 +0100 |
commit | a5552cde4b5ffe70159f1cb14fe2fabafbee2e80 (patch) | |
tree | a703898d6e4ecb3859464e51f918d7f6394f8fc0 | |
parent | 2dfba5e40f273bf09c0c06697667d57c579f374b (diff) | |
download | kernel_goldelico_gta04-a5552cde4b5ffe70159f1cb14fe2fabafbee2e80.zip kernel_goldelico_gta04-a5552cde4b5ffe70159f1cb14fe2fabafbee2e80.tar.gz kernel_goldelico_gta04-a5552cde4b5ffe70159f1cb14fe2fabafbee2e80.tar.bz2 |
BMP085: Clean up and enable use of interrupt for completion.
- pass GPIO or IRQ to driver and have it initialise the GPIO and
the IRQ
- finish waiting early if interrupt fires
- clean up GPIO and IRQ on exit.
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/misc/bmp085.c | 63 | ||||
-rw-r--r-- | include/linux/i2c/bmp085.h | 2 |
2 files changed, 58 insertions, 7 deletions
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c index 62e4182..768ee14 100644 --- a/drivers/misc/bmp085.c +++ b/drivers/misc/bmp085.c @@ -49,9 +49,12 @@ #include <linux/device.h> #include <linux/init.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/of.h> #include "bmp085.h" +#include <linux/interrupt.h> +#include <linux/completion.h> +#include <linux/gpio.h> +#include <linux/i2c/bmp085.h> #define BMP085_CHIP_ID 0x55 #define BMP085_CALIBRATION_DATA_START 0xAA @@ -84,8 +87,18 @@ struct bmp085_data { unsigned long last_temp_measurement; u8 chip_id; s32 b6; /* calculated temperature correction coefficient */ + int irq; + int gpio; + struct completion done; }; +static irqreturn_t bmp085_eoc_isr(int irq, void *devid) +{ + struct bmp085_data *data = devid; + complete(&data->done); + return IRQ_HANDLED; +} + static s32 bmp085_read_calibration_data(struct bmp085_data *data) { u16 tmp[BMP085_CALIBRATION_DATA_LENGTH]; @@ -116,6 +129,7 @@ static s32 bmp085_update_raw_temperature(struct bmp085_data *data) s32 status; mutex_lock(&data->lock); + init_completion(&data->done); status = regmap_write(data->regmap, BMP085_CTRL_REG, BMP085_TEMP_MEASUREMENT); if (status < 0) { @@ -123,7 +137,8 @@ static s32 bmp085_update_raw_temperature(struct bmp085_data *data) "Error while requesting temperature measurement.\n"); goto exit; } - msleep(BMP085_TEMP_CONVERSION_TIME); + wait_for_completion_timeout(&data->done, msecs_to_jiffies( + BMP085_TEMP_CONVERSION_TIME)); status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB, &tmp, sizeof(tmp)); @@ -147,6 +162,7 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data) s32 status; mutex_lock(&data->lock); + init_completion(&data->done); status = regmap_write(data->regmap, BMP085_CTRL_REG, BMP085_PRESSURE_MEASUREMENT + (data->oversampling_setting << 6)); @@ -157,8 +173,8 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data) } /* wait for the end of conversion */ - msleep(2+(3 << data->oversampling_setting)); - + wait_for_completion_timeout(&data->done, msecs_to_jiffies( + 2+(3 << data->oversampling_setting))); /* copy data into a u32 (4 bytes), but skip the first byte. */ status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB, ((u8 *)&tmp)+1, 3); @@ -423,6 +439,7 @@ EXPORT_SYMBOL_GPL(bmp085_regmap_config); __devinit int bmp085_probe(struct device *dev, struct regmap *regmap) { struct bmp085_data *data; + struct bmp085_platform_data *pdata = dev->platform_data; int err = 0; data = kzalloc(sizeof(struct bmp085_data), GFP_KERNEL); @@ -435,26 +452,55 @@ __devinit int bmp085_probe(struct device *dev, struct regmap *regmap) data->dev = dev; data->regmap = regmap; + init_completion(&data->done); + + if (pdata && gpio_is_valid(pdata->gpio)) { + err = devm_gpio_request(dev, pdata->gpio, "bmp085_eoc_irq"); + if (err) + goto exit_free; + err = gpio_direction_input(pdata->gpio); + if (err) + goto exit_free; + data->irq = gpio_to_irq(pdata->gpio); + data->gpio = pdata->gpio; + } else { + if (pdata) + data->irq = pdata->irq; + else + data->irq = 0; + data->gpio = -EINVAL; + } + if (data->irq > 0) { + err = request_any_context_irq(data->irq, bmp085_eoc_isr, + IRQF_TRIGGER_RISING, "bmp085", data); + if (err < 0) + goto exit_free; + } else + data->irq = 0; + /* Initialize the BMP085 chip */ err = bmp085_init_client(data); if (err < 0) - goto exit_free; + goto exit_free_irq; err = bmp085_detect(dev); if (err < 0) { dev_err(dev, "%s: chip_id failed!\n", BMP085_NAME); - goto exit_free; + goto exit_free_irq; } /* Register sysfs hooks */ err = sysfs_create_group(&dev->kobj, &bmp085_attr_group); if (err) - goto exit_free; + goto exit_free_irq; dev_info(dev, "Successfully initialized %s!\n", BMP085_NAME); return 0; +exit_free_irq: + if (data->irq) + free_irq(data->irq, data); exit_free: kfree(data); exit: @@ -466,6 +512,9 @@ int bmp085_remove(struct device *dev) { struct bmp085_data *data = dev_get_drvdata(dev); + if (data->irq) + free_irq(data->irq, data); + sysfs_remove_group(&data->dev->kobj, &bmp085_attr_group); kfree(data); diff --git a/include/linux/i2c/bmp085.h b/include/linux/i2c/bmp085.h index 6995599..629b735 100644 --- a/include/linux/i2c/bmp085.h +++ b/include/linux/i2c/bmp085.h @@ -5,6 +5,8 @@ struct bmp085_platform_data { int irq; + int gpio; + struct completion done; int (*init_platform_hw)(void); void (*exit_platform_hw)(void); |