/* * Copyright (c) 2016 ARM Ltd. * Copyright (c) 2019 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include LOG_MODULE_REGISTER(temp_nrf5, CONFIG_SENSOR_LOG_LEVEL); /* 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_dev; }; static void hfclk_on_callback(struct device *dev, clock_control_subsys_t subsys, void *user_data) { nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_START); } static int temp_nrf5_sample_fetch(struct device *dev, enum sensor_channel chan) { struct temp_nrf5_data *data = dev->driver_data; struct clock_control_async_data clk_data = { .cb = hfclk_on_callback }; int r; /* Error if before sensor initialized */ if (data->clk_dev == NULL) { return -EAGAIN; } if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { return -ENOTSUP; } r = clock_control_async_on(data->clk_dev, CLOCK_CONTROL_NRF_SUBSYS_HF, &clk_data); __ASSERT_NO_MSG(!r); k_sem_take(&data->device_sync_sem, K_FOREVER); r = clock_control_off(data->clk_dev, CLOCK_CONTROL_NRF_SUBSYS_HF); __ASSERT_NO_MSG(!r); data->sample = nrf_temp_result_get(NRF_TEMP); LOG_DBG("sample: %d", data->sample); nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_STOP); 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; if (chan != SENSOR_CHAN_DIE_TEMP) { return -ENOTSUP; } uval = data->sample * TEMP_NRF5_TEMP_SCALE; val->val1 = uval / 1000000; val->val2 = uval % 1000000; LOG_DBG("Temperature:%d,%d", val->val1, val->val2); 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_event_clear(NRF_TEMP, NRF_TEMP_EVENT_DATARDY); 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(""); /* A null clk_dev indicates sensor has not been initialized */ data->clk_dev = device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL); __ASSERT_NO_MSG(data->clk_dev); k_sem_init(&data->device_sync_sem, 0, UINT_MAX); IRQ_CONNECT( DT_INST_0_NORDIC_NRF_TEMP_IRQ_0, DT_INST_0_NORDIC_NRF_TEMP_IRQ_0_PRIORITY, temp_nrf5_isr, DEVICE_GET(temp_nrf5), 0); irq_enable(DT_INST_0_NORDIC_NRF_TEMP_IRQ_0); nrf_temp_int_enable(NRF_TEMP, NRF_TEMP_INT_DATARDY_MASK); return 0; } static struct temp_nrf5_data temp_nrf5_driver; DEVICE_AND_API_INIT(temp_nrf5, DT_INST_0_NORDIC_NRF_TEMP_LABEL, temp_nrf5_init, &temp_nrf5_driver, NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &temp_nrf5_driver_api);