1st round of new IIO drivers, functionality and cleanups for the 3.18 cycle.

Maintainer Updates
 
 * Add 3 designated reviewers for IIO.  Lars, Peter and Hartmut have been
   actively reviewing a lot of patches for a while now so this reflects
   the status quo.  These three are probably the only reason I keep
   my head above the water!
 
 New drivers and device support
 
 * max5821 DAC
 * Rockchip SARADC
 * TI ADC128S052 ADC
 * BMC150 Accelerometer
 * exynos ADC driver gains support for s3c24xx and s3c64xx parts.
 * kxcjk-1013 gainst range control and runtime PM support to drive
   down it's power usage.
 
 Driver removals
 
 * Drop ad5930, ad99850, ad9852, ad9910 and ad9951 drivers on the simple
   basis that they drivers just provided a register write function with
   no compliant user space ABI whatsoever.  Much better to drop them and
   start again for these in the fullness of time.
 
 Core Enhancements
 
 * Join together neighbouring elements in the demux units that feeds
   the binary interfaces.  This cuts down on the number of individual
   copies needed  when splitting out individual channels from the incoming
   channel scans.
 * Other demux related cleanups such as using roundup instead of a local
   implementation.
 
 Cleanups
 
 * Drop an unnecessary double setting of the owner field in xilinx adc.
 * Some more patches to use managed (devm) interfaces to cut down on
   complexity of removal code.
 * adis16060 coding style fixlets.
 * Fix some incorrect error returns in the Xilinx ADC driver.
 * Coding style fixlets for various accelerometer drivers.
 * Some sparse warning fixes to do with endianness and sign of variables.
 * Fix an incorrect and entirely pointless use of sizeof on a dynamic pointer
   in hid-sensor-magn-3d by dropping the relevant code.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABAgAGBQJT86rcAAoJEFSFNJnE9BaIhKoQAKJ+pIpOb36k1Kjppe0PgQjG
 0YCUJEte6z9RSM3s7Z47B6gm165MerYpscQW0GvTKCaxVB0GcnbE9IPYROIfZo+6
 QIQbMHe9J7mYW0+qtHBxY5ItOCcVUMSwGfbXar8nFVS6266OcXP+HAau4U9WweKt
 GmYMuTxLdzm5JYh6C+ljv2PaRZ6B9IascF+YCrDnvkL34ojq7YpLA4QE0GcJlI4s
 Fz3k7UE0ckrrkAytCumjJC/zn/BSntzyUu2ctN5Z8VO6WeMyuSyFo8uxhzhoyjtm
 NnISm89Y2Dn5iBtb+QA/6OfOEd9MtjbALauozj70u6ONL0sYdbayNcHvhUU6lnNu
 hge8xlKS5MhCKtMFZ02qJM0MD/cajNt77m/QYaOoZlbuFPbREI12PtsHah6F7SJT
 Ad3YQ8T8rT+wzq45EqlqYE863H1OMMJulyjqUom0I8LgTijz+Exs6HWs4/qMhz6V
 3T3ZwVoWSnhE4/yyRJFB/xD1P/uZIUGBP30EwlKxaiDmdxJ5X69Vlo9+AuecS3bq
 hRQvHSNFQG4cZEaDf/fzKGITkLv7V3oxqhg7yiSFtocj9kbF/6KyqgrUl5y7AZBL
 ZyW9m8OLr0K4ns8sKtRLeg9UmQ0Jxs2L1OvYtPSECAioMmMjLdij4Xt5U4Jv5ifC
 STIMv21b8mmNV9N8SdSo
 =zqHo
 -----END PGP SIGNATURE-----

Merge tag 'iio-for-3.18a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into work-next

Jonathan writes:

1st round of new IIO drivers, functionality and cleanups for the 3.18 cycle.

Maintainer Updates

* Add 3 designated reviewers for IIO.  Lars, Peter and Hartmut have been
  actively reviewing a lot of patches for a while now so this reflects
  the status quo.  These three are probably the only reason I keep
  my head above the water!

New drivers and device support

* max5821 DAC
* Rockchip SARADC
* TI ADC128S052 ADC
* BMC150 Accelerometer
* exynos ADC driver gains support for s3c24xx and s3c64xx parts.
* kxcjk-1013 gainst range control and runtime PM support to drive
  down it's power usage.

Driver removals

* Drop ad5930, ad99850, ad9852, ad9910 and ad9951 drivers on the simple
  basis that they drivers just provided a register write function with
  no compliant user space ABI whatsoever.  Much better to drop them and
  start again for these in the fullness of time.

Core Enhancements

* Join together neighbouring elements in the demux units that feeds
  the binary interfaces.  This cuts down on the number of individual
  copies needed  when splitting out individual channels from the incoming
  channel scans.
* Other demux related cleanups such as using roundup instead of a local
  implementation.

Cleanups

* Drop an unnecessary double setting of the owner field in xilinx adc.
* Some more patches to use managed (devm) interfaces to cut down on
  complexity of removal code.
* adis16060 coding style fixlets.
* Fix some incorrect error returns in the Xilinx ADC driver.
* Coding style fixlets for various accelerometer drivers.
* Some sparse warning fixes to do with endianness and sign of variables.
* Fix an incorrect and entirely pointless use of sizeof on a dynamic pointer
  in hid-sensor-magn-3d by dropping the relevant code.
This commit is contained in:
Greg Kroah-Hartman 2014-08-25 11:09:35 -07:00
commit 39bdc95871
40 changed files with 2757 additions and 1271 deletions

View file

@ -0,0 +1,7 @@
What: /sys/bus/iio/devices/triggerX/name = "bmc150_accel-any-motion-devX"
KernelVersion: 3.17
Contact: linux-iio@vger.kernel.org
Description:
The BMC150 accelerometer kernel module provides an additional trigger,
which sets driver in a mode, where data is pushed to the buffer
only when there is any motion.

View file

@ -11,13 +11,25 @@ New driver handles the following
Required properties:
- compatible: Must be "samsung,exynos-adc-v1"
for exynos4412/5250 controllers.
for exynos4412/5250 and s5pv210 controllers.
Must be "samsung,exynos-adc-v2" for
future controllers.
Must be "samsung,exynos3250-adc" for
controllers compatible with ADC of Exynos3250.
- reg: Contains ADC register address range (base address and
length) and the address of the phy enable register.
Must be "samsung,s3c2410-adc" for
the ADC in s3c2410 and compatibles
Must be "samsung,s3c2416-adc" for
the ADC in s3c2416 and compatibles
Must be "samsung,s3c2440-adc" for
the ADC in s3c2440 and compatibles
Must be "samsung,s3c2443-adc" for
the ADC in s3c2443 and compatibles
Must be "samsung,s3c6410-adc" for
the ADC in s3c6410 and compatibles
- reg: List of ADC register address range
- The base address and range of ADC register
- The base address and range of ADC_PHY register (every
SoC except for s3c24xx/s3c64xx ADC)
- interrupts: Contains the interrupt information for the timer. The
format is being dependent on which interrupt controller
the Samsung device uses.

View file

@ -0,0 +1,14 @@
Maxim max5821 DAC device driver
Required properties:
- compatible: Must be "maxim,max5821"
- reg: Should contain the DAC I2C address
- vref-supply: Phandle to the vref power supply
Example:
max5821@38 {
compatible = "maxim,max5821";
reg = <0x38>;
vref-supply = <&reg_max5821>;
};

View file

@ -685,6 +685,17 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://blackfin.uclinux.org/
S: Supported
F: sound/soc/blackfin/*
ANALOG DEVICES INC IIO DRIVERS
M: Lars-Peter Clausen <lars@metafoo.de>
M: Michael Hennerich <Michael.Hennerich@analog.com>
W: http://wiki.analog.com/
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/*/ad*
X: drivers/iio/*/adjd*
F: drivers/staging/iio/*/ad*
F: staging/iio/trigger/iio-trig-bfin-timer.c
AOA (Apple Onboard Audio) ALSA DRIVER
M: Johannes Berg <johannes@sipsolutions.net>
@ -4580,6 +4591,9 @@ F: drivers/media/rc/iguanair.c
IIO SUBSYSTEM AND DRIVERS
M: Jonathan Cameron <jic23@kernel.org>
R: Hartmut Knaack <knaack.h@gmx.de>
R: Lars-Peter Clausen <lars@metafoo.de>
R: Peter Meerwald <pmeerw@pmeerw.net>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/

View file

@ -604,9 +604,9 @@ static int sensor_hub_probe(struct hid_device *hdev,
ret = -EINVAL;
goto err_stop_hw;
}
sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt *
sizeof(struct mfd_cell),
GFP_KERNEL);
sd->hid_sensor_hub_client_devs = devm_kzalloc(&hdev->dev, dev_cnt *
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");
ret = -ENOMEM;
@ -618,11 +618,12 @@ static int sensor_hub_probe(struct hid_device *hdev,
if (collection->type == HID_COLLECTION_PHYSICAL) {
hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev),
GFP_KERNEL);
if (!hsdev) {
hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
ret = -ENOMEM;
goto err_no_mem;
goto err_stop_hw;
}
hsdev->hdev = hdev;
hsdev->vendor_id = hdev->vendor;
@ -631,13 +632,13 @@ static int sensor_hub_probe(struct hid_device *hdev,
if (last_hsdev)
last_hsdev->end_collection_index = i;
last_hsdev = hsdev;
name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x",
collection->usage);
name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
"HID-SENSOR-%x",
collection->usage);
if (name == NULL) {
hid_err(hdev, "Failed MFD device name\n");
ret = -ENOMEM;
kfree(hsdev);
goto err_no_mem;
goto err_stop_hw;
}
sd->hid_sensor_hub_client_devs[
sd->hid_sensor_client_cnt].id =
@ -661,16 +662,10 @@ 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, NULL);
if (ret < 0)
goto err_no_mem;
goto err_stop_hw;
return ret;
err_no_mem:
for (i = 0; i < sd->hid_sensor_client_cnt; ++i) {
kfree(sd->hid_sensor_hub_client_devs[i].name);
kfree(sd->hid_sensor_hub_client_devs[i].platform_data);
}
kfree(sd->hid_sensor_hub_client_devs);
err_stop_hw:
hid_hw_stop(hdev);
@ -681,7 +676,6 @@ static void sensor_hub_remove(struct hid_device *hdev)
{
struct sensor_hub_data *data = hid_get_drvdata(hdev);
unsigned long flags;
int i;
hid_dbg(hdev, " hardware removed\n");
hid_hw_close(hdev);
@ -691,11 +685,6 @@ static void sensor_hub_remove(struct hid_device *hdev)
complete(&data->pending.ready);
spin_unlock_irqrestore(&data->lock, flags);
mfd_remove_devices(&hdev->dev);
for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
kfree(data->hid_sensor_hub_client_devs[i].name);
kfree(data->hid_sensor_hub_client_devs[i].platform_data);
}
kfree(data->hid_sensor_hub_client_devs);
hid_set_drvdata(hdev, NULL);
mutex_destroy(&data->mutex);
}

