staging: iio: new ADT7316/7/8 and ADT7516/7/9 driver
IIO driver for temperature sensor, ADC and DAC devices over SPI and I2C. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Acked-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
bb6f19eafe
commit
35f6b6b86e
|
@ -42,6 +42,7 @@ config IIO_TRIGGER
|
||||||
|
|
||||||
source "drivers/staging/iio/accel/Kconfig"
|
source "drivers/staging/iio/accel/Kconfig"
|
||||||
source "drivers/staging/iio/adc/Kconfig"
|
source "drivers/staging/iio/adc/Kconfig"
|
||||||
|
source "drivers/staging/iio/addac/Kconfig"
|
||||||
source "drivers/staging/iio/gyro/Kconfig"
|
source "drivers/staging/iio/gyro/Kconfig"
|
||||||
source "drivers/staging/iio/imu/Kconfig"
|
source "drivers/staging/iio/imu/Kconfig"
|
||||||
source "drivers/staging/iio/light/Kconfig"
|
source "drivers/staging/iio/light/Kconfig"
|
||||||
|
|
|
@ -11,6 +11,7 @@ obj-$(CONFIG_IIO_SW_RING) += ring_sw.o
|
||||||
|
|
||||||
obj-y += accel/
|
obj-y += accel/
|
||||||
obj-y += adc/
|
obj-y += adc/
|
||||||
|
obj-y += addac/
|
||||||
obj-y += gyro/
|
obj-y += gyro/
|
||||||
obj-y += imu/
|
obj-y += imu/
|
||||||
obj-y += light/
|
obj-y += light/
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#
|
||||||
|
# ADDAC drivers
|
||||||
|
#
|
||||||
|
comment "Analog digital bi-direction convertors"
|
||||||
|
|
||||||
|
config ADT7316
|
||||||
|
tristate "Analog Devices ADT7316/7/8 ADT7516/7/9 temperature sensor, ADC and DAC driver"
|
||||||
|
help
|
||||||
|
Say yes here to build support for Analog Devices ADT7316, ADT7317, ADT7318
|
||||||
|
and ADT7516, ADT7517, ADT7519 temperature sensors, ADC and DAC.
|
||||||
|
|
||||||
|
config ADT7316_SPI
|
||||||
|
tristate "support SPI bus connection"
|
||||||
|
depends on SPI && ADT7316
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Say yes here to build SPI bus support for Analog Devices ADT7316/7/8
|
||||||
|
and ADT7516/7/9.
|
||||||
|
|
||||||
|
config ADT7316_I2C
|
||||||
|
tristate "support I2C bus connection"
|
||||||
|
depends on I2C && ADT7316
|
||||||
|
help
|
||||||
|
Say yes here to build I2C bus support for Analog Devices ADT7316/7/8
|
||||||
|
and ADT7516/7/9.
|
|
@ -0,0 +1,7 @@
|
||||||
|
#
|
||||||
|
# Makefile for industrial I/O ADDAC drivers
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_ADT7316) += adt7316.o
|
||||||
|
obj-$(CONFIG_ADT7316_SPI) += adt7316-spi.o
|
||||||
|
obj-$(CONFIG_ADT7316_I2C) += adt7316-i2c.o
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* I2C bus driver for ADT7316/7/8 ADT7516/7/9 digital temperature
|
||||||
|
* sensor, ADC and DAC
|
||||||
|
*
|
||||||
|
* Copyright 2010 Analog Devices Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the GPL-2 or later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
|
#include "adt7316.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* adt7316 register access by I2C
|
||||||
|
*/
|
||||||
|
static int adt7316_i2c_read(void *client, u8 reg, u8 *data)
|
||||||
|
{
|
||||||
|
struct i2c_client *cl = client;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte(cl, reg);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&cl->dev, "I2C fail to select reg\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte(client);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&cl->dev, "I2C read error\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adt7316_i2c_write(void *client, u8 reg, u8 data)
|
||||||
|
{
|
||||||
|
struct i2c_client *cl = client;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(cl, reg, data);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(&cl->dev, "I2C write error\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adt7316_i2c_multi_read(void *client, u8 reg, u8 count, u8 *data)
|
||||||
|
{
|
||||||
|
struct i2c_client *cl = client;
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
if (count > ADT7316_REG_MAX_ADDR)
|
||||||
|
count = ADT7316_REG_MAX_ADDR;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
ret = adt7316_i2c_read(cl, reg, &data[i]);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&cl->dev, "I2C multi read error\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adt7316_i2c_multi_write(void *client, u8 reg, u8 count, u8 *data)
|
||||||
|
{
|
||||||
|
struct i2c_client *cl = client;
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
if (count > ADT7316_REG_MAX_ADDR)
|
||||||
|
count = ADT7316_REG_MAX_ADDR;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
ret = adt7316_i2c_write(cl, reg, data[i]);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&cl->dev, "I2C multi write error\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* device probe and remove
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int __devinit adt7316_i2c_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct adt7316_bus bus = {
|
||||||
|
.client = client,
|
||||||
|
.irq = client->irq,
|
||||||
|
.irq_flags = IRQF_TRIGGER_LOW,
|
||||||
|
.read = adt7316_i2c_read,
|
||||||
|
.write = adt7316_i2c_write,
|
||||||
|
.multi_read = adt7316_i2c_multi_read,
|
||||||
|
.multi_write = adt7316_i2c_multi_write,
|
||||||
|
};
|
||||||
|
|
||||||
|
return adt7316_probe(&client->dev, &bus, id->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit adt7316_i2c_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
return adt7316_remove(&client->dev);;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id adt7316_i2c_id[] = {
|
||||||
|
{ "adt7316", 0 },
|
||||||
|
{ "adt7317", 0 },
|
||||||
|
{ "adt7318", 0 },
|
||||||
|
{ "adt7516", 0 },
|
||||||
|
{ "adt7517", 0 },
|
||||||
|
{ "adt7519", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(i2c, adt7316_i2c_id);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int adt7316_i2c_suspend(struct i2c_client *client, pm_message_t message)
|
||||||
|
{
|
||||||
|
return adt7316_disable(&client->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adt7316_i2c_resume(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
return adt7316_enable(&client->dev);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define adt7316_i2c_suspend NULL
|
||||||
|
# define adt7316_i2c_resume NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct i2c_driver adt7316_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "adt7316",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.probe = adt7316_i2c_probe,
|
||||||
|
.remove = __devexit_p(adt7316_i2c_remove),
|
||||||
|
.suspend = adt7316_i2c_suspend,
|
||||||
|
.resume = adt7316_i2c_resume,
|
||||||
|
.id_table = adt7316_i2c_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
static __init int adt7316_i2c_init(void)
|
||||||
|
{
|
||||||
|
return i2c_add_driver(&adt7316_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __exit void adt7316_i2c_exit(void)
|
||||||
|
{
|
||||||
|
i2c_del_driver(&adt7316_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
|
||||||
|
MODULE_DESCRIPTION("I2C bus driver for Analog Devices ADT7316/7/9 and"
|
||||||
|
"ADT7516/7/8 digital temperature sensor, ADC and DAC");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
||||||
|
module_init(adt7316_i2c_init);
|
||||||
|
module_exit(adt7316_i2c_exit);
|
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* API bus driver for ADT7316/7/8 ADT7516/7/9 digital temperature
|
||||||
|
* sensor, ADC and DAC
|
||||||
|
*
|
||||||
|
* Copyright 2010 Analog Devices Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the GPL-2 or later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
|
#include "adt7316.h"
|
||||||
|
|
||||||
|
#define ADT7316_SPI_MAX_FREQ_HZ 5000000
|
||||||
|
#define ADT7316_SPI_CMD_READ 0x91
|
||||||
|
#define ADT7316_SPI_CMD_WRITE 0x90
|
||||||
|
|
||||||
|
/*
|
||||||
|
* adt7316 register access by SPI
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int adt7316_spi_multi_read(void *client, u8 reg, u8 count, u8 *data)
|
||||||
|
{
|
||||||
|
struct spi_device *spi_dev = client;
|
||||||
|
u8 cmd[2];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (count > ADT7316_REG_MAX_ADDR)
|
||||||
|
count = ADT7316_REG_MAX_ADDR;
|
||||||
|
|
||||||
|
cmd[0] = ADT7316_SPI_CMD_WRITE;
|
||||||
|
cmd[1] = reg;
|
||||||
|
|
||||||
|
ret = spi_write(spi_dev, cmd, 2);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&spi_dev->dev, "SPI fail to select reg\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd[0] = ADT7316_SPI_CMD_READ;
|
||||||
|
|
||||||
|
ret = spi_write_then_read(spi_dev, cmd, 1, data, count);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&spi_dev->dev, "SPI read data error\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adt7316_spi_multi_write(void *client, u8 reg, u8 count, u8 *data)
|
||||||
|
{
|
||||||
|
struct spi_device *spi_dev = client;
|
||||||
|
u8 buf[ADT7316_REG_MAX_ADDR + 2];
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
if (count > ADT7316_REG_MAX_ADDR)
|
||||||
|
count = ADT7316_REG_MAX_ADDR;
|
||||||
|
|
||||||
|
buf[0] = ADT7316_SPI_CMD_WRITE;
|
||||||
|
buf[1] = reg;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
buf[i + 2] = data[i];
|
||||||
|
|
||||||
|
ret = spi_write(spi_dev, buf, count + 2);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&spi_dev->dev, "SPI write error\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adt7316_spi_read(void *client, u8 reg, u8 *data)
|
||||||
|
{
|
||||||
|
return adt7316_spi_multi_read(client, reg, 1, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adt7316_spi_write(void *client, u8 reg, u8 val)
|
||||||
|
{
|
||||||
|
return adt7316_spi_multi_write(client, reg, 1, &val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* device probe and remove
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int __devinit adt7316_spi_probe(struct spi_device *spi_dev)
|
||||||
|
{
|
||||||
|
struct adt7316_bus bus = {
|
||||||
|
.client = spi_dev,
|
||||||
|
.irq = spi_dev->irq,
|
||||||
|
.irq_flags = IRQF_TRIGGER_LOW,
|
||||||
|
.read = adt7316_spi_read,
|
||||||
|
.write = adt7316_spi_write,
|
||||||
|
.multi_read = adt7316_spi_multi_read,
|
||||||
|
.multi_write = adt7316_spi_multi_write,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* don't exceed max specified SPI CLK frequency */
|
||||||
|
if (spi_dev->max_speed_hz > ADT7316_SPI_MAX_FREQ_HZ) {
|
||||||
|
dev_err(&spi_dev->dev, "SPI CLK %d Hz?\n",
|
||||||
|
spi_dev->max_speed_hz);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* switch from default I2C protocol to SPI protocol */
|
||||||
|
adt7316_spi_write(spi_dev, 0, 0);
|
||||||
|
adt7316_spi_write(spi_dev, 0, 0);
|
||||||
|
adt7316_spi_write(spi_dev, 0, 0);
|
||||||
|
|
||||||
|
return adt7316_probe(&spi_dev->dev, &bus, spi_dev->modalias);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit adt7316_spi_remove(struct spi_device *spi_dev)
|
||||||
|
{
|
||||||
|
return adt7316_remove(&spi_dev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct spi_device_id adt7316_spi_id[] = {
|
||||||
|
{ "adt7316", 0 },
|
||||||
|
{ "adt7317", 0 },
|
||||||
|
{ "adt7318", 0 },
|
||||||
|
{ "adt7516", 0 },
|
||||||
|
{ "adt7517", 0 },
|
||||||
|
{ "adt7519", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(spi, adt7316_spi_id);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int adt7316_spi_suspend(struct spi_device *spi_dev, pm_message_t message)
|
||||||
|
{
|
||||||
|
return adt7316_disable(&spi_dev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adt7316_spi_resume(struct spi_device *spi_dev)
|
||||||
|
{
|
||||||
|
return adt7316_enable(&spi_dev->dev);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define adt7316_spi_suspend NULL
|
||||||
|
# define adt7316_spi_resume NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct spi_driver adt7316_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "adt7316",
|
||||||
|
.bus = &spi_bus_type,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.probe = adt7316_spi_probe,
|
||||||
|
.remove = __devexit_p(adt7316_spi_remove),
|
||||||
|
.suspend = adt7316_spi_suspend,
|
||||||
|
.resume = adt7316_spi_resume,
|
||||||
|
.id_table = adt7316_spi_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
static __init int adt7316_spi_init(void)
|
||||||
|
{
|
||||||
|
return spi_register_driver(&adt7316_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __exit void adt7316_spi_exit(void)
|
||||||
|
{
|
||||||
|
spi_unregister_driver(&adt7316_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
|
||||||
|
MODULE_DESCRIPTION("SPI bus driver for Analog Devices ADT7316/7/8 and"
|
||||||
|
"ADT7516/7/9 digital temperature sensor, ADC and DAC");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
||||||
|
module_init(adt7316_spi_init);
|
||||||
|
module_exit(adt7316_spi_exit);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* ADT7316 digital temperature sensor driver supporting ADT7316/7/8 ADT7516/7/9
|
||||||
|
*
|
||||||
|
* Copyright 2010 Analog Devices Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the GPL-2 or later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ADT7316_H_
|
||||||
|
#define _ADT7316_H_
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define ADT7316_REG_MAX_ADDR 0x3F
|
||||||
|
|
||||||
|
struct adt7316_bus {
|
||||||
|
void *client;
|
||||||
|
int irq;
|
||||||
|
int irq_flags;
|
||||||
|
int (*read) (void *client, u8 reg, u8 *data);
|
||||||
|
int (*write) (void *client, u8 reg, u8 val);
|
||||||
|
int (*multi_read) (void *client, u8 first_reg, u8 count, u8 *data);
|
||||||
|
int (*multi_write) (void *client, u8 first_reg, u8 count, u8 *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
int adt7316_disable(struct device *dev);
|
||||||
|
int adt7316_enable(struct device *dev);
|
||||||
|
#endif
|
||||||
|
int adt7316_probe(struct device *dev, struct adt7316_bus *bus, const char *name);
|
||||||
|
int adt7316_remove(struct device *dev);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue