blob: 62b2a6260abc89eefa784a52b0e81c32b464e6b0 [file] [log] [blame]
/*
* Copyright (c) 2016 ARM Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <device.h>
#include <sensor.h>
#include <clock_control.h>
#include <logging/log.h>
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
LOG_MODULE_REGISTER(TEMPNRF5);
#include "nrf.h"
/* The nRF5 temperature device returns measurements in 0.25C
* increments. Scale to mDegrees C.
*/
#define TEMP_NRF5_TEMP_SCALE (1000000 / 4)
struct temp_nrf5_data {
struct k_sem device_sync_sem;
s32_t sample;
struct device *clk_m16_dev;
};
static int temp_nrf5_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct temp_nrf5_data *data = dev->driver_data;
int r;
LOG_DBG("");
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
return -ENOTSUP;
}
/* The clock driver for nrf51 currently overloads the
* subsystem parameter with a flag to indicate whether or not
* it should block.
*/
r = clock_control_on(data->clk_m16_dev, (void *)1);
__ASSERT_NO_MSG(!r);
NRF_TEMP->TASKS_START = 1;
k_sem_take(&data->device_sync_sem, K_FOREVER);
r = clock_control_off(data->clk_m16_dev, (void *)1);
__ASSERT_NO_MSG(!r || r == -EBUSY);
data->sample = NRF_TEMP->TEMP;
NRF_TEMP->TASKS_STOP = 1;
return 0;
}
static int temp_nrf5_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct temp_nrf5_data *data = dev->driver_data;
s32_t uval;
LOG_DBG("");
if (chan != SENSOR_CHAN_DIE_TEMP) {
return -ENOTSUP;
}
uval = data->sample * TEMP_NRF5_TEMP_SCALE;
val->val1 = uval / 1000000;
val->val2 = uval % 1000000;
return 0;
}
static void temp_nrf5_isr(void *arg)
{
struct device *dev = (struct device *)arg;
struct temp_nrf5_data *data = dev->driver_data;
NRF_TEMP->EVENTS_DATARDY = 0;
k_sem_give(&data->device_sync_sem);
}
static const struct sensor_driver_api temp_nrf5_driver_api = {
.sample_fetch = temp_nrf5_sample_fetch,
.channel_get = temp_nrf5_channel_get,
};
DEVICE_DECLARE(temp_nrf5);
static int temp_nrf5_init(struct device *dev)
{
struct temp_nrf5_data *data = dev->driver_data;
LOG_DBG("");
data->clk_m16_dev =
device_get_binding(DT_NORDIC_NRF_CLOCK_0_LABEL "_16M");
__ASSERT_NO_MSG(data->clk_m16_dev);
k_sem_init(&data->device_sync_sem, 0, UINT_MAX);
IRQ_CONNECT(
DT_NORDIC_NRF_TEMP_0_IRQ_0,
DT_NORDIC_NRF_TEMP_0_IRQ_0_PRIORITY,
temp_nrf5_isr,
DEVICE_GET(temp_nrf5),
0);
irq_enable(DT_NORDIC_NRF_TEMP_0_IRQ_0);
NRF_TEMP->INTENSET = TEMP_INTENSET_DATARDY_Set;
return 0;
}
static struct temp_nrf5_data temp_nrf5_driver;
DEVICE_AND_API_INIT(temp_nrf5,
CONFIG_TEMP_NRF5_NAME,
temp_nrf5_init,
&temp_nrf5_driver,
NULL,
POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY,
&temp_nrf5_driver_api);