Commit 71c62902 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-v3.7e' of...

Merge tag 'iio-for-v3.7e' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Fifth round of new drivers and device support for the IIO
subsystem in the 3.7 cycle.

Here we have a mixed bag of new stuff, minor fixes and
more major fixes for drivers added earlier in this cycle.

1) A number of fixes for the HID sensors code added in previous
pull request.  Typical stuff that has become apparent as more eyes
have looked at the code post merging. Similar case for the ad5755 dac.

2) Cleanups of error handing in inkern.c - again typical stuff to see
as code comes into heavier use and people notice the naughty short
cuts that snuck in originally and kindly fix them.

3) A series from Lars that removes some incorrect error handling
from the remove functions of a number of drivers.  These have been
there for a very long time hence I'm not pushing these out for the
3.6 cycle.

4) Support for more parts in the ad7780 driver.

5) A driver for the adcs on the lp8788 power management unit

6) A client driver for IIO to allow it's ADCs to be used for
battery status measurement.  Note this driver has some dependencies
on some utility functions added to IIO in this series, hence it is
coming via this tree rather than Anton's.

7) A null pointer dereference bug in the 'fake' driver. I'm not
doing this as a fix for the 3.6 cycle because it only effects
'fake' hardware and that code is typically only used by people
investigating how IIO works as part of writing new drivers. Hence
it's hardly a critical fix.
parents 9970eeae 3fff2274
......@@ -173,7 +173,7 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
spin_unlock(&pdata->dyn_callback_lock);
return -EINVAL;
}
callback = kzalloc(sizeof(*callback), GFP_KERNEL);
callback = kzalloc(sizeof(*callback), GFP_ATOMIC);
if (!callback) {
spin_unlock(&pdata->dyn_callback_lock);
return -ENOMEM;
......@@ -214,9 +214,6 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
int ret = 0;
if (report_id < 0)
return -EINVAL;
mutex_lock(&data->mutex);
report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
if (!report || (field_index >= report->maxfield)) {
......@@ -241,9 +238,6 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
int ret = 0;
if (report_id < 0)
return -EINVAL;
mutex_lock(&data->mutex);
report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
if (!report || (field_index >= report->maxfield)) {
......@@ -271,9 +265,6 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
struct hid_report *report;
int ret_val = 0;
if (report_id < 0)
return -EINVAL;
mutex_lock(&data->mutex);
memset(&data->pending, 0, sizeof(data->pending));
init_completion(&data->pending.ready);
......@@ -462,7 +453,7 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
if (pdata->pending.status && pdata->pending.attr_usage_id ==
report->field[i]->usage->hid) {
hid_dbg(hdev, "data was pending ...\n");
pdata->pending.raw_data = kmalloc(sz, GFP_KERNEL);
pdata->pending.raw_data = kmalloc(sz, GFP_ATOMIC);
if (pdata->pending.raw_data) {
memcpy(pdata->pending.raw_data, ptr, sz);
pdata->pending.raw_size = sz;
......@@ -539,7 +530,6 @@ static int sensor_hub_probe(struct hid_device *hdev,
}
INIT_LIST_HEAD(&hdev->inputs);
hdev->claimed = HID_CLAIMED_INPUT;
ret = hid_hw_start(hdev, 0);
if (ret) {
hid_err(hdev, "hw start failed\n");
......@@ -565,8 +555,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
sizeof(struct mfd_cell),
GFP_KERNEL);
if (sd->hid_sensor_hub_client_devs == NULL) {
hid_err(hdev,
"Failed to allocate memory for mfd cells\n");
hid_err(hdev, "Failed to allocate memory for mfd cells\n");
ret = -ENOMEM;
goto err_close;
}
......@@ -578,10 +567,9 @@ static int sensor_hub_probe(struct hid_device *hdev,
name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x",
field->physical);
if (name == NULL) {
hid_err(hdev,
"Failed MFD device name\n");
hid_err(hdev, "Failed MFD device name\n");
ret = -ENOMEM;
goto err_free_cells;
goto err_free_names;
}
sd->hid_sensor_hub_client_devs[
sd->hid_sensor_client_cnt].name = name;
......@@ -596,7 +584,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
}
}
ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
sd->hid_sensor_client_cnt, NULL, 0);
sd->hid_sensor_client_cnt, NULL, 0, NULL);
if (ret < 0)
goto err_free_names;
......@@ -605,10 +593,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
err_free_names:
for (i = 0; i < sd->hid_sensor_client_cnt ; ++i)
kfree(sd->hid_sensor_hub_client_devs[i].name);
err_free_cells:
kfree(sd->hid_sensor_hub_client_devs);
err_close:
hid_hw_stop(hdev);
hid_hw_close(hdev);
err_stop_hw:
hid_hw_stop(hdev);
......@@ -627,9 +613,8 @@ static void sensor_hub_remove(struct hid_device *hdev)
int i;
hid_dbg(hdev, " hardware removed\n");
hdev->claimed &= ~HID_CLAIMED_INPUT;
hid_hw_stop(hdev);
hid_hw_close(hdev);
hid_hw_stop(hdev);
spin_lock_irqsave(&data->lock, flags);
if (data->pending.status)
complete(&data->pending.ready);
......
......@@ -54,4 +54,10 @@ config AT91_ADC
help
Say yes here to build support for Atmel AT91 ADC.
config LP8788_ADC
bool "LP8788 ADC driver"
depends on MFD_LP8788
help
Say yes here to build support for TI LP8788 ADC.
endmenu
......@@ -7,3 +7,4 @@ obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
/*
* TI LP8788 MFD - ADC driver
*
* Copyright 2012 Texas Instruments
*
* Author: Milo(Woogyom) Kim <milo.kim@ti.com>
*
* 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.
*/
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/iio/machine.h>
#include <linux/mfd/lp8788.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
/* register address */
#define LP8788_ADC_CONF 0x60
#define LP8788_ADC_RAW 0x61
#define LP8788_ADC_DONE 0x63
#define ADC_CONV_START 1
struct lp8788_adc {
struct lp8788 *lp;
struct iio_map *map;
struct mutex lock;
};
static const int lp8788_scale[LPADC_MAX] = {
[LPADC_VBATT_5P5] = 1343101,
[LPADC_VIN_CHG] = 3052503,
[LPADC_IBATT] = 610500,
[LPADC_IC_TEMP] = 61050,
[LPADC_VBATT_6P0] = 1465201,
[LPADC_VBATT_5P0] = 1221001,
[LPADC_ADC1] = 610500,
[LPADC_ADC2] = 610500,
[LPADC_VDD] = 1025641,
[LPADC_VCOIN] = 757020,
[LPADC_ADC3] = 610500,
[LPADC_ADC4] = 610500,
};
static int lp8788_get_adc_result(struct lp8788_adc *adc, enum lp8788_adc_id id,
int *val)
{
unsigned int msb;
unsigned int lsb;
unsigned int result;
u8 data;
u8 rawdata[2];
int size = ARRAY_SIZE(rawdata);
int retry = 5;
int ret;
data = (id << 1) | ADC_CONV_START;
ret = lp8788_write_byte(adc->lp, LP8788_ADC_CONF, data);
if (ret)
goto err_io;
/* retry until adc conversion is done */
data = 0;
while (retry--) {
usleep_range(100, 200);
ret = lp8788_read_byte(adc->lp, LP8788_ADC_DONE, &data);
if (ret)
goto err_io;
/* conversion done */
if (data)
break;
}
ret = lp8788_read_multi_bytes(adc->lp, LP8788_ADC_RAW, rawdata, size);
if (ret)
goto err_io;
msb = (rawdata[0] << 4) & 0x00000ff0;
lsb = (rawdata[1] >> 4) & 0x0000000f;
result = msb | lsb;
*val = result;
return 0;
err_io:
return ret;
}
static int lp8788_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct lp8788_adc *adc = iio_priv(indio_dev);
enum lp8788_adc_id id = chan->channel;
int ret;
mutex_lock(&adc->lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = lp8788_get_adc_result(adc, id, val) ? -EIO : IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
*val = lp8788_scale[id] / 1000000;
*val2 = lp8788_scale[id] % 1000000;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
ret = -EINVAL;
break;
}
mutex_unlock(&adc->lock);
return ret;
}
static const struct iio_info lp8788_adc_info = {
.read_raw = &lp8788_adc_read_raw,
.driver_module = THIS_MODULE,
};
#define LP8788_CHAN(_id, _type) { \
.type = _type, \
.indexed = 1, \
.channel = LPADC_##_id, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.datasheet_name = #_id, \
}
static const struct iio_chan_spec lp8788_adc_channels[] = {
[LPADC_VBATT_5P5] = LP8788_CHAN(VBATT_5P5, IIO_VOLTAGE),
[LPADC_VIN_CHG] = LP8788_CHAN(VIN_CHG, IIO_VOLTAGE),
[LPADC_IBATT] = LP8788_CHAN(IBATT, IIO_CURRENT),
[LPADC_IC_TEMP] = LP8788_CHAN(IC_TEMP, IIO_TEMP),
[LPADC_VBATT_6P0] = LP8788_CHAN(VBATT_6P0, IIO_VOLTAGE),
[LPADC_VBATT_5P0] = LP8788_CHAN(VBATT_5P0, IIO_VOLTAGE),
[LPADC_ADC1] = LP8788_CHAN(ADC1, IIO_VOLTAGE),
[LPADC_ADC2] = LP8788_CHAN(ADC2, IIO_VOLTAGE),
[LPADC_VDD] = LP8788_CHAN(VDD, IIO_VOLTAGE),
[LPADC_VCOIN] = LP8788_CHAN(VCOIN, IIO_VOLTAGE),
[LPADC_ADC3] = LP8788_CHAN(ADC3, IIO_VOLTAGE),
[LPADC_ADC4] = LP8788_CHAN(ADC4, IIO_VOLTAGE),
};
/* default maps used by iio consumer (lp8788-charger driver) */
static struct iio_map lp8788_default_iio_maps[] = {
{
.consumer_dev_name = "lp8788-charger",
.consumer_channel = "lp8788_vbatt_5p0",
.adc_channel_label = "VBATT_5P0",
},
{
.consumer_dev_name = "lp8788-charger",
.consumer_channel = "lp8788_adc1",
.adc_channel_label = "ADC1",
},
{ }
};
static int lp8788_iio_map_register(struct iio_dev *indio_dev,
struct lp8788_platform_data *pdata,
struct lp8788_adc *adc)
{
struct iio_map *map;
int ret;
map = (!pdata || !pdata->adc_pdata) ?
lp8788_default_iio_maps : pdata->adc_pdata;
ret = iio_map_array_register(indio_dev, map);
if (ret) {
dev_err(adc->lp->dev, "iio map err: %d\n", ret);
return ret;
}
adc->map = map;
return 0;
}
static inline void lp8788_iio_map_unregister(struct iio_dev *indio_dev,
struct lp8788_adc *adc)
{
iio_map_array_unregister(indio_dev, adc->map);
}
static int __devinit lp8788_adc_probe(struct platform_device *pdev)
{
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
struct iio_dev *indio_dev;
struct lp8788_adc *adc;
int ret;
indio_dev = iio_device_alloc(sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->lp = lp;
platform_set_drvdata(pdev, indio_dev);
ret = lp8788_iio_map_register(indio_dev, lp->pdata, adc);
if (ret)
goto err_iio_map;
mutex_init(&adc->lock);
indio_dev->dev.parent = lp->dev;
indio_dev->name = pdev->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &lp8788_adc_info;
indio_dev->channels = lp8788_adc_channels;
indio_dev->num_channels = ARRAY_SIZE(lp8788_adc_channels);
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(lp->dev, "iio dev register err: %d\n", ret);
goto err_iio_device;
}
return 0;
err_iio_device:
lp8788_iio_map_unregister(indio_dev, adc);
err_iio_map:
iio_device_free(indio_dev);
return ret;
}
static int __devexit lp8788_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct lp8788_adc *adc = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
lp8788_iio_map_unregister(indio_dev, adc);
iio_device_free(indio_dev);
return 0;
}
static struct platform_driver lp8788_adc_driver = {
.probe = lp8788_adc_probe,
.remove = __devexit_p(lp8788_adc_remove),
.driver = {
.name = LP8788_DEV_ADC,
.owner = THIS_MODULE,
},
};
module_platform_driver(lp8788_adc_driver);
MODULE_DESCRIPTION("Texas Instruments LP8788 ADC Driver");
MODULE_AUTHOR("Milo Kim");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:lp8788-adc");
......@@ -56,6 +56,7 @@ void hid_sensor_remove_trigger(struct iio_dev *indio_dev)
{
iio_trigger_unregister(indio_dev->trig);
iio_trigger_free(indio_dev->trig);
indio_dev->trig = NULL;
}
EXPORT_SYMBOL(hid_sensor_remove_trigger);
......
......@@ -451,9 +451,9 @@ static int __devinit ad5755_setup_pdata(struct iio_dev *indio_dev,
const struct ad5755_platform_data *pdata)
{
struct ad5755_state *st = iio_priv(indio_dev);
unsigned int ret;
unsigned int val;
unsigned int i;
int ret;
if (pdata->dc_dc_phase > AD5755_DC_DC_PHASE_90_DEGREE ||
pdata->dc_dc_freq > AD5755_DC_DC_FREQ_650kHZ ||
......
......@@ -111,6 +111,7 @@ struct iio_channel *iio_channel_get(const char *name, const char *channel_name)
{
struct iio_map_internal *c_i = NULL, *c = NULL;
struct iio_channel *channel;
int err;
if (name == NULL && channel_name == NULL)
return ERR_PTR(-ENODEV);
......@@ -131,8 +132,10 @@ struct iio_channel *iio_channel_get(const char *name, const char *channel_name)
return ERR_PTR(-ENODEV);
channel = kzalloc(sizeof(*channel), GFP_KERNEL);
if (channel == NULL)
return ERR_PTR(-ENOMEM);
if (channel == NULL) {
err = -ENOMEM;
goto error_no_mem;
}
channel->indio_dev = c->indio_dev;
......@@ -141,16 +144,19 @@ struct iio_channel *iio_channel_get(const char *name, const char *channel_name)
iio_chan_spec_from_name(channel->indio_dev,
c->map->adc_channel_label);
if (channel->channel == NULL)
if (channel->channel == NULL) {
err = -EINVAL;
goto error_no_chan;
}
}
return channel;
error_no_chan:
iio_device_put(c->indio_dev);
kfree(channel);
return ERR_PTR(-EINVAL);
error_no_mem:
iio_device_put(c->indio_dev);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(iio_channel_get);
......
......@@ -29,6 +29,13 @@ config APM_POWER
Say Y here to enable support APM status emulation using
battery class devices.
config GENERIC_ADC_BATTERY
tristate "Generic battery support using IIO"
depends on IIO
help
Say Y here to enable support for the generic battery driver
which uses IIO framework to read adc.
config MAX8925_POWER
tristate "MAX8925 battery charger support"
depends on MFD_MAX8925
......
......@@ -5,6 +5,7 @@ power_supply-$(CONFIG_SYSFS) += power_supply_sysfs.o
power_supply-$(CONFIG_LEDS_TRIGGERS) += power_supply_leds.o
obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o
obj-$(CONFIG_PDA_POWER) += pda_power.o
obj-$(CONFIG_APM_POWER) += apm_power.o
......
/*
* Generic battery driver code using IIO
* Copyright (C) 2012, Anish Kumar <anish198519851985@gmail.com>
* based on jz4740-battery.c
* based on s3c_adc_battery.c
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
*/
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/gpio.h>
#include <linux/err.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/iio/consumer.h>
#include <linux/iio/types.h>
#include <linux/power/generic-adc-battery.h>
#define JITTER_DEFAULT 10 /* hope 10ms is enough */
enum gab_chan_type {
GAB_VOLTAGE = 0,
GAB_CURRENT,
GAB_POWER,
GAB_MAX_CHAN_TYPE
};
/*
* gab_chan_name suggests the standard channel names for commonly used
* channel types.
*/
static const char *const gab_chan_name[] = {
[GAB_VOLTAGE] = "voltage",
[GAB_CURRENT] = "current",
[GAB_POWER] = "power",
};
struct gab {
struct power_supply psy;
struct iio_channel *channel[GAB_MAX_CHAN_TYPE];
struct gab_platform_data *pdata;
struct delayed_work bat_work;
int level;
int status;
bool cable_plugged;
};
static struct gab *to_generic_bat(struct power_supply *psy)
{
return container_of(psy, struct gab, psy);
}
static void gab_ext_power_changed(struct power_supply *psy)
{
struct gab *adc_bat = to_generic_bat(psy);
schedule_delayed_work(&adc_bat->bat_work, msecs_to_jiffies(0));
}
static const enum power_supply_property gab_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
POWER_SUPPLY_PROP_CHARGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_MODEL_NAME,
};
/*
* This properties are set based on the received platform data and this
* should correspond one-to-one with enum chan_type.
*/
static const enum power_supply_property gab_dyn_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_POWER_NOW,
};
static bool gab_charge_finished(struct gab *adc_bat)
{
struct gab_platform_data *pdata = adc_bat->pdata;
bool ret = gpio_get_value(pdata->gpio_charge_finished);
bool inv = pdata->gpio_inverted;
if (!gpio_is_valid(pdata->gpio_charge_finished))
return false;
return ret ^ inv;
}
static int gab_get_status(struct gab *adc_bat)
{
struct gab_platform_data *pdata = adc_bat->pdata;
struct power_supply_info *bat_info;
bat_info = &pdata->battery_info;
if (adc_bat->level == bat_info->charge_full_design)
return POWER_SUPPLY_STATUS_FULL;
return adc_bat->status;
}
static enum gab_chan_type gab_prop_to_chan(enum power_supply_property psp)
{
switch (psp) {
case POWER_SUPPLY_PROP_POWER_NOW:
return GAB_POWER;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
return GAB_VOLTAGE;
case POWER_SUPPLY_PROP_CURRENT_NOW:
return GAB_CURRENT;
default:
WARN_ON(1);
break;
}
return GAB_POWER;
}
static int read_channel(struct gab *adc_bat, enum power_supply_property psp,
int *result)
{
int ret;
int chan_index;
chan_index = gab_prop_to_chan(psp);
ret = iio_read_channel_processed(adc_bat->channel[chan_index],
result);
if (ret < 0)
pr_err("read channel error\n");
return ret;
}
static int gab_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
struct gab *adc_bat;
struct gab_platform_data *pdata;
struct power_supply_info *bat_info;
int result = 0;
int ret = 0;
adc_bat = to_generic_bat(psy);
if (!adc_bat) {
dev_err(psy->dev, "no battery infos ?!\n");
return -EINVAL;
}
pdata = adc_bat->pdata;
bat_info = &pdata->battery_info;
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
gab_get_status(adc_bat);
break;
case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
val->intval = pdata->cal_charge(result);
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
case POWER_SUPPLY_PROP_CURRENT_NOW:
case POWER_SUPPLY_PROP_POWER_NOW:
ret = read_channel(adc_bat, psp, &result);
if (ret < 0)
goto err;
val->intval = result;
break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = bat_info->technology;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
val->intval = bat_info->voltage_min_design;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
val->intval = bat_info->voltage_max_design;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
val->intval = bat_info->charge_full_design;
break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = bat_info->name;
break;
default:
return -EINVAL;
}
err:
return ret;
}
static void gab_work(struct work_struct *work)
{
struct gab *adc_bat;
struct gab_platform_data *pdata;
struct delayed_work *delayed_work;
bool is_plugged;
int status;
delayed_work = container_of(work, struct delayed_work, work);
adc_bat = container_of(delayed_work, struct gab, bat_work);
pdata = adc_bat->pdata;
status = adc_bat->status;
is_plugged = power_supply_am_i_supplied(&adc_bat->psy);
adc_bat->cable_plugged = is_plugged;
if (!is_plugged)
adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
else if (gab_charge_finished(adc_bat))
adc_bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
else
adc_bat->status = POWER_SUPPLY_STATUS_CHARGING;
if (status != adc_bat->status)
power_supply_changed(&adc_bat->psy);
}
static irqreturn_t gab_charged(int irq, void *dev_id)
{
struct gab *adc_bat = dev_id;
struct gab_platform_data *pdata = adc_bat->pdata;
int delay;
delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT;
schedule_delayed_work(&adc_bat->bat_work,
msecs_to_jiffies(delay));
return IRQ_HANDLED;
}
static int __devinit gab_probe(struct platform_device *pdev)
{
struct gab *adc_bat;
struct power_supply *psy;
struct gab_platform_data *pdata = pdev->dev.platform_data;
enum power_supply_property *properties;
int ret = 0;
int chan;
int index = 0;
adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL);
if (!adc_bat) {
dev_err(&pdev->dev, "failed to allocate memory\n");
return -ENOMEM;
}
psy = &adc_bat->psy;
psy->name = pdata->battery_info.name;
/* bootup default values for the battery */
adc_bat->cable_plugged = false;
adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
psy->type = POWER_SUPPLY_TYPE_BATTERY;
psy->get_property = gab_get_property;
psy->external_power_changed = gab_ext_power_changed;
adc_bat->pdata = pdata;
/* calculate the total number of channels */
chan = ARRAY_SIZE(gab_chan_name);
/*
* copying the static properties and allocating extra memory for holding
* the extra configurable properties received from platform data.
*/
psy->properties = kcalloc(ARRAY_SIZE(gab_props) +
ARRAY_SIZE(gab_chan_name),
sizeof(*psy->properties), GFP_KERNEL);
if (!psy->properties) {
ret = -ENOMEM;
goto first_mem_fail;
}
memcpy(psy->properties, gab_props, sizeof(gab_props));
properties = psy->properties + sizeof(gab_props);
/*
* getting channel from iio and copying the battery properties
* based on the channel supported by consumer device.
*/
for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
adc_bat->channel[chan] = iio_channel_get(dev_name(&pdev->dev),
gab_chan_name[chan]);
if (IS_ERR(adc_bat->channel[chan])) {
ret = PTR_ERR(adc_bat->channel[chan]);
} else {
/* copying properties for supported channels only */
memcpy(properties + sizeof(*(psy->properties)) * index,
&gab_dyn_props[chan],
sizeof(gab_dyn_props[chan]));
index++;
}
}
/* none of the channels are supported so let's bail out */
if (index == ARRAY_SIZE(gab_chan_name))
goto second_mem_fail;
/*
* Total number of properties is equal to static properties
* plus the dynamic properties.Some properties may not be set
* as come channels may be not be supported by the device.So
* we need to take care of that.
*/
psy->num_properties = ARRAY_SIZE(gab_props) + index;
ret = power_supply_register(&pdev->dev, psy);
if (ret)
goto err_reg_fail;
INIT_DELAYED_WORK(&adc_bat->bat_work, gab_work);
if (gpio_is_valid(pdata->gpio_charge_finished)) {
int irq;
ret = gpio_request(pdata->gpio_charge_finished, "charged");
if (ret)
goto gpio_req_fail;
irq = gpio_to_irq(pdata->gpio_charge_finished);
ret = request_any_context_irq(irq, gab_charged,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"battery charged", adc_bat);
if (ret)
goto err_gpio;
}
platform_set_drvdata(pdev, adc_bat);
/* Schedule timer to check current status */
schedule_delayed_work(&adc_bat->bat_work,
msecs_to_jiffies(0));
return 0;
err_gpio:
gpio_free(pdata->gpio_charge_finished);
gpio_req_fail:
power_supply_unregister(psy);
err_reg_fail:
for (chan = 0; ARRAY_SIZE(gab_chan_name); chan++)
iio_channel_release(adc_bat->channel[chan]);
second_mem_fail:
kfree(psy->properties);
first_mem_fail:
return ret;
}
static int __devexit gab_remove(struct platform_device *pdev)
{
int chan;
struct gab *adc_bat = platform_get_drvdata(pdev);
struct gab_platform_data *pdata = adc_bat->pdata;
power_supply_unregister(&adc_bat->psy);
if (gpio_is_valid(pdata->gpio_charge_finished)) {
free_irq(gpio_to_irq(pdata->gpio_charge_finished), adc_bat);
gpio_free(pdata->gpio_charge_finished);
}
for (chan = 0; ARRAY_SIZE(gab_chan_name); chan++)
iio_channel_release(adc_bat->channel[chan]);
kfree(adc_bat->psy.properties);
cancel_delayed_work(&adc_bat->bat_work);
return 0;
}
#ifdef CONFIG_PM
static int gab_suspend(struct device *dev)
{
struct gab *adc_bat = dev_get_drvdata(dev);
cancel_delayed_work_sync(&adc_bat->bat_work);
adc_bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
return 0;
}
static int gab_resume(struct device *dev)
{
struct gab *adc_bat = dev_get_drvdata(dev);
struct gab_platform_data *pdata = adc_bat->pdata;
int delay;
delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT;
/* Schedule timer to check current status */
schedule_delayed_work(&adc_bat->bat_work,
msecs_to_jiffies(delay));
return 0;
}
static const struct dev_pm_ops gab_pm_ops = {
.suspend = gab_suspend,
.resume = gab_resume,
};
#define GAB_PM_OPS (&gab_pm_ops)
#else
#define GAB_PM_OPS (NULL)
#endif
static struct platform_driver gab_driver = {
.driver = {
.name = "generic-adc-battery",
.owner = THIS_MODULE,
.pm = GAB_PM_OPS
},
.probe = gab_probe,
.remove = __devexit_p(gab_remove),
};
module_platform_driver(gab_driver);
MODULE_AUTHOR("anish kumar <anish198519851985@gmail.com>");
MODULE_DESCRIPTION("generic battery driver using IIO");
MODULE_LICENSE("GPL");
......@@ -782,19 +782,13 @@ static int lis3l02dq_stop_device(struct iio_dev *indio_dev)
/* fixme, confirm ordering in this function */
static int __devexit lis3l02dq_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct lis3l02dq_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
ret = lis3l02dq_disable_all_events(indio_dev);
if (ret)
goto err_ret;
ret = lis3l02dq_stop_device(indio_dev);
if (ret)
goto err_ret;
lis3l02dq_disable_all_events(indio_dev);
lis3l02dq_stop_device(indio_dev);
if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
free_irq(st->us->irq, indio_dev);
......@@ -804,8 +798,8 @@ static int __devexit lis3l02dq_remove(struct spi_device *spi)
lis3l02dq_unconfigure_buffer(indio_dev);
iio_device_free(indio_dev);
err_ret:
return ret;
return 0;
}
static struct spi_driver lis3l02dq_driver = {
......
......@@ -1237,11 +1237,9 @@ static int __devexit sca3000_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
/* Must ensure no interrupts can be generated after this!*/
ret = sca3000_stop_all_interrupts(st);
if (ret)
return ret;
sca3000_stop_all_interrupts(st);
if (spi->irq)
free_irq(spi->irq, indio_dev);
iio_device_unregister(indio_dev);
......
......@@ -82,12 +82,12 @@ config AD7887
module will be called ad7887.
config AD7780
tristate "Analog Devices AD7780 AD7781 ADC driver"
tristate "Analog Devices AD7780 and similar ADCs driver"
depends on SPI
depends on GPIOLIB
select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices
Say yes here to build support for Analog Devices AD7170, AD7171,
AD7780 and AD7781 SPI analog to digital converters (ADC).
If unsure, say N (but it's safe to say "Y").
......
/*
* AD7780/AD7781 SPI ADC driver
* AD7170/AD7171 and AD7780/AD7781 SPI ADC driver
*
* Copyright 2011 Analog Devices Inc.
*
......@@ -34,7 +34,9 @@
#define AD7780_PAT0 (1 << 0)
struct ad7780_chip_info {
struct iio_chan_spec channel;
struct iio_chan_spec channel;
unsigned int pattern_mask;
unsigned int pattern;
};
struct ad7780_state {
......@@ -48,6 +50,8 @@ struct ad7780_state {
};
enum ad7780_supported_device_ids {
ID_AD7170,
ID_AD7171,
ID_AD7780,
ID_AD7781,
};
......@@ -73,7 +77,8 @@ static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
break;
}
gpio_set_value(st->powerdown_gpio, val);
if (gpio_is_valid(st->powerdown_gpio))
gpio_set_value(st->powerdown_gpio, val);
return 0;
}
......@@ -108,9 +113,10 @@ static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
unsigned int raw_sample)
{
struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
const struct ad7780_chip_info *chip_info = st->chip_info;
if ((raw_sample & AD7780_ERR) ||
!((raw_sample & AD7780_PAT0) && !(raw_sample & AD7780_PAT1)))
((raw_sample & chip_info->pattern_mask) != chip_info->pattern))
return -EIO;
if (raw_sample & AD7780_GAIN)
......@@ -127,12 +133,29 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
.has_registers = false,
};
#define AD7780_CHANNEL(bits, wordsize) \
AD_SD_CHANNEL(1, 0, 0, bits, 32, wordsize - bits)
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7170] = {
.channel = AD7780_CHANNEL(12, 24),
.pattern = 0x5,
.pattern_mask = 0x7,
},
[ID_AD7171] = {
.channel = AD7780_CHANNEL(16, 24),
.pattern = 0x5,
.pattern_mask = 0x7,
},
[ID_AD7780] = {
.channel = AD_SD_CHANNEL(1, 0, 0, 24, 32, 8),
.channel = AD7780_CHANNEL(24, 32),
.pattern = 0x1,
.pattern_mask = 0x3,
},
[ID_AD7781] = {
.channel = AD_SD_CHANNEL(1, 0, 0, 20, 32, 12),
.channel = AD7780_CHANNEL(20, 32),
.pattern = 0x1,
.pattern_mask = 0x3,
},
};
......@@ -148,11 +171,6 @@ static int __devinit ad7780_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
int ret, voltage_uv = 0;
if (!pdata) {
dev_dbg(&spi->dev, "no platform data?\n");
return -ENODEV;
}
indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
......@@ -174,8 +192,6 @@ static int __devinit ad7780_probe(struct spi_device *spi)
st->chip_info =
&ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
st->powerdown_gpio = pdata->gpio_pdrst;
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
else if (voltage_uv)
......@@ -192,11 +208,17 @@ static int __devinit ad7780_probe(struct spi_device *spi)
indio_dev->num_channels = 1;
indio_dev->info = &ad7780_info;
ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
if (pdata && gpio_is_valid(pdata->gpio_pdrst)) {
ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
"AD7780 /PDRST");
if (ret) {
dev_err(&spi->dev, "failed to request GPIO PDRST\n");
goto error_disable_reg;
if (ret) {
dev_err(&spi->dev, "failed to request GPIO PDRST\n");
goto error_disable_reg;
}
st->powerdown_gpio = pdata->gpio_pdrst;
} else {
st->powerdown_gpio = -1;
}
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
......@@ -212,7 +234,8 @@ static int __devinit ad7780_probe(struct spi_device *spi)
error_cleanup_buffer_and_trigger:
ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_free_gpio:
gpio_free(pdata->gpio_pdrst);
if (pdata && gpio_is_valid(pdata->gpio_pdrst))
gpio_free(pdata->gpio_pdrst);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
......@@ -233,7 +256,9 @@ static int __devexit ad7780_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
gpio_free(st->powerdown_gpio);
if (gpio_is_valid(st->powerdown_gpio))
gpio_free(st->powerdown_gpio);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
......@@ -244,6 +269,8 @@ static int __devexit ad7780_remove(struct spi_device *spi)
}
static const struct spi_device_id ad7780_id[] = {
{"ad7170", ID_AD7170},
{"ad7171", ID_AD7171},
{"ad7780", ID_AD7780},
{"ad7781", ID_AD7781},
{}
......@@ -262,5 +289,5 @@ static struct spi_driver ad7780_driver = {
module_spi_driver(ad7780_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD7780/1 ADC");
MODULE_DESCRIPTION("Analog Devices AD7780 and similar ADCs");
MODULE_LICENSE("GPL v2");
......@@ -702,22 +702,16 @@ static int __devinit adis16260_probe(struct spi_device *spi)
static int __devexit adis16260_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);
iio_device_unregister(indio_dev);
ret = adis16260_stop_device(indio_dev);
if (ret)
goto err_ret;
adis16260_stop_device(indio_dev);
adis16260_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16260_unconfigure_ring(indio_dev);
iio_device_free(indio_dev);
err_ret:
return ret;
return 0;
}
/*
......
......@@ -445,26 +445,20 @@ static int __devinit iio_dummy_probe(int index)
if (ret < 0)
goto error_free_device;
/* Configure buffered capture support. */
ret = iio_simple_dummy_configure_buffer(indio_dev);
if (ret < 0)
goto error_unregister_events;
/*
* Register the channels with the buffer, but avoid the output
* channel being registered by reducing the number of channels by 1.
* Configure buffered capture support and register the channels with the
* buffer, but avoid the output channel being registered by reducing the
* number of channels by 1.
*/
ret = iio_buffer_register(indio_dev, iio_dummy_channels, 5);
ret = iio_simple_dummy_configure_buffer(indio_dev, iio_dummy_channels, 5);
if (ret < 0)
goto error_unconfigure_buffer;
goto error_unregister_events;
ret = iio_device_register(indio_dev);
if (ret < 0)
goto error_unregister_buffer;
goto error_unconfigure_buffer;
return 0;
error_unregister_buffer:
iio_buffer_unregister(indio_dev);
error_unconfigure_buffer:
iio_simple_dummy_unconfigure_buffer(indio_dev);
error_unregister_events:
......@@ -499,7 +493,6 @@ static int iio_dummy_remove(int index)
/* Device specific code to power down etc */
/* Buffered capture related cleanup */
iio_buffer_unregister(indio_dev);
iio_simple_dummy_unconfigure_buffer(indio_dev);
ret = iio_simple_dummy_events_unregister(indio_dev);
......@@ -530,6 +523,7 @@ static __init int iio_dummy_init(void)
instances = 1;
return -EINVAL;
}
/* Fake a bus */
iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs),
GFP_KERNEL);
......
......@@ -95,10 +95,12 @@ enum iio_simple_dummy_scan_elements {
};
#ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER
int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev);
int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev,
const struct iio_chan_spec *channels, unsigned int num_channels);
void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev);
#else
static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev,
const struct iio_chan_spec *channels, unsigned int num_channels)
{
return 0;
};
......
......@@ -126,7 +126,8 @@ static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = {
.predisable = &iio_triggered_buffer_predisable,
};
int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev,
const struct iio_chan_spec *channels, unsigned int num_channels)
{
int ret;
struct iio_buffer *buffer;
......@@ -182,8 +183,15 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
* driven by a trigger.
*/
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
ret = iio_buffer_register(indio_dev, channels, num_channels);
if (ret)
goto error_dealloc_pollfunc;
return 0;
error_dealloc_pollfunc:
iio_dealloc_pollfunc(indio_dev->pollfunc);
error_free_buffer:
iio_kfifo_free(indio_dev->buffer);
error_ret:
......@@ -197,6 +205,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
*/
void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev)
{
iio_buffer_unregister(indio_dev);
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_kfifo_free(indio_dev->buffer);
}
......@@ -1208,13 +1208,10 @@ static int __devinit adis16400_probe(struct spi_device *spi)
/* fixme, confirm ordering in this function */
static int __devexit adis16400_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);
iio_device_unregister(indio_dev);
ret = adis16400_stop_device(indio_dev);
if (ret)
goto err_ret;
adis16400_stop_device(indio_dev);
adis16400_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
......@@ -1222,9 +1219,6 @@ static int __devexit adis16400_remove(struct spi_device *spi)
iio_device_free(indio_dev);
return 0;
err_ret:
return ret;
}
static const struct spi_device_id adis16400_id[] = {
......
......@@ -557,18 +557,13 @@ static int __devinit ade7753_probe(struct spi_device *spi)
/* fixme, confirm ordering in this function */
static int __devexit ade7753_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);
iio_device_unregister(indio_dev);
ret = ade7753_stop_device(&(indio_dev->dev));
if (ret)
goto err_ret;
ade7753_stop_device(&indio_dev->dev);
iio_device_free(indio_dev);
err_ret:
return ret;
return 0;
}
static struct spi_driver ade7753_driver = {
......
......@@ -579,19 +579,13 @@ static int __devinit ade7754_probe(struct spi_device *spi)
/* fixme, confirm ordering in this function */
static int __devexit ade7754_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);
iio_device_unregister(indio_dev);
ret = ade7754_stop_device(&(indio_dev->dev));
if (ret)
goto err_ret;
ade7754_stop_device(&indio_dev->dev);
iio_device_free(indio_dev);
err_ret:
return ret;
return 0;
}
static struct spi_driver ade7754_driver = {
......
......@@ -966,13 +966,9 @@ static int __devexit ade7758_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ade7758_state *st = iio_priv(indio_dev);
int ret;
iio_device_unregister(indio_dev);
ret = ade7758_stop_device(&indio_dev->dev);
if (ret)
goto err_ret;
ade7758_stop_device(&indio_dev->dev);
ade7758_remove_trigger(indio_dev);
ade7758_uninitialize_ring(indio_dev);
ade7758_unconfigure_ring(indio_dev);
......@@ -981,8 +977,7 @@ static int __devexit ade7758_remove(struct spi_device *spi)
iio_device_free(indio_dev);
err_ret:
return ret;
return 0;
}
static const struct spi_device_id ade7758_id[] = {
......
......@@ -501,18 +501,13 @@ static int __devinit ade7759_probe(struct spi_device *spi)
/* fixme, confirm ordering in this function */
static int __devexit ade7759_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);
iio_device_unregister(indio_dev);
ret = ade7759_stop_device(&(indio_dev->dev));
if (ret)
goto err_ret;
ade7759_stop_device(&indio_dev->dev);
iio_device_free(indio_dev);
err_ret:
return ret;
return 0;
}
static struct spi_driver ade7759_driver = {
......
/*
* Copyright (C) 2012, Anish Kumar <anish198519851985@gmail.com>
* 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.
*/
#ifndef GENERIC_ADC_BATTERY_H
#define GENERIC_ADC_BATTERY_H
/**
* struct gab_platform_data - platform_data for generic adc iio battery driver.
* @battery_info: recommended structure to specify static power supply
* parameters
* @cal_charge: calculate charge level.
* @gpio_charge_finished: gpio for the charger.
* @gpio_inverted: Should be 1 if the GPIO is active low otherwise 0
* @jitter_delay: delay required after the interrupt to check battery
* status.Default set is 10ms.
*/
struct gab_platform_data {
struct power_supply_info battery_info;
int (*cal_charge)(long value);
int gpio_charge_finished;
bool gpio_inverted;
int jitter_delay;
};
#endif /* GENERIC_ADC_BATTERY_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment