Skip to content

Commit

Permalink
drivers: sensor: Add F75303 driver
Browse files Browse the repository at this point in the history
Add driver for F75303 temperature sensor IC.

Signed-off-by: Paweł Anikiel <pan@semihalf.com>
  • Loading branch information
Paweł Anikiel committed Aug 9, 2023
1 parent af55a8e commit fd5b8a1
Show file tree
Hide file tree
Showing 10 changed files with 465 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/sensor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ add_subdirectory_ifdef(CONFIG_DPS310 dps310)
add_subdirectory_ifdef(CONFIG_DS18B20 ds18b20)
add_subdirectory_ifdef(CONFIG_ENS210 ens210)
add_subdirectory_ifdef(CONFIG_ESP32_TEMP esp32_temp)
add_subdirectory_ifdef(CONFIG_F75303 f75303)
add_subdirectory_ifdef(CONFIG_FDC2X1X fdc2x1x)
add_subdirectory_ifdef(CONFIG_FXAS21002 fxas21002)
add_subdirectory_ifdef(CONFIG_FXOS8700 fxos8700)
Expand Down
1 change: 1 addition & 0 deletions drivers/sensor/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ source "drivers/sensor/dps310/Kconfig"
source "drivers/sensor/ds18b20/Kconfig"
source "drivers/sensor/ens210/Kconfig"
source "drivers/sensor/esp32_temp/Kconfig"
source "drivers/sensor/f75303/Kconfig"
source "drivers/sensor/fdc2x1x/Kconfig"
source "drivers/sensor/fxas21002/Kconfig"
source "drivers/sensor/fxos8700/Kconfig"
Expand Down
5 changes: 5 additions & 0 deletions drivers/sensor/f75303/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_library()
zephyr_library_sources(f75303.c)
zephyr_library_sources_ifdef(CONFIG_EMUL_F75303 f75303_emul.c)
22 changes: 22 additions & 0 deletions drivers/sensor/f75303/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# F75303 temperature sensor configuration options

# Copyright (c) 2023 Google LLC
# SPDX-License-Identifier: Apache-2.0

config F75303
bool "F75303 Temperature Sensor"
default y
depends on DT_HAS_FINTEK_F75303_ENABLED
select I2C
help
Enable the driver for Fintek F75303 Temperature Sensor.
This device has three temperature channels - one local (on-chip),
and two remote.

config EMUL_F75303
bool "Emulator for F75303"
default y
depends on F75303
depends on EMUL
help
Enable the hardware emulator for F75303 Temperature Sensor.
198 changes: 198 additions & 0 deletions drivers/sensor/f75303/f75303.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* Copyright (c) 2023 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT fintek_f75303

#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor/f75303.h>
#include "f75303.h"

#define F75303_SAMPLE_INT_SHIFT 3
#define F75303_SAMPLE_FRAC_MASK GENMASK(2, 0)
#define F75303_SAMPLE_MICROCELSIUS_PER_BIT 125000

LOG_MODULE_REGISTER(F75303, CONFIG_SENSOR_LOG_LEVEL);

static int f75303_fetch(const struct i2c_dt_spec *i2c,
uint8_t off_h, uint8_t off_l, uint16_t *sample)
{
uint8_t val_h;
uint8_t val_l;
int res;

res = i2c_reg_read_byte_dt(i2c, off_h, &val_h);
if (res) {
return res;
}

res = i2c_reg_read_byte_dt(i2c, off_l, &val_l);
if (res) {
return res;
}

*sample = val_h << 3 | val_l >> 5;

return 0;
}

static int f75303_fetch_local(const struct device *dev)
{
struct f75303_data *data = dev->data;
const struct f75303_config *config = dev->config;

return f75303_fetch(&config->i2c,
F75303_LOCAL_TEMP_H,
F75303_LOCAL_TEMP_L,
&data->sample_local);
}

static int f75303_fetch_remote1(const struct device *dev)
{
struct f75303_data *data = dev->data;
const struct f75303_config *config = dev->config;

return f75303_fetch(&config->i2c,
F75303_REMOTE1_TEMP_H,
F75303_REMOTE1_TEMP_L,
&data->sample_remote1);
}

static int f75303_fetch_remote2(const struct device *dev)
{
struct f75303_data *data = dev->data;
const struct f75303_config *config = dev->config;

return f75303_fetch(&config->i2c,
F75303_REMOTE2_TEMP_H,
F75303_REMOTE2_TEMP_L,
&data->sample_remote2);
}