View file

@ -17,6 +17,19 @@ config BMA180
To compile this driver as a module, choose M here: the
module will be called bma180.
config BMC150_ACCEL
tristate "Bosch BMC150 Accelerometer Driver"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for the Bosch BMC150 accelerometer.
Currently this only supports the device via an i2c interface.
This is a combo module with both accelerometer and magnetometer.
This driver is only implementing accelerometer part, which has
its own address and register map.
config HID_SENSOR_ACCEL_3D
depends on HID_SENSOR_HUB
select IIO_BUFFER

View file

@ -4,6 +4,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel.o
obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
obj-$(CONFIG_KXSD9) += kxsd9.o

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,8 @@
#include <linux/string.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
@ -71,15 +73,18 @@
#define KXCJK1013_DATA_MASK_12_BIT 0x0FFF
#define KXCJK1013_MAX_STARTUP_TIME_US 100000
#define KXCJK1013_SLEEP_DELAY_MS 2000
struct kxcjk1013_data {
struct i2c_client *client;
struct iio_trigger *trig;
bool trig_mode;
struct mutex mutex;
s16 buffer[8];
int power_state;
u8 odr_bits;
u8 range;
bool active_high_intr;
bool trigger_on;
};
enum kxcjk1013_axis {
@ -93,6 +98,12 @@ enum kxcjk1013_mode {
OPERATION,
};
enum kxcjk1013_range {
KXCJK1013_RANGE_2G,
KXCJK1013_RANGE_4G,
KXCJK1013_RANGE_8G,
};
static const struct {
int val;
int val2;
@ -112,6 +123,14 @@ static const struct {
{0x02, 21000}, {0x03, 11000}, {0x04, 6400},
{0x05, 3900}, {0x06, 2700}, {0x07, 2100} };
static const struct {
u16 scale;
u8 gsel_0;
u8 gsel_1;
} KXCJK1013_scale_table[] = { {9582, 0, 0},
{19163, 1, 0},
{38326, 0, 1} };
static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
enum kxcjk1013_mode mode)
{
@ -138,6 +157,51 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
return 0;
}
static int kxcjk1013_get_mode(struct kxcjk1013_data *data,
enum kxcjk1013_mode *mode)
{
int ret;
ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
}
if (ret & KXCJK1013_REG_CTRL1_BIT_PC1)
*mode = OPERATION;
else
*mode = STANDBY;
return 0;
}
static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
{
int ret;
ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
}
ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3);
ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4);
ret = i2c_smbus_write_byte_data(data->client,
KXCJK1013_REG_CTRL1,
ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
}
data->range = range_index;
return 0;
}
static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
{
int ret;
@ -160,10 +224,6 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
return ret;
}
/* Setting range to 4G */
ret |= KXCJK1013_REG_CTRL1_BIT_GSEL0;
ret &= ~KXCJK1013_REG_CTRL1_BIT_GSEL1;
/* Set 12 bit mode */
ret |= KXCJK1013_REG_CTRL1_BIT_RES;
@ -174,6 +234,14 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
return ret;
}
/* Setting range to 4G */
ret = kxcjk1013_set_range(data, KXCJK1013_RANGE_4G);
if (ret < 0)
return ret;
data->range = KXCJK1013_RANGE_4G;
ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_data_ctrl\n");
@ -201,6 +269,41 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
return ret;
}
ret = kxcjk1013_set_mode(data, OPERATION);
if (ret < 0)
return ret;
return 0;
}
static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
{
int i;
for (i = 0; i < ARRAY_SIZE(odr_start_up_times); ++i) {
if (odr_start_up_times[i].odr_bits == data->odr_bits)
return odr_start_up_times[i].usec;
}
return KXCJK1013_MAX_STARTUP_TIME_US;
}
static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
{
int ret;
if (on)
ret = pm_runtime_get_sync(&data->client->dev);
else {
pm_runtime_mark_last_busy(&data->client->dev);
ret = pm_runtime_put_autosuspend(&data->client->dev);
}
if (ret < 0) {
dev_err(&data->client->dev,
"Failed: kxcjk1013_set_power_state for %d\n", on);
return ret;
}
return 0;
}
@ -208,6 +311,11 @@ static int kxcjk1013_chip_setup_interrupt(struct kxcjk1013_data *data,
bool status)
{
int ret;
enum kxcjk1013_mode store_mode;
ret = kxcjk1013_get_mode(data, &store_mode);
if (ret < 0)
return ret;
/* This is requirement by spec to change state to STANDBY */
ret = kxcjk1013_set_mode(data, STANDBY);
@ -250,7 +358,13 @@ static int kxcjk1013_chip_setup_interrupt(struct kxcjk1013_data *data,
return ret;
}
return ret;
if (store_mode == OPERATION) {
ret = kxcjk1013_set_mode(data, OPERATION);
if (ret < 0)
return ret;
}
return 0;
}
static int kxcjk1013_convert_freq_to_bit(int val, int val2)
@ -271,6 +385,11 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
{
int ret;
int odr_bits;
enum kxcjk1013_mode store_mode;
ret = kxcjk1013_get_mode(data, &store_mode);
if (ret < 0)
return ret;
odr_bits = kxcjk1013_convert_freq_to_bit(val, val2);
if (odr_bits < 0)
@ -290,9 +409,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
data->odr_bits = odr_bits;
/* Check, if the ODR is changed after data enable */
if (data->power_state) {
/* Set the state back to operation */
if (store_mode == OPERATION) {
ret = kxcjk1013_set_mode(data, OPERATION);
if (ret < 0)
return ret;
@ -331,16 +448,38 @@ static int kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis)
return ret;
}
static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
static int kxcjk1013_set_scale(struct kxcjk1013_data *data, int val)
{
int i;
int ret, i;
enum kxcjk1013_mode store_mode;
for (i = 0; i < ARRAY_SIZE(odr_start_up_times); ++i) {
if (odr_start_up_times[i].odr_bits == data->odr_bits)
return odr_start_up_times[i].usec;
for (i = 0; i < ARRAY_SIZE(KXCJK1013_scale_table); ++i) {
if (KXCJK1013_scale_table[i].scale == val) {
ret = kxcjk1013_get_mode(data, &store_mode);
if (ret < 0)
return ret;
ret = kxcjk1013_set_mode(data, STANDBY);
if (ret < 0)
return ret;
ret = kxcjk1013_set_range(data, i);
if (ret < 0)
return ret;
if (store_mode == OPERATION) {
ret = kxcjk1013_set_mode(data, OPERATION);
if (ret)
return ret;
}
return 0;
}
}
return KXCJK1013_MAX_STARTUP_TIME_US;
return -EINVAL;
}
static int kxcjk1013_read_raw(struct iio_dev *indio_dev,
@ -356,34 +495,30 @@ static int kxcjk1013_read_raw(struct iio_dev *indio_dev,
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
else {
int sleep_val;
ret = kxcjk1013_set_mode(data, OPERATION);
ret = kxcjk1013_set_power_state(data, true);
if (ret < 0) {
mutex_unlock(&data->mutex);
return ret;
}
++data->power_state;
sleep_val = kxcjk1013_get_startup_times(data);
if (sleep_val < 20000)
usleep_range(sleep_val, 20000);
else
msleep_interruptible(sleep_val/1000);
ret = kxcjk1013_get_acc_reg(data, chan->scan_index);
if (--data->power_state == 0)
kxcjk1013_set_mode(data, STANDBY);
if (ret < 0) {
kxcjk1013_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
}
*val = sign_extend32(ret >> 4, 11);
ret = kxcjk1013_set_power_state(data, false);
}
mutex_unlock(&data->mutex);
if (ret < 0)
return ret;
*val = sign_extend32(ret >> 4, 11);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = 19163; /* range +-4g (4/2047*9.806650) */
*val2 = KXCJK1013_scale_table[data->range].scale;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
@ -410,6 +545,14 @@ static int kxcjk1013_write_raw(struct iio_dev *indio_dev,
ret = kxcjk1013_set_odr(data, val, val2);
mutex_unlock(&data->mutex);
break;
case IIO_CHAN_INFO_SCALE:
if (val)
return -EINVAL;
mutex_lock(&data->mutex);
ret = kxcjk1013_set_scale(data, val2);
mutex_unlock(&data->mutex);
break;
default:
ret = -EINVAL;
}
@ -431,8 +574,11 @@ static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev,
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600");
static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019163 0.038326");
static struct attribute *kxcjk1013_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
NULL,
};
@ -520,20 +666,21 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret;
if (state && data->trigger_on)
return 0;
mutex_lock(&data->mutex);
if (state) {
kxcjk1013_chip_setup_interrupt(data, true);
kxcjk1013_set_mode(data, OPERATION);
++data->power_state;
} else {
if (--data->power_state) {
ret = kxcjk1013_chip_setup_interrupt(data, state);
if (!ret) {
ret = kxcjk1013_set_power_state(data, state);
if (ret < 0) {
mutex_unlock(&data->mutex);
return 0;
return ret;
}
kxcjk1013_chip_setup_interrupt(data, false);
kxcjk1013_set_mode(data, STANDBY);
}
data->trigger_on = state;
mutex_unlock(&data->mutex);
return 0;
@ -661,14 +808,25 @@ static int kxcjk1013_probe(struct i2c_client *client,
}
}
ret = devm_iio_device_register(&client->dev, indio_dev);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
ret = pm_runtime_set_active(&client->dev);
if (ret)
goto err_iio_unregister;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
KXCJK1013_SLEEP_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
return 0;
err_iio_unregister:
iio_device_unregister(indio_dev);
err_buffer_cleanup:
if (data->trig_mode)
iio_triggered_buffer_cleanup(indio_dev);
@ -687,6 +845,12 @@ static int kxcjk1013_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct kxcjk1013_data *data = iio_priv(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
if (data->trig_mode) {
iio_triggered_buffer_cleanup(indio_dev);
iio_trigger_unregister(data->trig);
@ -705,35 +869,67 @@ static int kxcjk1013_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret;
mutex_lock(&data->mutex);
kxcjk1013_set_mode(data, STANDBY);
ret = kxcjk1013_set_mode(data, STANDBY);
mutex_unlock(&data->mutex);
return 0;
return ret;
}
static int kxcjk1013_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret = 0;
mutex_lock(&data->mutex);
if (data->power_state)
kxcjk1013_set_mode(data, OPERATION);
/* Check, if the suspend occured while active */
if (data->trigger_on)
ret = kxcjk1013_set_mode(data, OPERATION);
mutex_unlock(&data->mutex);
return ret;
}
#endif
#ifdef CONFIG_PM_RUNTIME
static int kxcjk1013_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct kxcjk1013_data *data = iio_priv(indio_dev);
return kxcjk1013_set_mode(data, STANDBY);
}
static int kxcjk1013_runtime_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret;
int sleep_val;
ret = kxcjk1013_set_mode(data, OPERATION);
if (ret < 0)
return ret;
sleep_val = kxcjk1013_get_startup_times(data);
if (sleep_val < 20000)
usleep_range(sleep_val, 20000);
else
msleep_interruptible(sleep_val/1000);
return 0;
}
static SIMPLE_DEV_PM_OPS(kxcjk1013_pm_ops, kxcjk1013_suspend, kxcjk1013_resume);
#define KXCJK1013_PM_OPS (&kxcjk1013_pm_ops)
#else
#define KXCJK1013_PM_OPS NULL
#endif
static const struct dev_pm_ops kxcjk1013_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume)
SET_RUNTIME_PM_OPS(kxcjk1013_runtime_suspend,
kxcjk1013_runtime_resume, NULL)
};
static const struct acpi_device_id kx_acpi_match[] = {
{"KXCJ1013", 0},
{ },
@ -751,7 +947,7 @@ static struct i2c_driver kxcjk1013_driver = {
.driver = {
.name = KXCJK1013_DRV_NAME,
.acpi_match_table = ACPI_PTR(kx_acpi_match),
.pm = KXCJK1013_PM_OPS,
.pm = &kxcjk1013_pm_ops,
},
.probe = kxcjk1013_probe,
.remove = kxcjk1013_remove,

View file

@ -129,7 +129,7 @@ config AT91_ADC
config EXYNOS_ADC
tristate "Exynos ADC driver support"
depends on ARCH_EXYNOS || (OF && COMPILE_TEST)
depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (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
@ -206,6 +206,16 @@ config NAU7802
To compile this driver as a module, choose M here: the
module will be called nau7802.
config ROCKCHIP_SARADC
tristate "Rockchip SARADC driver"
depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST)
help
Say yes here to build support for the SARADC found in SoCs from
Rockchip.
To compile this driver as a module, choose M here: the
module will be called rockchip_saradc.
config TI_ADC081C
tristate "Texas Instruments ADC081C021/027"
depends on I2C
@ -216,6 +226,16 @@ config TI_ADC081C
This driver can also be built as a module. If so, the module will be
called ti-adc081c.
config TI_ADC128S052
tristate "Texas Instruments ADC128S052"
depends on SPI
help
If you say yes here you get support for Texas Instruments ADC128S052
chip.
This driver can also be built as a module. If so, the module will be
called ti-adc128s052.
config TI_AM335X_ADC
tristate "TI's AM335X ADC driver"
depends on MFD_TI_AM335X_TSCADC

View file

@ -22,7 +22,9 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o

View file

@ -40,13 +40,16 @@
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
/* EXYNOS4412/5250 ADC_V1 registers definitions */
/* S3C/EXYNOS4412/5250 ADC_V1 registers definitions */
#define ADC_V1_CON(x) ((x) + 0x00)
#define ADC_V1_DLY(x) ((x) + 0x08)
#define ADC_V1_DATX(x) ((x) + 0x0C)
#define ADC_V1_INTCLR(x) ((x) + 0x18)
#define ADC_V1_MUX(x) ((x) + 0x1c)
/* S3C2410 ADC registers definitions */
#define ADC_S3C2410_MUX(x) ((x) + 0x18)
/* Future ADC_V2 registers definitions */
#define ADC_V2_CON1(x) ((x) + 0x00)
#define ADC_V2_CON2(x) ((x) + 0x04)
@ -61,6 +64,11 @@
#define ADC_V1_CON_PRSCLV(x) (((x) & 0xFF) << 6)
#define ADC_V1_CON_STANDBY (1u << 2)
/* Bit definitions for S3C2410 ADC */
#define ADC_S3C2410_CON_SELMUX(x) (((x) & 7) << 3)
#define ADC_S3C2410_DATX_MASK 0x3FF
#define ADC_S3C2416_CON_RES_SEL (1u << 3)
/* Bit definitions for ADC_V2 */
#define ADC_V2_CON1_SOFT_RESET (1u << 2)
@ -77,6 +85,7 @@
/* Bit definitions common for ADC_V1 and ADC_V2 */
#define ADC_CON_EN_START (1u << 0)
#define ADC_CON_EN_START_MASK (0x3 << 0)
#define ADC_DATX_MASK 0xFFF
#define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100))
@ -100,6 +109,8 @@ struct exynos_adc {
struct exynos_adc_data {
int num_channels;
bool needs_sclk;
bool needs_adc_phy;
u32 mask;
void (*init_hw)(struct exynos_adc *info);
void (*exit_hw)(struct exynos_adc *info);
@ -171,7 +182,8 @@ static void exynos_adc_v1_init_hw(struct exynos_adc *info)
{
u32 con1;
writel(1, info->enable_reg);
if (info->data->needs_adc_phy)
writel(1, info->enable_reg);
/* set default prescaler values and Enable prescaler */
con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
@ -185,7 +197,8 @@ static void exynos_adc_v1_exit_hw(struct exynos_adc *info)
{
u32 con;
writel(0, info->enable_reg);
if (info->data->needs_adc_phy)
writel(0, info->enable_reg);
con = readl(ADC_V1_CON(info->regs));
con |= ADC_V1_CON_STANDBY;
@ -210,6 +223,8 @@ static void exynos_adc_v1_start_conv(struct exynos_adc *info,
static const struct exynos_adc_data exynos_adc_v1_data = {
.num_channels = MAX_ADC_V1_CHANNELS,
.mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
.needs_adc_phy = true,
.init_hw = exynos_adc_v1_init_hw,
.exit_hw = exynos_adc_v1_exit_hw,
@ -217,11 +232,89 @@ static const struct exynos_adc_data exynos_adc_v1_data = {
.start_conv = exynos_adc_v1_start_conv,
};
static void exynos_adc_s3c2416_start_conv(struct exynos_adc *info,
unsigned long addr)
{
u32 con1;
/* Enable 12 bit ADC resolution */
con1 = readl(ADC_V1_CON(info->regs));
con1 |= ADC_S3C2416_CON_RES_SEL;
writel(con1, ADC_V1_CON(info->regs));
/* Select channel for S3C2416 */
writel(addr, ADC_S3C2410_MUX(info->regs));
con1 = readl(ADC_V1_CON(info->regs));
writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs));
}
static struct exynos_adc_data const exynos_adc_s3c2416_data = {
.num_channels = MAX_ADC_V1_CHANNELS,
.mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
.init_hw = exynos_adc_v1_init_hw,
.exit_hw = exynos_adc_v1_exit_hw,
.start_conv = exynos_adc_s3c2416_start_conv,
};
static void exynos_adc_s3c2443_start_conv(struct exynos_adc *info,
unsigned long addr)
{
u32 con1;
/* Select channel for S3C2433 */
writel(addr, ADC_S3C2410_MUX(info->regs));
con1 = readl(ADC_V1_CON(info->regs));
writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs));
}
static struct exynos_adc_data const exynos_adc_s3c2443_data = {
.num_channels = MAX_ADC_V1_CHANNELS,
.mask = ADC_S3C2410_DATX_MASK, /* 10 bit ADC resolution */
.init_hw = exynos_adc_v1_init_hw,
.exit_hw = exynos_adc_v1_exit_hw,
.start_conv = exynos_adc_s3c2443_start_conv,
};
static void exynos_adc_s3c64xx_start_conv(struct exynos_adc *info,
unsigned long addr)
{
u32 con1;
con1 = readl(ADC_V1_CON(info->regs));
con1 &= ~ADC_S3C2410_CON_SELMUX(0x7);
con1 |= ADC_S3C2410_CON_SELMUX(addr);
writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs));
}
static struct exynos_adc_data const exynos_adc_s3c24xx_data = {
.num_channels = MAX_ADC_V1_CHANNELS,
.mask = ADC_S3C2410_DATX_MASK, /* 10 bit ADC resolution */
.init_hw = exynos_adc_v1_init_hw,
.exit_hw = exynos_adc_v1_exit_hw,
.start_conv = exynos_adc_s3c64xx_start_conv,
};
static struct exynos_adc_data const exynos_adc_s3c64xx_data = {
.num_channels = MAX_ADC_V1_CHANNELS,
.mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
.init_hw = exynos_adc_v1_init_hw,
.exit_hw = exynos_adc_v1_exit_hw,
.clear_irq = exynos_adc_v1_clear_irq,
.start_conv = exynos_adc_s3c64xx_start_conv,
};
static void exynos_adc_v2_init_hw(struct exynos_adc *info)
{
u32 con1, con2;
writel(1, info->enable_reg);
if (info->data->needs_adc_phy)
writel(1, info->enable_reg);
con1 = ADC_V2_CON1_SOFT_RESET;
writel(con1, ADC_V2_CON1(info->regs));
@ -238,7 +331,8 @@ static void exynos_adc_v2_exit_hw(struct exynos_adc *info)
{
u32 con;
writel(0, info->enable_reg);
if (info->data->needs_adc_phy)
writel(0, info->enable_reg);
con = readl(ADC_V2_CON1(info->regs));
con &= ~ADC_CON_EN_START;
@ -266,6 +360,8 @@ static void exynos_adc_v2_start_conv(struct exynos_adc *info,
static const struct exynos_adc_data exynos_adc_v2_data = {
.num_channels = MAX_ADC_V2_CHANNELS,
.mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
.needs_adc_phy = true,
.init_hw = exynos_adc_v2_init_hw,
.exit_hw = exynos_adc_v2_exit_hw,
@ -275,7 +371,9 @@ static const struct exynos_adc_data exynos_adc_v2_data = {
static const struct exynos_adc_data exynos3250_adc_data = {
.num_channels = MAX_EXYNOS3250_ADC_CHANNELS,
.mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
.needs_sclk = true,
.needs_adc_phy = true,
.init_hw = exynos_adc_v2_init_hw,
.exit_hw = exynos_adc_v2_exit_hw,
@ -285,6 +383,21 @@ static const struct exynos_adc_data exynos3250_adc_data = {
static const struct of_device_id exynos_adc_match[] = {
{
.compatible = "samsung,s3c2410-adc",
.data = &exynos_adc_s3c24xx_data,
}, {
.compatible = "samsung,s3c2416-adc",
.data = &exynos_adc_s3c2416_data,
}, {
.compatible = "samsung,s3c2440-adc",
.data = &exynos_adc_s3c24xx_data,
}, {
.compatible = "samsung,s3c2443-adc",
.data = &exynos_adc_s3c2443_data,
}, {
.compatible = "samsung,s3c6410-adc",
.data = &exynos_adc_s3c64xx_data,
}, {
.compatible = "samsung,exynos-adc-v1",
.data = &exynos_adc_v1_data,
}, {
@ -347,9 +460,10 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
{
struct exynos_adc *info = (struct exynos_adc *)dev_id;
u32 mask = info->data->mask;
/* Read value */
info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
info->value = readl(ADC_V1_DATX(info->regs)) & mask;
/* clear irq */
if (info->data->clear_irq)
@ -442,10 +556,13 @@ static int exynos_adc_probe(struct platform_device *pdev)
if (IS_ERR(info->regs))
return PTR_ERR(info->regs);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
info->enable_reg = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(info->enable_reg))
return PTR_ERR(info->enable_reg);
if (info->data->needs_adc_phy) {
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
info->enable_reg = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(info->enable_reg))
return PTR_ERR(info->enable_reg);
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {

View file

@ -0,0 +1,317 @@
/*
* Rockchip Successive Approximation Register (SAR) A/D Converter
* Copyright (C) 2014 ROCKCHIP, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
#define SARADC_DATA 0x00
#define SARADC_DATA_MASK 0x3ff
#define SARADC_STAS 0x04
#define SARADC_STAS_BUSY BIT(0)
#define SARADC_CTRL 0x08
#define SARADC_CTRL_IRQ_STATUS BIT(6)
#define SARADC_CTRL_IRQ_ENABLE BIT(5)
#define SARADC_CTRL_POWER_CTRL BIT(3)
#define SARADC_CTRL_CHN_MASK 0x7
#define SARADC_DLY_PU_SOC 0x0c
#define SARADC_DLY_PU_SOC_MASK 0x3f
#define SARADC_BITS 10
#define SARADC_TIMEOUT msecs_to_jiffies(100)
struct rockchip_saradc {
void __iomem *regs;
struct clk *pclk;
struct clk *clk;
struct completion completion;
struct regulator *vref;
u16 last_val;
};
static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct rockchip_saradc *info = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
reinit_completion(&info->completion);
/* 8 clock periods as delay between power up and start cmd */
writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
/* Select the channel to be used and trigger conversion */
writel(SARADC_CTRL_POWER_CTRL
| (chan->channel & SARADC_CTRL_CHN_MASK)
| SARADC_CTRL_IRQ_ENABLE,
info->regs + SARADC_CTRL);
if (!wait_for_completion_timeout(&info->completion,
SARADC_TIMEOUT)) {
writel_relaxed(0, info->regs + SARADC_CTRL);
mutex_unlock(&indio_dev->mlock);
return -ETIMEDOUT;
}
*val = info->last_val;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(info->vref);
if (ret < 0) {
dev_err(&indio_dev->dev, "failed to get voltage\n");
return ret;
}
*val = ret / 1000;
*val2 = SARADC_BITS;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
{
struct rockchip_saradc *info = (struct rockchip_saradc *)dev_id;
/* Read value */
info->last_val = readl_relaxed(info->regs + SARADC_DATA);
info->last_val &= SARADC_DATA_MASK;
/* Clear irq & power down adc */
writel_relaxed(0, info->regs + SARADC_CTRL);
complete(&info->completion);
return IRQ_HANDLED;
}
static const struct iio_info rockchip_saradc_iio_info = {
.read_raw = rockchip_saradc_read_raw,
.driver_module = THIS_MODULE,
};
#define ADC_CHANNEL(_index, _id) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _index, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = _id, \
}
static const struct iio_chan_spec rockchip_saradc_iio_channels[] = {
ADC_CHANNEL(0, "adc0"),
ADC_CHANNEL(1, "adc1"),
ADC_CHANNEL(2, "adc2"),
};
static int rockchip_saradc_probe(struct platform_device *pdev)
{
struct rockchip_saradc *info = NULL;
struct device_node *np = pdev->dev.of_node;
struct iio_dev *indio_dev = NULL;
struct resource *mem;
int ret;
int irq;
u32 rate;
if (!np)
return -ENODEV;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
if (!indio_dev) {
dev_err(&pdev->dev, "failed allocating iio device\n");
return -ENOMEM;
}
info = iio_priv(indio_dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
info->regs = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(info->regs))
return PTR_ERR(info->regs);
init_completion(&info->completion);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n");
return irq;
}
ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,
0, dev_name(&pdev->dev), info);
if (ret < 0) {
dev_err(&pdev->dev, "failed requesting irq %d\n", irq);
return ret;
}
info->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
if (IS_ERR(info->pclk)) {
dev_err(&pdev->dev, "failed to get pclk\n");
return PTR_ERR(info->pclk);
}
info->clk = devm_clk_get(&pdev->dev, "saradc");
if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed to get adc clock\n");
return PTR_ERR(info->clk);
}
info->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(info->vref)) {
dev_err(&pdev->dev, "failed to get regulator, %ld\n",
PTR_ERR(info->vref));
return PTR_ERR(info->vref);
}
/*
* Use a default of 1MHz for the converter clock.
* This may become user-configurable in the future.
*/
ret = clk_set_rate(info->clk, 1000000);
if (ret < 0) {
dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret);
return ret;
}
ret = regulator_enable(info->vref);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable vref regulator\n");
return ret;
}
ret = clk_prepare_enable(info->pclk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable pclk\n");
goto err_reg_voltage;
}
ret = clk_prepare_enable(info->clk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable converter clock\n");
goto err_pclk;
}
platform_set_drvdata(pdev, indio_dev);
indio_dev->name = dev_name(&pdev->dev);
indio_dev->dev.parent = &pdev->dev;
indio_dev->dev.of_node = pdev->dev.of_node;
indio_dev->info = &rockchip_saradc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = rockchip_saradc_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels);
ret = iio_device_register(indio_dev);
if (ret)
goto err_clk;
return 0;
err_clk:
clk_disable_unprepare(info->clk);
err_pclk:
clk_disable_unprepare(info->pclk);
err_reg_voltage:
regulator_disable(info->vref);
return ret;
}
static int rockchip_saradc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct rockchip_saradc *info = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
clk_disable_unprepare(info->clk);
clk_disable_unprepare(info->pclk);
regulator_disable(info->vref);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int rockchip_saradc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct rockchip_saradc *info = iio_priv(indio_dev);
clk_disable_unprepare(info->clk);
clk_disable_unprepare(info->pclk);
regulator_disable(info->vref);
return 0;
}
static int rockchip_saradc_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct rockchip_saradc *info = iio_priv(indio_dev);
int ret;
ret = regulator_enable(info->vref);
if (ret)
return ret;
ret = clk_prepare_enable(info->pclk);
if (ret)
return ret;
ret = clk_prepare_enable(info->clk);
if (ret)
return ret;
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops,
rockchip_saradc_suspend, rockchip_saradc_resume);
static const struct of_device_id rockchip_saradc_match[] = {
{ .compatible = "rockchip,saradc" },
{},
};
MODULE_DEVICE_TABLE(of, rockchip_saradc_match);
static struct platform_driver rockchip_saradc_driver = {
.probe = rockchip_saradc_probe,
.remove = rockchip_saradc_remove,
.driver = {
.name = "rockchip-saradc",
.owner = THIS_MODULE,
.of_match_table = rockchip_saradc_match,
.pm = &rockchip_saradc_pm_ops,
},
};
module_platform_driver(rockchip_saradc_driver);

View file

@ -0,0 +1,179 @@
/*
* Copyright (C) 2014 Angelo Compagnucci <angelo.compagnucci@gmail.com>
*
* Driver for Texas Instruments' ADC128S052 ADC chip.
* Datasheet can be found here:
* http://www.ti.com/lit/ds/symlink/adc128s052.pdf
*
* 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/err.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
struct adc128 {
struct spi_device *spi;
struct regulator *reg;
struct mutex lock;
u8 buffer[2] ____cacheline_aligned;
};
static int adc128_adc_conversion(struct adc128 *adc, u8 channel)
{
int ret;
mutex_lock(&adc->lock);
adc->buffer[0] = channel << 3;
adc->buffer[1] = 0;
ret = spi_write(adc->spi, &adc->buffer, 2);
if (ret < 0) {
mutex_unlock(&adc->lock);
return ret;
}
ret = spi_read(adc->spi, &adc->buffer, 2);
mutex_unlock(&adc->lock);
if (ret < 0)
return ret;
return ((adc->buffer[0] << 8 | adc->buffer[1]) & 0xFFF);
}
static int adc128_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int *val,
int *val2, long mask)
{
struct adc128 *adc = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = adc128_adc_conversion(adc, channel->channel);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(adc->reg);
if (ret < 0)
return ret;
*val = ret / 1000;
*val2 = 12;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
#define ADC128_VOLTAGE_CHANNEL(num) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (num), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec adc128_channels[] = {
ADC128_VOLTAGE_CHANNEL(0),
ADC128_VOLTAGE_CHANNEL(1),
ADC128_VOLTAGE_CHANNEL(2),
ADC128_VOLTAGE_CHANNEL(3),
ADC128_VOLTAGE_CHANNEL(4),
ADC128_VOLTAGE_CHANNEL(5),
ADC128_VOLTAGE_CHANNEL(6),
ADC128_VOLTAGE_CHANNEL(7),
};
static const struct iio_info adc128_info = {
.read_raw = adc128_read_raw,
.driver_module = THIS_MODULE,
};
static int adc128_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct adc128 *adc;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->spi = spi;
spi_set_drvdata(spi, indio_dev);
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &adc128_info;
indio_dev->channels = adc128_channels;
indio_dev->num_channels = ARRAY_SIZE(adc128_channels);
adc->reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(adc->reg))
return PTR_ERR(adc->reg);
ret = regulator_enable(adc->reg);
if (ret < 0)
return ret;
mutex_init(&adc->lock);
ret = iio_device_register(indio_dev);
return ret;
}
static int adc128_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct adc128 *adc = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(adc->reg);
return 0;
}
static const struct spi_device_id adc128_id[] = {
{ "adc128s052", 0},
{ }
};
MODULE_DEVICE_TABLE(spi, adc128_id);
static struct spi_driver adc128_driver = {
.driver = {
.name = "adc128s052",
.owner = THIS_MODULE,
},
.probe = adc128_probe,
.remove = adc128_remove,
.id_table = adc128_id,
};
module_spi_driver(adc128_driver);
MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>");
MODULE_DESCRIPTION("Texas Instruments ADC128S052");
MODULE_LICENSE("GPL v2");

View file

@ -1201,12 +1201,16 @@ static int xadc_probe(struct platform_device *pdev)
goto err_device_free;
xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
if (IS_ERR(xadc->convst_trigger))
if (IS_ERR(xadc->convst_trigger)) {
ret = PTR_ERR(xadc->convst_trigger);
goto err_triggered_buffer_cleanup;
}
xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
"samplerate");
if (IS_ERR(xadc->samplerate_trigger))
if (IS_ERR(xadc->samplerate_trigger)) {
ret = PTR_ERR(xadc->samplerate_trigger);
goto err_free_convst_trigger;
}
}
xadc->clk = devm_clk_get(&pdev->dev, NULL);
@ -1322,7 +1326,6 @@ static struct platform_driver xadc_driver = {
.remove = xadc_remove,
.driver = {
.name = "xadc",
.owner = THIS_MODULE,
.of_match_table = xadc_of_match_table,
},
};

View file

@ -152,6 +152,14 @@ config MAX517
This driver can also be built as a module. If so, the module
will be called max517.
config MAX5821
tristate "Maxim MAX5821 DAC driver"
depends on I2C
depends on OF
help
Say yes here to build support for Maxim MAX5821
10 bits DAC.
config MCP4725
tristate "MCP4725 DAC driver"
depends on I2C

View file

@ -17,5 +17,6 @@ obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MAX5821) += max5821.o
obj-$(CONFIG_MCP4725) += mcp4725.o
obj-$(CONFIG_MCP4922) += mcp4922.o

405
drivers/iio/dac/max5821.c Normal file
View file

@ -0,0 +1,405 @@
/*
* iio/dac/max5821.c
* Copyright (C) 2014 Philippe Reynes
*
* 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/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
#define MAX5821_MAX_DAC_CHANNELS 2
/* command bytes */
#define MAX5821_LOAD_DAC_A_IN_REG_B 0x00
#define MAX5821_LOAD_DAC_B_IN_REG_A 0x10
#define MAX5821_EXTENDED_COMMAND_MODE 0xf0
#define MAX5821_READ_DAC_A_COMMAND 0xf1
#define MAX5821_READ_DAC_B_COMMAND 0xf2
#define MAX5821_EXTENDED_POWER_UP 0x00
#define MAX5821_EXTENDED_POWER_DOWN_MODE0 0x01
#define MAX5821_EXTENDED_POWER_DOWN_MODE1 0x02
#define MAX5821_EXTENDED_POWER_DOWN_MODE2 0x03
#define MAX5821_EXTENDED_DAC_A 0x04
#define MAX5821_EXTENDED_DAC_B 0x08
enum max5821_device_ids {
ID_MAX5821,
};
struct max5821_data {
struct i2c_client *client;
struct regulator *vref_reg;
unsigned short vref_mv;
bool powerdown[MAX5821_MAX_DAC_CHANNELS];
u8 powerdown_mode[MAX5821_MAX_DAC_CHANNELS];
struct mutex lock;
};
static const char * const max5821_powerdown_modes[] = {
"three_state",
"1kohm_to_gnd",
"100kohm_to_gnd",
};
enum {
MAX5821_THREE_STATE,
MAX5821_1KOHM_TO_GND,
MAX5821_100KOHM_TO_GND
};
static int max5821_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct max5821_data *st = iio_priv(indio_dev);
return st->powerdown_mode[chan->channel];
}
static int max5821_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
unsigned int mode)
{
struct max5821_data *st = iio_priv(indio_dev);
st->powerdown_mode[chan->channel] = mode;
return 0;
}
static const struct iio_enum max5821_powerdown_mode_enum = {
.items = max5821_powerdown_modes,
.num_items = ARRAY_SIZE(max5821_powerdown_modes),
.get = max5821_get_powerdown_mode,
.set = max5821_set_powerdown_mode,
};
static ssize_t max5821_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
char *buf)
{
struct max5821_data *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->powerdown[chan->channel]);
}
static int max5821_sync_powerdown_mode(struct max5821_data *data,
const struct iio_chan_spec *chan)
{
u8 outbuf[2];
outbuf[0] = MAX5821_EXTENDED_COMMAND_MODE;
if (chan->channel == 0)
outbuf[1] = MAX5821_EXTENDED_DAC_A;
else
outbuf[1] = MAX5821_EXTENDED_DAC_B;
if (data->powerdown[chan->channel])
outbuf[1] |= data->powerdown_mode[chan->channel] + 1;
else
outbuf[1] |= MAX5821_EXTENDED_POWER_UP;
return i2c_master_send(data->client, outbuf, 2);
}
static ssize_t max5821_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
const char *buf, size_t len)
{
struct max5821_data *data = iio_priv(indio_dev);
bool powerdown;
int ret;
ret = strtobool(buf, &powerdown);
if (ret)
return ret;
data->powerdown[chan->channel] = powerdown;
ret = max5821_sync_powerdown_mode(data, chan);
if (ret < 0)
return ret;
return len;
}
static const struct iio_chan_spec_ext_info max5821_ext_info[] = {
{
.name = "powerdown",
.read = max5821_read_dac_powerdown,
.write = max5821_write_dac_powerdown,
.shared = IIO_SEPARATE,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &max5821_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &max5821_powerdown_mode_enum),
{ },
};
#define MAX5821_CHANNEL(chan) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (chan), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \
.ext_info = max5821_ext_info, \
}
static const struct iio_chan_spec max5821_channels[] = {
MAX5821_CHANNEL(0),
MAX5821_CHANNEL(1)
};
static const u8 max5821_read_dac_command[] = {
MAX5821_READ_DAC_A_COMMAND,
MAX5821_READ_DAC_B_COMMAND
};
static const u8 max5821_load_dac_command[] = {
MAX5821_LOAD_DAC_A_IN_REG_B,
MAX5821_LOAD_DAC_B_IN_REG_A
};
static int max5821_get_value(struct iio_dev *indio_dev,
int *val, int channel)
{
struct max5821_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
u8 outbuf[1];
u8 inbuf[2];
int ret;
if ((channel != 0) && (channel != 1))
return -EINVAL;
outbuf[0] = max5821_read_dac_command[channel];
mutex_lock(&data->lock);
ret = i2c_master_send(client, outbuf, 1);
if (ret < 0) {
mutex_unlock(&data->lock);
return ret;
} else if (ret != 1) {
mutex_unlock(&data->lock);
return -EIO;
}
ret = i2c_master_recv(client, inbuf, 2);
if (ret < 0) {
mutex_unlock(&data->lock);
return ret;
} else if (ret != 2) {
mutex_unlock(&data->lock);
return -EIO;
}
mutex_unlock(&data->lock);
*val = ((inbuf[0] & 0x0f) << 6) | (inbuf[1] >> 2);
return IIO_VAL_INT;
}
static int max5821_set_value(struct iio_dev *indio_dev,
int val, int channel)
{
struct max5821_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
u8 outbuf[2];
int ret;
if ((val < 0) || (val > 1023))
return -EINVAL;
if ((channel != 0) && (channel != 1))
return -EINVAL;
outbuf[0] = max5821_load_dac_command[channel];
outbuf[0] |= val >> 6;
outbuf[1] = (val & 0x3f) << 2;
ret = i2c_master_send(client, outbuf, 2);
if (ret < 0)
return ret;
else if (ret != 2)
return -EIO;
else
return 0;
}
static int max5821_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct max5821_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
return max5821_get_value(indio_dev, val, chan->channel);
case IIO_CHAN_INFO_SCALE:
*val = data->vref_mv;
*val2 = 10;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
static int max5821_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
if (val2 != 0)
return -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_RAW:
return max5821_set_value(indio_dev, val, chan->channel);
default:
return -EINVAL;
}
}
#ifdef CONFIG_PM_SLEEP
static int max5821_suspend(struct device *dev)
{
u8 outbuf[2] = { MAX5821_EXTENDED_COMMAND_MODE,
MAX5821_EXTENDED_DAC_A |
MAX5821_EXTENDED_DAC_B |
MAX5821_EXTENDED_POWER_DOWN_MODE2 };
return i2c_master_send(to_i2c_client(dev), outbuf, 2);
}
static int max5821_resume(struct device *dev)
{
u8 outbuf[2] = { MAX5821_EXTENDED_COMMAND_MODE,
MAX5821_EXTENDED_DAC_A |
MAX5821_EXTENDED_DAC_B |
MAX5821_EXTENDED_POWER_UP };
return i2c_master_send(to_i2c_client(dev), outbuf, 2);
}
static SIMPLE_DEV_PM_OPS(max5821_pm_ops, max5821_suspend, max5821_resume);
#define MAX5821_PM_OPS (&max5821_pm_ops)
#else
#define MAX5821_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
static const struct iio_info max5821_info = {
.read_raw = max5821_read_raw,
.write_raw = max5821_write_raw,
.driver_module = THIS_MODULE,
};
static int max5821_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max5821_data *data;
struct iio_dev *indio_dev;
u32 tmp;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->lock);
/* max5821 start in powerdown mode 100Kohm to ground */
for (tmp = 0; tmp < MAX5821_MAX_DAC_CHANNELS; tmp++) {
data->powerdown[tmp] = true;
data->powerdown_mode[tmp] = MAX5821_100KOHM_TO_GND;
}
data->vref_reg = devm_regulator_get(&client->dev, "vref");
if (IS_ERR(data->vref_reg)) {
ret = PTR_ERR(data->vref_reg);
dev_err(&client->dev,
"Failed to get vref regulator: %d\n", ret);
goto error_free_reg;
}
ret = regulator_enable(data->vref_reg);
if (ret) {
dev_err(&client->dev,
"Failed to enable vref regulator: %d\n", ret);
goto error_free_reg;
}
ret = regulator_get_voltage(data->vref_reg);
if (ret < 0) {
dev_err(&client->dev,
"Failed to get voltage on regulator: %d\n", ret);
goto error_disable_reg;
}
data->vref_mv = ret / 1000;
indio_dev->name = id->name;
indio_dev->dev.parent = &client->dev;
indio_dev->num_channels = ARRAY_SIZE(max5821_channels);
indio_dev->channels = max5821_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &max5821_info;
return iio_device_register(indio_dev);
error_disable_reg:
regulator_disable(data->vref_reg);
error_free_reg:
return ret;
}
static int max5821_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct max5821_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(data->vref_reg);
return 0;
}
static const struct i2c_device_id max5821_id[] = {
{ "max5821", ID_MAX5821 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max5821_id);
static const struct of_device_id max5821_of_match[] = {
{ .compatible = "maxim,max5821" },
{ }
};
static struct i2c_driver max5821_driver = {
.driver = {
.name = "max5821",
.pm = MAX5821_PM_OPS,
.owner = THIS_MODULE,
},
.probe = max5821_probe,
.remove = max5821_remove,
.id_table = max5821_id,
};
module_i2c_driver(max5821_driver);
MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>");
MODULE_DESCRIPTION("MAX5821 DAC");
MODULE_LICENSE("GPL v2");

View file

@ -942,13 +942,34 @@ int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
}
EXPORT_SYMBOL_GPL(iio_push_to_buffers);
static int iio_buffer_add_demux(struct iio_buffer *buffer,
struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc,
unsigned int length)
{
if (*p && (*p)->from + (*p)->length == in_loc &&
(*p)->to + (*p)->length == out_loc) {
(*p)->length += length;
} else {
*p = kmalloc(sizeof(**p), GFP_KERNEL);
if (*p == NULL)
return -ENOMEM;
(*p)->from = in_loc;
(*p)->to = out_loc;
(*p)->length = length;
list_add_tail(&(*p)->l, &buffer->demux_list);
}
return 0;
}
static int iio_buffer_update_demux(struct iio_dev *indio_dev,
struct iio_buffer *buffer)
{
const struct iio_chan_spec *ch;
int ret, in_ind = -1, out_ind, length;
unsigned in_loc = 0, out_loc = 0;
struct iio_demux_table *p;
struct iio_demux_table *p = NULL;
/* Clear out any old demux */
iio_buffer_demux_free(buffer);
@ -979,14 +1000,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
else
length = ch->scan_type.storagebits / 8;
/* Make sure we are aligned */
in_loc += length;
if (in_loc % length)
in_loc += length - in_loc % length;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
ret = -ENOMEM;
goto error_clear_mux_table;
in_loc = roundup(in_loc, length) + length;
}
ch = iio_find_channel_from_si(indio_dev, in_ind);
if (ch->scan_type.repeat > 1)
@ -994,24 +1008,16 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
ch->scan_type.repeat;
else
length = ch->scan_type.storagebits / 8;
if (out_loc % length)
out_loc += length - out_loc % length;
if (in_loc % length)
in_loc += length - in_loc % length;
p->from = in_loc;
p->to = out_loc;
p->length = length;
list_add_tail(&p->l, &buffer->demux_list);
out_loc = roundup(out_loc, length);
in_loc = roundup(in_loc, length);
ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
if (ret)
goto error_clear_mux_table;
out_loc += length;
in_loc += length;
}
/* Relies on scan_timestamp being last */
if (buffer->scan_timestamp) {
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
ret = -ENOMEM;
goto error_clear_mux_table;
}
ch = iio_find_channel_from_si(indio_dev,
indio_dev->scan_index_timestamp);
if (ch->scan_type.repeat > 1)
@ -1019,14 +1025,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
ch->scan_type.repeat;
else
length = ch->scan_type.storagebits / 8;
if (out_loc % length)
out_loc += length - out_loc % length;
if (in_loc % length)
in_loc += length - in_loc % length;
p->from = in_loc;
p->to = out_loc;
p->length = length;
list_add_tail(&p->l, &buffer->demux_list);
out_loc = roundup(out_loc, length);
in_loc = roundup(in_loc, length);
ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
if (ret)
goto error_clear_mux_table;
out_loc += length;
in_loc += length;
}

