From 10ef1a7cbada7ef3d841b6d2f6110cea9077c75e Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Sun, 8 Jan 2023 14:27:52 +0900 Subject: [PATCH] drivers: sensors: Add support for RaspberryPi Pico CPU temperature Support for the measuring the CPU die temperature for the RaspberryPi Pico. Signed-off-by: TOKITA Hiroshi --- drivers/sensor/CMakeLists.txt | 1 + drivers/sensor/Kconfig | 2 + drivers/sensor/rpi_pico_temp/CMakeLists.txt | 6 + drivers/sensor/rpi_pico_temp/Kconfig | 13 ++ drivers/sensor/rpi_pico_temp/rpi_pico_temp.c | 133 ++++++++++++++++++ dts/arm/rpi_pico/rp2040.dtsi | 10 ++ .../sensor/raspberrrypi,pico-temp.yaml | 35 +++++ 7 files changed, 200 insertions(+) create mode 100644 drivers/sensor/rpi_pico_temp/CMakeLists.txt create mode 100644 drivers/sensor/rpi_pico_temp/Kconfig create mode 100644 drivers/sensor/rpi_pico_temp/rpi_pico_temp.c create mode 100644 dts/bindings/sensor/raspberrrypi,pico-temp.yaml diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index c412416e9d2..61ea2d14523 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -116,6 +116,7 @@ add_subdirectory_ifdef(CONFIG_TACH_IT8XXX2 ite_tach_it8xxx2) add_subdirectory_ifdef(CONFIG_VCMP_IT8XXX2 ite_vcmp_it8xxx2) add_subdirectory_ifdef(CONFIG_PCNT_ESP32 pcnt_esp32) add_subdirectory_ifdef(CONFIG_ESP32_TEMP esp32_temp) +add_subdirectory_ifdef(CONFIG_RPI_PICO_TEMP rpi_pico_temp) if(CONFIG_USERSPACE OR CONFIG_SENSOR_SHELL OR CONFIG_SENSOR_SHELL_BATTERY) # The above if() is needed or else CMake would complain about diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 8f9efe534fb..49d7d16694a 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -271,4 +271,6 @@ source "drivers/sensor/pcnt_esp32/Kconfig" source "drivers/sensor/esp32_temp/Kconfig" +source "drivers/sensor/rpi_pico_temp/Kconfig" + endif # SENSOR diff --git a/drivers/sensor/rpi_pico_temp/CMakeLists.txt b/drivers/sensor/rpi_pico_temp/CMakeLists.txt new file mode 100644 index 00000000000..5e87675353d --- /dev/null +++ b/drivers/sensor/rpi_pico_temp/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(rpi_pico_temp.c) diff --git a/drivers/sensor/rpi_pico_temp/Kconfig b/drivers/sensor/rpi_pico_temp/Kconfig new file mode 100644 index 00000000000..9b618984d88 --- /dev/null +++ b/drivers/sensor/rpi_pico_temp/Kconfig @@ -0,0 +1,13 @@ +# Raspberry Pi Pico temperature sensor configuration options + +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config RPI_PICO_TEMP + bool "Raspberry Pi Pico CPU Temperature Sensor" + default y + depends on DT_HAS_RASPBERRYPI_PICO_TEMP_ENABLED + depends on ADC + + help + Enable driver for Raspberry Pi Pico CPU temperature sensor. diff --git a/drivers/sensor/rpi_pico_temp/rpi_pico_temp.c b/drivers/sensor/rpi_pico_temp/rpi_pico_temp.c new file mode 100644 index 00000000000..894b2b0cabf --- /dev/null +++ b/drivers/sensor/rpi_pico_temp/rpi_pico_temp.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(rpi_pico_temp, CONFIG_SENSOR_LOG_LEVEL); + +#define DT_DRV_COMPAT raspberrypi_pico_temp + +struct rpi_pico_temp_config { + const struct device *adc; + const struct adc_channel_cfg ch_cfg; + const int32_t vbe; + const int32_t vbe_slope; +}; + +struct rpi_pico_temp_data { + struct adc_sequence adc_seq; + int16_t sample; +}; + +static int rpi_pico_temp_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct rpi_pico_temp_config *cfg = dev->config; + struct rpi_pico_temp_data *data = dev->data; + int rc; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + rc = adc_channel_setup(cfg->adc, &cfg->ch_cfg); + if (rc) { + LOG_DBG("Setup ADC channel %u failed with %d", cfg->ch_cfg.channel_id, rc); + return rc; + } + + rc = adc_read(cfg->adc, &data->adc_seq); + + return rc; +} + +static int rpi_pico_temp_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + const struct rpi_pico_temp_config *cfg = dev->config; + struct rpi_pico_temp_data *data = dev->data; + int32_t mv = 0; + int32_t work; + int rc; + + if (chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + mv = data->sample; + rc = adc_raw_to_millivolts(adc_ref_internal(cfg->adc), cfg->ch_cfg.gain, + data->adc_seq.resolution, &mv); + if (rc) { + LOG_DBG("adc_raw_to_millivolts() failed %d", rc); + return rc; + } + + /* + * Calculate CPU temperature from voltage by the equation: + * T = 27 - (ADC_Voltage - 0.706)/0.001721 + */ + work = ((27 * (-cfg->vbe_slope)) - (mv * 1000 - cfg->vbe)); + val->val1 = work / (-cfg->vbe_slope); + work -= val->val1 * (-cfg->vbe_slope); + val->val2 = work * 1000000 / (-cfg->vbe_slope); + + return 0; +} + +static const struct sensor_driver_api rpi_pico_temp_driver_api = { + .sample_fetch = rpi_pico_temp_sample_fetch, + .channel_get = rpi_pico_temp_channel_get, +}; + +static int rpi_pico_temp_init(const struct device *dev) +{ + const struct rpi_pico_temp_config *cfg = dev->config; + + if (!device_is_ready(cfg->adc)) { + LOG_ERR("Device %s is not ready", cfg->adc->name); + return -ENODEV; + } + + adc_set_temp_sensor_enabled(true); + + return 0; +} + +#define RPI_PICO_TEMP_DEFINE(inst) \ + static const struct rpi_pico_temp_config rpi_pico_temp_config_##inst = { \ + .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \ + .vbe = DT_INST_PROP(inst, vbe), \ + .vbe_slope = DT_INST_PROP(inst, vbe_slope), \ + .ch_cfg = \ + { \ + .gain = ADC_GAIN_1, \ + .reference = ADC_REF_INTERNAL, \ + .acquisition_time = ADC_ACQ_TIME_DEFAULT, \ + .channel_id = DT_INST_IO_CHANNELS_INPUT(inst), \ + .differential = 0, \ + }, \ + }; \ + static struct rpi_pico_temp_data rpi_pico_temp_dev_data_##inst = { \ + .adc_seq = \ + { \ + .channels = BIT(DT_INST_IO_CHANNELS_INPUT(inst)), \ + .buffer = &rpi_pico_temp_dev_data_##inst.sample, \ + .buffer_size = sizeof(rpi_pico_temp_dev_data_##inst.sample), \ + .resolution = 12U, \ + }, \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, rpi_pico_temp_init, NULL, \ + &rpi_pico_temp_dev_data_##inst, &rpi_pico_temp_config_##inst, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &rpi_pico_temp_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RPI_PICO_TEMP_DEFINE) diff --git a/dts/arm/rpi_pico/rp2040.dtsi b/dts/arm/rpi_pico/rp2040.dtsi index 7a74dba4482..a5a6fe8d9e9 100644 --- a/dts/arm/rpi_pico/rp2040.dtsi +++ b/dts/arm/rpi_pico/rp2040.dtsi @@ -12,6 +12,10 @@ #include "rpi_pico_common.dtsi" / { + aliases { + die-temp0 = &die_temp; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -185,6 +189,12 @@ pinctrl: pin-controller { compatible = "raspberrypi,pico-pinctrl"; }; + + die_temp: dietemp { + compatible = "raspberrypi,pico-temp"; + io-channels = <&adc 4>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/bindings/sensor/raspberrrypi,pico-temp.yaml b/dts/bindings/sensor/raspberrrypi,pico-temp.yaml new file mode 100644 index 00000000000..98b1e119292 --- /dev/null +++ b/dts/bindings/sensor/raspberrrypi,pico-temp.yaml @@ -0,0 +1,35 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: RaspberryPi Pico family temperature sensor node + +compatible: "raspberrypi,pico-temp" + +include: sensor-device.yaml + +properties: + io-channels: + required: true + description: ADC channel for CPU temperature sensor + + vbe: + type: int + default: 706000 + description: | + Vbe voltage in microvolts at 27 degrees C. Vbe = 0.706V typically. + The temperature sensor measures the Vbe voltage of a biased bipolar diode. + The temperature calculates from the Vbe voltage measured by the sensor + using the following equation typical case. + + T = 27 - (ADC_Voltage - 0.706)/0.001721 + + See also the vbe-slope section. + + vbe-slope: + type: int + default: -1721 + description: | + The slope of Vbe voltage in microvolts per degree C. + Typically, a slope of -1.721mV per degree. + + See also the vbe section.