Commit 39bdc958 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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.
parents ed7f92da ff9e7621
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.
...@@ -11,13 +11,25 @@ New driver handles the following ...@@ -11,13 +11,25 @@ New driver handles the following
Required properties: Required properties:
- compatible: Must be "samsung,exynos-adc-v1" - compatible: Must be "samsung,exynos-adc-v1"
for exynos4412/5250 controllers. for exynos4412/5250 and s5pv210 controllers.
Must be "samsung,exynos-adc-v2" for Must be "samsung,exynos-adc-v2" for
future controllers. future controllers.
Must be "samsung,exynos3250-adc" for Must be "samsung,exynos3250-adc" for
controllers compatible with ADC of Exynos3250. controllers compatible with ADC of Exynos3250.
- reg: Contains ADC register address range (base address and Must be "samsung,s3c2410-adc" for
length) and the address of the phy enable register. 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 - interrupts: Contains the interrupt information for the timer. The
format is being dependent on which interrupt controller format is being dependent on which interrupt controller
the Samsung device uses. the Samsung device uses.
......
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>;
};
...@@ -685,6 +685,17 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) ...@@ -685,6 +685,17 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://blackfin.uclinux.org/ W: http://blackfin.uclinux.org/
S: Supported S: Supported
F: sound/soc/blackfin/* 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 AOA (Apple Onboard Audio) ALSA DRIVER
M: Johannes Berg <johannes@sipsolutions.net> M: Johannes Berg <johannes@sipsolutions.net>
...@@ -4580,6 +4591,9 @@ F: drivers/media/rc/iguanair.c ...@@ -4580,6 +4591,9 @@ F: drivers/media/rc/iguanair.c
IIO SUBSYSTEM AND DRIVERS IIO SUBSYSTEM AND DRIVERS
M: Jonathan Cameron <jic23@kernel.org> 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 L: linux-iio@vger.kernel.org
S: Maintained S: Maintained
F: drivers/iio/ F: drivers/iio/
......
...@@ -604,9 +604,9 @@ static int sensor_hub_probe(struct hid_device *hdev, ...@@ -604,9 +604,9 @@ static int sensor_hub_probe(struct hid_device *hdev,
ret = -EINVAL; ret = -EINVAL;
goto err_stop_hw; goto err_stop_hw;
} }
sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt * sd->hid_sensor_hub_client_devs = devm_kzalloc(&hdev->dev, dev_cnt *
sizeof(struct mfd_cell), sizeof(struct mfd_cell),
GFP_KERNEL); GFP_KERNEL);
if (sd->hid_sensor_hub_client_devs == NULL) { if (sd->hid_sensor_hub_client_devs == NULL) {
hid_err(hdev, "Failed to allocate memory for mfd cells\n"); hid_err(hdev, "Failed to allocate memory for mfd cells\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -618,11 +618,12 @@ static int sensor_hub_probe(struct hid_device *hdev, ...@@ -618,11 +618,12 @@ static int sensor_hub_probe(struct hid_device *hdev,
if (collection->type == HID_COLLECTION_PHYSICAL) { if (collection->type == HID_COLLECTION_PHYSICAL) {
hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL); hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev),
GFP_KERNEL);
if (!hsdev) { if (!hsdev) {
hid_err(hdev, "cannot allocate hid_sensor_hub_device\n"); hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_no_mem; goto err_stop_hw;
} }
hsdev->hdev = hdev; hsdev->hdev = hdev;
hsdev->vendor_id = hdev->vendor; hsdev->vendor_id = hdev->vendor;
...@@ -631,13 +632,13 @@ static int sensor_hub_probe(struct hid_device *hdev, ...@@ -631,13 +632,13 @@ static int sensor_hub_probe(struct hid_device *hdev,
if (last_hsdev) if (last_hsdev)
last_hsdev->end_collection_index = i; last_hsdev->end_collection_index = i;
last_hsdev = hsdev; last_hsdev = hsdev;
name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x", name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
collection->usage); "HID-SENSOR-%x",
collection->usage);
if (name == NULL) { if (name == NULL) {
hid_err(hdev, "Failed MFD device name\n"); hid_err(hdev, "Failed MFD device name\n");
ret = -ENOMEM; ret = -ENOMEM;
kfree(hsdev); goto err_stop_hw;
goto err_no_mem;
} }
sd->hid_sensor_hub_client_devs[ sd->hid_sensor_hub_client_devs[
sd->hid_sensor_client_cnt].id = sd->hid_sensor_client_cnt].id =
...@@ -661,16 +662,10 @@ static int sensor_hub_probe(struct hid_device *hdev, ...@@ -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, ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
sd->hid_sensor_client_cnt, NULL, 0, NULL); sd->hid_sensor_client_cnt, NULL, 0, NULL);
if (ret < 0) if (ret < 0)
goto err_no_mem; goto err_stop_hw;
return ret; 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: err_stop_hw:
hid_hw_stop(hdev); hid_hw_stop(hdev);
...@@ -681,7 +676,6 @@ static void sensor_hub_remove(struct hid_device *hdev) ...@@ -681,7 +676,6 @@ static void sensor_hub_remove(struct hid_device *hdev)
{ {
struct sensor_hub_data *data = hid_get_drvdata(hdev); struct sensor_hub_data *data = hid_get_drvdata(hdev);
unsigned long flags; unsigned long flags;
int i;
hid_dbg(hdev, " hardware removed\n"); hid_dbg(hdev, " hardware removed\n");
hid_hw_close(hdev); hid_hw_close(hdev);
...@@ -691,11 +685,6 @@ static void sensor_hub_remove(struct hid_device *hdev) ...@@ -691,11 +685,6 @@ static void sensor_hub_remove(struct hid_device *hdev)
complete(&data->pending.ready); complete(&data->pending.ready);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
mfd_remove_devices(&hdev->dev); 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); hid_set_drvdata(hdev, NULL);
mutex_destroy(&data->mutex); mutex_destroy(&data->mutex);
} }
......
...@@ -17,6 +17,19 @@ config BMA180 ...@@ -17,6 +17,19 @@ config BMA180
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bma180. 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 config HID_SENSOR_ACCEL_3D
depends on HID_SENSOR_HUB depends on HID_SENSOR_HUB
select IIO_BUFFER select IIO_BUFFER
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_BMA180) += bma180.o 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_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
obj-$(CONFIG_KXSD9) += kxsd9.o obj-$(CONFIG_KXSD9) += kxsd9.o
......
This diff is collapsed.
This diff is collapsed.
...@@ -129,7 +129,7 @@ config AT91_ADC ...@@ -129,7 +129,7 @@ config AT91_ADC
config EXYNOS_ADC config EXYNOS_ADC
tristate "Exynos ADC driver support" tristate "Exynos ADC driver support"
depends on ARCH_EXYNOS || (OF && COMPILE_TEST) depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
help help
Core support for the ADC block found in the Samsung EXYNOS series 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 of SoCs for drivers such as the touchscreen and hwmon to use to share
...@@ -206,6 +206,16 @@ config NAU7802 ...@@ -206,6 +206,16 @@ config NAU7802
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called nau7802. 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 config TI_ADC081C
tristate "Texas Instruments ADC081C021/027" tristate "Texas Instruments ADC081C021/027"
depends on I2C depends on I2C
...@@ -216,6 +226,16 @@ config TI_ADC081C ...@@ -216,6 +226,16 @@ config TI_ADC081C
This driver can also be built as a module. If so, the module will be This driver can also be built as a module. If so, the module will be
called ti-adc081c. 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 config TI_AM335X_ADC
tristate "TI's AM335X ADC driver" tristate "TI's AM335X ADC driver"
depends on MFD_TI_AM335X_TSCADC depends on MFD_TI_AM335X_TSCADC
......
...@@ -22,7 +22,9 @@ obj-$(CONFIG_MCP320X) += mcp320x.o ...@@ -22,7 +22,9 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
obj-$(CONFIG_NAU7802) += nau7802.o obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.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_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
......
...@@ -40,13 +40,16 @@ ...@@ -40,13 +40,16 @@
#include <linux/iio/machine.h> #include <linux/iio/machine.h>
#include <linux/iio/driver.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_CON(x) ((x) + 0x00)
#define ADC_V1_DLY(x) ((x) + 0x08) #define ADC_V1_DLY(x) ((x) + 0x08)
#define ADC_V1_DATX(x) ((x) + 0x0C) #define ADC_V1_DATX(x) ((x) + 0x0C)
#define ADC_V1_INTCLR(x) ((x) + 0x18) #define ADC_V1_INTCLR(x) ((x) + 0x18)
#define ADC_V1_MUX(x) ((x) + 0x1c) #define ADC_V1_MUX(x) ((x) + 0x1c)
/* S3C2410 ADC registers definitions */
#define ADC_S3C2410_MUX(x) ((x) + 0x18)
/* Future ADC_V2 registers definitions */ /* Future ADC_V2 registers definitions */
#define ADC_V2_CON1(x) ((x) + 0x00) #define ADC_V2_CON1(x) ((x) + 0x00)
#define ADC_V2_CON2(x) ((x) + 0x04) #define ADC_V2_CON2(x) ((x) + 0x04)
...@@ -61,6 +64,11 @@ ...@@ -61,6 +64,11 @@
#define ADC_V1_CON_PRSCLV(x) (((x) & 0xFF) << 6) #define ADC_V1_CON_PRSCLV(x) (((x) & 0xFF) << 6)
#define ADC_V1_CON_STANDBY (1u << 2) #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 */ /* Bit definitions for ADC_V2 */
#define ADC_V2_CON1_SOFT_RESET (1u << 2) #define ADC_V2_CON1_SOFT_RESET (1u << 2)
...@@ -77,6 +85,7 @@ ...@@ -77,6 +85,7 @@
/* Bit definitions common for ADC_V1 and ADC_V2 */ /* Bit definitions common for ADC_V1 and ADC_V2 */
#define ADC_CON_EN_START (1u << 0) #define ADC_CON_EN_START (1u << 0)
#define ADC_CON_EN_START_MASK (0x3 << 0)
#define ADC_DATX_MASK 0xFFF #define ADC_DATX_MASK 0xFFF
#define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100)) #define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100))
...@@ -100,6 +109,8 @@ struct exynos_adc { ...@@ -100,6 +109,8 @@ struct exynos_adc {
struct exynos_adc_data { struct exynos_adc_data {
int num_channels; int num_channels;
bool needs_sclk; bool needs_sclk;
bool needs_adc_phy;
u32 mask;
void (*init_hw)(struct exynos_adc *info); void (*init_hw)(struct exynos_adc *info);
void (*exit_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) ...@@ -171,7 +182,8 @@ static void exynos_adc_v1_init_hw(struct exynos_adc *info)
{ {
u32 con1; 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 */ /* set default prescaler values and Enable prescaler */
con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN; 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) ...@@ -185,7 +197,8 @@ static void exynos_adc_v1_exit_hw(struct exynos_adc *info)
{ {
u32 con; 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 = readl(ADC_V1_CON(info->regs));
con |= ADC_V1_CON_STANDBY; con |= ADC_V1_CON_STANDBY;
...@@ -210,6 +223,8 @@ static void exynos_adc_v1_start_conv(struct exynos_adc *info, ...@@ -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 = { static const struct exynos_adc_data exynos_adc_v1_data = {
.num_channels = MAX_ADC_V1_CHANNELS, .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, .init_hw = exynos_adc_v1_init_hw,
.exit_hw = exynos_adc_v1_exit_hw, .exit_hw = exynos_adc_v1_exit_hw,
...@@ -217,11 +232,89 @@ static const struct exynos_adc_data exynos_adc_v1_data = { ...@@ -217,11 +232,89 @@ static const struct exynos_adc_data exynos_adc_v1_data = {
.start_conv = exynos_adc_v1_start_conv, .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) static void exynos_adc_v2_init_hw(struct exynos_adc *info)
{ {
u32 con1, con2; 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; con1 = ADC_V2_CON1_SOFT_RESET;
writel(con1, ADC_V2_CON1(info->regs)); writel(con1, ADC_V2_CON1(info->regs));
...@@ -238,7 +331,8 @@ static void exynos_adc_v2_exit_hw(struct exynos_adc *info) ...@@ -238,7 +331,8 @@ static void exynos_adc_v2_exit_hw(struct exynos_adc *info)
{ {
u32 con; 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 = readl(ADC_V2_CON1(info->regs));
con &= ~ADC_CON_EN_START; con &= ~ADC_CON_EN_START;
...@@ -266,6 +360,8 @@ static void exynos_adc_v2_start_conv(struct exynos_adc *info, ...@@ -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 = { static const struct exynos_adc_data exynos_adc_v2_data = {
.num_channels = MAX_ADC_V2_CHANNELS, .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, .init_hw = exynos_adc_v2_init_hw,
.exit_hw = exynos_adc_v2_exit_hw, .exit_hw = exynos_adc_v2_exit_hw,
...@@ -275,7 +371,9 @@ static const struct exynos_adc_data exynos_adc_v2_data = { ...@@ -275,7 +371,9 @@ static const struct exynos_adc_data exynos_adc_v2_data = {
static const struct exynos_adc_data exynos3250_adc_data = { static const struct exynos_adc_data exynos3250_adc_data = {
.num_channels = MAX_EXYNOS3250_ADC_CHANNELS, .num_channels = MAX_EXYNOS3250_ADC_CHANNELS,
.mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
.needs_sclk = true, .needs_sclk = true,
.needs_adc_phy = true,
.init_hw = exynos_adc_v2_init_hw, .init_hw = exynos_adc_v2_init_hw,
.exit_hw = exynos_adc_v2_exit_hw, .exit_hw = exynos_adc_v2_exit_hw,
...@@ -285,6 +383,21 @@ static const struct exynos_adc_data exynos3250_adc_data = { ...@@ -285,6 +383,21 @@ static const struct exynos_adc_data exynos3250_adc_data = {
static const struct of_device_id exynos_adc_match[] = { 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", .compatible = "samsung,exynos-adc-v1",
.data = &exynos_adc_v1_data, .data = &exynos_adc_v1_data,
}, { }, {
...@@ -347,9 +460,10 @@ static int exynos_read_raw(struct iio_dev *indio_dev, ...@@ -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) static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
{ {
struct exynos_adc *info = (struct exynos_adc *)dev_id; struct exynos_adc *info = (struct exynos_adc *)dev_id;
u32 mask = info->data->mask;
/* Read value */ /* Read value */
info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK; info->value = readl(ADC_V1_DATX(info->regs)) & mask;
/* clear irq */ /* clear irq */
if (info->data->clear_irq) if (info->data->clear_irq)
...@@ -442,10 +556,13 @@ static int exynos_adc_probe(struct platform_device *pdev) ...@@ -442,10 +556,13 @@ static int exynos_adc_probe(struct platform_device *pdev)
if (IS_ERR(info->regs)) if (IS_ERR(info->regs))
return PTR_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 (info->data->needs_adc_phy) {
if (IS_ERR(info->enable_reg)) mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
return PTR_ERR(info->enable_reg); 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); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
......
/*
* 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);
/*
* 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");
...@@ -1201,12 +1201,16 @@ static int xadc_probe(struct platform_device *pdev) ...@@ -1201,12 +1201,16 @@ static int xadc_probe(struct platform_device *pdev)
goto err_device_free; goto err_device_free;
xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst"); 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; goto err_triggered_buffer_cleanup;
}
xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev, xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
"samplerate"); "samplerate");
if (IS_ERR(xadc->samplerate_trigger)) if (IS_ERR(xadc->samplerate_trigger)) {
ret = PTR_ERR(xadc->samplerate_trigger);
goto err_free_convst_trigger; goto err_free_convst_trigger;
}
} }
xadc->clk = devm_clk_get(&pdev->dev, NULL); xadc->clk = devm_clk_get(&pdev->dev, NULL);
...@@ -1322,7 +1326,6 @@ static struct platform_driver xadc_driver = { ...@@ -1322,7 +1326,6 @@ static struct platform_driver xadc_driver = {
.remove = xadc_remove, .remove = xadc_remove,
.driver = { .driver = {
.name = "xadc", .name = "xadc",
.owner = THIS_MODULE,
.of_match_table = xadc_of_match_table, .of_match_table = xadc_of_match_table,
}, },
}; };
......
...@@ -152,6 +152,14 @@ config MAX517 ...@@ -152,6 +152,14 @@ config MAX517
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called max517. 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 config MCP4725
tristate "MCP4725 DAC driver" tristate "MCP4725 DAC driver"
depends on I2C depends on I2C
......
...@@ -17,5 +17,6 @@ obj-$(CONFIG_AD5791) += ad5791.o ...@@ -17,5 +17,6 @@ obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MAX5821) += max5821.o
obj-$(CONFIG_MCP4725) += mcp4725.o obj-$(CONFIG_MCP4725) += mcp4725.o
obj-$(CONFIG_MCP4922) += mcp4922.o obj-$(CONFIG_MCP4922) += mcp4922.o
/*
* 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");
...@@ -942,13 +942,34 @@ int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data) ...@@ -942,13 +942,34 @@ int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
} }
EXPORT_SYMBOL_GPL(iio_push_to_buffers); 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, static int iio_buffer_update_demux(struct iio_dev *indio_dev,
struct iio_buffer *buffer) struct iio_buffer *buffer)
{ {
const struct iio_chan_spec *ch; const struct iio_chan_spec *ch;
int ret, in_ind = -1, out_ind, length; int ret, in_ind = -1, out_ind, length;
unsigned in_loc = 0, out_loc = 0; unsigned in_loc = 0, out_loc = 0;
struct iio_demux_table *p; struct iio_demux_table *p = NULL;
/* Clear out any old demux */ /* Clear out any old demux */
iio_buffer_demux_free(buffer); iio_buffer_demux_free(buffer);
...@@ -979,14 +1000,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, ...@@ -979,14 +1000,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
else else
length = ch->scan_type.storagebits / 8; length = ch->scan_type.storagebits / 8;
/* Make sure we are aligned */ /* Make sure we are aligned */
in_loc += length; in_loc = roundup(in_loc, length) + 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;
} }
ch = iio_find_channel_from_si(indio_dev, in_ind); ch = iio_find_channel_from_si(indio_dev, in_ind);
if (ch->scan_type.repeat > 1) if (ch->scan_type.repeat > 1)
...@@ -994,24 +1008,16 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, ...@@ -994,24 +1008,16 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
ch->scan_type.repeat; ch->scan_type.repeat;
else else
length = ch->scan_type.storagebits / 8; length = ch->scan_type.storagebits / 8;
if (out_loc % length) out_loc = roundup(out_loc, length);
out_loc += length - out_loc % length; in_loc = roundup(in_loc, length);
if (in_loc % length) ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
in_loc += length - in_loc % length; if (ret)
p->from = in_loc; goto error_clear_mux_table;
p->to = out_loc;
p->length = length;
list_add_tail(&p->l, &buffer->demux_list);
out_loc += length; out_loc += length;
in_loc += length; in_loc += length;
} }
/* Relies on scan_timestamp being last */ /* Relies on scan_timestamp being last */
if (buffer->scan_timestamp) { 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, ch = iio_find_channel_from_si(indio_dev,
indio_dev->scan_index_timestamp); indio_dev->scan_index_timestamp);
if (ch->scan_type.repeat > 1) if (ch->scan_type.repeat > 1)
...@@ -1019,14 +1025,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, ...@@ -1019,14 +1025,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
ch->scan_type.repeat; ch->scan_type.repeat;
else else
length = ch->scan_type.storagebits / 8; length = ch->scan_type.storagebits / 8;
if (out_loc % length) out_loc = roundup(out_loc, length);
out_loc += length - out_loc % length; in_loc = roundup(in_loc, length);
if (in_loc % length) ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
in_loc += length - in_loc % length; if (ret)
p->from = in_loc; goto error_clear_mux_table;
p->to = out_loc;
p->length = length;
list_add_tail(&p->l, &buffer->demux_list);
out_loc += length; out_loc += length;
in_loc += length; in_loc += length;
} }
......
...@@ -246,8 +246,7 @@ static const struct iio_info magn_3d_info = { ...@@ -246,8 +246,7 @@ static const struct iio_info magn_3d_info = {
}; };
/* Function to push data to buffer */ /* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data, static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data)
int len)
{ {
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
iio_push_to_buffers(indio_dev, data); iio_push_to_buffers(indio_dev, data);
...@@ -263,9 +262,7 @@ static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev, ...@@ -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"); dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n");
if (atomic_read(&magn_state->common_attributes.data_ready)) if (atomic_read(&magn_state->common_attributes.data_ready))
hid_sensor_push_data(indio_dev, hid_sensor_push_data(indio_dev, magn_state->iio_vals);
magn_state->iio_vals,
sizeof(magn_state->iio_vals));
return 0; return 0;
} }
......
...@@ -111,6 +111,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, ...@@ -111,6 +111,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
int bits; int bits;
s16 val16; s16 val16;
u8 addr; u8 addr;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) { switch (chan->type) {
...@@ -131,8 +132,8 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, ...@@ -131,8 +132,8 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
} }
static const struct iio_chan_spec adis16201_channels[] = { static const struct iio_chan_spec adis16201_channels[] = {
ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 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_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12),
ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X, ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y, ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,
......
...@@ -37,6 +37,7 @@ static int adis16203_write_raw(struct iio_dev *indio_dev, ...@@ -37,6 +37,7 @@ static int adis16203_write_raw(struct iio_dev *indio_dev,
struct adis *st = iio_priv(indio_dev); struct adis *st = iio_priv(indio_dev);
/* currently only one writable parameter which keeps this simple */ /* currently only one writable parameter which keeps this simple */
u8 addr = adis16203_addresses[chan->scan_index]; u8 addr = adis16203_addresses[chan->scan_index];
return adis_write_reg_16(st, addr, val & 0x3FFF); return adis_write_reg_16(st, addr, val & 0x3FFF);
} }
...@@ -50,6 +51,7 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, ...@@ -50,6 +51,7 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
int bits; int bits;
u8 addr; u8 addr;
s16 val16; s16 val16;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
return adis_single_conversion(indio_dev, chan, return adis_single_conversion(indio_dev, chan,
......
...@@ -119,6 +119,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, ...@@ -119,6 +119,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
int bits; int bits;
s16 val16; s16 val16;
u8 addr; u8 addr;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) { switch (chan->type) {
......
...@@ -44,6 +44,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev, ...@@ -44,6 +44,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
int bits; int bits;
s16 val16; s16 val16;
u8 addr; u8 addr;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) { switch (chan->type) {
......
...@@ -163,6 +163,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, ...@@ -163,6 +163,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
int bits = 10; int bits = 10;
s16 val16; s16 val16;
u8 addr; u8 addr;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
val16 = val & ((1 << bits) - 1); val16 = val & ((1 << bits) - 1);
......
...@@ -212,6 +212,7 @@ static int lis3l02dq_write_thresh(struct iio_dev *indio_dev, ...@@ -212,6 +212,7 @@ static int lis3l02dq_write_thresh(struct iio_dev *indio_dev,
int val, int val2) int val, int val2)
{ {
u16 value = val; u16 value = val;
return lis3l02dq_spi_write_reg_s16(indio_dev, return lis3l02dq_spi_write_reg_s16(indio_dev,
LIS3L02DQ_REG_THS_L_ADDR, LIS3L02DQ_REG_THS_L_ADDR,
value); value);
...@@ -226,6 +227,7 @@ static int lis3l02dq_write_raw(struct iio_dev *indio_dev, ...@@ -226,6 +227,7 @@ static int lis3l02dq_write_raw(struct iio_dev *indio_dev,
int ret = -EINVAL, reg; int ret = -EINVAL, reg;
u8 uval; u8 uval;
s8 sval; s8 sval;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
if (val > 255 || val < -256) if (val > 255 || val < -256)
...@@ -302,6 +304,7 @@ static ssize_t lis3l02dq_read_frequency(struct device *dev, ...@@ -302,6 +304,7 @@ static ssize_t lis3l02dq_read_frequency(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
int ret, len = 0; int ret, len = 0;
s8 t; s8 t;
ret = lis3l02dq_spi_read_reg_8(indio_dev, ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR, LIS3L02DQ_REG_CTRL_1_ADDR,
(u8 *)&t); (u8 *)&t);
...@@ -565,6 +568,7 @@ static int lis3l02dq_read_event_config(struct iio_dev *indio_dev, ...@@ -565,6 +568,7 @@ static int lis3l02dq_read_event_config(struct iio_dev *indio_dev,
u8 val; u8 val;
int ret; int ret;
u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING))); u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
ret = lis3l02dq_spi_read_reg_8(indio_dev, ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_WAKE_UP_CFG_ADDR, LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
&val); &val);
......
...@@ -19,6 +19,7 @@ static inline u16 combine_8_to_16(u8 lower, u8 upper) ...@@ -19,6 +19,7 @@ static inline u16 combine_8_to_16(u8 lower, u8 upper)
{ {
u16 _lower = lower; u16 _lower = lower;
u16 _upper = upper; u16 _upper = upper;
return _lower | (_upper << 8); return _lower | (_upper << 8);
} }
......
...@@ -506,7 +506,8 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, ...@@ -506,7 +506,8 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
return ret; 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); mutex_unlock(&st->lock);
return IIO_VAL_INT; return IIO_VAL_INT;
...@@ -713,6 +714,7 @@ static int sca3000_read_thresh(struct iio_dev *indio_dev, ...@@ -713,6 +714,7 @@ static int sca3000_read_thresh(struct iio_dev *indio_dev,
int ret, i; int ret, i;
struct sca3000_state *st = iio_priv(indio_dev); struct sca3000_state *st = iio_priv(indio_dev);
int num = chan->channel2; int num = chan->channel2;
mutex_lock(&st->lock); mutex_lock(&st->lock);
ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]); ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]);
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
......
...@@ -3,13 +3,6 @@ ...@@ -3,13 +3,6 @@
# #
menu "Direct Digital Synthesis" 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 config AD9832
tristate "Analog Devices ad9832/5 driver" tristate "Analog Devices ad9832/5 driver"
depends on SPI depends on SPI
...@@ -30,32 +23,4 @@ config AD9834 ...@@ -30,32 +23,4 @@ config AD9834
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ad9834. 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 endmenu
...@@ -2,10 +2,5 @@ ...@@ -2,10 +2,5 @@
# Makefile for Direct Digital Synthesis drivers # Makefile for Direct Digital Synthesis drivers
# #
obj-$(CONFIG_AD5930) += ad5930.o
obj-$(CONFIG_AD9832) += ad9832.o obj-$(CONFIG_AD9832) += ad9832.o
obj-$(CONFIG_AD9834) += ad9834.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
/*
* 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);
/*
* 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);
/*
* 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);
/*
* 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);
/*
* 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);
...@@ -180,6 +180,7 @@ static int adis16060_w_probe(struct spi_device *spi) ...@@ -180,6 +180,7 @@ static int adis16060_w_probe(struct spi_device *spi)
int ret; int ret;
struct iio_dev *indio_dev = adis16060_iio_dev; struct iio_dev *indio_dev = adis16060_iio_dev;
struct adis16060_state *st; struct adis16060_state *st;
if (!indio_dev) { if (!indio_dev) {
ret = -ENODEV; ret = -ENODEV;
goto error_ret; goto error_ret;
......
...@@ -220,7 +220,7 @@ static int ad5933_set_freq(struct ad5933_state *st, ...@@ -220,7 +220,7 @@ static int ad5933_set_freq(struct ad5933_state *st,
{ {
unsigned long long freqreg; unsigned long long freqreg;
union { union {
u32 d32; __be32 d32;
u8 d8[4]; u8 d8[4];
} dat; } dat;
...@@ -244,7 +244,7 @@ static int ad5933_set_freq(struct ad5933_state *st, ...@@ -244,7 +244,7 @@ static int ad5933_set_freq(struct ad5933_state *st,
static int ad5933_setup(struct ad5933_state *st) static int ad5933_setup(struct ad5933_state *st)
{ {
unsigned short dat; __be16 dat;
int ret; int ret;
ret = ad5933_reset(st); ret = ad5933_reset(st);
...@@ -297,7 +297,7 @@ static ssize_t ad5933_show_frequency(struct device *dev, ...@@ -297,7 +297,7 @@ static ssize_t ad5933_show_frequency(struct device *dev,
int ret; int ret;
unsigned long long freqreg; unsigned long long freqreg;
union { union {
u32 d32; __be32 d32;
u8 d8[4]; u8 d8[4];
} dat; } dat;
...@@ -402,7 +402,7 @@ static ssize_t ad5933_store(struct device *dev, ...@@ -402,7 +402,7 @@ static ssize_t ad5933_store(struct device *dev,
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u16 val; u16 val;
int i, ret = 0; int i, ret = 0;
unsigned short dat; __be16 dat;
if (this_attr->address != AD5933_IN_PGA_GAIN) { if (this_attr->address != AD5933_IN_PGA_GAIN) {
ret = kstrtou16(buf, 10, &val); ret = kstrtou16(buf, 10, &val);
...@@ -521,7 +521,7 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, ...@@ -521,7 +521,7 @@ static int ad5933_read_raw(struct iio_dev *indio_dev,
long m) long m)
{ {
struct ad5933_state *st = iio_priv(indio_dev); struct ad5933_state *st = iio_priv(indio_dev);
unsigned short dat; __be16 dat;
int ret = -EINVAL; int ret = -EINVAL;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
......
...@@ -454,7 +454,7 @@ static const struct attribute_group isl29108_group = { ...@@ -454,7 +454,7 @@ static const struct attribute_group isl29108_group = {
static int isl29018_chip_init(struct isl29018_chip *chip) static int isl29018_chip_init(struct isl29018_chip *chip)
{ {
int status; int status;
int new_adc_bit; unsigned int new_adc_bit;
unsigned int new_range; unsigned int new_range;
/* Code added per Intersil Application Note 1534: /* Code added per Intersil Application Note 1534:
......
...@@ -131,7 +131,7 @@ static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode) ...@@ -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) static int hmc5843_wait_measurement(struct hmc5843_data *data)
{ {
int tries = 150; int tries = 150;
int val; unsigned int val;
int ret; int ret;
while (tries-- > 0) { while (tries-- > 0) {
...@@ -209,7 +209,7 @@ static ssize_t hmc5843_show_measurement_configuration(struct device *dev, ...@@ -209,7 +209,7 @@ static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
char *buf) char *buf)
{ {
struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
int val; unsigned int val;
int ret; int ret;
ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &val); ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &val);
...@@ -344,7 +344,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, ...@@ -344,7 +344,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask) int *val, int *val2, long mask)
{ {
struct hmc5843_data *data = iio_priv(indio_dev); struct hmc5843_data *data = iio_priv(indio_dev);
int rval; unsigned int rval;
int ret; int ret;
switch (mask) { switch (mask) {
......
...@@ -491,7 +491,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev, ...@@ -491,7 +491,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev,
switch (chan->type) { switch (chan->type) {
case IIO_ANGL: case IIO_ANGL:
pos = be16_to_cpup((u16 *)st->rx); pos = be16_to_cpup((__be16 *) st->rx);
if (st->hysteresis) if (st->hysteresis)
pos >>= 16 - st->resolution; pos >>= 16 - st->resolution;
*val = pos; *val = pos;
...@@ -499,7 +499,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev, ...@@ -499,7 +499,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev,
break; break;
case IIO_ANGL_VEL: case IIO_ANGL_VEL:
negative = st->rx[0] & 0x80; negative = st->rx[0] & 0x80;
vel = be16_to_cpup((s16 *)st->rx); vel = be16_to_cpup((__be16 *) st->rx);
vel >>= 16 - st->resolution; vel >>= 16 - st->resolution;
if (vel & 0x8000) { if (vel & 0x8000) {
negative = (0xffff >> st->resolution) << st->resolution; negative = (0xffff >> st->resolution) << st->resolution;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment