2016-11-24 04:28:28 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 ARM Ltd.
|
|
|
|
*
|
2017-01-19 09:01:01 +08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2016-11-24 04:28:28 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <device.h>
|
|
|
|
#include <sensor.h>
|
|
|
|
#include <clock_control.h>
|
|
|
|
|
|
|
|
#define SYS_LOG_DOMAIN "TEMPNRF5"
|
|
|
|
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL
|
2016-12-18 01:56:56 +08:00
|
|
|
#include <logging/sys_log.h>
|
2016-11-24 04:28:28 +08:00
|
|
|
|
|
|
|
#include "nrf.h"
|
2018-03-19 21:10:26 +08:00
|
|
|
#include "nrf_common.h"
|
2016-11-24 04:28:28 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* 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 {
|
2016-12-16 09:39:47 +08:00
|
|
|
struct k_sem device_sync_sem;
|
2017-04-21 23:03:20 +08:00
|
|
|
s32_t sample;
|
2016-11-24 04:28:28 +08:00
|
|
|
struct device *clk_m16_dev;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int temp_nrf5_sample_fetch(struct device *dev, enum sensor_channel chan)
|
|
|
|
{
|
|
|
|
volatile NRF_TEMP_Type *temp = NRF_TEMP;
|
|
|
|
struct temp_nrf5_data *data = dev->driver_data;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
SYS_LOG_DBG("");
|
|
|
|
|
2018-04-04 15:13:58 +08:00
|
|
|
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
|
2016-11-24 04:28:28 +08:00
|
|
|
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);
|
|
|
|
|
|
|
|
temp->TASKS_START = 1;
|
2016-12-16 09:39:47 +08:00
|
|
|
k_sem_take(&data->device_sync_sem, K_FOREVER);
|
2016-11-24 04:28:28 +08:00
|
|
|
|
|
|
|
r = clock_control_off(data->clk_m16_dev, (void *)1);
|
|
|
|
__ASSERT_NO_MSG(!r);
|
|
|
|
|
|
|
|
data->sample = temp->TEMP;
|
|
|
|
|
|
|
|
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;
|
2017-04-21 23:03:20 +08:00
|
|
|
s32_t uval;
|
2016-11-24 04:28:28 +08:00
|
|
|
|
|
|
|
SYS_LOG_DBG("");
|
|
|
|
|
2018-04-04 15:13:58 +08:00
|
|
|
if (chan != SENSOR_CHAN_DIE_TEMP) {
|
2016-11-24 04:28:28 +08:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
volatile NRF_TEMP_Type *temp = NRF_TEMP;
|
|
|
|
struct device *dev = (struct device *)arg;
|
|
|
|
struct temp_nrf5_data *data = dev->driver_data;
|
|
|
|
|
|
|
|
temp->EVENTS_DATARDY = 0;
|
2016-12-16 09:39:47 +08:00
|
|
|
k_sem_give(&data->device_sync_sem);
|
2016-11-24 04:28:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct sensor_driver_api temp_nrf5_driver_api = {
|
|
|
|
.sample_fetch = temp_nrf5_sample_fetch,
|
|
|
|
.channel_get = temp_nrf5_channel_get,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int temp_nrf5_init(struct device *dev);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
static int temp_nrf5_init(struct device *dev)
|
|
|
|
{
|
|
|
|
volatile NRF_TEMP_Type *temp = NRF_TEMP;
|
|
|
|
struct temp_nrf5_data *data = dev->driver_data;
|
|
|
|
|
|
|
|
SYS_LOG_DBG("");
|
|
|
|
|
|
|
|
data->clk_m16_dev =
|
|
|
|
device_get_binding(CONFIG_CLOCK_CONTROL_NRF5_M16SRC_DRV_NAME);
|
|
|
|
__ASSERT_NO_MSG(data->clk_m16_dev);
|
|
|
|
|
2016-12-16 09:39:47 +08:00
|
|
|
k_sem_init(&data->device_sync_sem, 0, UINT_MAX);
|
2016-11-24 04:28:28 +08:00
|
|
|
IRQ_CONNECT(NRF5_IRQ_TEMP_IRQn, CONFIG_TEMP_NRF5_PRI,
|
|
|
|
temp_nrf5_isr, DEVICE_GET(temp_nrf5), 0);
|
|
|
|
irq_enable(NRF5_IRQ_TEMP_IRQn);
|
|
|
|
|
|
|
|
temp->INTENSET = TEMP_INTENSET_DATARDY_Set;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|