summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMax Krummenacher <max.oss.09@gmail.com>2014-08-16 21:12:36 +0200
committerMax Krummenacher <max.krummenacher@toradex.com>2015-05-29 13:43:41 +0200
commitf490a9132772ce39fbc9c19711d9ef45b4d5241e (patch)
tree74ef5657b12254e919fe0ba8fa49f7fe6b668e8b /drivers
parentd590761df4903e4fefa4b5672e3caf92738d664a (diff)
stmpe-adc: add temperature channel
read the chips temperature in millikelvin while at it sort the #include directives in alphabetical order.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/stmpe.c8
-rw-r--r--drivers/staging/iio/adc/stmpe-adc.c124
2 files changed, 88 insertions, 44 deletions
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 7c00d922418a..29dbd65f0577 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -422,6 +422,12 @@ static const struct mfd_cell stmpe_ts_cell = {
static struct resource stmpe_adc_resources[] = {
{
+ .name = "STMPE_TEMP_SENS",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
.name = "STMPE_ADC",
.start = 0,
.end = 0,
@@ -470,7 +476,7 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
},
{
.cell = &stmpe_adc_cell,
- .irq = STMPE811_IRQ_ADC,
+ .irq = STMPE811_IRQ_TEMP_SENS,
.block = STMPE_BLOCK_ADC,
},
};
diff --git a/drivers/staging/iio/adc/stmpe-adc.c b/drivers/staging/iio/adc/stmpe-adc.c
index 9669240cc87f..64d081a0d98a 100644
--- a/drivers/staging/iio/adc/stmpe-adc.c
+++ b/drivers/staging/iio/adc/stmpe-adc.c
@@ -20,24 +20,22 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/io.h>
#include <linux/clk.h>
#include <linux/completion.h>
-#include <linux/regulator/consumer.h>
-#include <linux/of_platform.h>
+#include <linux/delay.h>
#include <linux/err.h>
-
-#include <linux/mfd/stmpe.h>
-
+#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
#define STMPE_REG_INT_STA 0x0B
#define STMPE_REG_ADC_INT_EN 0x0E
@@ -48,6 +46,11 @@
#define STMPE_REG_ADC_CAPT 0x22
#define STMPE_REG_ADC_DATA_CH(channel) (0x30 + 2*channel)
+#define STMPE_REG_TEMP_CTRL 0x60
+#define STMPE_START_ONE_TEMP_CONV (0x08 + 0x02 + 0x01)
+#define STMPE_REG_TEMP_DATA 0x61
+#define STMPE_REG_TEMP_TH 0x63
+
#define STMPE_ADC_CH(channel) ((1 << channel) & 0xff)
#define STMPE_ADC_TIMEOUT (msecs_to_jiffies(1000))
@@ -83,16 +86,36 @@ static int stmpe_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
info->channel = (u8)chan->channel;
- stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
- STMPE_ADC_CH(info->channel));
-
- stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT,
- STMPE_ADC_CH(info->channel));
-
- timeout = wait_for_completion_interruptible_timeout
- (&info->completion, STMPE_ADC_TIMEOUT);
-
- *val = info->value;
+ switch (chan->type)
+ {
+ case IIO_VOLTAGE:
+ BUG_ON(info->channel > 7);
+ stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
+ STMPE_ADC_CH(info->channel));
+
+ stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT,
+ STMPE_ADC_CH(info->channel));
+
+ timeout = wait_for_completion_interruptible_timeout
+ (&info->completion, STMPE_ADC_TIMEOUT);
+
+ *val = info->value;
+ break;
+ case IIO_TEMP:
+ BUG_ON(info->channel != 8);
+ stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL,
+ STMPE_START_ONE_TEMP_CONV);
+
+ timeout = wait_for_completion_interruptible_timeout
+ (&info->completion, STMPE_ADC_TIMEOUT);
+ /* absolute temp = +V3.3 * value /7.51 [K] */
+ /* scale to [milli °C] */
+ *val = ((449960l * info->value) / 1024l) - 273150;
+ break;
+ default:
+ BUG();
+ break;
+ }
mutex_unlock(&indio_dev->mlock);
@@ -111,20 +134,29 @@ static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
u8 data[2];
int int_sta;
- int_sta = stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA);
+ if(info->channel < 8) {
+ int_sta = stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA);
- /* Is the interrupt relevant */
- if (!(int_sta & STMPE_ADC_CH(info->channel)))
- return IRQ_NONE;
+ /* Is the interrupt relevant */
+ if (!(int_sta & STMPE_ADC_CH(info->channel)))
+ return IRQ_NONE;
- /* Read value */
- stmpe_block_read(info->stmpe, STMPE_REG_ADC_DATA_CH(info->channel), 2,
- data);
- info->value = ((u32)data[0] << 8) + data[1];
+ /* Read value */
+ stmpe_block_read(info->stmpe,
+ STMPE_REG_ADC_DATA_CH(info->channel), 2, data);
+ info->value = ((u32)data[0] << 8) + data[1];
- stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta);
+ stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta);
- complete(&info->completion);
+ complete(&info->completion);
+ } else if (info->channel == 8) {
+ /* Read value */
+ stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2, data);
+ info->value = ((u32)data[0] << 8) + data[1];
+
+ complete(&info->completion);
+ } else
+ return IRQ_NONE;
return IRQ_HANDLED;
}
@@ -157,19 +189,15 @@ static const struct iio_chan_spec stmpe_adc_all_iio_channels[] = {
STMPE_VOLTAGE_CHAN(5),
STMPE_VOLTAGE_CHAN(6),
STMPE_VOLTAGE_CHAN(7),
-#if 0
{
.type = IIO_TEMP,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.indexed = 1,
.channel = 8,
.event_mask =
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)
}
-#endif
};
static const struct iio_chan_spec stmpe_adc_iio_channels[] = {
@@ -177,19 +205,15 @@ static const struct iio_chan_spec stmpe_adc_iio_channels[] = {
STMPE_VOLTAGE_CHAN(5),
STMPE_VOLTAGE_CHAN(6),
STMPE_VOLTAGE_CHAN(7),
-#if 0
{
.type = IIO_TEMP,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.indexed = 1,
.channel = 8,
.event_mask =
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)
}
-#endif
};
@@ -233,6 +257,10 @@ static int stmpe_adc_init_hw(struct stmpe_adc *adc)
return ret;
}
+ /* use temp irq for each conversion completion */
+ stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH, 0);
+ stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH + 1, 0);
+
return 0;
}
@@ -296,6 +324,16 @@ static int stmpe_adc_probe(struct platform_device *pdev)
info->irq);
goto err_free;
}
+
+ irq = platform_get_irq_byname(pdev, "STMPE_TEMP_SENS");
+ ret = -1;
+ if (irq >= 0)
+ ret = request_threaded_irq(irq, NULL, stmpe_adc_isr, IRQF_ONESHOT,
+ "stmpe-adc", info);
+ if (ret < 0)
+ dev_warn(&pdev->dev, "failed requesting irq for temp sensor, irq = %d\n",
+ info->irq);
+
platform_set_drvdata(pdev, indio_dev);
indio_dev->name = dev_name(&pdev->dev);