static int f75303_sample_fetch(const struct device *dev,
enum sensor_channel chan)
{
enum pm_device_state pm_state;
int res;

(void)pm_device_state_get(dev, &pm_state);
if (pm_state != PM_DEVICE_STATE_ACTIVE) {
return -EIO;
}

switch ((uint32_t)chan) {
case SENSOR_CHAN_ALL:
res = f75303_fetch_local(dev);
if (res) {
break;
}
res = f75303_fetch_remote1(dev);
if (res) {
break;
}
res = f75303_fetch_remote2(dev);
break;
case SENSOR_CHAN_AMBIENT_TEMP:
return f75303_fetch_local(dev);
case SENSOR_CHAN_F75303_REMOTE1:
return f75303_fetch_remote1(dev);
case SENSOR_CHAN_F75303_REMOTE2:
return f75303_fetch_remote2(dev);
default:
return -ENOTSUP;
}

return res;
}

static int f75303_channel_get(const struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct f75303_data *data = dev->data;
uint16_t sample;

switch ((uint32_t)chan) {
case SENSOR_CHAN_AMBIENT_TEMP:
sample = data->sample_local;
break;
case SENSOR_CHAN_F75303_REMOTE1:
sample = data->sample_remote1;
break;
case SENSOR_CHAN_F75303_REMOTE2:
sample = data->sample_remote2;
break;
default:
return -ENOTSUP;
}

/*
* The reading is given in steps of 0.125 degrees celsius, i.e. the
* temperature in degrees celsius is equal to sample / 8.
*/
val->val1 = sample >> F75303_SAMPLE_INT_SHIFT;
val->val2 = (sample & F75303_SAMPLE_FRAC_MASK) * F75303_SAMPLE_MICROCELSIUS_PER_BIT;

return 0;
}

static const struct sensor_driver_api f75303_driver_api = {
.sample_fetch = f75303_sample_fetch,
.channel_get = f75303_channel_get,
};

static int f75303_init(const struct device *dev)
{
const struct f75303_config *config = dev->config;
int res = 0;

if (!i2c_is_ready_dt(&config->i2c)) {
LOG_ERR("I2C device not ready");
return -ENODEV;
}

#ifdef CONFIG_PM_DEVICE_RUNTIME
pm_device_init_suspended(dev);

res = pm_device_runtime_enable(dev);
if (res) {
LOG_ERR("Failed to enable runtime power management");
}
#endif

return res;
}

#ifdef CONFIG_PM_DEVICE
static int f75303_pm_action(const struct device *dev, enum pm_device_action action)
{
switch (action) {
case PM_DEVICE_ACTION_TURN_ON:
case PM_DEVICE_ACTION_RESUME:
case PM_DEVICE_ACTION_TURN_OFF:
case PM_DEVICE_ACTION_SUSPEND:
return 0;
default:
return -ENOTSUP;
}
}
#endif

#define F75303_INST(inst) \
static struct f75303_data f75303_data_##inst; \
static const struct f75303_config f75303_config_##inst = { \
.i2c = I2C_DT_SPEC_INST_GET(inst), \
}; \
PM_DEVICE_DT_INST_DEFINE(inst, f75303_pm_action); \
SENSOR_DEVICE_DT_INST_DEFINE(inst, f75303_init, PM_DEVICE_DT_INST_GET(inst), \
&f75303_data_##inst, &f75303_config_##inst, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, &f75303_driver_api);

DT_INST_FOREACH_STATUS_OKAY(F75303_INST)
30 changes: 30 additions & 0 deletions drivers/sensor/f75303/f75303.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2023 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_DRIVERS_SENSOR_F75303_F75303_H_
#define ZEPHYR_DRIVERS_SENSOR_F75303_F75303_H_

#include <zephyr/device.h>
#include <zephyr/sys/util.h>

#define F75303_LOCAL_TEMP_H 0x00
#define F75303_REMOTE1_TEMP_H 0x01
#define F75303_REMOTE1_TEMP_L 0x10
#define F75303_REMOTE2_TEMP_H 0x23
#define F75303_REMOTE2_TEMP_L 0x24
#define F75303_LOCAL_TEMP_L 0x29

struct f75303_data {
uint16_t sample_local;
uint16_t sample_remote1;
uint16_t sample_remote2;
};

struct f75303_config {
struct i2c_dt_spec i2c;
};

#endif
Loading

0 comments on commit fd5b8a1

Please sign in to comment.