1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020 Philippe Reynes <philippe.reynes@softathome.com>
4 *
5 * Based on led.c
6 */
7
8#include <common.h>
9#include <dm.h>
10#include <adc.h>
11#include <button.h>
12#include <power/regulator.h>
13#include <power/sandbox_pmic.h>
14#include <asm/gpio.h>
15#include <dm/test.h>
16#include <dt-bindings/input/input.h>
17#include <test/ut.h>
18
19/* Base test of the button uclass */
20static int dm_test_button_base(struct unit_test_state *uts)
21{
22	struct udevice *dev;
23
24	/* Get the top-level gpio buttons device */
25	ut_assertok(uclass_get_device(UCLASS_BUTTON, 0, &dev));
26	/* Get the 2 gpio buttons */
27	ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &dev));
28	ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, &dev));
29
30	/* Get the top-level adc buttons device */
31	ut_assertok(uclass_get_device(UCLASS_BUTTON, 3, &dev));
32	/* Get the 3 adc buttons */
33	ut_assertok(uclass_get_device(UCLASS_BUTTON, 4, &dev));
34	ut_assertok(uclass_get_device(UCLASS_BUTTON, 5, &dev));
35	ut_assertok(uclass_get_device(UCLASS_BUTTON, 6, &dev));
36
37	ut_asserteq(-ENODEV, uclass_get_device(UCLASS_BUTTON, 7, &dev));
38
39	return 0;
40}
41DM_TEST(dm_test_button_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
42
43/* Test of the button uclass using the button_gpio driver */
44static int dm_test_button_gpio(struct unit_test_state *uts)
45{
46	const int offset = 3;
47	struct udevice *dev, *gpio;
48
49	/*
50	 * Check that we can manipulate a BUTTON. BUTTON 1 is connected to GPIO
51	 * bank gpio_a, offset 3.
52	 */
53	ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &dev));
54	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
55
56	ut_asserteq(0, sandbox_gpio_set_value(gpio, offset, 0));
57	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
58	ut_asserteq(BUTTON_OFF, button_get_state(dev));
59
60	ut_asserteq(0, sandbox_gpio_set_value(gpio, offset, 1));
61	ut_asserteq(1, sandbox_gpio_get_value(gpio, offset));
62	ut_asserteq(BUTTON_ON, button_get_state(dev));
63
64	return 0;
65}
66DM_TEST(dm_test_button_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
67
68/* Test obtaining a BUTTON by label */
69static int dm_test_button_label(struct unit_test_state *uts)
70{
71	struct udevice *dev, *cmp;
72
73	ut_assertok(button_get_by_label("button1", &dev));
74	ut_asserteq(1, device_active(dev));
75	ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &cmp));
76	ut_asserteq_ptr(dev, cmp);
77
78	ut_assertok(button_get_by_label("button2", &dev));
79	ut_asserteq(1, device_active(dev));
80	ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, &cmp));
81	ut_asserteq_ptr(dev, cmp);
82
83	ut_asserteq(-ENODEV, button_get_by_label("nobutton", &dev));
84
85	return 0;
86}
87DM_TEST(dm_test_button_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
88
89/* Test button has linux,code */
90static int dm_test_button_linux_code(struct unit_test_state *uts)
91{
92	struct udevice *dev;
93
94	ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &dev));
95	ut_asserteq(BTN_1, button_get_code(dev));
96
97	return 0;
98}
99DM_TEST(dm_test_button_linux_code, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
100
101/* Test adc-keys driver */
102static int dm_test_button_keys_adc(struct unit_test_state *uts)
103{
104	struct udevice *supply;
105	struct udevice *dev;
106	int uV;
107
108	ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev));
109
110	ut_assertok(regulator_get_by_devname(SANDBOX_BUCK2_DEVNAME, &supply));
111	ut_assertok(regulator_set_value(supply, SANDBOX_BUCK2_SET_UV));
112	ut_asserteq(SANDBOX_BUCK2_SET_UV, regulator_get_value(supply));
113	/* Update ADC plat and get new Vdd value */
114	ut_assertok(adc_vdd_value(dev, &uV));
115	ut_asserteq(SANDBOX_BUCK2_SET_UV, uV);
116
117	/*
118	 * sandbox-adc returns constant value on channel 3, is used by adc-keys:
119	 * SANDBOX_ADC_CHANNEL3_DATA * SANDBOX_BUCK2_SET_UV / SANDBOX_ADC_DATA_MASK =
120	 * 0x3000 * 3300000 / 0xffff = 618759uV
121	 * This means that button3 and button4 are released and button5
122	 * is pressed.
123	 */
124	ut_assertok(button_get_by_label("button3", &dev));
125	ut_asserteq(BUTTON_OFF, button_get_state(dev));
126	ut_assertok(button_get_by_label("button4", &dev));
127	ut_asserteq(BUTTON_OFF, button_get_state(dev));
128	ut_assertok(button_get_by_label("button5", &dev));
129	ut_asserteq(BUTTON_ON, button_get_state(dev));
130
131	return 0;
132}
133DM_TEST(dm_test_button_keys_adc, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
134
135/* Test of the button uclass using the button_gpio driver */
136static int dm_test_button_cmd(struct unit_test_state *uts)
137{
138	struct udevice *btn1_dev, *btn2_dev, *gpio;
139	const char *envstr;
140
141#define BTN1_GPIO 3
142#define BTN2_GPIO 4
143#define BTN1_PASS_VAR "test_button_cmds_0"
144#define BTN2_PASS_VAR "test_button_cmds_1"
145
146	/*
147	 * Buttons 1 and 2 are connected to gpio_a gpios 3 and 4 respectively.
148	 * set the GPIOs to known values and then check that the appropriate
149	 * commands are run when invoking process_button_cmds().
150	 */
151	ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &btn1_dev));
152	ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, &btn2_dev));
153	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
154
155	/*
156	 * Map a command to button 1 and check that it process_button_cmds()
157	 * runs it if called with button 1 pressed.
158	 */
159	ut_assertok(env_set("button_cmd_0_name", "button1"));
160	ut_assertok(env_set("button_cmd_0", "env set " BTN1_PASS_VAR " PASS"));
161	ut_assertok(sandbox_gpio_set_value(gpio, BTN1_GPIO, 1));
162	/* Sanity check that the button is actually pressed */
163	ut_asserteq(BUTTON_ON, button_get_state(btn1_dev));
164	process_button_cmds();
165	ut_assertnonnull((envstr = env_get(BTN1_PASS_VAR)));
166	ut_asserteq_str(envstr, "PASS");
167
168	/* Clear result */
169	ut_assertok(env_set(BTN1_PASS_VAR, NULL));
170
171	/*
172	 * Map a command for button 2, press it, check that only the command
173	 * for button 1 runs because it comes first and is also pressed.
174	 */
175	ut_assertok(env_set("button_cmd_1_name", "button2"));
176	ut_assertok(env_set("button_cmd_1", "env set " BTN2_PASS_VAR " PASS"));
177	ut_assertok(sandbox_gpio_set_value(gpio, BTN2_GPIO, 1));
178	ut_asserteq(BUTTON_ON, button_get_state(btn2_dev));
179	process_button_cmds();
180	/* Check that button 1 triggered again */
181	ut_assertnonnull((envstr = env_get(BTN1_PASS_VAR)));
182	ut_asserteq_str(envstr, "PASS");
183	/* And button 2 didn't */
184	ut_assertnull(env_get(BTN2_PASS_VAR));
185
186	/* Clear result */
187	ut_assertok(env_set(BTN1_PASS_VAR, NULL));
188
189	/*
190	 * Release button 1 and check that the command for button 2 is run
191	 */
192	ut_assertok(sandbox_gpio_set_value(gpio, BTN1_GPIO, 0));
193	process_button_cmds();
194	ut_assertnull(env_get(BTN1_PASS_VAR));
195	/* Check that the command for button 2 ran */
196	ut_assertnonnull((envstr = env_get(BTN2_PASS_VAR)));
197	ut_asserteq_str(envstr, "PASS");
198
199	/* Clear result */
200	ut_assertok(env_set(BTN2_PASS_VAR, NULL));
201
202	/*
203	 * Unset "button_cmd_0_name" and check that no commands run even
204	 * with both buttons pressed.
205	 */
206	ut_assertok(env_set("button_cmd_0_name", NULL));
207	/* Press button 1 (button 2 is already pressed )*/
208	ut_assertok(sandbox_gpio_set_value(gpio, BTN1_GPIO, 1));
209	ut_asserteq(BUTTON_ON, button_get_state(btn1_dev));
210	process_button_cmds();
211	ut_assertnull(env_get(BTN1_PASS_VAR));
212	ut_assertnull(env_get(BTN2_PASS_VAR));
213
214	/*
215	 * Check that no command is run if the button name is wrong.
216	 */
217	ut_assertok(env_set("button_cmd_0_name", "invalid_button"));
218	process_button_cmds();
219	ut_assertnull(env_get(BTN1_PASS_VAR));
220	ut_assertnull(env_get(BTN2_PASS_VAR));
221
222#undef BTN1_PASS_VAR
223#undef BTN2_PASS_VAR
224#undef BTN1_GPIO
225#undef BTN2_GPIO
226
227	return 0;
228}
229DM_TEST(dm_test_button_cmd, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
230