You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
@@ -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
Reference in New Issue
Block a user