Software APIs
usbdev_pincfg_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 //
5 // USB pincfg test
6 //
7 // For each of the pin/bus configurations in turn, this test runs the USB test
8 // software, device and DPI model through all of the initial communications to
9 // set up the device and select a configuration.
10 //
11 // It is necessary to perform a complete reset of the usbdev hardware block
12 // before starting the next test because the DIF keeps the 'Available buffers'
13 // FIFO topped up with buffers, but would itself forget about those buffers
14 // when reinitialized for the next test.
15 //
16 // This test works best with the DPI model in Verilator top-level simulation
17 // because it is capable of reading and adapting to the pin configuration and
18 // thus implementing all bus types:
19 //
20 // - differential vs single-ended, in each direction
21 // - pin-swapped vs unswapped
22 //
23 // With DV sim at chip level, where we have just the physical two wire USB
24 // between the chip and DPI model, 4 configurations may be exercised.
25 //
26 // On the CW310/340 target, only two configurations may be tested
27 // programmatically without the manual intervention required to flip pins. No
28 // host-side application support is required in this case - just a physical wire
29 // to the host controller, and the OS/device layer will configure the device.
30 
36 #include "sw/device/lib/testing/pinmux_testutils.h"
37 #include "sw/device/lib/testing/test_framework/check.h"
39 #include "sw/device/lib/testing/usb_testutils.h"
40 #include "sw/device/lib/testing/usb_testutils_controlep.h"
41 
42 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
43 
44 /**
45  * Configuration values for USB.
46  */
47 static const uint8_t kConfigDescriptors[] = {
48  USB_CFG_DSCR_HEAD(
49  USB_CFG_DSCR_LEN + 2 * (USB_INTERFACE_DSCR_LEN + 2 * USB_EP_DSCR_LEN),
50  2),
51  VEND_INTERFACE_DSCR(0, 2, 0x50, 1),
52  USB_BULK_EP_DSCR(0, 1, 32, 0),
53  USB_BULK_EP_DSCR(1, 1, 32, 4),
54  VEND_INTERFACE_DSCR(1, 2, 0x50, 1),
55  USB_BULK_EP_DSCR(0, 2, 32, 0),
56  USB_BULK_EP_DSCR(1, 2, 32, 4),
57 };
58 
59 /**
60  * Test descriptor
61  */
62 static const uint8_t kTestDescriptor[] = {
63  USB_TESTUTILS_TEST_DSCR(kUsbTestNumberPinCfg, 0, 0, 0, 0)};
64 
65 /**
66  * USB device context types.
67  */
68 static usb_testutils_ctx_t usbdev;
69 static usb_testutils_controlep_ctx_t usbdev_control;
70 
71 /**
72  * Pinmux handle
73  */
74 static dif_pinmux_t pinmux;
75 
76 /**
77  * Rstmgr handler
78  */
79 static dif_rstmgr_t rstmgr;
80 
81 /**
82  * Verbose reporting?
83  */
84 static bool verbose = false;
85 
86 OTTF_DEFINE_TEST_CONFIG();
87 
88 bool test_main(void) {
89  LOG_INFO("Running USBDEV PINCFG test");
90 
91  CHECK_DIF_OK(dif_pinmux_init(
93  pinmux_testutils_init(&pinmux);
94  CHECK_DIF_OK(dif_pinmux_input_select(
97  CHECK_DIF_OK(dif_rstmgr_init(
99 
100  // Construct the test list appropriate to this target
101  struct {
102  bool pinflip;
103  bool en_diff_rcvr;
104  bool tx_use_d_se0;
105  } test_cfg[8U];
106 
107  unsigned ntests;
108  switch (kDeviceType) {
109  case kDeviceSimDV:
110  // DV simulation can exercise pin-flipping and differential rcvr on/off
111  // but there's no point wasting simulation time trying both tx modes;
112  // D+/D- are always used directly as differential signals.
113  ntests = 4U;
114  for (unsigned test = 0U; test < ntests; ++test) {
115  test_cfg[test].pinflip = ((test & 1U) != 0U);
116  test_cfg[test].en_diff_rcvr = ((test & 2U) != 0U);
117  test_cfg[test].tx_use_d_se0 = false;
118  }
119  break;
120 
121  case kDeviceFpgaCw340:
122  case kDeviceFpgaCw310:
123  // For the CW310/340 pin-flipping is only useful if the SBU signals of
124  // the USB-C connector are being driven; this is not the case we're
125  // testing.
127  case kDeviceSilicon:
128  // Silicon would require external pin-flipping in some form,
129  // eg. configurable hardware or a reversible cable. Only the differential
130  // rcvr on/off may be exercised.
131  LOG_INFO(" - CW310/340/Teacup does not support pinflipping; ignoring");
132  LOG_INFO(" - CW310/340/Teacup employs only differential transmission");
133  ntests = 2U;
134  for (unsigned test = 0U; test < ntests; ++test) {
135  test_cfg[test].pinflip = false;
136  test_cfg[test].en_diff_rcvr = ((test & 1U) != 0U);
137  // D+/D- signals are always used directly as differential signals.
138  test_cfg[test].tx_use_d_se0 = false;
139  }
140  // Fine to employ verbose logging because behavior on FPGA is not
141  // timing-sensitive.
142  verbose = true;
143  break;
144 
145  // Verilator can operate with any pin/bus configuration because it has
146  // ready access to the configuration information.
147  default:
149  ntests = 8U;
150  for (unsigned test = 0U; test < ntests; ++test) {
151  test_cfg[test].pinflip = ((test & 1U) != 0U);
152  test_cfg[test].en_diff_rcvr = ((test & 2U) != 0U);
153  test_cfg[test].tx_use_d_se0 = ((test & 4U) != 0U);
154  }
155  break;
156  }
157 
158  for (unsigned test = 0U; test < ntests; ++test) {
159  bool tx_use_d_se0 = test_cfg[test].tx_use_d_se0;
160  bool en_diff_rcvr = test_cfg[test].en_diff_rcvr;
161  bool pinflip = test_cfg[test].pinflip;
162 
163  if (verbose) {
164  LOG_INFO("Init test %u pinflip %!b en_diff_rcvr %!b tx_use_d_se0 %!b",
165  test, pinflip, en_diff_rcvr, tx_use_d_se0);
166  }
167 
168  // Note: this call will result in the buffer pool being (re)initialised and
169  // as such it _would_ be in disagreement with the hardware if usbdev were
170  // not reset after the previous test
171  CHECK_STATUS_OK(
172  usb_testutils_init(&usbdev, pinflip, en_diff_rcvr, tx_use_d_se0));
173 
174  // Set up the control endpoint and see that we enter the configured state,
175  // implying successful communication between the DPI model and device
176  CHECK_STATUS_OK(usb_testutils_controlep_init(
177  &usbdev_control, &usbdev, 0, kConfigDescriptors,
178  sizeof(kConfigDescriptors), kTestDescriptor, sizeof(kTestDescriptor)));
179 
180  // Configuration shall have been selected only after the host/DPI model has
181  // successfully concluded the SET_CONFIGURATION control transfer
182  CHECK_STATUS_OK(
183  usb_testutils_controlep_config_wait(&usbdev_control, &usbdev));
184 
186  // TODO: We shall probably want simply to drop the connection and control
187  // the DPI in time, as we do for the physical host at present.
188  dif_usbdev_link_state_t link_state;
189  do {
190  CHECK_STATUS_OK(usb_testutils_poll(&usbdev));
191  CHECK_DIF_OK(dif_usbdev_status_get_link_state(usbdev.dev, &link_state));
192  } while (link_state == kDifUsbdevLinkStateActive);
193  }
194 
195  // Shut down the usb_testutils layer, in preparation for restarting;
196  // this disconnects usbdev from the bus. The DPI model will detect this and
197  // restart, awaiting a further connection attempt.
198  CHECK_STATUS_OK(usb_testutils_fin(&usbdev));
199 
200  // We must force a reset of the entire usbdev block in order to perform
201  // the next test successfully, because otherwise buffers remain in the
202  // internal FIFOs
203  if (verbose) {
204  LOG_INFO(" - Hold reset");
205  }
206  CHECK_DIF_OK(dif_rstmgr_software_reset(&rstmgr,
207  kTopEarlgreyResetManagerSwResetsUsb,
209  if (verbose) {
210  LOG_INFO(" - Release reset");
211  }
212  CHECK_DIF_OK(dif_rstmgr_software_reset(&rstmgr,
213  kTopEarlgreyResetManagerSwResetsUsb,
215  }
216 
217  return true;
218 }