Merge tag 'staging-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging into next

Pull staging driver updates from Greg KH:
 "Here is the big staging driver pull request for 3.16-rc1.

  Lots of stuff here, tons of cleanup patches, a few new drivers, and
  some removed as well, but I think we are still adding a few thousand
  more lines than we remove, due to the new drivers being bigger than
  the ones deleted.

  One notible bit of work did stand out, Jes Sorensen has gone on a
  tear, fixing up a wireless driver to be "more sane" than it originally
  was from the vendor, with over 500 patches merged here.  Good stuff,
  and a number of users laptops are better off for it.

  All of this has been in linux-next for a while"

* tag 'staging-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1703 commits)
  staging: skein: fix sparse warning for static declarations
  staging/mt29f_spinand: coding style fixes
  staging: silicom: fix sparse warning for static variable
  staging: lustre: Fix coding style
  staging: android: binder.c: Use more appropriate functions for euid retrieval
  staging: lustre: fix integer as NULL pointer warnings
  Revert "staging: dgap: remove unneeded kfree() in dgap_tty_register_ports()"
  Staging: rtl8192u: r8192U_wx.c Fixed a misplaced brace
  staging: ion: shrink highmem pages on kswapd
  staging: ion: use compound pages on high order pages for system heap
  staging: ion: remove struct ion_page_pool_item
  staging: ion: simplify ion_page_pool_total()
  staging: ion: tidy up a bit
  staging: rtl8723au: Remove redundant casting in usb_ops_linux.c
  staging: rtl8723au: Remove redundant casting in rtl8723a_hal_init.c
  staging: rtl8723au: Remove redundant casting in rtw_xmit.c
  staging: rtl8723au: Remove redundant casting in rtw_wlan_util.c
  staging: rtl8723au: Remove redundant casting in rtw_sta_mgt.c
  staging: rtl8723au: Remove redundant casting in rtw_recv.c
  staging: rtl8723au: Remove redundant casting in rtw_mlme.c
  ...