View file

@ -246,8 +246,7 @@ static const struct iio_info magn_3d_info = {
};
/* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
int len)
static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data)
{
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
iio_push_to_buffers(indio_dev, data);
@ -263,9 +262,7 @@ static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev,
dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n");
if (atomic_read(&magn_state->common_attributes.data_ready))
hid_sensor_push_data(indio_dev,
magn_state->iio_vals,
sizeof(magn_state->iio_vals));
hid_sensor_push_data(indio_dev, magn_state->iio_vals);
return 0;
}

View file

@ -111,6 +111,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
int bits;
s16 val16;
u8 addr;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
@ -131,8 +132,8 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
}
static const struct iio_chan_spec adis16201_channels[] = {
ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12),
ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12),
ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12),
ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12),
ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,

View file

@ -37,6 +37,7 @@ static int adis16203_write_raw(struct iio_dev *indio_dev,
struct adis *st = iio_priv(indio_dev);
/* currently only one writable parameter which keeps this simple */
u8 addr = adis16203_addresses[chan->scan_index];
return adis_write_reg_16(st, addr, val & 0x3FFF);
}
@ -50,6 +51,7 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
int bits;
u8 addr;
s16 val16;
switch (mask) {
case IIO_CHAN_INFO_RAW:
return adis_single_conversion(indio_dev, chan,

View file

@ -119,6 +119,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
int bits;
s16 val16;
u8 addr;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {

View file

@ -44,6 +44,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
int bits;
s16 val16;
u8 addr;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {

View file

@ -163,6 +163,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
int bits = 10;
s16 val16;
u8 addr;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
val16 = val & ((1 << bits) - 1);

View file

@ -212,6 +212,7 @@ static int lis3l02dq_write_thresh(struct iio_dev *indio_dev,
int val, int val2)
{
u16 value = val;
return lis3l02dq_spi_write_reg_s16(indio_dev,
LIS3L02DQ_REG_THS_L_ADDR,
value);
@ -226,6 +227,7 @@ static int lis3l02dq_write_raw(struct iio_dev *indio_dev,
int ret = -EINVAL, reg;
u8 uval;
s8 sval;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
if (val > 255 || val < -256)
@ -302,6 +304,7 @@ static ssize_t lis3l02dq_read_frequency(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
int ret, len = 0;
s8 t;
ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
(u8 *)&t);
@ -565,6 +568,7 @@ static int lis3l02dq_read_event_config(struct iio_dev *indio_dev,
u8 val;
int ret;
u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
&val);

View file

@ -19,6 +19,7 @@ static inline u16 combine_8_to_16(u8 lower, u8 upper)
{
u16 _lower = lower;
u16 _upper = upper;
return _lower | (_upper << 8);
}

View file

@ -506,7 +506,8 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&st->lock);
return ret;
}
*val = ((st->rx[0] & 0x3F) << 3) | ((st->rx[1] & 0xE0) >> 5);
*val = ((st->rx[0] & 0x3F) << 3) |
((st->rx[1] & 0xE0) >> 5);
}
mutex_unlock(&st->lock);
return IIO_VAL_INT;
@ -713,6 +714,7 @@ static int sca3000_read_thresh(struct iio_dev *indio_dev,
int ret, i;
struct sca3000_state *st = iio_priv(indio_dev);
int num = chan->channel2;
mutex_lock(&st->lock);
ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]);
mutex_unlock(&st->lock);

View file

@ -3,13 +3,6 @@
#
menu "Direct Digital Synthesis"
config AD5930
tristate "Analog Devices ad5930/5932 driver"
depends on SPI
help
Say yes here to build support for Analog Devices DDS chip
ad5930/ad5932, provides direct access via sysfs.
config AD9832
tristate "Analog Devices ad9832/5 driver"
depends on SPI
@ -30,32 +23,4 @@ config AD9834
To compile this driver as a module, choose M here: the
module will be called ad9834.
config AD9850
tristate "Analog Devices ad9850/1 driver"
depends on SPI
help
Say yes here to build support for Analog Devices DDS chip
ad9850/1, provides direct access via sysfs.
config AD9852
tristate "Analog Devices ad9852/4 driver"
depends on SPI
help
Say yes here to build support for Analog Devices DDS chip
ad9852/4, provides direct access via sysfs.
config AD9910
tristate "Analog Devices ad9910 driver"
depends on SPI
help
Say yes here to build support for Analog Devices DDS chip
ad9910, provides direct access via sysfs.
config AD9951
tristate "Analog Devices ad9951 driver"
depends on SPI
help
Say yes here to build support for Analog Devices DDS chip
ad9951, provides direct access via sysfs.
endmenu

View file

@ -2,10 +2,5 @@
# Makefile for Direct Digital Synthesis drivers
#
obj-$(CONFIG_AD5930) += ad5930.o
obj-$(CONFIG_AD9832) += ad9832.o
obj-$(CONFIG_AD9834) += ad9834.o
obj-$(CONFIG_AD9850) += ad9850.o
obj-$(CONFIG_AD9852) += ad9852.o
obj-$(CONFIG_AD9910) += ad9910.o
obj-$(CONFIG_AD9951) += ad9951.o

View file

@ -1,140 +0,0 @@
/*
* Driver for ADI Direct Digital Synthesis ad5930
*
* Copyright (c) 2010-2010 Analog Devices Inc.
*
* 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/types.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define DRV_NAME "ad5930"
#define value_mask (u16)0xf000
#define addr_shift 12
/* Register format: 4 bits addr + 12 bits value */
struct ad5903_config {
u16 control;
u16 incnum;
u16 frqdelt[2];
u16 incitvl;
u16 buritvl;
u16 strtfrq[2];
};
struct ad5930_state {
struct mutex lock;
struct spi_device *sdev;
};
static ssize_t ad5930_set_parameter(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct spi_transfer xfer;
int ret;
struct ad5903_config *config = (struct ad5903_config *)buf;
struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad5930_state *st = iio_priv(idev);
config->control = (config->control & ~value_mask);
config->incnum = (config->control & ~value_mask) | (1 << addr_shift);
config->frqdelt[0] = (config->control & ~value_mask) | (2 << addr_shift);
config->frqdelt[1] = (config->control & ~value_mask) | 3 << addr_shift;
config->incitvl = (config->control & ~value_mask) | 4 << addr_shift;
config->buritvl = (config->control & ~value_mask) | 8 << addr_shift;
config->strtfrq[0] = (config->control & ~value_mask) | 0xc << addr_shift;
config->strtfrq[1] = (config->control & ~value_mask) | 0xd << addr_shift;
xfer.len = len;
xfer.tx_buf = config;
mutex_lock(&st->lock);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
mutex_unlock(&st->lock);
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad5930_set_parameter, 0);
static struct attribute *ad5930_attributes[] = {
&iio_dev_attr_dds.dev_attr.attr,
NULL,
};
static const struct attribute_group ad5930_attribute_group = {
.attrs = ad5930_attributes,
};
static const struct iio_info ad5930_info = {
.attrs = &ad5930_attribute_group,
.driver_module = THIS_MODULE,
};
static int ad5930_probe(struct spi_device *spi)
{
struct ad5930_state *st;
struct iio_dev *idev;
int ret = 0;
idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!idev)
return -ENOMEM;
spi_set_drvdata(spi, idev);
st = iio_priv(idev);
mutex_init(&st->lock);
st->sdev = spi;
idev->dev.parent = &spi->dev;
idev->info = &ad5930_info;
idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(idev);
if (ret)
return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 16;
spi_setup(spi);
return 0;
}
static int ad5930_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver ad5930_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = ad5930_probe,
.remove = ad5930_remove,
};
module_spi_driver(ad5930_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad5930 driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:" DRV_NAME);

View file

@ -1,120 +0,0 @@
/*
* Driver for ADI Direct Digital Synthesis ad9850
*
* Copyright (c) 2010-2010 Analog Devices Inc.
*
* 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/types.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define DRV_NAME "ad9850"
/* Register format: 4 bits addr + 12 bits value */
struct ad9850_config {
u8 control[5];
};
struct ad9850_state {
struct mutex lock;
struct spi_device *sdev;
};
static ssize_t ad9850_set_parameter(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct spi_transfer xfer;
int ret;
struct ad9850_config *config = (struct ad9850_config *)buf;
struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad9850_state *st = iio_priv(idev);
xfer.len = len;
xfer.tx_buf = config;
mutex_lock(&st->lock);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
mutex_unlock(&st->lock);
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9850_set_parameter, 0);
static struct attribute *ad9850_attributes[] = {
&iio_dev_attr_dds.dev_attr.attr,
NULL,
};
static const struct attribute_group ad9850_attribute_group = {
.attrs = ad9850_attributes,
};
static const struct iio_info ad9850_info = {
.attrs = &ad9850_attribute_group,
.driver_module = THIS_MODULE,
};
static int ad9850_probe(struct spi_device *spi)
{
struct ad9850_state *st;
struct iio_dev *idev;
int ret = 0;
idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!idev)
return -ENOMEM;
spi_set_drvdata(spi, idev);
st = iio_priv(idev);
mutex_init(&st->lock);
st->sdev = spi;
idev->dev.parent = &spi->dev;
idev->info = &ad9850_info;
idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(idev);
if (ret)
return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 16;
spi_setup(spi);
return 0;
}
static int ad9850_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver ad9850_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = ad9850_probe,
.remove = ad9850_remove,
};
module_spi_driver(ad9850_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad9850 driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:" DRV_NAME);

View file

@ -1,253 +0,0 @@
/*
* Driver for ADI Direct Digital Synthesis ad9852
*
* Copyright (c) 2010 Analog Devices Inc.
*
* 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/types.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define DRV_NAME "ad9852"
#define addr_phaad1 0x0
#define addr_phaad2 0x1
#define addr_fretu1 0x2
#define addr_fretu2 0x3
#define addr_delfre 0x4
#define addr_updclk 0x5
#define addr_ramclk 0x6
#define addr_contrl 0x7
#define addr_optskm 0x8
#define addr_optskr 0xa
#define addr_dacctl 0xb
#define COMPPD (1 << 4)
#define REFMULT2 (1 << 2)
#define BYPPLL (1 << 5)
#define PLLRANG (1 << 6)
#define IEUPCLK (1)
#define OSKEN (1 << 5)
#define read_bit (1 << 7)
/* Register format: 1 byte addr + value */
struct ad9852_config {
u8 phajst0[3];
u8 phajst1[3];
u8 fretun1[6];
u8 fretun2[6];
u8 dltafre[6];
u8 updtclk[5];
u8 ramprat[4];
u8 control[5];
u8 outpskm[3];
u8 outpskr[2];
u8 daccntl[3];
};
struct ad9852_state {
struct mutex lock;
struct spi_device *sdev;
};
static ssize_t ad9852_set_parameter(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct spi_transfer xfer;
int ret;
struct ad9852_config *config = (struct ad9852_config *)buf;
struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad9852_state *st = iio_priv(idev);
xfer.len = 3;
xfer.tx_buf = &config->phajst0[0];
mutex_lock(&st->lock);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->phajst1[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 6;
xfer.tx_buf = &config->fretun1[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 6;
xfer.tx_buf = &config->fretun2[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 6;
xfer.tx_buf = &config->dltafre[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->updtclk[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 4;
xfer.tx_buf = &config->ramprat[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->control[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->outpskm[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 2;
xfer.tx_buf = &config->outpskr[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->daccntl[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
mutex_unlock(&st->lock);
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0);
static void ad9852_init(struct ad9852_state *st)
{
struct spi_transfer xfer;
int ret;
u8 config[5];
config[0] = addr_contrl;
config[1] = COMPPD;
config[2] = REFMULT2 | BYPPLL | PLLRANG;
config[3] = IEUPCLK;
config[4] = OSKEN;
mutex_lock(&st->lock);
xfer.len = 5;
xfer.tx_buf = &config;
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
mutex_unlock(&st->lock);
}
static struct attribute *ad9852_attributes[] = {
&iio_dev_attr_dds.dev_attr.attr,
NULL,
};
static const struct attribute_group ad9852_attribute_group = {
.attrs = ad9852_attributes,
};
static const struct iio_info ad9852_info = {
.attrs = &ad9852_attribute_group,
.driver_module = THIS_MODULE,
};
static int ad9852_probe(struct spi_device *spi)
{
struct ad9852_state *st;
struct iio_dev *idev;
int ret = 0;
idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!idev)
return -ENOMEM;
st = iio_priv(idev);
spi_set_drvdata(spi, idev);
mutex_init(&st->lock);
st->sdev = spi;
idev->dev.parent = &spi->dev;
idev->info = &ad9852_info;
idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(idev);
if (ret)
return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
ad9852_init(st);
return 0;
}
static int ad9852_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver ad9852_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = ad9852_probe,
.remove = ad9852_remove,
};
module_spi_driver(ad9852_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad9852 driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:" DRV_NAME);

View file

@ -1,371 +0,0 @@
/*
* Driver for ADI Direct Digital Synthesis ad9910
*
* Copyright (c) 2010 Analog Devices Inc.
*
* 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/types.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define DRV_NAME "ad9910"
#define CFR1 0x0
#define CFR2 0x1
#define CFR3 0x2
#define AUXDAC 0x3
#define IOUPD 0x4
#define FTW 0x7
#define POW 0x8
#define ASF 0x9
#define MULTC 0x0A
#define DIG_RAMPL 0x0B
#define DIG_RAMPS 0x0C
#define DIG_RAMPR 0x0D
#define SIN_TONEP0 0x0E
#define SIN_TONEP1 0x0F
#define SIN_TONEP2 0x10
#define SIN_TONEP3 0x11
#define SIN_TONEP4 0x12
#define SIN_TONEP5 0x13
#define SIN_TONEP6 0x14
#define SIN_TONEP7 0x15
#define RAM_ENABLE (1 << 7)
#define MANUAL_OSK (1 << 7)
#define INVSIC (1 << 6)
#define DDS_SINEOP (1)
#define AUTO_OSK (1)
#define OSKEN (1 << 1)
#define LOAD_ARR (1 << 2)
#define CLR_PHA (1 << 3)
#define CLR_DIG (1 << 4)
#define ACLR_PHA (1 << 5)
#define ACLR_DIG (1 << 6)
#define LOAD_LRR (1 << 7)
#define LSB_FST (1)
#define SDIO_IPT (1 << 1)
#define EXT_PWD (1 << 3)
#define ADAC_PWD (1 << 4)
#define REFCLK_PWD (1 << 5)
#define DAC_PWD (1 << 6)
#define DIG_PWD (1 << 7)
#define ENA_AMP (1)
#define READ_FTW (1)
#define DIGR_LOW (1 << 1)
#define DIGR_HIGH (1 << 2)
#define DIGR_ENA (1 << 3)
#define SYNCCLK_ENA (1 << 6)
#define ITER_IOUPD (1 << 7)
#define TX_ENA (1 << 1)
#define PDCLK_INV (1 << 2)
#define PDCLK_ENB (1 << 3)
#define PARA_ENA (1 << 4)
#define SYNC_DIS (1 << 5)
#define DATA_ASS (1 << 6)
#define MATCH_ENA (1 << 7)
#define PLL_ENA (1)
#define PFD_RST (1 << 2)
#define REFCLK_RST (1 << 6)
#define REFCLK_BYP (1 << 7)
/* Register format: 1 byte addr + value */
struct ad9910_config {
u8 auxdac[5];
u8 ioupd[5];
u8 ftw[5];
u8 pow[3];
u8 asf[5];
u8 multc[5];
u8 dig_rampl[9];
u8 dig_ramps[9];
u8 dig_rampr[5];
u8 sin_tonep0[9];
u8 sin_tonep1[9];
u8 sin_tonep2[9];
u8 sin_tonep3[9];
u8 sin_tonep4[9];
u8 sin_tonep5[9];
u8 sin_tonep6[9];
u8 sin_tonep7[9];
};
struct ad9910_state {
struct mutex lock;
struct spi_device *sdev;
};
static ssize_t ad9910_set_parameter(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct spi_transfer xfer;
int ret;
struct ad9910_config *config = (struct ad9910_config *)buf;
struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad9910_state *st = iio_priv(idev);
xfer.len = 5;
xfer.tx_buf = &config->auxdac[0];
mutex_lock(&st->lock);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->ioupd[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->ftw[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->pow[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->asf[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->multc[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->dig_rampl[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->dig_ramps[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->dig_rampr[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep0[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep1[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep2[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep3[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep4[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep5[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep6[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep7[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
mutex_unlock(&st->lock);
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0);
static void ad9910_init(struct ad9910_state *st)
{
struct spi_transfer xfer;
int ret;
u8 cfr[5];
cfr[0] = CFR1;
cfr[1] = 0;
cfr[2] = MANUAL_OSK | INVSIC | DDS_SINEOP;
cfr[3] = AUTO_OSK | OSKEN | ACLR_PHA | ACLR_DIG | LOAD_LRR;
cfr[4] = 0;
mutex_lock(&st->lock);
xfer.len = 5;
xfer.tx_buf = &cfr;
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
cfr[0] = CFR2;
cfr[1] = ENA_AMP;
cfr[2] = READ_FTW | DIGR_ENA | ITER_IOUPD;
cfr[3] = TX_ENA | PDCLK_INV | PDCLK_ENB;
cfr[4] = PARA_ENA;
xfer.len = 5;
xfer.tx_buf = &cfr;
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
cfr[0] = CFR3;
cfr[1] = PLL_ENA;
cfr[2] = 0;
cfr[3] = REFCLK_RST | REFCLK_BYP;
cfr[4] = 0;
xfer.len = 5;
xfer.tx_buf = &cfr;
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
mutex_unlock(&st->lock);
}
static struct attribute *ad9910_attributes[] = {
&iio_dev_attr_dds.dev_attr.attr,
NULL,
};
static const struct attribute_group ad9910_attribute_group = {
.attrs = ad9910_attributes,
};
static const struct iio_info ad9910_info = {
.attrs = &ad9910_attribute_group,
.driver_module = THIS_MODULE,
};
static int ad9910_probe(struct spi_device *spi)
{
struct ad9910_state *st;
struct iio_dev *idev;
int ret = 0;
idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!idev)
return -ENOMEM;
spi_set_drvdata(spi, idev);
st = iio_priv(idev);
mutex_init(&st->lock);
st->sdev = spi;
idev->dev.parent = &spi->dev;
idev->info = &ad9910_info;
idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(idev);
if (ret)
return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
ad9910_init(st);
return 0;
}
static int ad9910_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver ad9910_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = ad9910_probe,
.remove = ad9910_remove,
};
module_spi_driver(ad9910_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad9910 driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:" DRV_NAME);

View file

@ -1,209 +0,0 @@
/*
* Driver for ADI Direct Digital Synthesis ad9951
*
* Copyright (c) 2010 Analog Devices Inc.
*
* 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/types.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define DRV_NAME "ad9951"
#define CFR1 0x0
#define CFR2 0x1
#define AUTO_OSK (1)
#define OSKEN (1 << 1)
#define LOAD_ARR (1 << 2)
#define AUTO_SYNC (1 << 7)
#define LSB_FST (1)
#define SDIO_IPT (1 << 1)
#define CLR_PHA (1 << 2)
#define SINE_OPT (1 << 4)
#define ACLR_PHA (1 << 5)
#define VCO_RANGE (1 << 2)
#define CRS_OPT (1 << 1)
#define HMANU_SYNC (1 << 2)
#define HSPD_SYNC (1 << 3)
/* Register format: 1 byte addr + value */
struct ad9951_config {
u8 asf[3];
u8 arr[2];
u8 ftw0[5];
u8 ftw1[3];
};
struct ad9951_state {
struct mutex lock;
struct spi_device *sdev;
};
static ssize_t ad9951_set_parameter(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct spi_transfer xfer;
int ret;
struct ad9951_config *config = (struct ad9951_config *)buf;
struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad9951_state *st = iio_priv(idev);
xfer.len = 3;
xfer.tx_buf = &config->asf[0];
mutex_lock(&st->lock);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 2;
xfer.tx_buf = &config->arr[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->ftw0[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->ftw1[0];
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
mutex_unlock(&st->lock);
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9951_set_parameter, 0);
static void ad9951_init(struct ad9951_state *st)
{
struct spi_transfer xfer;
int ret;
u8 cfr[5];
cfr[0] = CFR1;
cfr[1] = 0;
cfr[2] = LSB_FST | CLR_PHA | SINE_OPT | ACLR_PHA;
cfr[3] = AUTO_OSK | OSKEN | LOAD_ARR;
cfr[4] = 0;
mutex_lock(&st->lock);
xfer.len = 5;
xfer.tx_buf = &cfr;
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
cfr[0] = CFR2;
cfr[1] = VCO_RANGE;
cfr[2] = HSPD_SYNC;
cfr[3] = 0;
xfer.len = 4;
xfer.tx_buf = &cfr;
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
mutex_unlock(&st->lock);
}
static struct attribute *ad9951_attributes[] = {
&iio_dev_attr_dds.dev_attr.attr,
NULL,
};
static const struct attribute_group ad9951_attribute_group = {
.attrs = ad9951_attributes,
};
static const struct iio_info ad9951_info = {
.attrs = &ad9951_attribute_group,
.driver_module = THIS_MODULE,
};
static int ad9951_probe(struct spi_device *spi)
{
struct ad9951_state *st;
struct iio_dev *idev;
int ret = 0;
idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!idev)
return -ENOMEM;
spi_set_drvdata(spi, idev);
st = iio_priv(idev);
mutex_init(&st->lock);
st->sdev = spi;
idev->dev.parent = &spi->dev;
idev->info = &ad9951_info;
idev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(idev);
if (ret)
return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
ad9951_init(st);
return 0;
}
static int ad9951_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver ad9951_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = ad9951_probe,
.remove = ad9951_remove,
};
module_spi_driver(ad9951_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad9951 driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:" DRV_NAME);

View file

@ -180,6 +180,7 @@ static int adis16060_w_probe(struct spi_device *spi)
int ret;
struct iio_dev *indio_dev = adis16060_iio_dev;
struct adis16060_state *st;
if (!indio_dev) {
ret = -ENODEV;
goto error_ret;

View file

@ -220,7 +220,7 @@ static int ad5933_set_freq(struct ad5933_state *st,
{
unsigned long long freqreg;
union {
u32 d32;
__be32 d32;
u8 d8[4];
} dat;
@ -244,7 +244,7 @@ static int ad5933_set_freq(struct ad5933_state *st,
static int ad5933_setup(struct ad5933_state *st)
{
unsigned short dat;
__be16 dat;
int ret;
ret = ad5933_reset(st);
@ -297,7 +297,7 @@ static ssize_t ad5933_show_frequency(struct device *dev,
int ret;
unsigned long long freqreg;
union {
u32 d32;
__be32 d32;
u8 d8[4];
} dat;
@ -402,7 +402,7 @@ static ssize_t ad5933_store(struct device *dev,
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u16 val;
int i, ret = 0;
unsigned short dat;
__be16 dat;
if (this_attr->address != AD5933_IN_PGA_GAIN) {
ret = kstrtou16(buf, 10, &val);
@ -521,7 +521,7 @@ static int ad5933_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad5933_state *st = iio_priv(indio_dev);
unsigned short dat;
__be16 dat;
int ret = -EINVAL;
mutex_lock(&indio_dev->mlock);

View file

@ -454,7 +454,7 @@ static const struct attribute_group isl29108_group = {
static int isl29018_chip_init(struct isl29018_chip *chip)
{
int status;
int new_adc_bit;
unsigned int new_adc_bit;
unsigned int new_range;
/* Code added per Intersil Application Note 1534:

View file

@ -131,7 +131,7 @@ static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
static int hmc5843_wait_measurement(struct hmc5843_data *data)
{
int tries = 150;
int val;
unsigned int val;
int ret;
while (tries-- > 0) {
@ -209,7 +209,7 @@ static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
char *buf)
{
struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
int val;
unsigned int val;
int ret;
ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &val);
@ -344,7 +344,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct hmc5843_data *data = iio_priv(indio_dev);
int rval;
unsigned int rval;
int ret;
switch (mask) {

View file

@ -491,7 +491,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev,
switch (chan->type) {
case IIO_ANGL:
pos = be16_to_cpup((u16 *)st->rx);
pos = be16_to_cpup((__be16 *) st->rx);
if (st->hysteresis)
pos >>= 16 - st->resolution;
*val = pos;
@ -499,7 +499,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev,
break;
case IIO_ANGL_VEL:
negative = st->rx[0] & 0x80;
vel = be16_to_cpup((s16 *)st->rx);
vel = be16_to_cpup((__be16 *) st->rx);
vel >>= 16 - st->resolution;
if (vel & 0x8000) {
negative = (0xffff >> st->resolution) << st->resolution;