summaryrefslogtreecommitdiff
path: root/zephyr/test/drivers/default/src/temp_sensor.c
blob: 5caecc556c5c0c41b34eb8d4f5b15bbb59f0776e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* Copyright 2021 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/drivers/adc/adc_emul.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_emul.h>

#include <math.h>

#include "common.h"
#include "temp_sensor.h"
#include "temp_sensor/temp_sensor.h"
#include "test/drivers/test_state.h"

#define GPIO_PG_EC_DSW_PWROK_PATH DT_PATH(named_gpios, pg_ec_dsw_pwrok)
#define GPIO_PG_EC_DSW_PWROK_PORT DT_GPIO_PIN(GPIO_PG_EC_DSW_PWROK_PATH, gpios)

#define GPIO_EC_PG_PIN_TEMP_PATH DT_PATH(named_gpios, ec_pg_pin_temp)
#define GPIO_EC_PG_PIN_TEMP_PORT DT_GPIO_PIN(GPIO_EC_PG_PIN_TEMP_PATH, gpios)

#define ADC_DEVICE_NODE DT_NODELABEL(adc0)
#define ADC_CHANNELS_NUM DT_PROP(DT_NODELABEL(adc0), nchannels)

/** Test error code when invalid sensor is passed to temp_sensor_read() */
ZTEST_USER(temp_sensor, test_temp_sensor_wrong_id)
{
	int temp;

	zassert_equal(EC_ERROR_INVAL,
		      temp_sensor_read(TEMP_SENSOR_COUNT, &temp), NULL);
}

/** Test error code when temp_sensor_read() is called with powered off ADC */
ZTEST_USER(temp_sensor, test_temp_sensor_adc_error)
{
	const struct device *gpio_dev =
		DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_PG_EC_DSW_PWROK_PATH, gpios));
	int temp;

	zassert_not_null(gpio_dev, "Cannot get GPIO device");

	/*
	 * pg_ec_dsw_pwrok = 0 means ADC is not powered.
	 * adc_read will return error
	 */
	zassert_ok(gpio_emul_input_set(gpio_dev, GPIO_PG_EC_DSW_PWROK_PORT, 0),
		   NULL);

	zassert_equal(EC_ERROR_NOT_POWERED,
		      temp_sensor_read(
			      TEMP_SENSOR_ID(DT_NODELABEL(named_temp_charger)),
			      &temp),
		      NULL);
	zassert_equal(EC_ERROR_NOT_POWERED,
		      temp_sensor_read(
			      TEMP_SENSOR_ID(DT_NODELABEL(named_temp_ddr_soc)),
			      &temp),
		      NULL);
	zassert_equal(
		EC_ERROR_NOT_POWERED,
		temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL(named_temp_fan)),
				 &temp),
		NULL);
	zassert_equal(EC_ERROR_NOT_POWERED,
		      temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL(
					       named_temp_pp3300_regulator)),
				       &temp),
		      NULL);

	/* power ADC */
	zassert_ok(gpio_emul_input_set(gpio_dev, GPIO_PG_EC_DSW_PWROK_PORT, 1),
		   NULL);
}

/** Test error code when temp_sensor_read() is called power-good-pin low */
ZTEST_USER(temp_sensor, test_temp_sensor_pg_pin)
{
	const struct device *gpio_dev =
		DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_EC_PG_PIN_TEMP_PATH, gpios));
	int temp;

	zassert_not_null(gpio_dev, "Cannot get GPIO device");

	/* ec_pg_pin_temp = 0 means temperature sensors are not powered. */
	zassert_ok(gpio_emul_input_set(gpio_dev, GPIO_EC_PG_PIN_TEMP_PORT, 0),
		   NULL);

	zassert_equal(EC_ERROR_NOT_POWERED,
		      temp_sensor_read(
			      TEMP_SENSOR_ID(DT_NODELABEL(named_temp_charger)),
			      &temp),
		      NULL);
	zassert_equal(EC_ERROR_NOT_POWERED,
		      temp_sensor_read(
			      TEMP_SENSOR_ID(DT_NODELABEL(named_temp_ddr_soc)),
			      &temp),
		      NULL);
	zassert_equal(
		EC_ERROR_NOT_POWERED,
		temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL(named_temp_fan)),
				 &temp),
		NULL);
	zassert_equal(EC_ERROR_NOT_POWERED,
		      temp_sensor_read(TEMP_SENSOR_ID(DT_NODELABEL(
					       named_temp_pp3300_regulator)),
				       &temp),
		      NULL);

	/* power ADC */
	zassert_ok(gpio_emul_input_set(gpio_dev, GPIO_EC_PG_PIN_TEMP_PORT, 1),
		   NULL);
}

