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