This commit is contained in:
Linus Torvalds
2014-06-03 08:34:00 -07:00
994 changed files with 86269 additions and 77374 deletions
+44 -2
View File
@@ -114,14 +114,17 @@ What: /sys/bus/iio/devices/iio:deviceX/in_temp_raw
What: /sys/bus/iio/devices/iio:deviceX/in_tempX_raw
What: /sys/bus/iio/devices/iio:deviceX/in_temp_x_raw
What: /sys/bus/iio/devices/iio:deviceX/in_temp_y_raw
What: /sys/bus/iio/devices/iio:deviceX/in_temp_z_raw
What: /sys/bus/iio/devices/iio:deviceX/in_temp_ambient_raw
What: /sys/bus/iio/devices/iio:deviceX/in_temp_object_raw
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no bias removal etc.) temperature measurement.
If an axis is specified it generally means that the temperature
sensor is associated with one part of a compound device (e.g.
a gyroscope axis). Units after application of scale and offset
a gyroscope axis). The ambient and object modifiers distinguish
between ambient (reference) and distant temperature for contact-
less measurements. Units after application of scale and offset
are milli degrees Celsius.
What: /sys/bus/iio/devices/iio:deviceX/in_tempX_input
@@ -210,6 +213,14 @@ Contact: linux-iio@vger.kernel.org
Description:
Scaled humidity measurement in milli percent.
What: /sys/bus/iio/devices/iio:deviceX/in_X_mean_raw
KernelVersion: 3.5
Contact: linux-iio@vger.kernel.org
Description:
Averaged raw measurement from channel X. The number of values
used for averaging is device specific. The converting rules for
normal raw values also applies to the averaged raw values.
What: /sys/bus/iio/devices/iio:deviceX/in_accel_offset
What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_offset
What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset
@@ -784,6 +795,7 @@ What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en
What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_en
What: /sys/.../iio:deviceX/scan_elements/in_pressure_en
What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_en
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
@@ -799,6 +811,7 @@ What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_type
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type
What: /sys/.../iio:deviceX/scan_elements/in_pressure_type
What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_type
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
@@ -845,6 +858,7 @@ What: /sys/.../iio:deviceX/scan_elements/in_incli_y_index
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_index
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_index
What: /sys/.../iio:deviceX/scan_elements/in_pressure_index
What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_index
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
@@ -881,6 +895,25 @@ Description:
on-chip EEPROM. After power-up or chip reset the device will
automatically load the saved configuration.
What: /sys/.../iio:deviceX/in_illuminanceY_input
What: /sys/.../iio:deviceX/in_illuminanceY_raw
What: /sys/.../iio:deviceX/in_illuminanceY_mean_raw
KernelVersion: 3.4
Contact: linux-iio@vger.kernel.org
Description:
Illuminance measurement, units after application of scale
and offset are lux.
What: /sys/.../iio:deviceX/in_intensityY_raw
What: /sys/.../iio:deviceX/in_intensityY_ir_raw
What: /sys/.../iio:deviceX/in_intensityY_both_raw
KernelVersion: 3.4
Contact: linux-iio@vger.kernel.org
Description:
Unit-less light intensity. Modifiers both and ir indicate
that measurements contains visible and infrared light
components or just infrared light, respectively.
What: /sys/.../iio:deviceX/in_intensity_red_integration_time
What: /sys/.../iio:deviceX/in_intensity_green_integration_time
What: /sys/.../iio:deviceX/in_intensity_blue_integration_time
@@ -891,3 +924,12 @@ Contact: linux-iio@vger.kernel.org
Description:
This attribute is used to get/set the integration time in
seconds.
What: /sys/bus/iio/devices/iio:deviceX/in_rot_quaternion_raw
KernelVersion: 3.15
Contact: linux-iio@vger.kernel.org
Description:
Raw value of quaternion components using a format
x y z w. Here x, y, and z component represents the axis about
which a rotation will occur and w component represents the
amount of rotation.
@@ -0,0 +1,16 @@
What /sys/bus/iio/devices/iio:deviceX/in_proximity_raw
Date: March 2014
KernelVersion: 3.15
Contact: Matt Ranostay <mranostay@gmail.com>
Description:
Get the current distance in meters of storm (1km steps)
1000-40000 = distance in meters
What /sys/bus/iio/devices/iio:deviceX/sensor_sensitivity
Date: March 2014
KernelVersion: 3.15
Contact: Matt Ranostay <mranostay@gmail.com>
Description:
Show or set the gain boost of the amp, from 0-31 range.
18 = indoors (default)
14 = outdoors
@@ -0,0 +1,28 @@
Austrian Microsystems AS3935 Franklin lightning sensor device driver
Required properties:
- compatible: must be "ams,as3935"
- reg: SPI chip select number for the device
- spi-cpha: SPI Mode 1. Refer to spi/spi-bus.txt for generic SPI
slave node bindings.
- interrupt-parent : should be the phandle for the interrupt controller
- interrupts : the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic
interrupt client node bindings.
Optional properties:
- ams,tuning-capacitor-pf: Calibration tuning capacitor stepping
value 0 - 120pF. This will require using the calibration data from
the manufacturer.
Example:
as3935@0 {
compatible = "ams,as3935";
reg = <0>;
spi-cpha;
interrupt-parent = <&gpio1>;
interrupts = <16 1>;
ams,tuning-capacitor-pf = <80>;
};
@@ -61,6 +61,7 @@ Required properties:
Optional properties:
- interface_pix_fmt: How this display is connected to the
display interface. Currently supported types: "rgb24", "rgb565", "bgr666"
and "lvds666".
- edid: verbatim EDID data block describing attached display.
- ddc: phandle describing the i2c bus handling the display data
channel
@@ -13,6 +13,7 @@ allwinner Allwinner Technology Co., Ltd.
altr Altera Corp.
amcc Applied Micro Circuits Corporation (APM, formally AMCC)
amd Advanced Micro Devices (AMD), Inc.
ams AMS AG
amstaos AMS-Taos Inc.
apm Applied Micro Circuits Corporation (APM)
arm ARM Ltd.
+3
View File
@@ -236,6 +236,9 @@ certainly invest a bit more effort into libata core layer).
MEM
devm_kzalloc()
devm_kfree()
devm_kmemdup()
devm_get_free_pages()
devm_free_pages()
IIO
devm_iio_device_alloc()
+10 -1
View File
@@ -2779,12 +2779,14 @@ F: sound/soc/codecs/da[79]*.[ch]
DIGI NEO AND CLASSIC PCI PRODUCTS
M: Lidza Louina <lidza.louina@gmail.com>
M: Mark Hounschell <markh@compro.net>
L: driverdev-devel@linuxdriverproject.org
S: Maintained
F: drivers/staging/dgnc/
DIGI EPCA PCI PRODUCTS
M: Lidza Louina <lidza.louina@gmail.com>
M: Mark Hounschell <markh@compro.net>
L: driverdev-devel@linuxdriverproject.org
S: Maintained
F: drivers/staging/dgap/
@@ -8491,7 +8493,7 @@ S: Maintained
F: drivers/staging/olpc_dcon/
STAGING - OZMO DEVICES USB OVER WIFI DRIVER
M: Rupesh Gujare <rupesh.gujare@atmel.com>
M: Shigekatsu Tateno <shigekatsu.tateno@atmel.com>
S: Maintained
F: drivers/staging/ozwpan/
@@ -8506,6 +8508,13 @@ M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
S: Odd Fixes
F: drivers/staging/rtl8712/
STAGING - REALTEK RTL8723U WIRELESS DRIVER
M: Larry Finger <Larry.Finger@lwfinger.net>
M: Jes Sorensen <Jes.Sorensen@redhat.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/staging/rtl8723au/
STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER
M: Teddy Wang <teddy.wang@siliconmotion.com.cn>
S: Odd Fixes
-1
View File
@@ -415,7 +415,6 @@ config X86_UV
config X86_GOLDFISH
bool "Goldfish (Virtual Platform)"
depends on X86_32
depends on X86_EXTENDED_PLATFORM
---help---
Enable support for the Goldfish virtual platform used primarily
+97
View File
@@ -831,3 +831,100 @@ void devm_kfree(struct device *dev, void *p)
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_kfree);
/**
* devm_kmemdup - Resource-managed kmemdup
* @dev: Device this memory belongs to
* @src: Memory region to duplicate
* @len: Memory region length
* @gfp: GFP mask to use
*
* Duplicate region of a memory using resource managed kmalloc
*/
void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp)
{
void *p;
p = devm_kmalloc(dev, len, gfp);
if (p)
memcpy(p, src, len);
return p;
}
EXPORT_SYMBOL_GPL(devm_kmemdup);
struct pages_devres {
unsigned long addr;
unsigned int order;
};
static int devm_pages_match(struct device *dev, void *res, void *p)
{
struct pages_devres *devres = res;
struct pages_devres *target = p;
return devres->addr == target->addr;
}
static void devm_pages_release(struct device *dev, void *res)
{
struct pages_devres *devres = res;
free_pages(devres->addr, devres->order);
}
/**
* devm_get_free_pages - Resource-managed __get_free_pages
* @dev: Device to allocate memory for
* @gfp_mask: Allocation gfp flags
* @order: Allocation size is (1 << order) pages
*
* Managed get_free_pages. Memory allocated with this function is
* automatically freed on driver detach.
*
* RETURNS:
* Address of allocated memory on success, 0 on failure.
*/
unsigned long devm_get_free_pages(struct device *dev,
gfp_t gfp_mask, unsigned int order)
{
struct pages_devres *devres;
unsigned long addr;
addr = __get_free_pages(gfp_mask, order);
if (unlikely(!addr))
return 0;
devres = devres_alloc(devm_pages_release,
sizeof(struct pages_devres), GFP_KERNEL);
if (unlikely(!devres)) {
free_pages(addr, order);
return 0;
}
devres->addr = addr;
devres->order = order;
devres_add(dev, devres);
return addr;
}
EXPORT_SYMBOL_GPL(devm_get_free_pages);
/**
* devm_free_pages - Resource-managed free_pages
* @dev: Device this memory belongs to
* @addr: Memory to free
*
* Free memory allocated with devm_get_free_pages(). Unlike free_pages,
* there is no need to supply the @order.
*/
void devm_free_pages(struct device *dev, unsigned long addr)
{
struct pages_devres devres = { .addr = addr };
WARN_ON(devres_release(dev, devm_pages_release, devm_pages_match,
&devres));
}
EXPORT_SYMBOL_GPL(devm_free_pages);
+2
View File
@@ -4,6 +4,7 @@
menuconfig IIO
tristate "Industrial I/O support"
select ANON_INODES
help
The industrial I/O subsystem provides a unified framework for
drivers for many different types of embedded sensors using a
@@ -74,6 +75,7 @@ if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
endif #IIO_TRIGGER
source "drivers/iio/pressure/Kconfig"
source "drivers/iio/proximity/Kconfig"
source "drivers/iio/temperature/Kconfig"
endif # IIO
+1
View File
@@ -24,5 +24,6 @@ obj-y += light/
obj-y += magnetometer/
obj-y += orientation/
obj-y += pressure/
obj-y += proximity/
obj-y += temperature/
obj-y += trigger/
+12
View File
@@ -65,4 +65,16 @@ config KXSD9
Say yes here to build support for the Kionix KXSD9 accelerometer.
Currently this only supports the device via an SPI interface.
config MMA8452
tristate "Freescale MMA8452Q Accelerometer Driver"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for the Freescale MMA8452Q 3-axis
accelerometer.
To compile this driver as a module, choose M here: the module
will be called mma8452.
endmenu
+1
View File
@@ -6,6 +6,7 @@
obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
obj-$(CONFIG_KXSD9) += kxsd9.o
obj-$(CONFIG_MMA8452) += mma8452.o
obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
st_accel-y := st_accel_core.o
+34 -11
View File
@@ -22,6 +22,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/hid-sensor-hub.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -42,6 +43,10 @@ struct accel_3d_state {
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX];
u32 accel_val[ACCEL_3D_CHANNEL_MAX];
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
int value_offset;
};
static const u32 accel_3d_addresses[ACCEL_3D_CHANNEL_MAX] = {
@@ -56,6 +61,7 @@ static const struct iio_chan_spec accel_3d_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
@@ -65,6 +71,7 @@ static const struct iio_chan_spec accel_3d_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
@@ -74,6 +81,7 @@ static const struct iio_chan_spec accel_3d_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
@@ -104,31 +112,42 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
u32 address;
int ret;
int ret_type;
s32 poll_value;
*val = 0;
*val2 = 0;
switch (mask) {
case 0:
poll_value = hid_sensor_read_poll_value(
&accel_state->common_attributes);
if (poll_value < 0)
return -EINVAL;
hid_sensor_power_state(&accel_state->common_attributes, true);
msleep_interruptible(poll_value * 2);
report_id = accel_state->accel[chan->scan_index].report_id;
address = accel_3d_addresses[chan->scan_index];
if (report_id >= 0)
*val = sensor_hub_input_attr_get_raw_value(
accel_state->common_attributes.hsdev,
HID_USAGE_SENSOR_ACCEL_3D, address,
report_id);
accel_state->common_attributes.hsdev,
HID_USAGE_SENSOR_ACCEL_3D, address,
report_id);
else {
*val = 0;
hid_sensor_power_state(&accel_state->common_attributes,
false);
return -EINVAL;
}
hid_sensor_power_state(&accel_state->common_attributes, false);
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
*val = accel_state->accel[CHANNEL_SCAN_INDEX_X].units;
ret_type = IIO_VAL_INT;
*val = accel_state->scale_pre_decml;
*val2 = accel_state->scale_post_decml;
ret_type = accel_state->scale_precision;
break;
case IIO_CHAN_INFO_OFFSET:
*val = hid_sensor_convert_exponent(
accel_state->accel[CHANNEL_SCAN_INDEX_X].unit_expo);
*val = accel_state->value_offset;
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -197,9 +216,8 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev,
struct iio_dev *indio_dev = platform_get_drvdata(priv);
struct accel_3d_state *accel_state = iio_priv(indio_dev);
dev_dbg(&indio_dev->dev, "accel_3d_proc_event [%d]\n",
accel_state->common_attributes.data_ready);
if (accel_state->common_attributes.data_ready)
dev_dbg(&indio_dev->dev, "accel_3d_proc_event\n");
if (atomic_read(&accel_state->common_attributes.data_ready))
hid_sensor_push_data(indio_dev,
accel_state->accel_val,
sizeof(accel_state->accel_val));
@@ -262,6 +280,11 @@ static int accel_3d_parse_report(struct platform_device *pdev,
st->accel[1].index, st->accel[1].report_id,
st->accel[2].index, st->accel[2].report_id);
st->scale_precision = hid_sensor_format_scale(
HID_USAGE_SENSOR_ACCEL_3D,
&st->accel[CHANNEL_SCAN_INDEX_X],
&st->scale_pre_decml, &st->scale_post_decml);
/* Set Sensitivity field ids, when there is no individual modifier */
if (st->common_attributes.sensitivity.index < 0) {
sensor_hub_input_get_attribute_info(hsdev,
@@ -333,7 +356,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
goto error_free_dev_mem;
}
accel_state->common_attributes.data_ready = false;
atomic_set(&accel_state->common_attributes.data_ready, 0);
ret = hid_sensor_setup_trigger(indio_dev, name,
&accel_state->common_attributes);
if (ret < 0) {
+439
View File
@@ -0,0 +1,439 @@
/*
* mma8452.c - Support for Freescale MMA8452Q 3-axis 12-bit accelerometer
*
* Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* 7-bit I2C slave address 0x1c/0x1d (pin selectable)
*
* TODO: interrupt, thresholding, orientation / freefall events, autosleep
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/delay.h>
#define MMA8452_STATUS 0x00
#define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */
#define MMA8452_OUT_Y 0x03
#define MMA8452_OUT_Z 0x05
#define MMA8452_WHO_AM_I 0x0d
#define MMA8452_DATA_CFG 0x0e
#define MMA8452_OFF_X 0x2f
#define MMA8452_OFF_Y 0x30
#define MMA8452_OFF_Z 0x31
#define MMA8452_CTRL_REG1 0x2a
#define MMA8452_CTRL_REG2 0x2b
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
#define MMA8452_CTRL_DR_MASK (BIT(5) | BIT(4) | BIT(3))
#define MMA8452_CTRL_DR_SHIFT 3
#define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
#define MMA8452_CTRL_ACTIVE BIT(0)
#define MMA8452_DATA_CFG_FS_MASK (BIT(1) | BIT(0))
#define MMA8452_DATA_CFG_FS_2G 0
#define MMA8452_DATA_CFG_FS_4G 1
#define MMA8452_DATA_CFG_FS_8G 2
#define MMA8452_DEVICE_ID 0x2a
struct mma8452_data {
struct i2c_client *client;
struct mutex lock;
u8 ctrl_reg1;
u8 data_cfg;
};
static int mma8452_drdy(struct mma8452_data *data)
{
int tries = 150;
while (tries-- > 0) {
int ret = i2c_smbus_read_byte_data(data->client,
MMA8452_STATUS);
if (ret < 0)
return ret;
if ((ret & MMA8452_STATUS_DRDY) == MMA8452_STATUS_DRDY)
return 0;
msleep(20);
}
dev_err(&data->client->dev, "data not ready\n");
return -EIO;
}
static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
{
int ret = mma8452_drdy(data);
if (ret < 0)
return ret;
return i2c_smbus_read_i2c_block_data(data->client,
MMA8452_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
}
static ssize_t mma8452_show_int_plus_micros(char *buf,
const int (*vals)[2], int n)
{
size_t len = 0;
while (n-- > 0)
len += scnprintf(buf + len, PAGE_SIZE - len,
"%d.%06d ", vals[n][0], vals[n][1]);
/* replace trailing space by newline */
buf[len - 1] = '\n';
return len;
}
static int mma8452_get_int_plus_micros_index(const int (*vals)[2], int n,
int val, int val2)
{
while (n-- > 0)
if (val == vals[n][0] && val2 == vals[n][1])
return n;
return -EINVAL;
}
static const int mma8452_samp_freq[8][2] = {
{800, 0}, {400, 0}, {200, 0}, {100, 0}, {50, 0}, {12, 500000},
{6, 250000}, {1, 560000}
};
static const int mma8452_scales[3][2] = {
{0, 977}, {0, 1953}, {0, 3906}
};
static ssize_t mma8452_show_samp_freq_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
return mma8452_show_int_plus_micros(buf, mma8452_samp_freq,
ARRAY_SIZE(mma8452_samp_freq));
}
static ssize_t mma8452_show_scale_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
return mma8452_show_int_plus_micros(buf, mma8452_scales,
ARRAY_SIZE(mma8452_scales));
}
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail);
static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO,
mma8452_show_scale_avail, NULL, 0);
static int mma8452_get_samp_freq_index(struct mma8452_data *data,
int val, int val2)
{
return mma8452_get_int_plus_micros_index(mma8452_samp_freq,
ARRAY_SIZE(mma8452_samp_freq), val, val2);
}
static int mma8452_get_scale_index(struct mma8452_data *data,
int val, int val2)
{
return mma8452_get_int_plus_micros_index(mma8452_scales,
ARRAY_SIZE(mma8452_scales), val, val2);
}
static int mma8452_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct mma8452_data *data = iio_priv(indio_dev);
__be16 buffer[3];
int i, ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
mutex_lock(&data->lock);
ret = mma8452_read(data, buffer);
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
*val = sign_extend32(
be16_to_cpu(buffer[chan->scan_index]) >> 4, 11);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
*val = mma8452_scales[i][0];
*val2 = mma8452_scales[i][1];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
i = (data->ctrl_reg1 & MMA8452_CTRL_DR_MASK) >>
MMA8452_CTRL_DR_SHIFT;
*val = mma8452_samp_freq[i][0];
*val2 = mma8452_samp_freq[i][1];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_CALIBBIAS:
ret = i2c_smbus_read_byte_data(data->client, MMA8452_OFF_X +
chan->scan_index);
if (ret < 0)
return ret;
*val = sign_extend32(ret, 7);
return IIO_VAL_INT;
}
return -EINVAL;
}
static int mma8452_standby(struct mma8452_data *data)
{
return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
}
static int mma8452_active(struct mma8452_data *data)
{
return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
data->ctrl_reg1);
}
static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
{
int ret;
mutex_lock(&data->lock);
/* config can only be changed when in standby */
ret = mma8452_standby(data);
if (ret < 0)
goto fail;
ret = i2c_smbus_write_byte_data(data->client, reg, val);
if (ret < 0)
goto fail;
ret = mma8452_active(data);
if (ret < 0)
goto fail;
ret = 0;
fail:
mutex_unlock(&data->lock);
return ret;
}
static int mma8452_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct mma8452_data *data = iio_priv(indio_dev);
int i;
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
i = mma8452_get_samp_freq_index(data, val, val2);
if (i < 0)
return -EINVAL;
data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK;
data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT;
return mma8452_change_config(data, MMA8452_CTRL_REG1,
data->ctrl_reg1);
case IIO_CHAN_INFO_SCALE:
i = mma8452_get_scale_index(data, val, val2);
if (i < 0)
return -EINVAL;
data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK;
data->data_cfg |= i;
return mma8452_change_config(data, MMA8452_DATA_CFG,
data->data_cfg);
case IIO_CHAN_INFO_CALIBBIAS:
if (val < -128 || val > 127)
return -EINVAL;
return mma8452_change_config(data, MMA8452_OFF_X +
chan->scan_index, val);
default:
return -EINVAL;
}
}
static irqreturn_t mma8452_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct mma8452_data *data = iio_priv(indio_dev);
u8 buffer[16]; /* 3 16-bit channels + padding + ts */
int ret;
ret = mma8452_read(data, (__be16 *) buffer);
if (ret < 0)
goto done;
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
iio_get_time_ns());
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
#define MMA8452_CHANNEL(axis, idx) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = idx, \
.scan_type = { \
.sign = 's', \
.realbits = 12, \
.storagebits = 16, \
.shift = 4, \
.endianness = IIO_BE, \
}, \
}
static const struct iio_chan_spec mma8452_channels[] = {
MMA8452_CHANNEL(X, 0),
MMA8452_CHANNEL(Y, 1),
MMA8452_CHANNEL(Z, 2),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
static struct attribute *mma8452_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
NULL
};
static const struct attribute_group mma8452_group = {
.attrs = mma8452_attributes,
};
static const struct iio_info mma8452_info = {
.attrs = &mma8452_group,
.read_raw = &mma8452_read_raw,
.write_raw = &mma8452_write_raw,
.driver_module = THIS_MODULE,
};
static const unsigned long mma8452_scan_masks[] = {0x7, 0};
static int mma8452_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mma8452_data *data;
struct iio_dev *indio_dev;
int ret;
ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I);
if (ret < 0)
return ret;
if (ret != MMA8452_DEVICE_ID)
return -ENODEV;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
data->client = client;
mutex_init(&data->lock);
i2c_set_clientdata(client, indio_dev);
indio_dev->info = &mma8452_info;
indio_dev->name = id->name;
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = mma8452_channels;
indio_dev->num_channels = ARRAY_SIZE(mma8452_channels);
indio_dev->available_scan_masks = mma8452_scan_masks;
data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
(MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
data->ctrl_reg1);
if (ret < 0)
return ret;
data->data_cfg = MMA8452_DATA_CFG_FS_2G;
ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG,
data->data_cfg);
if (ret < 0)
return ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
mma8452_trigger_handler, NULL);
if (ret < 0)
return ret;
ret = iio_device_register(indio_dev);
if (ret < 0)
goto buffer_cleanup;
return 0;
buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
static int mma8452_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
mma8452_standby(iio_priv(indio_dev));
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int mma8452_suspend(struct device *dev)
{
return mma8452_standby(iio_priv(i2c_get_clientdata(
to_i2c_client(dev))));
}
static int mma8452_resume(struct device *dev)
{
return mma8452_active(iio_priv(i2c_get_clientdata(
to_i2c_client(dev))));
}
static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume);
#define MMA8452_PM_OPS (&mma8452_pm_ops)
#else
#define MMA8452_PM_OPS NULL
#endif
static const struct i2c_device_id mma8452_id[] = {
{ "mma8452", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mma8452_id);
static struct i2c_driver mma8452_driver = {
.driver = {
.name = "mma8452",
.pm = MMA8452_PM_OPS,
},
.probe = mma8452_probe,
.remove = mma8452_remove,
.id_table = mma8452_id,
};
module_i2c_driver(mma8452_driver);
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
MODULE_DESCRIPTION("Freescale MMA8452 accelerometer driver");
MODULE_LICENSE("GPL");
+7
View File
@@ -459,6 +459,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &accel_info;
st_sensors_power_enable(indio_dev);
err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_accel_sensors), st_accel_sensors);
if (err < 0)
@@ -496,6 +498,9 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
if (err)
goto st_accel_device_register_error;
dev_info(&indio_dev->dev, "registered accelerometer %s\n",
indio_dev->name);
return 0;
st_accel_device_register_error:
@@ -512,6 +517,8 @@ void st_accel_common_remove(struct iio_dev *indio_dev)
{
struct st_sensor_data *adata = iio_priv(indio_dev);
st_sensors_power_disable(indio_dev);
iio_device_unregister(indio_dev);
if (adata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev);
+17 -4
View File
@@ -96,9 +96,21 @@ config AD7923
To compile this driver as a module, choose M here: the
module will be called ad7923.
config AD799X
tristate "Analog Devices AD799x ADC driver"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Analog Devices:
ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998
i2c analog to digital converters (ADC). Provides direct access
via sysfs.
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91
depends on INPUT
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select SYSFS
@@ -107,7 +119,7 @@ config AT91_ADC
config EXYNOS_ADC
tristate "Exynos ADC driver support"
depends on OF
depends on ARCH_EXYNOS || (OF && COMPILE_TEST)
help
Core support for the ADC block found in the Samsung EXYNOS series
of SoCs for drivers such as the touchscreen and hwmon to use to share
@@ -146,11 +158,12 @@ config MCP320X
called mcp320x.
config MCP3422
tristate "Microchip Technology MCP3422/3/4 driver"
tristate "Microchip Technology MCP3422/3/4/6/7/8 driver"
depends on I2C
help
Say yes here to build support for Microchip Technology's MCP3422,
MCP3423 or MCP3424 analog to digital converters.
Say yes here to build support for Microchip Technology's
MCP3422, MCP3423, MCP3424, MCP3426, MCP3427 or MCP3428
analog to digital converters.
This driver can also be built as a module. If so, the module will be
called mcp3422.
+1
View File
@@ -11,6 +11,7 @@ obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
@@ -37,8 +37,144 @@
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include "ad799x.h"
#define AD799X_CHANNEL_SHIFT 4
#define AD799X_STORAGEBITS 16
/*
* AD7991, AD7995 and AD7999 defines
*/
#define AD7991_REF_SEL 0x08
#define AD7991_FLTR 0x04
#define AD7991_BIT_TRIAL_DELAY 0x02
#define AD7991_SAMPLE_DELAY 0x01
/*
* AD7992, AD7993, AD7994, AD7997 and AD7998 defines
*/
#define AD7998_FLTR 0x08
#define AD7998_ALERT_EN 0x04
#define AD7998_BUSY_ALERT 0x02
#define AD7998_BUSY_ALERT_POL 0x01
#define AD7998_CONV_RES_REG 0x0
#define AD7998_ALERT_STAT_REG 0x1
#define AD7998_CONF_REG 0x2
#define AD7998_CYCLE_TMR_REG 0x3
#define AD7998_DATALOW_REG(x) ((x) * 3 + 0x4)
#define AD7998_DATAHIGH_REG(x) ((x) * 3 + 0x5)
#define AD7998_HYST_REG(x) ((x) * 3 + 0x6)
#define AD7998_CYC_MASK 0x7
#define AD7998_CYC_DIS 0x0
#define AD7998_CYC_TCONF_32 0x1
#define AD7998_CYC_TCONF_64 0x2
#define AD7998_CYC_TCONF_128 0x3
#define AD7998_CYC_TCONF_256 0x4
#define AD7998_CYC_TCONF_512 0x5
#define AD7998_CYC_TCONF_1024 0x6
#define AD7998_CYC_TCONF_2048 0x7
#define AD7998_ALERT_STAT_CLEAR 0xFF
/*
* AD7997 and AD7997 defines
*/
#define AD7997_8_READ_SINGLE 0x80
#define AD7997_8_READ_SEQUENCE 0x70
/* TODO: move this into a common header */
#define RES_MASK(bits) ((1 << (bits)) - 1)
enum {
ad7991,
ad7995,
ad7999,
ad7992,
ad7993,
ad7994,
ad7997,
ad7998
};
/**
* struct ad799x_chip_info - chip specific information
* @channel: channel specification
* @num_channels: number of channels
* @monitor_mode: whether the chip supports monitor interrupts
* @default_config: device default configuration
* @event_attrs: pointer to the monitor event attribute group
*/
struct ad799x_chip_info {
struct iio_chan_spec channel[9];
int num_channels;
u16 default_config;
const struct iio_info *info;
};
struct ad799x_state {
struct i2c_client *client;
const struct ad799x_chip_info *chip_info;
struct regulator *reg;
struct regulator *vref;
unsigned id;
u16 config;
u8 *rx_buf;
unsigned int transfer_size;
};
/**
* ad799x_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
**/
static irqreturn_t ad799x_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad799x_state *st = iio_priv(indio_dev);
int b_sent;
u8 cmd;
switch (st->id) {
case ad7991:
case ad7995:
case ad7999:
cmd = st->config |
(*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT);
break;
case ad7992:
case ad7993:
case ad7994:
cmd = (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT) |
AD7998_CONV_RES_REG;
break;
case ad7997:
case ad7998:
cmd = AD7997_8_READ_SEQUENCE | AD7998_CONV_RES_REG;
break;
default:
cmd = 0;
}
b_sent = i2c_smbus_read_i2c_block_data(st->client,
cmd, st->transfer_size, st->rx_buf);
if (b_sent < 0)
goto out;
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
iio_get_time_ns());
out:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
/*
* ad799x register access by I2C
@@ -578,9 +714,10 @@ static int ad799x_probe(struct i2c_client *client,
indio_dev->channels = st->chip_info->channel;
indio_dev->num_channels = st->chip_info->num_channels;
ret = ad799x_register_ring_funcs_and_init(indio_dev);
ret = iio_triggered_buffer_setup(indio_dev, NULL,
&ad799x_trigger_handler, NULL);
if (ret)
goto error_disable_reg;
goto error_disable_vref;
if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev,
@@ -601,12 +738,11 @@ static int ad799x_probe(struct i2c_client *client,
return 0;
error_cleanup_ring:
ad799x_ring_cleanup(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
error_disable_vref:
regulator_disable(st->vref);
error_disable_reg:
if (!IS_ERR(st->vref))
regulator_disable(st->vref);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
regulator_disable(st->reg);
return ret;
}
@@ -618,11 +754,9 @@ static int ad799x_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
ad799x_ring_cleanup(indio_dev);
if (!IS_ERR(st->vref))
regulator_disable(st->vref);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(st->vref);
regulator_disable(st->reg);
kfree(st->rx_buf);
return 0;
+71 -60
View File
@@ -82,7 +82,7 @@ enum adc_version {
#define ADC_CON_EN_START (1u << 0)
#define ADC_DATX_MASK 0xFFF
#define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(1000))
#define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100))
struct exynos_adc {
void __iomem *regs;
@@ -112,6 +112,30 @@ static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
return (unsigned int)match->data;
}
static void exynos_adc_hw_init(struct exynos_adc *info)
{
u32 con1, con2;
if (info->version == ADC_V2) {
con1 = ADC_V2_CON1_SOFT_RESET;
writel(con1, ADC_V2_CON1(info->regs));
con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
writel(con2, ADC_V2_CON2(info->regs));
/* Enable interrupts */
writel(1, ADC_V2_INT_EN(info->regs));
} else {
/* set default prescaler values and Enable prescaler */
con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
/* Enable 12-bit ADC resolution */
con1 |= ADC_V1_CON_RES;
writel(con1, ADC_V1_CON(info->regs));
}
}
static int exynos_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
@@ -121,11 +145,13 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
struct exynos_adc *info = iio_priv(indio_dev);
unsigned long timeout;
u32 con1, con2;
int ret;
if (mask != IIO_CHAN_INFO_RAW)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
reinit_completion(&info->completion);
/* Select the channel to be used and Trigger conversion */
if (info->version == ADC_V2) {
@@ -145,16 +171,21 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
ADC_V1_CON(info->regs));
}
timeout = wait_for_completion_interruptible_timeout
timeout = wait_for_completion_timeout
(&info->completion, EXYNOS_ADC_TIMEOUT);
*val = info->value;
if (timeout == 0) {
dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
exynos_adc_hw_init(info);
ret = -ETIMEDOUT;
} else {
*val = info->value;
*val2 = 0;
ret = IIO_VAL_INT;
}
mutex_unlock(&indio_dev->mlock);
if (timeout == 0)
return -ETIMEDOUT;
return IIO_VAL_INT;
return ret;
}
static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
@@ -226,30 +257,6 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
return 0;
}
static void exynos_adc_hw_init(struct exynos_adc *info)
{
u32 con1, con2;
if (info->version == ADC_V2) {
con1 = ADC_V2_CON1_SOFT_RESET;
writel(con1, ADC_V2_CON1(info->regs));
con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
writel(con2, ADC_V2_CON2(info->regs));
/* Enable interrupts */
writel(1, ADC_V2_INT_EN(info->regs));
} else {
/* set default prescaler values and Enable prescaler */
con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
/* Enable 12-bit ADC resolution */
con1 |= ADC_V1_CON_RES;
writel(con1, ADC_V1_CON(info->regs));
}
}
static int exynos_adc_probe(struct platform_device *pdev)
{
struct exynos_adc *info = NULL;
@@ -290,32 +297,30 @@ static int exynos_adc_probe(struct platform_device *pdev)
init_completion(&info->completion);
ret = request_irq(info->irq, exynos_adc_isr,
0, dev_name(&pdev->dev), info);
if (ret < 0) {
dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
info->irq);
return ret;
}
writel(1, info->enable_reg);
info->clk = devm_clk_get(&pdev->dev, "adc");
if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed getting clock, err = %ld\n",
PTR_ERR(info->clk));
ret = PTR_ERR(info->clk);
goto err_irq;
return PTR_ERR(info->clk);
}
info->vdd = devm_regulator_get(&pdev->dev, "vdd");
if (IS_ERR(info->vdd)) {
dev_err(&pdev->dev, "failed getting regulator, err = %ld\n",
PTR_ERR(info->vdd));
ret = PTR_ERR(info->vdd);
goto err_irq;
return PTR_ERR(info->vdd);
}
ret = regulator_enable(info->vdd);
if (ret)
return ret;
ret = clk_prepare_enable(info->clk);
if (ret)
goto err_disable_reg;
writel(1, info->enable_reg);
info->version = exynos_adc_get_version(pdev);
platform_set_drvdata(pdev, indio_dev);
@@ -332,16 +337,18 @@ static int exynos_adc_probe(struct platform_device *pdev)
else
indio_dev->num_channels = MAX_ADC_V2_CHANNELS;
ret = request_irq(info->irq, exynos_adc_isr,
0, dev_name(&pdev->dev), info);
if (ret < 0) {
dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
info->irq);
goto err_disable_clk;
}
ret = iio_device_register(indio_dev);
if (ret)
goto err_irq;
ret = regulator_enable(info->vdd);
if (ret)
goto err_iio_dev;
clk_prepare_enable(info->clk);
exynos_adc_hw_init(info);
ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
@@ -355,12 +362,14 @@ static int exynos_adc_probe(struct platform_device *pdev)
err_of_populate:
device_for_each_child(&indio_dev->dev, NULL,
exynos_adc_remove_devices);
regulator_disable(info->vdd);
clk_disable_unprepare(info->clk);
err_iio_dev:
iio_device_unregister(indio_dev);
err_irq:
free_irq(info->irq, info);
err_disable_clk:
writel(0, info->enable_reg);
clk_disable_unprepare(info->clk);
err_disable_reg:
regulator_disable(info->vdd);
return ret;
}
@@ -371,11 +380,11 @@ static int exynos_adc_remove(struct platform_device *pdev)
device_for_each_child(&indio_dev->dev, NULL,
exynos_adc_remove_devices);
regulator_disable(info->vdd);
clk_disable_unprepare(info->clk);
writel(0, info->enable_reg);
iio_device_unregister(indio_dev);
free_irq(info->irq, info);
writel(0, info->enable_reg);
clk_disable_unprepare(info->clk);
regulator_disable(info->vdd);
return 0;
}
@@ -397,8 +406,8 @@ static int exynos_adc_suspend(struct device *dev)
writel(con, ADC_V1_CON(info->regs));
}
clk_disable_unprepare(info->clk);
writel(0, info->enable_reg);
clk_disable_unprepare(info->clk);
regulator_disable(info->vdd);
return 0;
@@ -414,9 +423,11 @@ static int exynos_adc_resume(struct device *dev)
if (ret)
return ret;
writel(1, info->enable_reg);
clk_prepare_enable(info->clk);
ret = clk_prepare_enable(info->clk);
if (ret)
return ret;
writel(1, info->enable_reg);
exynos_adc_hw_init(info);
return 0;

Some files were not shown because too many files have changed in this diff Show More