/** Simple ADC emulator custom function which always return error */
static int adc_error_func(const struct device *dev, unsigned int channel,
			  void *param, uint32_t *result)
{
	return -EINVAL;
}

/**
 * Set valid response only for ADC channel connected with tested sensor.
 * Check if temp_sensor_read() from tested sensor returns EC_SUCCESS and
 * valid temperature. Set invalid response on ADC channel for next test.
 */
static void check_valid_temperature(const struct device *adc_dev, int sensor)
{
	int temp;

	/* ADC channel of tested sensor return valid value */
	zassert_ok(adc_emul_const_value_set(adc_dev, temp_sensors[sensor].idx,
					    1000),
		   "adc_emul_const_value_set() failed (sensor %d)", sensor);
	zassert_equal(EC_SUCCESS, temp_sensor_read(sensor, &temp), NULL);
	zassert_within(
		temp, 273 + 50, 51,
		"Expected temperature in 0*C-100*C, got %d*C (sensor %d)",
		temp - 273, sensor);
	/* Return error on ADC channel of tested sensor */
	zassert_ok(adc_emul_value_func_set(adc_dev, temp_sensors[sensor].idx,
					   adc_error_func, NULL),
		   "adc_emul_value_func_set() failed (sensor %d)", sensor);
}

/** Test if temp_sensor_read() returns temperature on success */
ZTEST_USER(temp_sensor, test_temp_sensor_read)
{
	const struct device *adc_dev = DEVICE_DT_GET(ADC_DEVICE_NODE);
	int chan;

	zassert_not_null(adc_dev, "Cannot get ADC device");

	/* Return error on all ADC channels */
	for (chan = 0; chan < ADC_CHANNELS_NUM; chan++) {
		zassert_ok(adc_emul_value_func_set(adc_dev, chan,
						   adc_error_func, NULL),
			   "channel %d adc_emul_value_func_set() failed", chan);
	}

	check_valid_temperature(
		adc_dev, TEMP_SENSOR_ID(DT_NODELABEL(named_temp_charger)));
	check_valid_temperature(
		adc_dev, TEMP_SENSOR_ID(DT_NODELABEL(named_temp_ddr_soc)));
	check_valid_temperature(adc_dev,
				TEMP_SENSOR_ID(DT_NODELABEL(named_temp_fan)));
	check_valid_temperature(adc_dev, TEMP_SENSOR_ID(DT_NODELABEL(
						 named_temp_pp3300_regulator)));

	/* Return correct value on all ADC channels */
	for (chan = 0; chan < ADC_CHANNELS_NUM; chan++) {
		zassert_ok(adc_emul_const_value_set(adc_dev, chan, 1000),
			   "channel %d adc_emul_const_value_set() failed",
			   chan);
	}
}

static void *temp_sensor_setup(void)
{
	const struct device *dev =
		DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_PG_EC_DSW_PWROK_PATH, gpios));
	const struct device *dev_pin =
		DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_EC_PG_PIN_TEMP_PATH, gpios));

	zassert_not_null(dev, NULL);
	/* Before tests make sure that power pins are set. */
	zassert_ok(gpio_emul_input_set(dev, GPIO_PG_EC_DSW_PWROK_PORT, 1),
		   NULL);
	zassert_ok(gpio_emul_input_set(dev_pin, GPIO_EC_PG_PIN_TEMP_PORT, 1),
		   NULL);

	return NULL;
}

ZTEST_SUITE(temp_sensor, drivers_predicate_post_main, temp_sensor_setup, NULL,
	    NULL, NULL);