common/sensor/sensor.c (255 lines of code) (raw):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sdr.h"
#include "pal.h"
#include "sensor.h"
#include "sensor_def.h"
#define SENSOR_DRIVE_INIT_DECLARE(name) uint8_t name##_init(uint8_t sensor_num)
#define SENSOR_DRIVE_TYPE_INIT_MAP(name) \
{ \
sensor_dev_##name, name##_init \
}
#define SENSOR_READ_RETRY_MAX 3
struct k_thread sensor_poll;
K_KERNEL_STACK_MEMBER(sensor_poll_stack, sensor_poll_stack_size);
uint8_t SensorNum_SensorCfg_map[SENSOR_NUM_MAX];
uint8_t SensorNum_SDR_map[SENSOR_NUM_MAX];
bool enable_sensor_poll = 1;
static bool sensor_poll_eanble_flag = 1;
const int negative_ten_power[16] = { 1, 1, 1, 1, 1, 1,
1, 1000000000, 100000000, 10000000, 1000000, 100000,
10000, 1000, 100, 10 };
sensor_cfg *sensor_config;
SENSOR_DRIVE_INIT_DECLARE(tmp75);
SENSOR_DRIVE_INIT_DECLARE(ast_adc);
SENSOR_DRIVE_INIT_DECLARE(isl69259);
SENSOR_DRIVE_INIT_DECLARE(nvme);
SENSOR_DRIVE_INIT_DECLARE(mp5990);
SENSOR_DRIVE_INIT_DECLARE(isl28022);
SENSOR_DRIVE_INIT_DECLARE(pex89000);
SENSOR_DRIVE_INIT_DECLARE(intel_peci);
SENSOR_DRIVE_INIT_DECLARE(pch);
SENSOR_DRIVE_INIT_DECLARE(adm1278);
SENSOR_DRIVE_INIT_DECLARE(tps53689);
SENSOR_DRIVE_INIT_DECLARE(xdpe15284);
SENSOR_DRIVE_INIT_DECLARE(ltc4282);
SENSOR_DRIVE_INIT_DECLARE(tmp431);
struct sensor_drive_api {
enum sensor_dev dev;
uint8_t (*init)(uint8_t);
} sensor_drive_tbl[] = {
SENSOR_DRIVE_TYPE_INIT_MAP(tmp75), SENSOR_DRIVE_TYPE_INIT_MAP(ast_adc),
SENSOR_DRIVE_TYPE_INIT_MAP(isl69259), SENSOR_DRIVE_TYPE_INIT_MAP(nvme),
SENSOR_DRIVE_TYPE_INIT_MAP(mp5990), SENSOR_DRIVE_TYPE_INIT_MAP(isl28022),
SENSOR_DRIVE_TYPE_INIT_MAP(pex89000), SENSOR_DRIVE_TYPE_INIT_MAP(intel_peci),
SENSOR_DRIVE_TYPE_INIT_MAP(pch), SENSOR_DRIVE_TYPE_INIT_MAP(adm1278),
SENSOR_DRIVE_TYPE_INIT_MAP(tps53689), SENSOR_DRIVE_TYPE_INIT_MAP(xdpe15284),
SENSOR_DRIVE_TYPE_INIT_MAP(ltc4282), SENSOR_DRIVE_TYPE_INIT_MAP(tmp431),
};
static void init_SensorNum(void)
{
for (int i = 0; i < SENSOR_NUM_MAX; i++) {
SensorNum_SDR_map[i] = 0xFF;
SensorNum_SensorCfg_map[i] = 0xFF;
}
}
void map_SensorNum_SDR_CFG(void)
{
uint8_t i, j;
for (i = 0; i < SENSOR_NUM_MAX; i++) {
for (j = 0; j < SDR_NUM; j++) {
if (i == full_sensor_table[j].sensor_num) {
SensorNum_SDR_map[i] = j;
break;
} else if (i == SDR_NUM) {
SensorNum_SDR_map[i] = sensor_null;
}
}
for (j = 0; j < SDR_NUM; j++) {
if (i == sensor_config[j].num) {
SensorNum_SensorCfg_map[i] = j;
break;
} else if (i == SDR_NUM) {
SensorNum_SensorCfg_map[i] = sensor_null;
}
}
}
return;
}
bool access_check(uint8_t sensor_num)
{
bool (*access_checker)(uint8_t);
access_checker = sensor_config[SensorNum_SensorCfg_map[sensor_num]].access_checker;
return (access_checker)(sensor_config[SensorNum_SensorCfg_map[sensor_num]].num);
}
void clear_unaccessible_sensor_cache()
{
uint8_t poll_num;
for (poll_num = 0; poll_num < SENSOR_NUM_MAX; poll_num++) {
if (SensorNum_SensorCfg_map[poll_num] == sensor_null) { // sensor not exist
continue;
}
if (!access_check(poll_num)) {
sensor_config[SensorNum_SensorCfg_map[poll_num]].cache = sensor_fail;
sensor_config[SensorNum_SensorCfg_map[poll_num]].cache_status =
SENSOR_INIT_STATUS;
}
}
}
uint8_t get_sensor_reading(uint8_t sensor_num, int *reading, uint8_t read_mode)
{
if (SensorNum_SDR_map[sensor_num] == 0xFF) { // look for sensor in SDR table
return SENSOR_NOT_FOUND;
}
if (!access_check(sensor_num)) { // sensor not accessable
return SENSOR_NOT_ACCESSIBLE;
}
sensor_cfg *cfg = &sensor_config[SensorNum_SensorCfg_map[sensor_num]];
if (read_mode == get_from_sensor) {
if (cfg->pre_sensor_read_hook) {
if (cfg->pre_sensor_read_hook(sensor_num, cfg->pre_sensor_read_args) ==
false) {
printf("sensor %d pre sensor read failed!\n", sensor_num);
return SENSOR_PRE_READ_ERROR;
}
}
int status = SENSOR_READ_API_UNREGISTER;
if (cfg->read)
status = cfg->read(sensor_num, reading);
if (status == SENSOR_READ_SUCCESS || status == SENSOR_READ_ACUR_SUCCESS) {
cfg->retry = 0;
if (!access_check(
sensor_num)) { // double check access to avoid not accessible read at same moment status change
return SENSOR_NOT_ACCESSIBLE;
}
if (cfg->post_sensor_read_hook) {
if (cfg->post_sensor_read_hook(sensor_num,
cfg->post_sensor_read_args,
reading) == false) {
printf("sensor %d post sensor read failed!\n", sensor_num);
cfg->cache_status = SENSOR_POST_READ_ERROR;
return SENSOR_POST_READ_ERROR;
}
}
memcpy(&cfg->cache, reading, sizeof(*reading));
status = SENSOR_READ_4BYTE_ACUR_SUCCESS;
cfg->cache_status = status;
return cfg->cache_status;
} else {
/* common retry */
if (cfg->retry >= SENSOR_READ_RETRY_MAX)
cfg->cache_status = status;
else
cfg->retry++;
return cfg->cache_status;
}
} else if (read_mode == get_from_cache) {
if (cfg->cache_status == SENSOR_READ_SUCCESS ||
cfg->cache_status == SENSOR_READ_ACUR_SUCCESS ||
cfg->cache_status == SENSOR_READ_4BYTE_ACUR_SUCCESS) {
if (cfg->cache_status == SENSOR_READ_4BYTE_ACUR_SUCCESS)
memcpy(reading, &cfg->cache, sizeof(cfg->cache));
else
*reading = cfg->cache;
if (!access_check(
sensor_num)) { // double check access to avoid not accessible read at same moment status change
return SENSOR_NOT_ACCESSIBLE;
}
return cfg->cache_status;
} else if (cfg->cache_status == SENSOR_INIT_STATUS) {
cfg->cache = sensor_fail;
return cfg->cache_status;
} else {
cfg->cache = sensor_fail;
printf("sensor[%x] cache read fail, status %x\n", sensor_num,
cfg->cache_status);
return cfg->cache_status;
}
}
return SENSOR_UNSPECIFIED_ERROR; // should not reach here
}
void sensor_poll_disable()
{
sensor_poll_eanble_flag = 0;
}
void sensor_poll_enable()
{
sensor_poll_eanble_flag = 1;
}
void sensor_poll_handler(void *arug0, void *arug1, void *arug2)
{
uint8_t poll_num;
int SENSOR_POLL_INTERVEL_ms;
k_msleep(1000); // delay 1 second to wait for drivers ready before start sensor polling
pal_set_sensor_poll_interval(&SENSOR_POLL_INTERVEL_ms);
while (1) {
for (poll_num = 0; poll_num < SENSOR_NUM_MAX; poll_num++) {
if (sensor_poll_eanble_flag == 0) { /* skip if disable sensor poll */
break;
}
if (SensorNum_SensorCfg_map[poll_num] == sensor_null) { // sensor not exist
continue;
}
int reading = 0;
get_sensor_reading(poll_num, &reading, get_from_sensor);
k_yield();
}
k_msleep(SENSOR_POLL_INTERVEL_ms);
}
}
void sensor_poll_init()
{
k_thread_create(&sensor_poll, sensor_poll_stack, K_THREAD_STACK_SIZEOF(sensor_poll_stack),
sensor_poll_handler, NULL, NULL, NULL, CONFIG_MAIN_THREAD_PRIORITY, 0,
K_NO_WAIT);
k_thread_name_set(&sensor_poll, "sensor_poll");
return;
}
static void drive_init(void)
{
uint16_t drive_num = ARRAY_SIZE(sensor_drive_tbl);
uint16_t i, j;
uint8_t ret;
for (i = 0; i < SDR_NUM; i++) {
sensor_cfg *p = sensor_config + i;
for (j = 0; j < drive_num; j++) {
if (p->type == sensor_drive_tbl[j].dev) {
ret = sensor_drive_tbl[j].init(p->num);
if (ret != SENSOR_INIT_SUCCESS)
printk("sensor num %d initial fail, ret %d\n", p->num, ret);
break;
}
}
if (j == drive_num) {
printk("sensor %d, type = %d is not supported!\n", i, p->type);
p->read = NULL;
}
}
}
bool sensor_init(void)
{
init_SensorNum();
SDR_init();
if (SDR_NUM != 0) {
sensor_config = (sensor_cfg *)malloc(SDR_NUM * sizeof(sensor_cfg));
if (sensor_config != NULL) {
pal_load_sensor_config();
} else {
printf("sensor_config alloc fail\n");
return false;
}
} else {
printf("SDR_NUM == 0\n");
return false;
}
pal_fix_Sensorconfig();
map_SensorNum_SDR_CFG();
/* register read api of sensor_config */
drive_init();
if (DEBUG_SENSOR) {
printf("SENSOR0: %s\n", full_sensor_table[SensorNum_SDR_map[1]].ID_str);
}
if (enable_sensor_poll) {
sensor_poll_init();
}
return true;
}