Software APIs
dif_usbdev.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 
6 
7 #include <assert.h>
8 
10 
11 #include "usbdev_regs.h" // Generated.
12 
13 /**
14  * Definition in the header file (and probably other places) must be updated if
15  * there is a hardware change.
16  */
17 static_assert(USBDEV_NUM_ENDPOINTS == USBDEV_PARAM_N_ENDPOINTS,
18  "Mismatch in number of endpoints");
19 
20 /**
21  * Max packet size is equal to the size of device buffers.
22  */
23 #define USBDEV_BUFFER_ENTRY_SIZE_BYTES USBDEV_MAX_PACKET_SIZE
24 
25 /**
26  * Constants used to indicate that a buffer pool is full or empty.
27  */
28 #define BUFFER_POOL_FULL (USBDEV_NUM_BUFFERS - 1)
29 #define BUFFER_POOL_EMPTY -1
30 
31 /**
32  * Hardware information for endpoints.
33  */
34 typedef struct endpoint_hw_info {
35  uint32_t config_in_reg_offset;
36  uint8_t bit_index;
38 
39 /**
40  * Helper macro to define an `endpoint_hw_info_t` entry for endpoint N.
41  *
42  * Note: This uses the bit indices of `USBDEV_IN_SENT` register for the sake
43  * of conciseness because other endpoint registers use the same layout.
44  */
45 #define ENDPOINT_HW_INFO_ENTRY(N) \
46  [N] = {.config_in_reg_offset = USBDEV_CONFIGIN_##N##_REG_OFFSET, \
47  .bit_index = USBDEV_IN_SENT_SENT_##N##_BIT}
48 
49 static const endpoint_hw_info_t kEndpointHwInfos[USBDEV_NUM_ENDPOINTS] = {
50  ENDPOINT_HW_INFO_ENTRY(0), ENDPOINT_HW_INFO_ENTRY(1),
51  ENDPOINT_HW_INFO_ENTRY(2), ENDPOINT_HW_INFO_ENTRY(3),
52  ENDPOINT_HW_INFO_ENTRY(4), ENDPOINT_HW_INFO_ENTRY(5),
53  ENDPOINT_HW_INFO_ENTRY(6), ENDPOINT_HW_INFO_ENTRY(7),
54  ENDPOINT_HW_INFO_ENTRY(8), ENDPOINT_HW_INFO_ENTRY(9),
55  ENDPOINT_HW_INFO_ENTRY(10), ENDPOINT_HW_INFO_ENTRY(11),
56 };
57 
58 #undef ENDPOINT_HW_INFO_ENTRY
59 
60 /**
61  * Static functions for the free buffer pool.
62  */
63 
64 /**
65  * Checks if a buffer pool is full.
66  *
67  * A buffer pool is full if it contains `USBDEV_NUM_BUFFERS` buffers.
68  *
69  * @param pool A buffer pool.
70  * @return `true` if the buffer pool if full, `false` otherwise.
71  */
73 static bool buffer_pool_is_full(dif_usbdev_buffer_pool_t *pool) {
74  return pool->top == BUFFER_POOL_FULL;
75 }
76 
77 /**
78  * Checks if a buffer pool is empty.
79  *
80  * @param pool A buffer pool.
81  * @return `true` if the buffer pool is empty, `false` otherwise.
82  */
84 static bool buffer_pool_is_empty(dif_usbdev_buffer_pool_t *pool) {
85  return pool->top == BUFFER_POOL_EMPTY;
86 }
87 
88 /**
89  * Checks if a buffer id is valid.
90  *
91  * A buffer id is valid if it is less than `USBDEV_NUM_BUFFERS`.
92  *
93  * @param buffer_id A buffer id.
94  * @return `true` if `buffer_id` is valid, `false` otherwise.
95  */
97 static bool buffer_pool_is_valid_buffer_id(uint8_t buffer_id) {
98  return buffer_id < USBDEV_NUM_BUFFERS;
99 }
100 
101 /**
102  * Adds a buffer to a buffer pool.
103  *
104  * @param pool A buffer pool.
105  * @param buffer_id A buffer id.
106  * @return `true` if the operation was successful, `false` otherwise.
107  */
109 static bool buffer_pool_add(dif_usbdev_buffer_pool_t *pool, uint8_t buffer_id) {
110  if (buffer_pool_is_full(pool) || !buffer_pool_is_valid_buffer_id(buffer_id)) {
111  return false;
112  }
113 
114  ++pool->top;
115  pool->buffers[pool->top] = buffer_id;
116 
117  return true;
118 }
119 
120 /**
121  * Removes a buffer from a buffer pool.
122  *
123  * @param pool A buffer pool.
124  * @param buffer_id A buffer id.
125  * @return `true` if the operation was successful, `false` otherwise.
126  */
128 static bool buffer_pool_remove(dif_usbdev_buffer_pool_t *pool,
129  uint8_t *buffer_id) {
130  if (buffer_pool_is_empty(pool) || buffer_id == NULL) {
131  return false;
132  }
133 
134  *buffer_id = pool->buffers[pool->top];
135  --pool->top;
136 
137  return true;
138 }
139 
140 /**
141  * Initializes the buffer pool.
142  *
143  * At the end of this operation, the buffer pool contains `USBDEV_NUM_BUFFERS`
144  * buffers.
145  *
146  * @param pool A buffer pool.
147  * @return `true` if the operation was successful, `false` otherwise.
148  */
150 static bool buffer_pool_init(dif_usbdev_buffer_pool_t *pool) {
151  // Start with an empty pool
152  pool->top = -1;
153 
154  // Add all buffers
155  for (uint8_t i = 0; i < USBDEV_NUM_BUFFERS; ++i) {
156  if (!buffer_pool_add(pool, i)) {
157  return false;
158  }
159  }
160 
161  return true;
162 }
163 
164 /**
165  * Utility functions
166  */
167 
168 /**
169  * Checks if the given value is a valid endpoint number.
170  */
172 static bool is_valid_endpoint(uint8_t endpoint_number) {
173  return endpoint_number < USBDEV_NUM_ENDPOINTS;
174 }
175 
176 /**
177  * Enables/disables the functionality controlled by the register at `reg_offset`
178  * for an endpoint.
179  */
181 static dif_result_t endpoint_functionality_enable(const dif_usbdev_t *usbdev,
182  uint32_t reg_offset,
183  uint8_t endpoint,
184  dif_toggle_t new_state) {
185  if (usbdev == NULL || !is_valid_endpoint(endpoint) ||
186  !dif_is_valid_toggle(new_state)) {
187  return kDifBadArg;
188  }
189 
190  uint32_t reg_val =
191  mmio_region_read32(usbdev->base_addr, (ptrdiff_t)reg_offset);
192  reg_val = bitfield_bit32_write(reg_val, kEndpointHwInfos[endpoint].bit_index,
193  dif_toggle_to_bool(new_state));
194  mmio_region_write32(usbdev->base_addr, (ptrdiff_t)reg_offset, reg_val);
195  return kDifOk;
196 }
197 
198 /**
199  * Returns the address that corresponds to the given buffer and offset
200  * into that buffer.
201  */
203 static uint32_t get_buffer_addr(uint8_t buffer_id, size_t offset) {
204  return USBDEV_BUFFER_REG_OFFSET +
205  (buffer_id * USBDEV_BUFFER_ENTRY_SIZE_BYTES) + offset;
206 }
207 
208 /**
209  * USBDEV DIF library functions.
210  */
211 
213  dif_usbdev_buffer_pool_t *buffer_pool,
214  dif_usbdev_config_t config) {
215  if (usbdev == NULL || buffer_pool == NULL) {
216  return kDifBadArg;
217  }
218 
219  // Configure the free buffer pool.
220  if (!buffer_pool_init(buffer_pool)) {
221  return kDifError;
222  }
223 
224  // Check enum fields.
227  !dif_is_valid_toggle(config.single_bit_eop) ||
228  !dif_is_valid_toggle(config.pin_flip) ||
230  return kDifBadArg;
231  }
232 
233  // Determine the value of the PHY_CONFIG register.
234  uint32_t phy_config_val = 0;
235  phy_config_val = bitfield_bit32_write(
236  phy_config_val, USBDEV_PHY_CONFIG_USE_DIFF_RCVR_BIT,
238  phy_config_val =
239  bitfield_bit32_write(phy_config_val, USBDEV_PHY_CONFIG_TX_USE_D_SE0_BIT,
241  phy_config_val =
242  bitfield_bit32_write(phy_config_val, USBDEV_PHY_CONFIG_EOP_SINGLE_BIT_BIT,
243  dif_toggle_to_bool(config.single_bit_eop));
244  phy_config_val =
245  bitfield_bit32_write(phy_config_val, USBDEV_PHY_CONFIG_PINFLIP_BIT,
246  dif_toggle_to_bool(config.pin_flip));
247  phy_config_val = bitfield_bit32_write(
248  phy_config_val, USBDEV_PHY_CONFIG_USB_REF_DISABLE_BIT,
250 
251  // Write configuration to PHY_CONFIG register
252  mmio_region_write32(usbdev->base_addr, USBDEV_PHY_CONFIG_REG_OFFSET,
253  phy_config_val);
254 
255  return kDifOk;
256 }
257 
259  const dif_usbdev_t *usbdev, dif_usbdev_buffer_pool_t *buffer_pool) {
260  if (usbdev == NULL || buffer_pool == NULL) {
261  return kDifBadArg;
262  }
263 
264  // Remove buffers from the pool and write as many as possible into the FIFOs
265  while (!buffer_pool_is_empty(buffer_pool)) {
266  uint32_t status =
267  mmio_region_read32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET);
268  // Prioritize available SETUP buffers
269  uint32_t av_setup_depth =
270  bitfield_field32_read(status, USBDEV_USBSTAT_AV_SETUP_DEPTH_FIELD);
271  if (av_setup_depth >= 2) {
272  // Available SETUP Buffer FIFO is okay, what about the OUT buffers?
273  bool av_out_full =
274  bitfield_bit32_read(status, USBDEV_USBSTAT_AV_OUT_FULL_BIT);
275  if (av_out_full) {
276  break;
277  }
278  }
279  uint8_t buffer_id;
280  if (!buffer_pool_remove(buffer_pool, &buffer_id)) {
281  return kDifError;
282  }
283  if (av_setup_depth >= 2) {
284  // Supply Available OUT Buffer
285  uint32_t reg_val =
286  bitfield_field32_write(0, USBDEV_AVOUTBUFFER_BUFFER_FIELD, buffer_id);
287  mmio_region_write32(usbdev->base_addr, USBDEV_AVOUTBUFFER_REG_OFFSET,
288  reg_val);
289  } else {
290  // Supply Available SETUP Buffer
291  uint32_t reg_val = bitfield_field32_write(
292  0, USBDEV_AVSETUPBUFFER_BUFFER_FIELD, buffer_id);
293  mmio_region_write32(usbdev->base_addr, USBDEV_AVSETUPBUFFER_REG_OFFSET,
294  reg_val);
295  }
296  }
297 
298  return kDifOk;
299 }
300 
302  uint8_t endpoint,
303  dif_toggle_t new_state) {
304  return endpoint_functionality_enable(usbdev, USBDEV_RXENABLE_SETUP_REG_OFFSET,
305  endpoint, new_state);
306 }
307 
309  uint8_t endpoint,
310  dif_toggle_t new_state) {
311  return endpoint_functionality_enable(usbdev, USBDEV_RXENABLE_OUT_REG_OFFSET,
312  endpoint, new_state);
313 }
314 
316  uint8_t endpoint,
317  dif_toggle_t new_state) {
318  return endpoint_functionality_enable(usbdev, USBDEV_SET_NAK_OUT_REG_OFFSET,
319  endpoint, new_state);
320 }
321 
323  dif_usbdev_endpoint_id_t endpoint,
324  dif_toggle_t new_state) {
325  if (endpoint.direction == USBDEV_ENDPOINT_DIR_IN) {
326  return endpoint_functionality_enable(usbdev, USBDEV_IN_STALL_REG_OFFSET,
327  endpoint.number, new_state);
328  } else {
329  return endpoint_functionality_enable(usbdev, USBDEV_OUT_STALL_REG_OFFSET,
330  endpoint.number, new_state);
331  }
332 }
333 
335  dif_usbdev_endpoint_id_t endpoint,
336  bool *state) {
337  if (usbdev == NULL || state == NULL || !is_valid_endpoint(endpoint.number)) {
338  return kDifBadArg;
339  }
340 
341  ptrdiff_t reg_offset = endpoint.direction == USBDEV_ENDPOINT_DIR_IN
342  ? USBDEV_IN_STALL_REG_OFFSET
343  : USBDEV_OUT_STALL_REG_OFFSET;
344  uint32_t reg_val = mmio_region_read32(usbdev->base_addr, reg_offset);
345  *state =
346  bitfield_bit32_read(reg_val, kEndpointHwInfos[endpoint.number].bit_index);
347 
348  return kDifOk;
349 }
350 
352  dif_usbdev_endpoint_id_t endpoint,
353  dif_toggle_t new_state) {
354  if (endpoint.direction == USBDEV_ENDPOINT_DIR_IN) {
355  return endpoint_functionality_enable(usbdev, USBDEV_IN_ISO_REG_OFFSET,
356  endpoint.number, new_state);
357  } else {
358  return endpoint_functionality_enable(usbdev, USBDEV_OUT_ISO_REG_OFFSET,
359  endpoint.number, new_state);
360  }
361 }
362 
364  dif_usbdev_endpoint_id_t endpoint,
365  dif_toggle_t new_state) {
366  if (endpoint.direction == USBDEV_ENDPOINT_DIR_IN) {
367  return endpoint_functionality_enable(usbdev, USBDEV_EP_IN_ENABLE_REG_OFFSET,
368  endpoint.number, new_state);
369  } else {
370  return endpoint_functionality_enable(
371  usbdev, USBDEV_EP_OUT_ENABLE_REG_OFFSET, endpoint.number, new_state);
372  }
373  return kDifOk;
374 }
375 
377  dif_toggle_t new_state) {
378  if (usbdev == NULL || !dif_is_valid_toggle(new_state)) {
379  return kDifBadArg;
380  }
381 
382  uint32_t reg_val =
383  mmio_region_read32(usbdev->base_addr, USBDEV_USBCTRL_REG_OFFSET);
384  reg_val = bitfield_bit32_write(reg_val, USBDEV_USBCTRL_ENABLE_BIT,
385  dif_toggle_to_bool(new_state));
386  mmio_region_write32(usbdev->base_addr, USBDEV_USBCTRL_REG_OFFSET, reg_val);
387 
388  return kDifOk;
389 }
390 
393  dif_usbdev_buffer_t *buffer) {
394  if (usbdev == NULL || info == NULL || buffer == NULL) {
395  return kDifBadArg;
396  }
397 
398  // Check if the RX FIFO is empty
399  uint32_t fifo_status =
400  mmio_region_read32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET);
401  if (bitfield_bit32_read(fifo_status, USBDEV_USBSTAT_RX_EMPTY_BIT)) {
402  return kDifUnavailable;
403  }
404 
405  // Read fifo entry
406  const uint32_t fifo_entry =
407  mmio_region_read32(usbdev->base_addr, USBDEV_RXFIFO_REG_OFFSET);
408  // Init packet info
409  *info = (dif_usbdev_rx_packet_info_t){
410  .endpoint =
411  (uint8_t)bitfield_field32_read(fifo_entry, USBDEV_RXFIFO_EP_FIELD),
412  .is_setup = bitfield_bit32_read(fifo_entry, USBDEV_RXFIFO_SETUP_BIT),
413  .length =
414  (uint8_t)bitfield_field32_read(fifo_entry, USBDEV_RXFIFO_SIZE_FIELD),
415  };
416  // Init buffer struct
417  *buffer = (dif_usbdev_buffer_t){
418  .id = (uint8_t)bitfield_field32_read(fifo_entry,
419  USBDEV_RXFIFO_BUFFER_FIELD),
420  .offset = 0,
421  .remaining_bytes = info->length,
422  .type = kDifUsbdevBufferTypeRead,
423  };
424 
425  return kDifOk;
426 }
427 
429  dif_usbdev_buffer_pool_t *buffer_pool,
430  dif_usbdev_buffer_t *buffer) {
431  if (usbdev == NULL || buffer_pool == NULL || buffer == NULL) {
432  return kDifBadArg;
433  }
434 
435  if (buffer_pool_is_empty(buffer_pool)) {
436  return kDifUnavailable;
437  }
438 
439  uint8_t buffer_id;
440  if (!buffer_pool_remove(buffer_pool, &buffer_id)) {
441  return kDifError;
442  }
443 
444  *buffer = (dif_usbdev_buffer_t){
445  .id = buffer_id,
446  .offset = 0,
447  .remaining_bytes = USBDEV_BUFFER_ENTRY_SIZE_BYTES,
449  };
450 
451  return kDifOk;
452 }
453 
455  dif_usbdev_buffer_pool_t *buffer_pool,
456  dif_usbdev_buffer_t *buffer) {
457  if (usbdev == NULL || buffer_pool == NULL || buffer == NULL) {
458  return kDifBadArg;
459  }
460 
461  switch (buffer->type) {
464  // Return the buffer to the free buffer pool
465  if (!buffer_pool_add(buffer_pool, buffer->id)) {
466  return kDifError;
467  }
468  // Mark the buffer as stale
470  return kDifOk;
471  default:
472  return kDifBadArg;
473  }
474 }
475 
477  dif_usbdev_buffer_pool_t *buffer_pool,
478  dif_usbdev_buffer_t *buffer, uint8_t *dst,
479  size_t dst_len, size_t *bytes_written) {
480  if (usbdev == NULL || buffer_pool == NULL || buffer == NULL ||
481  buffer->type != kDifUsbdevBufferTypeRead || dst == NULL) {
482  return kDifBadArg;
483  }
484 
485  // bytes_to_copy is the minimum of remaining_bytes and dst_len
486  size_t bytes_to_copy = buffer->remaining_bytes;
487  if (bytes_to_copy > dst_len) {
488  bytes_to_copy = dst_len;
489  }
490  // Copy from buffer to dst
491  const uint32_t buffer_addr = get_buffer_addr(buffer->id, buffer->offset);
492  mmio_region_memcpy_from_mmio32(usbdev->base_addr, buffer_addr, dst,
493  bytes_to_copy);
494  // Update buffer state
495  buffer->offset += bytes_to_copy;
496  buffer->remaining_bytes -= bytes_to_copy;
497 
498  if (bytes_written != NULL) {
499  *bytes_written = bytes_to_copy;
500  }
501 
502  // Check if there are any remaining bytes
503  if (buffer->remaining_bytes > 0) {
504  return kDifOk;
505  }
506 
507  // Return the buffer to the free buffer pool
508  if (!buffer_pool_add(buffer_pool, buffer->id)) {
509  return kDifError;
510  }
511 
512  // Mark the buffer as stale
514  return kDifOk;
515 }
516 
518  dif_usbdev_buffer_t *buffer,
519  const uint8_t *src, size_t src_len,
520  size_t *bytes_written) {
521  if (usbdev == NULL || buffer == NULL ||
522  buffer->type != kDifUsbdevBufferTypeWrite || src == NULL) {
523  return kDifBadArg;
524  }
525 
526  // bytes_to_copy is the minimum of remaining_bytes and src_len.
527  size_t bytes_to_copy = buffer->remaining_bytes;
528  if (bytes_to_copy > src_len) {
529  bytes_to_copy = src_len;
530  }
531 
532  // Write bytes to the buffer
533  uint32_t buffer_addr = get_buffer_addr(buffer->id, buffer->offset);
534  mmio_region_memcpy_to_mmio32(usbdev->base_addr, buffer_addr, src,
535  bytes_to_copy);
536 
537  buffer->offset += bytes_to_copy;
538  buffer->remaining_bytes -= bytes_to_copy;
539 
540  if (bytes_written) {
541  *bytes_written = bytes_to_copy;
542  }
543 
544  if (buffer->remaining_bytes == 0 && bytes_to_copy < src_len) {
545  return kDifError;
546  }
547 
548  return kDifOk;
549 }
550 
551 dif_result_t dif_usbdev_send(const dif_usbdev_t *usbdev, uint8_t endpoint,
552  dif_usbdev_buffer_t *buffer) {
553  if (usbdev == NULL || !is_valid_endpoint(endpoint) || buffer == NULL ||
554  buffer->type != kDifUsbdevBufferTypeWrite) {
555  return kDifBadArg;
556  }
557 
558  // Get the configin register offset of the endpoint.
559  const uint32_t config_in_reg_offset =
560  kEndpointHwInfos[endpoint].config_in_reg_offset;
561 
562  // Configure USBDEV_CONFIGINX register.
563  // Note: Using mask and offset values for the USBDEV_CONFIGIN0 register
564  // for all endpoints because all USBDEV_CONFIGINX registers have the same
565  // layout.
566  uint32_t config_in_val = 0;
567  config_in_val = bitfield_field32_write(
568  config_in_val, USBDEV_CONFIGIN_0_BUFFER_0_FIELD, buffer->id);
569  config_in_val = bitfield_field32_write(
570  config_in_val, USBDEV_CONFIGIN_0_SIZE_0_FIELD, buffer->offset);
571  mmio_region_write32(usbdev->base_addr, (ptrdiff_t)config_in_reg_offset,
572  config_in_val);
573 
574  // Mark the packet as ready for transmission
575  config_in_val =
576  bitfield_bit32_write(config_in_val, USBDEV_CONFIGIN_0_RDY_0_BIT, true);
577  mmio_region_write32(usbdev->base_addr, (ptrdiff_t)config_in_reg_offset,
578  config_in_val);
579 
580  // Mark the buffer as stale. It will be returned to the free buffer pool
581  // in dif_usbdev_get_tx_status once transmission is complete.
583 
584  return kDifOk;
585 }
586 
588  uint16_t *sent) {
589  if (usbdev == NULL || sent == NULL) {
590  return kDifBadArg;
591  }
592  *sent = (uint16_t)mmio_region_read32(usbdev->base_addr,
593  USBDEV_IN_SENT_REG_OFFSET);
594  return kDifOk;
595 }
596 
598  dif_usbdev_buffer_pool_t *buffer_pool,
599  uint8_t endpoint) {
600  if (usbdev == NULL || buffer_pool == NULL || !is_valid_endpoint(endpoint)) {
601  return kDifBadArg;
602  }
603  // Get the configin register offset and bit index of the endpoint.
604  uint32_t config_in_reg_offset =
605  kEndpointHwInfos[endpoint].config_in_reg_offset;
606  uint32_t config_in_reg_val =
607  mmio_region_read32(usbdev->base_addr, (ptrdiff_t)config_in_reg_offset);
608  uint8_t buffer = (uint8_t)bitfield_field32_read(
609  config_in_reg_val, USBDEV_CONFIGIN_0_BUFFER_0_FIELD);
610 
611  mmio_region_write32(usbdev->base_addr, (ptrdiff_t)config_in_reg_offset,
612  1u << USBDEV_CONFIGIN_0_PEND_0_BIT);
613  // Clear IN_SENT bit (rw1c).
614  mmio_region_write32(usbdev->base_addr, USBDEV_IN_SENT_REG_OFFSET,
615  1u << endpoint);
616  // Return the buffer back to the free buffer pool.
617  if (!buffer_pool_add(buffer_pool, buffer)) {
618  return kDifError;
619  }
620  return kDifOk;
621 }
622 
624  uint8_t endpoint,
626  if (usbdev == NULL || status == NULL || !is_valid_endpoint(endpoint)) {
627  return kDifBadArg;
628  }
629 
630  // Get the configin register offset and bit index of the endpoint.
631  uint32_t config_in_reg_offset =
632  kEndpointHwInfos[endpoint].config_in_reg_offset;
633  uint8_t endpoint_bit_index = kEndpointHwInfos[endpoint].bit_index;
634 
635  // Read the configin register.
636  uint32_t config_in_val =
637  mmio_region_read32(usbdev->base_addr, (ptrdiff_t)config_in_reg_offset);
638 
639  // Check the status of the packet.
640  if (bitfield_bit32_read(config_in_val, USBDEV_CONFIGIN_0_RDY_0_BIT)) {
641  // Packet is marked as ready to be sent and pending transmission.
643  } else if (bitfield_bit32_read(mmio_region_read32(usbdev->base_addr,
644  USBDEV_IN_SENT_REG_OFFSET),
645  endpoint_bit_index)) {
646  // Packet was sent successfully.
648  } else if (bitfield_bit32_read(config_in_val, USBDEV_CONFIGIN_0_PEND_0_BIT)) {
649  // Canceled due to an IN SETUP packet or link reset.
651  } else {
652  // No packet has been queued for this endpoint.
654  }
655 
656  return kDifOk;
657 }
658 
659 dif_result_t dif_usbdev_address_set(const dif_usbdev_t *usbdev, uint8_t addr) {
660  if (usbdev == NULL) {
661  return kDifBadArg;
662  }
663 
664  uint32_t reg_val =
665  mmio_region_read32(usbdev->base_addr, USBDEV_USBCTRL_REG_OFFSET);
666  reg_val = bitfield_field32_write(reg_val, USBDEV_USBCTRL_DEVICE_ADDRESS_FIELD,
667  addr);
668  mmio_region_write32(usbdev->base_addr, USBDEV_USBCTRL_REG_OFFSET, reg_val);
669 
670  return kDifOk;
671 }
672 
673 dif_result_t dif_usbdev_address_get(const dif_usbdev_t *usbdev, uint8_t *addr) {
674  if (usbdev == NULL || addr == NULL) {
675  return kDifBadArg;
676  }
677 
678  uint32_t reg_val =
679  mmio_region_read32(usbdev->base_addr, USBDEV_USBCTRL_REG_OFFSET);
680  // Note: Size of address is 7 bits.
681  *addr = (uint8_t)bitfield_field32_read(reg_val,
682  USBDEV_USBCTRL_DEVICE_ADDRESS_FIELD);
683 
684  return kDifOk;
685 }
686 
688  uint16_t *toggles) {
689  if (usbdev == NULL || toggles == NULL) {
690  return kDifBadArg;
691  }
692 
693  uint32_t reg_val =
694  mmio_region_read32(usbdev->base_addr, USBDEV_OUT_DATA_TOGGLE_REG_OFFSET);
695  // Note: only 12 OUT endpoints defined.
696  *toggles = (uint16_t)reg_val;
697 
698  return kDifOk;
699 }
700 
702  uint16_t *toggles) {
703  if (usbdev == NULL || toggles == NULL) {
704  return kDifBadArg;
705  }
706 
707  uint32_t reg_val =
708  mmio_region_read32(usbdev->base_addr, USBDEV_IN_DATA_TOGGLE_REG_OFFSET);
709  // Note: only 12 OUT endpoints defined.
710  *toggles = (uint16_t)reg_val;
711 
712  return kDifOk;
713 }
714 
716  uint16_t mask, uint16_t state) {
717  if (usbdev == NULL) {
718  return kDifBadArg;
719  }
720 
721  // Note: only 12 OUT endpoints defined.
722  mmio_region_write32(usbdev->base_addr, USBDEV_OUT_DATA_TOGGLE_REG_OFFSET,
723  ((uint32_t)mask << 16) | state);
724 
725  return kDifOk;
726 }
727 
729  uint16_t mask, uint16_t state) {
730  if (usbdev == NULL) {
731  return kDifBadArg;
732  }
733 
734  // Note: only 12 OUT endpoints defined.
735  mmio_region_write32(usbdev->base_addr, USBDEV_IN_DATA_TOGGLE_REG_OFFSET,
736  ((uint32_t)mask << 16) | state);
737 
738  return kDifOk;
739 }
740 
742  uint8_t endpoint) {
743  if (usbdev == NULL) {
744  return kDifBadArg;
745  }
746 
747  uint32_t reg_val = (uint32_t)1u << (endpoint + 16u);
748  mmio_region_write32(usbdev->base_addr, USBDEV_OUT_DATA_TOGGLE_REG_OFFSET,
749  reg_val);
750  mmio_region_write32(usbdev->base_addr, USBDEV_IN_DATA_TOGGLE_REG_OFFSET,
751  reg_val);
752 
753  return kDifOk;
754 }
755 
757  uint16_t *frame_index) {
758  if (usbdev == NULL || frame_index == NULL) {
759  return kDifBadArg;
760  }
761 
762  uint32_t reg_val =
763  mmio_region_read32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET);
764  // Note: size of frame index is 11 bits.
765  *frame_index =
766  (uint8_t)bitfield_field32_read(reg_val, USBDEV_USBSTAT_FRAME_FIELD);
767 
768  return kDifOk;
769 }
770 
772  bool *host_lost) {
773  if (usbdev == NULL || host_lost == NULL) {
774  return kDifBadArg;
775  }
776 
777  *host_lost =
778  mmio_region_get_bit32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET,
779  USBDEV_USBSTAT_HOST_LOST_BIT);
780 
781  return kDifOk;
782 }
783 
785  const dif_usbdev_t *usbdev, dif_usbdev_link_state_t *link_state) {
786  if (usbdev == NULL || link_state == NULL) {
787  return kDifBadArg;
788  }
789 
790  uint32_t val =
791  mmio_region_read32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET);
792  val = bitfield_field32_read(val, USBDEV_USBSTAT_LINK_STATE_FIELD);
793 
794  switch (val) {
795  case USBDEV_USBSTAT_LINK_STATE_VALUE_DISCONNECTED:
796  *link_state = kDifUsbdevLinkStateDisconnected;
797  break;
798  case USBDEV_USBSTAT_LINK_STATE_VALUE_POWERED:
799  *link_state = kDifUsbdevLinkStatePowered;
800  break;
801  case USBDEV_USBSTAT_LINK_STATE_VALUE_POWERED_SUSPENDED:
802  *link_state = kDifUsbdevLinkStatePoweredSuspended;
803  break;
804  case USBDEV_USBSTAT_LINK_STATE_VALUE_ACTIVE:
805  *link_state = kDifUsbdevLinkStateActive;
806  break;
807  case USBDEV_USBSTAT_LINK_STATE_VALUE_SUSPENDED:
808  *link_state = kDifUsbdevLinkStateSuspended;
809  break;
810  case USBDEV_USBSTAT_LINK_STATE_VALUE_ACTIVE_NOSOF:
811  *link_state = kDifUsbdevLinkStateActiveNoSof;
812  break;
813  case USBDEV_USBSTAT_LINK_STATE_VALUE_RESUMING:
814  *link_state = kDifUsbdevLinkStateResuming;
815  break;
816  default:
817  return kDifError;
818  }
819 
820  return kDifOk;
821 }
822 
824  bool *sense) {
825  if (usbdev == NULL || sense == NULL) {
826  return kDifBadArg;
827  }
828 
829  *sense = mmio_region_get_bit32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET,
830  USBDEV_USBSTAT_SENSE_BIT);
831 
832  return kDifOk;
833 }
834 
836  const dif_usbdev_t *usbdev, uint8_t *setup_depth, uint8_t *out_depth) {
837  if (usbdev == NULL || setup_depth == NULL || out_depth == NULL) {
838  return kDifBadArg;
839  }
840 
841  uint32_t reg_val =
842  mmio_region_read32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET);
843  // Note: Size of Available SETUP FIFO depth is 3 bits.
844  *setup_depth = (uint8_t)bitfield_field32_read(
845  reg_val, USBDEV_USBSTAT_AV_SETUP_DEPTH_FIELD);
846  // Note: Size of Available OUT FIFO depth is 4 bits.
847  *out_depth = (uint8_t)bitfield_field32_read(
848  reg_val, USBDEV_USBSTAT_AV_OUT_DEPTH_FIELD);
849 
850  return kDifOk;
851 }
852 
854  const dif_usbdev_t *usbdev, bool *setup_is_full, bool *out_is_full) {
855  if (usbdev == NULL || setup_is_full == NULL || out_is_full == NULL) {
856  return kDifBadArg;
857  }
858 
859  uint32_t reg_val =
860  mmio_region_read32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET);
861  *setup_is_full =
862  bitfield_bit32_read(reg_val, USBDEV_USBSTAT_AV_SETUP_FULL_BIT);
863  *out_is_full = bitfield_bit32_read(reg_val, USBDEV_USBSTAT_AV_OUT_FULL_BIT);
864 
865  return kDifOk;
866 }
867 
869  uint8_t *depth) {
870  if (usbdev == NULL || depth == NULL) {
871  return kDifBadArg;
872  }
873 
874  uint32_t reg_val =
875  mmio_region_read32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET);
876  // Note: Size of RX FIFO depth is 4 bits.
877  *depth =
878  (uint8_t)bitfield_field32_read(reg_val, USBDEV_USBSTAT_RX_DEPTH_FIELD);
879 
880  return kDifOk;
881 }
882 
884  bool *is_empty) {
885  if (usbdev == NULL || is_empty == NULL) {
886  return kDifBadArg;
887  }
888 
889  uint32_t reg_val =
890  mmio_region_read32(usbdev->base_addr, USBDEV_USBSTAT_REG_OFFSET);
891  *is_empty = bitfield_bit32_read(reg_val, USBDEV_USBSTAT_RX_EMPTY_BIT);
892 
893  return kDifOk;
894 }
895 
897  dif_toggle_t enable) {
898  if (usbdev == NULL || !dif_is_valid_toggle(enable)) {
899  return kDifBadArg;
900  }
901  bool set_tx_osc_mode = dif_toggle_to_bool(enable);
902  uint32_t reg_val =
903  mmio_region_read32(usbdev->base_addr, USBDEV_PHY_CONFIG_REG_OFFSET);
904  reg_val = bitfield_bit32_write(
905  reg_val, USBDEV_PHY_CONFIG_TX_OSC_TEST_MODE_BIT, set_tx_osc_mode);
906  mmio_region_write32(usbdev->base_addr, USBDEV_PHY_CONFIG_REG_OFFSET, reg_val);
907  return kDifOk;
908 }
909 
911  dif_toggle_t enable) {
912  if (usbdev == NULL || !dif_is_valid_toggle(enable)) {
913  return kDifBadArg;
914  }
915  uint32_t reg_val;
916  if (dif_toggle_to_bool(enable)) {
917  reg_val =
918  bitfield_bit32_write(0, USBDEV_WAKE_CONTROL_SUSPEND_REQ_BIT, true);
919  } else {
920  reg_val = bitfield_bit32_write(0, USBDEV_WAKE_CONTROL_WAKE_ACK_BIT, true);
921  }
922  mmio_region_write32(usbdev->base_addr, USBDEV_WAKE_CONTROL_REG_OFFSET,
923  reg_val);
924  return kDifOk;
925 }
926 
929  if (usbdev == NULL || status == NULL) {
930  return kDifBadArg;
931  }
932  uint32_t reg_val =
933  mmio_region_read32(usbdev->base_addr, USBDEV_WAKE_EVENTS_REG_OFFSET);
934  status->active =
935  bitfield_bit32_read(reg_val, USBDEV_WAKE_EVENTS_MODULE_ACTIVE_BIT);
936  status->disconnected =
937  bitfield_bit32_read(reg_val, USBDEV_WAKE_EVENTS_DISCONNECTED_BIT);
938  status->bus_reset =
939  bitfield_bit32_read(reg_val, USBDEV_WAKE_EVENTS_BUS_RESET_BIT);
940  return kDifOk;
941 }
942 
944  if (usbdev == NULL) {
945  return kDifBadArg;
946  }
947  uint32_t reg_val =
948  mmio_region_read32(usbdev->base_addr, USBDEV_USBCTRL_REG_OFFSET);
949  reg_val = bitfield_bit32_write(reg_val, USBDEV_USBCTRL_RESUME_LINK_ACTIVE_BIT,
950  true);
951  mmio_region_write32(usbdev->base_addr, USBDEV_USBCTRL_REG_OFFSET, reg_val);
952  return kDifOk;
953 }
954 
957  if (usbdev == NULL || status == NULL) {
958  return kDifBadArg;
959  }
960  uint32_t reg_val =
961  mmio_region_read32(usbdev->base_addr, USBDEV_PHY_PINS_SENSE_REG_OFFSET);
962  status->rx_dp =
963  bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_RX_DP_I_BIT);
964  status->rx_dn =
965  bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_RX_DN_I_BIT);
966  status->rx_d = bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_RX_D_I_BIT);
967  status->tx_dp =
968  bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_TX_DP_O_BIT);
969  status->tx_dn =
970  bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_TX_DN_O_BIT);
971  status->tx_d = bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_TX_D_O_BIT);
972  status->tx_se0 =
973  bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_TX_SE0_O_BIT);
974  status->output_enable =
975  bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_TX_OE_O_BIT);
976  status->vbus_sense =
977  bitfield_bit32_read(reg_val, USBDEV_PHY_PINS_SENSE_PWR_SENSE_BIT);
978  return kDifOk;
979 }
980 
982  const dif_usbdev_t *usbdev, dif_toggle_t override_enable,
983  dif_usbdev_phy_pins_drive_t overrides) {
984  if (usbdev == NULL || !dif_is_valid_toggle(override_enable)) {
985  return kDifBadArg;
986  }
987  bool drive_en = dif_toggle_to_bool(override_enable);
988  uint32_t reg_val =
989  bitfield_bit32_write(0, USBDEV_PHY_PINS_DRIVE_EN_BIT, drive_en);
990  if (drive_en) {
991  reg_val = bitfield_bit32_write(reg_val, USBDEV_PHY_PINS_DRIVE_DP_O_BIT,
992  overrides.dp);
993  reg_val = bitfield_bit32_write(reg_val, USBDEV_PHY_PINS_DRIVE_DN_O_BIT,
994  overrides.dn);
995  reg_val = bitfield_bit32_write(reg_val, USBDEV_PHY_PINS_DRIVE_D_O_BIT,
996  overrides.data);
997  reg_val = bitfield_bit32_write(reg_val, USBDEV_PHY_PINS_DRIVE_SE0_O_BIT,
998  overrides.se0);
999  reg_val = bitfield_bit32_write(reg_val, USBDEV_PHY_PINS_DRIVE_OE_O_BIT,
1000  overrides.output_enable);
1001  reg_val =
1002  bitfield_bit32_write(reg_val, USBDEV_PHY_PINS_DRIVE_RX_ENABLE_O_BIT,
1003  overrides.diff_receiver_enable);
1004  reg_val =
1005  bitfield_bit32_write(reg_val, USBDEV_PHY_PINS_DRIVE_DP_PULLUP_EN_O_BIT,
1006  overrides.dp_pullup_en);
1007  reg_val =
1008  bitfield_bit32_write(reg_val, USBDEV_PHY_PINS_DRIVE_DN_PULLUP_EN_O_BIT,
1009  overrides.dn_pullup_en);
1010  }
1011  mmio_region_write32(usbdev->base_addr, USBDEV_PHY_PINS_DRIVE_REG_OFFSET,
1012  reg_val);
1013  return kDifOk;
1014 }