From ef65f155c21536b3ca21450f2814ed281edc360d Mon Sep 17 00:00:00 2001 From: Bogdan Davidoaia Date: Fri, 26 Feb 2016 14:40:25 +0200 Subject: [PATCH] sensor: add driver for HDC1008 temperature and humidity sensor Add driver for the HDC1008 temperature and relative humidity sensor. Datasheet: http://www.ti.com/lit/ds/symlink/hdc1008.pdf Origin: Original Change-Id: I63cb4cdd94120b80d0d6f3205da073f0817c4f17 Signed-off-by: Bogdan Davidoaia --- drivers/sensor/Kconfig | 2 + drivers/sensor/Kconfig.hdc1008 | 101 ++++++++++++++++++++++ drivers/sensor/Makefile | 1 + drivers/sensor/sensor_hdc1008.c | 144 ++++++++++++++++++++++++++++++++ drivers/sensor/sensor_hdc1008.h | 43 ++++++++++ 5 files changed, 291 insertions(+) create mode 100644 drivers/sensor/Kconfig.hdc1008 create mode 100644 drivers/sensor/sensor_hdc1008.c create mode 100644 drivers/sensor/sensor_hdc1008.h diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 7aefae56c60..cf5516c2bfe 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -46,6 +46,8 @@ config SENSOR_DEBUG source "drivers/sensor/Kconfig.bma280" +source "drivers/sensor/Kconfig.hdc1008" + source "drivers/sensor/Kconfig.isl29035" source "drivers/sensor/Kconfig.mcp9808" diff --git a/drivers/sensor/Kconfig.hdc1008 b/drivers/sensor/Kconfig.hdc1008 new file mode 100644 index 00000000000..8a21f914943 --- /dev/null +++ b/drivers/sensor/Kconfig.hdc1008 @@ -0,0 +1,101 @@ +# Kconfig.hdc1008 - HDC1008 temperature and humidity sensor configuration options + +# +# Copyright (c) 2016 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +menuconfig HDC1008 + bool + prompt "HDC1008 Temperature and Humidity Sensor" + depends on SENSOR && I2C && GPIO + default n + help + Enable driver for HDC1008 temperature and humidity sensors. + +config HDC1008_NAME + string + prompt "Driver name" + default "HDC1008" + depends on HDC1008 + help + Device name with which the HDC1008 sensor is identified. + +config HDC1008_INIT_PRIORITY + int + prompt "Init priority" + depends on HDC1008 + default 70 + help + Device driver initialization priority. + +choice + prompt "I2C address" + depends on HDC1008 + default HDC1008_I2C_ADDR_0 + help + I2C address of the HDC1008 sensor. + +config HDC1008_I2C_ADDR_0 + bool + prompt "0x40" + help + A0 connected GND and A1 connected to GND. + +config HDC1008_I2C_ADDR_1 + bool + prompt "0x41" + help + A0 connected VDD and A1 connected to GND. + +config HDC1008_I2C_ADDR_2 + bool + prompt "0x42" + help + A0 connected GND and A1 connected to VDD. + +config HDC1008_I2C_ADDR_3 + bool + prompt "0x43" + help + A0 connected VDD and A1 connected to VDD. + +endchoice + +config HDC1008_I2C_MASTER_DEV_NAME + string + prompt "I2C master where HDC1008 is connected" + depends on HDC1008 + default "I2C0" + help + Specify the device name of the I2C master device to which the + HDC1008 chip is connected. + +config HDC1008_GPIO_DEV_NAME + string + prompt "GPIO device" + default "GPIO_0" + depends on HDC1008 + help + The device name of the GPIO device to which the HDC1008 data-ready + pin is connected. + +config HDC1008_GPIO_PIN_NUM + int + prompt "Interrupt GPIO pin number" + default 0 + depends on HDC1008 + help + The number of the GPIO on which the data-ready signal from the HDC1008 + chip will be received. diff --git a/drivers/sensor/Makefile b/drivers/sensor/Makefile index c7559d26a10..246789dc37b 100644 --- a/drivers/sensor/Makefile +++ b/drivers/sensor/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_SENSOR_DELAYED_WORK) += sensor.o obj-$(CONFIG_BMA280) += sensor_bma280.o obj-$(CONFIG_BMA280_TRIGGER) += sensor_bma280_trigger.o +obj-$(CONFIG_HDC1008) += sensor_hdc1008.o obj-$(CONFIG_ISL29035) += sensor_isl29035.o obj-$(CONFIG_ISL29035_TRIGGER) += sensor_isl29035_trigger.o obj-$(CONFIG_MCP9808) += sensor_mcp9808.o diff --git a/drivers/sensor/sensor_hdc1008.c b/drivers/sensor/sensor_hdc1008.c new file mode 100644 index 00000000000..ef57df2c4f1 --- /dev/null +++ b/drivers/sensor/sensor_hdc1008.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "sensor_hdc1008.h" + +#ifndef CONFIG_SENSOR_DEBUG +#define DBG(...) { ; } +#else +#include +#define DBG printk +#endif /* CONFIG_SENSOR_DEBUG */ + +static struct hdc1008_data hdc1008_driver; + +static void hdc1008_gpio_callback(struct device *dev, uint32_t pin) +{ + gpio_pin_disable_callback(dev, pin); + nano_sem_give(&hdc1008_driver.data_sem); +} + +static int hdc1008_sample_fetch(struct device *dev) +{ + struct hdc1008_data *drv_data = dev->driver_data; + uint8_t buf[4]; + int rc; + + gpio_pin_enable_callback(drv_data->gpio, CONFIG_HDC1008_GPIO_PIN_NUM); + + buf[0] = HDC1008_REG_TEMP; + rc = i2c_write(drv_data->i2c, buf, 1, HDC1008_I2C_ADDRESS); + if (rc != DEV_OK) { + DBG("Failed to write address pointer\n"); + return DEV_FAIL; + } + + nano_sem_take(&drv_data->data_sem, TICKS_UNLIMITED); + + rc = i2c_read(drv_data->i2c, buf, 4, HDC1008_I2C_ADDRESS); + if (rc != DEV_OK) { + DBG("Failed to read sample data\n"); + return DEV_FAIL; + } + + drv_data->t_sample = (buf[0] << 8) + buf[1]; + drv_data->rh_sample = (buf[2] << 8) + buf[3]; + + return DEV_OK; +} + + +static int hdc1008_channel_get(struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct hdc1008_data *drv_data = dev->driver_data; + uint64_t tmp; + + /* + * See datasheet "Temperature Register" and "Humidity + * Register" sections for more details on processing + * sample data. + */ + if (chan == SENSOR_CHAN_TEMP) { + /* val = -40 + 165 * sample / 2^16 */ + tmp = 165 * (uint64_t)drv_data->t_sample; + val->type = SENSOR_TYPE_INT_PLUS_MICRO; + val->val1 = (int32_t)(tmp >> 16) - 40; + val->val2 = (1000000 * (tmp & 0xFFFF)) >> 16; + } else if (chan == SENSOR_CHAN_HUMIDITY) { + /* val = 100000 * sample / 2^16 */ + tmp = 100000 * (uint64_t)drv_data->rh_sample; + val->type = SENSOR_TYPE_INT_PLUS_MICRO; + val->val1 = tmp >> 16; + val->val2 = (1000000 * (tmp & 0xFFFF)) >> 16; + } else { + return DEV_INVALID_OP; + } + + return DEV_OK; +} + +static struct sensor_driver_api hdc1008_driver_api = { + .sample_fetch = hdc1008_sample_fetch, + .channel_get = hdc1008_channel_get, +}; + +int hdc1008_init(struct device *dev) +{ + struct hdc1008_data *drv_data = dev->driver_data; + int rc; + + dev->driver_api = &hdc1008_driver_api; + + drv_data->i2c = device_get_binding(CONFIG_HDC1008_I2C_MASTER_DEV_NAME); + if (drv_data->i2c == NULL) { + DBG("Failed to get pointer to %s device!\n", + CONFIG_HDC1008_I2C_MASTER_DEV_NAME); + return DEV_INVALID_CONF; + } + + nano_sem_init(&drv_data->data_sem); + + /* setup data ready gpio interrupt */ + drv_data->gpio = device_get_binding(CONFIG_HDC1008_GPIO_DEV_NAME); + if (drv_data->gpio == NULL) { + DBG("Failed to get pointer to %s device\n", + CONFIG_HDC1008_GPIO_DEV_NAME); + return DEV_INVALID_CONF; + } + + gpio_pin_configure(drv_data->gpio, CONFIG_HDC1008_GPIO_PIN_NUM, + GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | + GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE); + + rc = gpio_set_callback(drv_data->gpio, hdc1008_gpio_callback); + if (rc != DEV_OK) { + DBG("Failed to set GPIO callback\n"); + return DEV_FAIL; + } + + return DEV_OK; +} + +DEVICE_INIT(hdc1008, CONFIG_HDC1008_NAME, hdc1008_init, &hdc1008_driver, + NULL, SECONDARY, CONFIG_HDC1008_INIT_PRIORITY); diff --git a/drivers/sensor/sensor_hdc1008.h b/drivers/sensor/sensor_hdc1008.h new file mode 100644 index 00000000000..60d62b64b3a --- /dev/null +++ b/drivers/sensor/sensor_hdc1008.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SENSOR_HDC1008 +#define _SENSOR_HDC1008 + +#include + +#if CONFIG_HDC1008_I2C_ADDR_0 + #define HDC1008_I2C_ADDRESS 0x40 +#elif CONFIG_HDC1008_I2C_ADDR_1 + #define HDC1008_I2C_ADDRESS 0x41 +#elif CONFIG_HDC1008_I2C_ADDR_2 + #define HDC1008_I2C_ADDRESS 0x42 +#elif CONFIG_HDC1008_I2C_ADDR_3 + #define HDC1008_I2C_ADDRESS 0x43 +#endif + +#define HDC1008_REG_TEMP 0x0 +#define HDC1008_REG_HUMIDITY 0x1 + +struct hdc1008_data { + struct device *i2c; + struct device *gpio; + uint16_t t_sample; + uint16_t rh_sample; + struct nano_sem data_sem; +}; + +#endif