xref: /rk3399_rockchip-uboot/test/dm/usb.c (revision 88033d737d9f46e7eebda6a8f9770957eb9aae9c)
1e00cb223SSimon Glass /*
2e00cb223SSimon Glass  * Copyright (C) 2015 Google, Inc
3e00cb223SSimon Glass  *
4e00cb223SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
5e00cb223SSimon Glass  */
6e00cb223SSimon Glass 
7e00cb223SSimon Glass #include <common.h>
824b852a7SSimon Glass #include <console.h>
9e00cb223SSimon Glass #include <dm.h>
10e00cb223SSimon Glass #include <usb.h>
11e00cb223SSimon Glass #include <asm/io.h>
123884c98cSSimon Glass #include <asm/state.h>
13bff1a71eSSimon Glass #include <asm/test.h>
143884c98cSSimon Glass #include <dm/device-internal.h>
15e00cb223SSimon Glass #include <dm/test.h>
16431cbd6dSSimon Glass #include <dm/uclass-internal.h>
17e721b882SJoe Hershberger #include <test/ut.h>
18e00cb223SSimon Glass 
19431cbd6dSSimon Glass DECLARE_GLOBAL_DATA_PTR;
20431cbd6dSSimon Glass 
21e00cb223SSimon Glass /* Test that sandbox USB works correctly */
dm_test_usb_base(struct unit_test_state * uts)22e721b882SJoe Hershberger static int dm_test_usb_base(struct unit_test_state *uts)
23e00cb223SSimon Glass {
24e00cb223SSimon Glass 	struct udevice *bus;
25e00cb223SSimon Glass 
26e00cb223SSimon Glass 	ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 0, &bus));
27e00cb223SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_USB, 0, &bus));
28e00cb223SSimon Glass 	ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 2, &bus));
29e00cb223SSimon Glass 
30e00cb223SSimon Glass 	return 0;
31e00cb223SSimon Glass }
32e00cb223SSimon Glass DM_TEST(dm_test_usb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
33e00cb223SSimon Glass 
34e00cb223SSimon Glass /*
35e00cb223SSimon Glass  * Test that we can use the flash stick. This is more of a functional test. It
36e00cb223SSimon Glass  * covers scanning the bug, setting up a hub and a flash stick and reading
37e00cb223SSimon Glass  * data from the flash stick.
38e00cb223SSimon Glass  */
dm_test_usb_flash(struct unit_test_state * uts)39e721b882SJoe Hershberger static int dm_test_usb_flash(struct unit_test_state *uts)
40e00cb223SSimon Glass {
41e00cb223SSimon Glass 	struct udevice *dev;
424101f687SSimon Glass 	struct blk_desc *dev_desc;
43e00cb223SSimon Glass 	char cmp[1024];
44e00cb223SSimon Glass 
453884c98cSSimon Glass 	state_set_skip_delays(true);
46e00cb223SSimon Glass 	ut_assertok(usb_init());
47e00cb223SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
48ebac37cfSSimon Glass 	ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
49e00cb223SSimon Glass 
50e00cb223SSimon Glass 	/* Read a few blocks and look for the string we expect */
51e00cb223SSimon Glass 	ut_asserteq(512, dev_desc->blksz);
52e00cb223SSimon Glass 	memset(cmp, '\0', sizeof(cmp));
532a981dc2SSimon Glass 	ut_asserteq(2, blk_dread(dev_desc, 0, 2, cmp));
54e00cb223SSimon Glass 	ut_assertok(strcmp(cmp, "this is a test"));
55*61ccd886SSimon Glass 	ut_assertok(usb_stop());
56e00cb223SSimon Glass 
57e00cb223SSimon Glass 	return 0;
58e00cb223SSimon Glass }
59e00cb223SSimon Glass DM_TEST(dm_test_usb_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
60431cbd6dSSimon Glass 
61431cbd6dSSimon Glass /* test that we can handle multiple storage devices */
dm_test_usb_multi(struct unit_test_state * uts)62431cbd6dSSimon Glass static int dm_test_usb_multi(struct unit_test_state *uts)
63431cbd6dSSimon Glass {
64431cbd6dSSimon Glass 	struct udevice *dev;
65431cbd6dSSimon Glass 
66431cbd6dSSimon Glass 	state_set_skip_delays(true);
67431cbd6dSSimon Glass 	ut_assertok(usb_init());
68431cbd6dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
69431cbd6dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
70431cbd6dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
71*61ccd886SSimon Glass 	ut_assertok(usb_stop());
72431cbd6dSSimon Glass 
73431cbd6dSSimon Glass 	return 0;
74431cbd6dSSimon Glass }
75431cbd6dSSimon Glass DM_TEST(dm_test_usb_multi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
76431cbd6dSSimon Glass 
count_usb_devices(void)77431cbd6dSSimon Glass static int count_usb_devices(void)
78431cbd6dSSimon Glass {
79431cbd6dSSimon Glass 	struct udevice *hub;
80431cbd6dSSimon Glass 	struct uclass *uc;
81431cbd6dSSimon Glass 	int count = 0;
82431cbd6dSSimon Glass 	int ret;
83431cbd6dSSimon Glass 
84431cbd6dSSimon Glass 	ret = uclass_get(UCLASS_USB_HUB, &uc);
85431cbd6dSSimon Glass 	if (ret)
86431cbd6dSSimon Glass 		return ret;
87431cbd6dSSimon Glass 
88431cbd6dSSimon Glass 	uclass_foreach_dev(hub, uc) {
89431cbd6dSSimon Glass 		struct udevice *dev;
90431cbd6dSSimon Glass 
91431cbd6dSSimon Glass 		count++;
92431cbd6dSSimon Glass 		for (device_find_first_child(hub, &dev);
93431cbd6dSSimon Glass 		     dev;
94431cbd6dSSimon Glass 		     device_find_next_child(&dev)) {
95431cbd6dSSimon Glass 			count++;
96431cbd6dSSimon Glass 		}
97431cbd6dSSimon Glass 	}
98431cbd6dSSimon Glass 
99431cbd6dSSimon Glass 	return count;
100431cbd6dSSimon Glass }
101431cbd6dSSimon Glass 
102431cbd6dSSimon Glass /* test that we can remove an emulated device and it is then not found */
dm_test_usb_remove(struct unit_test_state * uts)103431cbd6dSSimon Glass static int dm_test_usb_remove(struct unit_test_state *uts)
104431cbd6dSSimon Glass {
105431cbd6dSSimon Glass 	struct udevice *dev, *emul;
106431cbd6dSSimon Glass 
107431cbd6dSSimon Glass 	/* Scan and check that all devices are present */
108431cbd6dSSimon Glass 	state_set_skip_delays(true);
109431cbd6dSSimon Glass 	ut_assertok(usb_init());
110431cbd6dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
111431cbd6dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
112431cbd6dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
113a57a8174SSimon Glass 	ut_asserteq(6, count_usb_devices());
114431cbd6dSSimon Glass 	ut_assertok(usb_stop());
115a57a8174SSimon Glass 	ut_asserteq(6, count_usb_devices());
116431cbd6dSSimon Glass 
117431cbd6dSSimon Glass 	/* Remove the second emulation device */
118431cbd6dSSimon Glass 	ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
119431cbd6dSSimon Glass 					       &dev));
120431cbd6dSSimon Glass 	ut_assertok(device_unbind(dev));
121431cbd6dSSimon Glass 
122431cbd6dSSimon Glass 	/* Rescan - only the first and third should be present */
123431cbd6dSSimon Glass 	ut_assertok(usb_init());
124431cbd6dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
125431cbd6dSSimon Glass 	ut_assertok(usb_emul_find_for_dev(dev, &emul));
126431cbd6dSSimon Glass 	ut_asserteq_str("flash-stick@0", emul->name);
127431cbd6dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
128431cbd6dSSimon Glass 	ut_assertok(usb_emul_find_for_dev(dev, &emul));
129431cbd6dSSimon Glass 	ut_asserteq_str("flash-stick@2", emul->name);
130431cbd6dSSimon Glass 
131431cbd6dSSimon Glass 	ut_asserteq(-ENODEV, uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
132431cbd6dSSimon Glass 
133a57a8174SSimon Glass 	ut_asserteq(5, count_usb_devices());
134431cbd6dSSimon Glass 	ut_assertok(usb_stop());
135a57a8174SSimon Glass 	ut_asserteq(5, count_usb_devices());
136431cbd6dSSimon Glass 
137431cbd6dSSimon Glass 	return 0;
138431cbd6dSSimon Glass }
139431cbd6dSSimon Glass DM_TEST(dm_test_usb_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
140431cbd6dSSimon Glass 
141431cbd6dSSimon Glass const char usb_tree_base[] =
142431cbd6dSSimon Glass "  1  Hub (12 Mb/s, 100mA)\n"
143431cbd6dSSimon Glass "  |  sandbox hub 2345\n"
144431cbd6dSSimon Glass "  |\n"
145431cbd6dSSimon Glass "  |\b+-2  Mass Storage (12 Mb/s, 100mA)\n"
146431cbd6dSSimon Glass "  |    sandbox flash flash-stick@0\n"
147431cbd6dSSimon Glass "  |  \n"
148431cbd6dSSimon Glass "  |\b+-3  Mass Storage (12 Mb/s, 100mA)\n"
149431cbd6dSSimon Glass "  |    sandbox flash flash-stick@1\n"
150431cbd6dSSimon Glass "  |  \n"
151431cbd6dSSimon Glass "  |\b+-4  Mass Storage (12 Mb/s, 100mA)\n"
152a57a8174SSimon Glass "  |    sandbox flash flash-stick@2\n"
153a57a8174SSimon Glass "  |  \n"
154a57a8174SSimon Glass "  |\b+-5  Human Interface (12 Mb/s, 100mA)\n"
155a57a8174SSimon Glass "       sandbox keyboard keyb@3\n"
156431cbd6dSSimon Glass "     \n";
157431cbd6dSSimon Glass 
158431cbd6dSSimon Glass /* test that the 'usb tree' command output looks correct */
dm_test_usb_tree(struct unit_test_state * uts)159431cbd6dSSimon Glass static int dm_test_usb_tree(struct unit_test_state *uts)
160431cbd6dSSimon Glass {
161431cbd6dSSimon Glass 	char *data;
162431cbd6dSSimon Glass 	int len;
163431cbd6dSSimon Glass 
164431cbd6dSSimon Glass 	state_set_skip_delays(true);
165431cbd6dSSimon Glass 	ut_assertok(usb_init());
166431cbd6dSSimon Glass 	console_record_reset_enable();
167431cbd6dSSimon Glass 	usb_show_tree();
168431cbd6dSSimon Glass 	len = membuff_getraw(&gd->console_out, -1, true, &data);
169431cbd6dSSimon Glass 	if (len)
170431cbd6dSSimon Glass 		data[len] = '\0';
171431cbd6dSSimon Glass 	ut_asserteq_str(usb_tree_base, data);
172431cbd6dSSimon Glass 	ut_assertok(usb_stop());
173431cbd6dSSimon Glass 
174431cbd6dSSimon Glass 	return 0;
175431cbd6dSSimon Glass }
176431cbd6dSSimon Glass DM_TEST(dm_test_usb_tree, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
177431cbd6dSSimon Glass 
178431cbd6dSSimon Glass const char usb_tree_remove[] =
179431cbd6dSSimon Glass "  1  Hub (12 Mb/s, 100mA)\n"
180431cbd6dSSimon Glass "  |  sandbox hub 2345\n"
181431cbd6dSSimon Glass "  |\n"
182431cbd6dSSimon Glass "  |\b+-2  Mass Storage (12 Mb/s, 100mA)\n"
183431cbd6dSSimon Glass "  |    sandbox flash flash-stick@0\n"
184431cbd6dSSimon Glass "  |  \n"
185431cbd6dSSimon Glass "  |\b+-3  Mass Storage (12 Mb/s, 100mA)\n"
186a57a8174SSimon Glass "  |    sandbox flash flash-stick@2\n"
187a57a8174SSimon Glass "  |  \n"
188a57a8174SSimon Glass "  |\b+-4  Human Interface (12 Mb/s, 100mA)\n"
189a57a8174SSimon Glass "       sandbox keyboard keyb@3\n"
190431cbd6dSSimon Glass "     \n";
191431cbd6dSSimon Glass 
192431cbd6dSSimon Glass /*
193431cbd6dSSimon Glass  * test that the 'usb tree' command output looks correct when we remove a
194431cbd6dSSimon Glass  * device
195431cbd6dSSimon Glass  */
dm_test_usb_tree_remove(struct unit_test_state * uts)196431cbd6dSSimon Glass static int dm_test_usb_tree_remove(struct unit_test_state *uts)
197431cbd6dSSimon Glass {
198431cbd6dSSimon Glass 	struct udevice *dev;
199431cbd6dSSimon Glass 	char *data;
200431cbd6dSSimon Glass 	int len;
201431cbd6dSSimon Glass 
202431cbd6dSSimon Glass 	/* Remove the second emulation device */
203431cbd6dSSimon Glass 	ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
204431cbd6dSSimon Glass 					       &dev));
205431cbd6dSSimon Glass 	ut_assertok(device_unbind(dev));
206431cbd6dSSimon Glass 
207431cbd6dSSimon Glass 	state_set_skip_delays(true);
208431cbd6dSSimon Glass 	ut_assertok(usb_init());
209431cbd6dSSimon Glass 	console_record_reset_enable();
210431cbd6dSSimon Glass 	usb_show_tree();
211431cbd6dSSimon Glass 	len = membuff_getraw(&gd->console_out, -1, true, &data);
212431cbd6dSSimon Glass 	if (len)
213431cbd6dSSimon Glass 		data[len] = '\0';
214431cbd6dSSimon Glass 	ut_asserteq_str(usb_tree_remove, data);
215431cbd6dSSimon Glass 	ut_assertok(usb_stop());
216431cbd6dSSimon Glass 
217431cbd6dSSimon Glass 	return 0;
218431cbd6dSSimon Glass }
219431cbd6dSSimon Glass DM_TEST(dm_test_usb_tree_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
220cd716372SSimon Glass 
221cd716372SSimon Glass const char usb_tree_reorder[] =
222cd716372SSimon Glass "  1  Hub (12 Mb/s, 100mA)\n"
223cd716372SSimon Glass "  |  sandbox hub 2345\n"
224cd716372SSimon Glass "  |\n"
225cd716372SSimon Glass "  |\b+-2  Mass Storage (12 Mb/s, 100mA)\n"
226cd716372SSimon Glass "  |    sandbox flash flash-stick@0\n"
227cd716372SSimon Glass "  |  \n"
228cd716372SSimon Glass "  |\b+-3  Mass Storage (12 Mb/s, 100mA)\n"
229cd716372SSimon Glass "  |    sandbox flash flash-stick@2\n"
230cd716372SSimon Glass "  |  \n"
231a57a8174SSimon Glass "  |\b+-4  Human Interface (12 Mb/s, 100mA)\n"
232a57a8174SSimon Glass "  |    sandbox keyboard keyb@3\n"
233a57a8174SSimon Glass "  |  \n"
234a57a8174SSimon Glass "  |\b+-5  Mass Storage (12 Mb/s, 100mA)\n"
235cd716372SSimon Glass "       sandbox flash flash-stick@1\n"
236cd716372SSimon Glass "     \n";
237cd716372SSimon Glass 
238cd716372SSimon Glass /*
239cd716372SSimon Glass  * test that the 'usb tree' command output looks correct when we reorder two
240cd716372SSimon Glass  * devices.
241cd716372SSimon Glass  */
dm_test_usb_tree_reorder(struct unit_test_state * uts)242cd716372SSimon Glass static int dm_test_usb_tree_reorder(struct unit_test_state *uts)
243cd716372SSimon Glass {
244cd716372SSimon Glass 	struct udevice *dev, *parent;
245cd716372SSimon Glass 	char *data;
246cd716372SSimon Glass 	int len;
247cd716372SSimon Glass 
248cd716372SSimon Glass 	/* Remove the second emulation device */
249cd716372SSimon Glass 	ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
250cd716372SSimon Glass 					       &dev));
251cd716372SSimon Glass 	parent = dev->parent;
252cd716372SSimon Glass 
253cd716372SSimon Glass 	/* Reorder the devices in the parent list and uclass list */
254cd716372SSimon Glass 	list_del(&dev->sibling_node);
255cd716372SSimon Glass 	list_add_tail(&dev->sibling_node, &parent->child_head);
256cd716372SSimon Glass 
257cd716372SSimon Glass 	list_del(&dev->uclass_node);
258cd716372SSimon Glass 	list_add_tail(&dev->uclass_node, &dev->uclass->dev_head);
259cd716372SSimon Glass 
260cd716372SSimon Glass 	state_set_skip_delays(true);
261cd716372SSimon Glass 	ut_assertok(usb_init());
262cd716372SSimon Glass 	console_record_reset_enable();
263cd716372SSimon Glass 	usb_show_tree();
264cd716372SSimon Glass 	len = membuff_getraw(&gd->console_out, -1, true, &data);
265cd716372SSimon Glass 	if (len)
266cd716372SSimon Glass 		data[len] = '\0';
267cd716372SSimon Glass 	ut_asserteq_str(usb_tree_reorder, data);
268cd716372SSimon Glass 	ut_assertok(usb_stop());
269cd716372SSimon Glass 
270cd716372SSimon Glass 	return 0;
271cd716372SSimon Glass }
272cd716372SSimon Glass DM_TEST(dm_test_usb_tree_reorder, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
273bff1a71eSSimon Glass 
dm_test_usb_keyb(struct unit_test_state * uts)274bff1a71eSSimon Glass static int dm_test_usb_keyb(struct unit_test_state *uts)
275bff1a71eSSimon Glass {
276bff1a71eSSimon Glass 	struct udevice *dev;
277bff1a71eSSimon Glass 
278bff1a71eSSimon Glass 	state_set_skip_delays(true);
279bff1a71eSSimon Glass 	ut_assertok(usb_init());
280bff1a71eSSimon Glass 
281bff1a71eSSimon Glass 	/* Initially there should be no characters */
282bff1a71eSSimon Glass 	ut_asserteq(0, tstc());
283bff1a71eSSimon Glass 
284bff1a71eSSimon Glass 	ut_assertok(uclass_get_device_by_name(UCLASS_USB_EMUL, "keyb",
285bff1a71eSSimon Glass 					      &dev));
286bff1a71eSSimon Glass 
287bff1a71eSSimon Glass 	/*
288bff1a71eSSimon Glass 	 * Add a string to the USB keyboard buffer - it should appear in
289bff1a71eSSimon Glass 	 * stdin
290bff1a71eSSimon Glass 	 */
291bff1a71eSSimon Glass 	ut_assertok(sandbox_usb_keyb_add_string(dev, "ab"));
292bff1a71eSSimon Glass 	ut_asserteq(1, tstc());
293bff1a71eSSimon Glass 	ut_asserteq('a', getc());
294bff1a71eSSimon Glass 	ut_asserteq(1, tstc());
295bff1a71eSSimon Glass 	ut_asserteq('b', getc());
296bff1a71eSSimon Glass 	ut_asserteq(0, tstc());
297bff1a71eSSimon Glass 
298bff1a71eSSimon Glass 	ut_assertok(usb_stop());
299bff1a71eSSimon Glass 
300bff1a71eSSimon Glass 	return 0;
301bff1a71eSSimon Glass }
302bff1a71eSSimon Glass DM_TEST(dm_test_usb_keyb, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
303