| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |  * The MIT License (MIT) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2021 Koji Kitayama | 
					
						
							|  |  |  |  * Portions copyrighted (c) 2021 Roland Winistoerfer | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | 
					
						
							|  |  |  |  * of this software and associated documentation files (the "Software"), to deal | 
					
						
							|  |  |  |  * in the Software without restriction, including without limitation the rights | 
					
						
							|  |  |  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
					
						
							|  |  |  |  * copies of the Software, and to permit persons to whom the Software is | 
					
						
							|  |  |  |  * furnished to do so, subject to the following conditions: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The above copyright notice and this permission notice shall be included in | 
					
						
							|  |  |  |  * all copies or substantial portions of the Software. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
					
						
							|  |  |  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
					
						
							|  |  |  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
					
						
							|  |  |  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
					
						
							|  |  |  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
					
						
							|  |  |  |  * THE SOFTWARE. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is part of the TinyUSB stack. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "tusb_option.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  | #if CFG_TUH_ENABLED && (TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) || \
 | 
					
						
							|  |  |  |                         TU_CHECK_MCU(OPT_MCU_RAXXX)) | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | #include "host/hcd.h"
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:03:08 +07:00
										 |  |  | #include "rusb2_type.h"
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N)
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:03:08 +07:00
										 |  |  |   #include "rusb2_rx.h"
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | #elif TU_CHECK_MCU(OPT_MCU_RAXXX)
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:03:08 +07:00
										 |  |  |   #include "rusb2_ra.h"
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:03:08 +07:00
										 |  |  |   #error "Unsupported MCU"
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 14:21:58 +02:00
										 |  |  | #define TU_RUSB2_HCD_DBG   0
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | // MACRO TYPEDEF CONSTANT ENUM DECLARATION
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* LINK core registers */ | 
					
						
							|  |  |  | #if defined(__CCRX__)
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   #define RUSB2 ((RUSB2_REG_t __evenaccess*) RUSB2_REG_BASE)
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   #define RUSB2 ((RUSB2_REG_t*) RUSB2_REG_BASE)
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | TU_ATTR_PACKED_BEGIN | 
					
						
							|  |  |  | TU_ATTR_BIT_FIELD_ORDER_BEGIN | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | typedef struct TU_ATTR_PACKED { | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   union { | 
					
						
							|  |  |  |     struct { | 
					
						
							|  |  |  |       uint16_t      : 8; | 
					
						
							|  |  |  |       uint16_t TRCLR: 1; | 
					
						
							|  |  |  |       uint16_t TRENB: 1; | 
					
						
							|  |  |  |       uint16_t      : 0; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     uint16_t TRE; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   uint16_t TRN; | 
					
						
							|  |  |  | } reg_pipetre_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | typedef union TU_ATTR_PACKED { | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   struct { | 
					
						
							|  |  |  |     volatile uint16_t u8: 8; | 
					
						
							|  |  |  |     volatile uint16_t   : 0; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   volatile uint16_t u16; | 
					
						
							|  |  |  | } hw_fifo_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | typedef struct TU_ATTR_PACKED { | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   void      *buf;      /* the start address of a transfer data buffer */ | 
					
						
							|  |  |  |   uint16_t  length;    /* the number of bytes in the buffer */ | 
					
						
							|  |  |  |   uint16_t  remaining; /* the number of bytes remaining in the buffer */ | 
					
						
							|  |  |  |   struct { | 
					
						
							|  |  |  |     uint32_t ep  : 8;  /* an assigned endpoint address */ | 
					
						
							|  |  |  |     uint32_t dev : 8;  /* an assigned device address */ | 
					
						
							|  |  |  |     uint32_t ff  : 1;  /* `buf` is TU_FUFO or POD */ | 
					
						
							|  |  |  |     uint32_t     : 0; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } pipe_state_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TU_ATTR_PACKED_END  // End of definition of packed structs (used by the CCRX toolchain)
 | 
					
						
							|  |  |  | TU_ATTR_BIT_FIELD_ORDER_END | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bool         need_reset; /* The device has not been reset after connection. */ | 
					
						
							|  |  |  |   pipe_state_t pipe[10]; | 
					
						
							|  |  |  |   uint8_t ep[4][2][15];   /* a lookup table for a pipe index from an endpoint address */ | 
					
						
							|  |  |  |   uint8_t      ctl_mps[5]; /* EP0 max packet size for each device */ | 
					
						
							|  |  |  | } hcd_data_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | // INTERNAL OBJECT & FUNCTION DECLARATION
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | static hcd_data_t _hcd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned find_pipe(unsigned xfer) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (xfer) { | 
					
						
							|  |  |  |   case TUSB_XFER_ISOCHRONOUS: | 
					
						
							|  |  |  |     for (int i = 1; i <= 2; ++i) { | 
					
						
							|  |  |  |       if (0 == _hcd.pipe[i].ep) return  i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case TUSB_XFER_BULK: | 
					
						
							|  |  |  |     for (int i = 3; i <= 5; ++i) { | 
					
						
							|  |  |  |       if (0 == _hcd.pipe[i].ep) return  i; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-23 10:26:45 +02:00
										 |  |  |     for (int i = 1; i <= 2; ++i) { | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |       if (0 == _hcd.pipe[i].ep) return  i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case TUSB_XFER_INTERRUPT: | 
					
						
							|  |  |  |     for (int i = 6; i <= 9; ++i) { | 
					
						
							|  |  |  |       if (0 == _hcd.pipe[i].ep) return  i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   default: | 
					
						
							|  |  |  |     /* No support for control transfer */ | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static volatile uint16_t* get_pipectr(unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (num) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     return (volatile uint16_t*)&(RUSB2->PIPE_CTR[num - 1]); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     return (volatile uint16_t*)&(RUSB2->DCPCTR); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static volatile reg_pipetre_t* get_pipetre(unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   volatile reg_pipetre_t* tre = NULL; | 
					
						
							|  |  |  |   if ((1 <= num) && (num <= 5)) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     tre = (volatile reg_pipetre_t*)&(RUSB2->PIPE_TR[num - 1].E); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  |   return tre; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static volatile uint16_t* addr_to_pipectr(uint8_t dev_addr, unsigned ep_addr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  |   const unsigned epn = tu_edpt_number(ep_addr); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   if (epn) { | 
					
						
							|  |  |  |     const unsigned dir_in = tu_edpt_dir(ep_addr); | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  |     const unsigned num = _hcd.ep[dev_addr][dir_in][epn - 1]; | 
					
						
							|  |  |  |     return get_pipectr(num); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  |     return get_pipectr(0); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned edpt0_max_packet_size(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   return RUSB2->DCPMAXP_b.MXPS; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned edpt_max_packet_size(unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->PIPESEL = num; | 
					
						
							|  |  |  |   return RUSB2->PIPEMAXP_b.MXPS; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void pipe_wait_for_ready(unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   while (RUSB2->D0FIFOSEL_b.CURPIPE != num) ; | 
					
						
							|  |  |  |   while (!RUSB2->D0FIFOCTR_b.FRDY) ; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; | 
					
						
							|  |  |  |   uintptr_t addr = (uintptr_t)buf; | 
					
						
							|  |  |  |   while (len >= 2) { | 
					
						
							|  |  |  |     reg->u16 = *(const uint16_t *)addr; | 
					
						
							|  |  |  |     addr += 2; | 
					
						
							|  |  |  |     len  -= 2; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (len) { | 
					
						
							|  |  |  |     reg->u8 = *(const uint8_t *)addr; | 
					
						
							|  |  |  |     ++addr; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint8_t *p   = (uint8_t*)buf; | 
					
						
							|  |  |  |   volatile uint8_t *reg = (volatile uint8_t*)fifo;  /* byte access is always at base register address */ | 
					
						
							|  |  |  |   while (len--) *p++ = *reg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool pipe0_xfer_in(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   pipe_state_t *pipe = &_hcd.pipe[0]; | 
					
						
							|  |  |  |   const unsigned rem = pipe->remaining; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const unsigned mps = edpt0_max_packet_size(); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   const unsigned vld = RUSB2->CFIFOCTR_b.DTLN; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); | 
					
						
							|  |  |  |   void          *buf = pipe->buf; | 
					
						
							|  |  |  |   if (len) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; | 
					
						
							|  |  |  |     pipe_read_packet(buf, (volatile void*)&RUSB2->CFIFO, len); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     pipe->buf = (uint8_t*)buf + len; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   if (len < mps) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   pipe->remaining = rem - len; | 
					
						
							|  |  |  |   if ((len < mps) || (rem == len)) { | 
					
						
							|  |  |  |     pipe->buf = NULL; | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_BUF; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool pipe0_xfer_out(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   pipe_state_t *pipe = &_hcd.pipe[0]; | 
					
						
							|  |  |  |   const unsigned rem = pipe->remaining; | 
					
						
							|  |  |  |   if (!rem) { | 
					
						
							|  |  |  |     pipe->buf = NULL; | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const unsigned mps = edpt0_max_packet_size(); | 
					
						
							|  |  |  |   const unsigned len = TU_MIN(mps, rem); | 
					
						
							|  |  |  |   void          *buf = pipe->buf; | 
					
						
							|  |  |  |   if (len) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     pipe_write_packet(buf, (volatile void*)&RUSB2->CFIFO, len); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     pipe->buf = (uint8_t*)buf + len; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   if (len < mps) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   pipe->remaining = rem - len; | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool pipe_xfer_in(unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   pipe_state_t  *pipe = &_hcd.pipe[num]; | 
					
						
							|  |  |  |   const unsigned rem  = pipe->remaining; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   const unsigned mps  = edpt_max_packet_size(num); | 
					
						
							|  |  |  |   pipe_wait_for_ready(num); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   const unsigned vld  = RUSB2->D0FIFOCTR_b.DTLN; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   const unsigned len  = TU_MIN(TU_MIN(rem, mps), vld); | 
					
						
							|  |  |  |   void          *buf  = pipe->buf; | 
					
						
							|  |  |  |   if (len) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     pipe_read_packet(buf, (volatile void*)&RUSB2->D0FIFO, len); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     pipe->buf = (uint8_t*)buf + len; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   if (len < mps) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->D0FIFOSEL = 0; | 
					
						
							|  |  |  |   while (RUSB2->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */ | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  |   pipe->remaining = rem - len; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   if ((len < mps) || (rem == len)) { | 
					
						
							|  |  |  |     pipe->buf = NULL; | 
					
						
							|  |  |  |     return NULL != buf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool pipe_xfer_out(unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   pipe_state_t  *pipe = &_hcd.pipe[num]; | 
					
						
							|  |  |  |   const unsigned rem  = pipe->remaining; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!rem) { | 
					
						
							|  |  |  |     pipe->buf = NULL; | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   const unsigned mps  = edpt_max_packet_size(num); | 
					
						
							|  |  |  |   pipe_wait_for_ready(num); | 
					
						
							|  |  |  |   const unsigned len  = TU_MIN(rem, mps); | 
					
						
							|  |  |  |   void          *buf  = pipe->buf; | 
					
						
							|  |  |  |   if (len) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     pipe_write_packet(buf, (volatile void*)&RUSB2->D0FIFO, len); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     pipe->buf = (uint8_t*)buf + len; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  |   if (len < mps) | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk; | 
					
						
							|  |  |  |   RUSB2->D0FIFOSEL = 0; | 
					
						
							|  |  |  |   while (RUSB2->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */ | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   pipe->remaining = rem - len; | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool process_pipe0_xfer(uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)dev_addr; | 
					
						
							|  |  |  |   const unsigned dir_in = tu_edpt_dir(ep_addr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* configure fifo direction and access unit settings */ | 
					
						
							|  |  |  |   if (dir_in) { /* IN, a byte */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT; | 
					
						
							|  |  |  |     while (RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ; | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  |   } else { /* OUT, 2 bytes */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | | 
					
						
							|  |  |  |                          (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); | 
					
						
							|  |  |  |     while (!(RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) ; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   pipe_state_t *pipe = &_hcd.pipe[0]; | 
					
						
							|  |  |  |   pipe->ep        = ep_addr; | 
					
						
							|  |  |  |   pipe->length    = buflen; | 
					
						
							|  |  |  |   pipe->remaining = buflen; | 
					
						
							|  |  |  |   if (buflen) { | 
					
						
							|  |  |  |     pipe->buf     = buffer; | 
					
						
							|  |  |  |     if (!dir_in) { /* OUT */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |       TU_ASSERT(RUSB2->DCPCTR_b.BSTS && (RUSB2->USBREQ & 0x80)); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |       pipe0_xfer_out(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else { /* ZLP */ | 
					
						
							|  |  |  |     pipe->buf        = NULL; | 
					
						
							|  |  |  |     if (!dir_in) { /* OUT */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |       RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     if (dir_in == RUSB2->DCPCFG_b.DIR) { | 
					
						
							|  |  |  |       TU_ASSERT(RUSB2_PIPE_CTR_PID_NAK == RUSB2->DCPCTR_b.PID); | 
					
						
							|  |  |  |       RUSB2->DCPCTR_b.SQSET = 1; | 
					
						
							|  |  |  |       RUSB2->DCPCFG_b.DIR = dir_in ^ 1; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_BUF; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | static bool process_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, void *buffer, uint16_t buflen) | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | { | 
					
						
							|  |  |  |   const unsigned epn    = tu_edpt_number(ep_addr); | 
					
						
							|  |  |  |   const unsigned dir_in = tu_edpt_dir(ep_addr); | 
					
						
							|  |  |  |   const unsigned num    = _hcd.ep[dev_addr - 1][dir_in][epn - 1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   TU_ASSERT(num); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   pipe_state_t *pipe  = &_hcd.pipe[num]; | 
					
						
							|  |  |  |   pipe->buf       = buffer; | 
					
						
							|  |  |  |   pipe->length    = buflen; | 
					
						
							|  |  |  |   pipe->remaining = buflen; | 
					
						
							|  |  |  |   if (!dir_in) { /* OUT */ | 
					
						
							|  |  |  |     if (buflen) { | 
					
						
							|  |  |  |       pipe_xfer_out(num); | 
					
						
							|  |  |  |     } else { /* ZLP */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |       RUSB2->D0FIFOSEL = num; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |       pipe_wait_for_ready(num); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |       RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk; | 
					
						
							|  |  |  |       RUSB2->D0FIFOSEL = 0; | 
					
						
							|  |  |  |       while (RUSB2->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */ | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     } | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     volatile uint16_t     *ctr = get_pipectr(num); | 
					
						
							|  |  |  |     volatile reg_pipetre_t *pt = get_pipetre(num); | 
					
						
							|  |  |  |     if (pt) { | 
					
						
							|  |  |  |       const unsigned     mps = edpt_max_packet_size(num); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |       if (*ctr & 0x3) *ctr = RUSB2_PIPE_CTR_PID_NAK; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |       pt->TRE   = TU_BIT(8); | 
					
						
							|  |  |  |       pt->TRN   = (buflen + mps - 1) / mps; | 
					
						
							|  |  |  |       pt->TRENB = 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     *ctr = RUSB2_PIPE_CTR_PID_BUF; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool process_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const unsigned epn = tu_edpt_number(ep_addr); | 
					
						
							|  |  |  |   if (0 == epn) { | 
					
						
							|  |  |  |     return process_pipe0_xfer(dev_addr, ep_addr, buffer, buflen); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     return process_pipe_xfer(dev_addr, ep_addr, buffer, buflen); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void process_pipe0_bemp(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							|  |  |  |   bool completed = pipe0_xfer_out(); | 
					
						
							|  |  |  |   if (completed) { | 
					
						
							|  |  |  |     pipe_state_t *pipe = &_hcd.pipe[0]; | 
					
						
							|  |  |  |     hcd_event_xfer_complete(pipe->dev, | 
					
						
							|  |  |  |                             tu_edpt_addr(0, TUSB_DIR_OUT), | 
					
						
							|  |  |  |                             pipe->length - pipe->remaining, | 
					
						
							|  |  |  |                             XFER_RESULT_SUCCESS, true); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void process_pipe_nrdy(uint8_t rhport, unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							| 
									
										
										
										
											2023-05-15 18:27:45 +02:00
										 |  |  |   xfer_result_t result; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   uint16_t volatile *ctr = get_pipectr(num); | 
					
						
							| 
									
										
										
										
											2023-06-23 14:21:58 +02:00
										 |  |  |   TU_LOG(TU_RUSB2_HCD_DBG, "NRDY %d %x\n", num, *ctr); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   switch (*ctr & RUSB2_PIPE_CTR_PID_Msk) { | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     default: return; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     case RUSB2_PIPE_CTR_PID_STALL: result = XFER_RESULT_STALLED; break; | 
					
						
							| 
									
										
										
										
											2023-06-23 10:26:45 +02:00
										 |  |  |     case RUSB2_PIPE_CTR_PID_STALL2: result = XFER_RESULT_STALLED; break; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     case RUSB2_PIPE_CTR_PID_NAK:   result = XFER_RESULT_FAILED;  break; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  |   pipe_state_t *pipe = &_hcd.pipe[num]; | 
					
						
							|  |  |  |   hcd_event_xfer_complete(pipe->dev, pipe->ep, | 
					
						
							|  |  |  |                           pipe->length - pipe->remaining, | 
					
						
							|  |  |  |                           result, true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void process_pipe_brdy(uint8_t rhport, unsigned num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							|  |  |  |   pipe_state_t  *pipe   = &_hcd.pipe[num]; | 
					
						
							|  |  |  |   const unsigned dir_in = tu_edpt_dir(pipe->ep); | 
					
						
							|  |  |  |   bool completed; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (dir_in) { /* IN */ | 
					
						
							|  |  |  |     if (num) { | 
					
						
							|  |  |  |       completed = pipe_xfer_in(num); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       completed = pipe0_xfer_in(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     completed = pipe_xfer_out(num); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (completed) { | 
					
						
							|  |  |  |     hcd_event_xfer_complete(pipe->dev, pipe->ep, | 
					
						
							|  |  |  |                             pipe->length - pipe->remaining, | 
					
						
							|  |  |  |                             XFER_RESULT_SUCCESS, true); | 
					
						
							| 
									
										
										
										
											2023-06-23 14:21:58 +02:00
										 |  |  |     TU_LOG(TU_RUSB2_HCD_DBG, "C %d %d\r\n", num, pipe->length - pipe->remaining); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------------------------------------------*/ | 
					
						
							|  |  |  | /* Host API
 | 
					
						
							|  |  |  |  *------------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if 0 // previously present in the rx driver before generalization
 | 
					
						
							|  |  |  | static uint32_t disable_interrupt(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint32_t pswi; | 
					
						
							|  |  |  | #if defined(__CCRX__)
 | 
					
						
							|  |  |  |   pswi = get_psw() & 0x010000; | 
					
						
							|  |  |  |   clrpsw_i(); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   pswi = __builtin_rx_mvfc(0) & 0x010000; | 
					
						
							|  |  |  |   __builtin_rx_clrpsw('I'); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   return pswi; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void enable_interrupt(uint32_t pswi) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(__CCRX__)
 | 
					
						
							|  |  |  |   set_psw(get_psw() | pswi); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   __builtin_rx_mvtc(0, __builtin_rx_mvfc(0) | pswi); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | bool hcd_init(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  | #if 0 // previously present in the rx driver before generalization
 | 
					
						
							|  |  |  |   uint32_t pswi = disable_interrupt(); | 
					
						
							|  |  |  |   SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1; | 
					
						
							|  |  |  |   MSTP(USB0) = 0; | 
					
						
							|  |  |  |   SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY; | 
					
						
							|  |  |  |   enable_interrupt(pswi); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->SYSCFG_b.SCKE = 1; | 
					
						
							|  |  |  |   while (!RUSB2->SYSCFG_b.SCKE) ; | 
					
						
							|  |  |  |   RUSB2->SYSCFG_b.DPRPU = 0; | 
					
						
							|  |  |  |   RUSB2->SYSCFG_b.DRPD = 0; | 
					
						
							|  |  |  |   RUSB2->SYSCFG_b.DCFM = 1; | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DVSTCTR0_b.VBUSEN = 1; | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->SYSCFG_b.DRPD = 1; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   for (volatile int i = 0; i < 30000; ++i) ; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->SYSCFG_b.USBE = 1; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  |   // MCU specific PHY init
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   rusb2_phy_init(); | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->PHYSLEW = 0x5; | 
					
						
							|  |  |  |   RUSB2->DPUSR0R_FS_b.FIXPHY0 = 0u; /* Transceiver Output fixed */ | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Setup default control pipe */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DCPCFG  = RUSB2_PIPECFG_SHTNAK_Msk; | 
					
						
							|  |  |  |   RUSB2->DCPMAXP = 64; | 
					
						
							|  |  |  |   RUSB2->INTENB0 = RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_NRDY_Msk | RUSB2_INTSTS0_BEMP_Msk; | 
					
						
							|  |  |  |   RUSB2->INTENB1 = RUSB2_INTSTS1_SACK_Msk | RUSB2_INTSTS1_SIGN_Msk | RUSB2_INTSTS1_ATTCH_Msk | RUSB2_INTSTS1_DTCH_Msk; | 
					
						
							|  |  |  |   RUSB2->BEMPENB = 1; | 
					
						
							|  |  |  |   RUSB2->NRDYENB = 1; | 
					
						
							|  |  |  |   RUSB2->BRDYENB = 1; | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcd_int_enable(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   rusb2_int_enable(rhport); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcd_int_disable(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   rusb2_int_disable(rhport); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint32_t hcd_frame_number(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  |   /* The device must be reset at least once after connection
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |    * in order to start the frame counter. */ | 
					
						
							|  |  |  |   if (_hcd.need_reset) hcd_port_reset(rhport); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   return RUSB2->FRMNUM_b.FRNM; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------+
 | 
					
						
							|  |  |  |  * Port API | 
					
						
							|  |  |  |  *--------------------------------------------------------------------+*/ | 
					
						
							|  |  |  | bool hcd_port_connect_status(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   return RUSB2->INTSTS1_b.ATTCH ? true : false; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcd_port_reset(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; | 
					
						
							|  |  |  |   while (RUSB2->DCPCTR_b.PBUSY) ; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   hcd_int_disable(rhport); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DVSTCTR0_b.UACT = 0; | 
					
						
							|  |  |  |   if (RUSB2->DCPCTR_b.SUREQ) { | 
					
						
							|  |  |  |     RUSB2->DCPCTR_b.SUREQCLR = 1; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   hcd_int_enable(rhport); | 
					
						
							|  |  |  |   /* Reset should be asserted 10-20ms. */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DVSTCTR0_b.USBRST = 1; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   for (volatile int i = 0; i < 2400000; ++i) ; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DVSTCTR0_b.USBRST = 0; | 
					
						
							|  |  |  |   RUSB2->DVSTCTR0_b.UACT = 1; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   _hcd.need_reset = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-02 12:33:47 +07:00
										 |  |  | void hcd_port_reset_end(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) rhport; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | tusb_speed_t hcd_port_speed_get(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   switch (RUSB2->DVSTCTR0_b.RHST) { | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     default: return TUSB_SPEED_INVALID; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     case RUSB2_DVSTCTR0_RHST_FS: return TUSB_SPEED_FULL; | 
					
						
							|  |  |  |     case RUSB2_DVSTCTR0_RHST_LS:  return TUSB_SPEED_LOW; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcd_device_close(uint8_t rhport, uint8_t dev_addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							|  |  |  |   uint16_t volatile *ctr; | 
					
						
							|  |  |  |   TU_ASSERT(dev_addr < 6,); /* USBa can only handle addresses from 0 to 5. */ | 
					
						
							|  |  |  |   if (!dev_addr) return; | 
					
						
							|  |  |  |   _hcd.ctl_mps[dev_addr] = 0; | 
					
						
							|  |  |  |   uint8_t *ep = &_hcd.ep[dev_addr - 1][0][0]; | 
					
						
							|  |  |  |   for (int i = 0; i < 2 * 15; ++i, ++ep) { | 
					
						
							|  |  |  |     unsigned num = *ep; | 
					
						
							| 
									
										
										
										
											2023-06-23 10:26:45 +02:00
										 |  |  |     if (!num || (dev_addr != _hcd.pipe[num].dev)) continue; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     ctr = (uint16_t volatile*)&RUSB2->PIPE_CTR[num - 1]; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     *ctr = 0; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->NRDYENB &= ~TU_BIT(num); | 
					
						
							|  |  |  |     RUSB2->BRDYENB &= ~TU_BIT(num); | 
					
						
							|  |  |  |     RUSB2->PIPESEL = num; | 
					
						
							|  |  |  |     RUSB2->PIPECFG = 0; | 
					
						
							|  |  |  |     RUSB2->PIPEMAXP = 0; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     _hcd.pipe[num].ep  = 0; | 
					
						
							|  |  |  |     _hcd.pipe[num].dev = 0; | 
					
						
							|  |  |  |     *ep                = 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------+
 | 
					
						
							|  |  |  |  * Endpoints API | 
					
						
							|  |  |  |  *--------------------------------------------------------------------+*/ | 
					
						
							|  |  |  | bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							| 
									
										
										
										
											2023-06-23 14:21:58 +02:00
										 |  |  |   TU_LOG(TU_RUSB2_HCD_DBG, "S %d %x\n", dev_addr, RUSB2->DCPCTR); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   TU_ASSERT(dev_addr < 6); /* USBa can only handle addresses from 0 to 5. */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   TU_ASSERT(0 == RUSB2->DCPCTR_b.SUREQ); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   _hcd.pipe[0].buf       = NULL; | 
					
						
							|  |  |  |   _hcd.pipe[0].length    = 8; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   _hcd.pipe[0].remaining = 0; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |   _hcd.pipe[0].dev       = dev_addr; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   while (RUSB2->DCPCTR_b.PBUSY) ; | 
					
						
							|  |  |  |   RUSB2->DCPMAXP = (dev_addr << 12) | _hcd.ctl_mps[dev_addr]; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Set direction in advance for DATA stage */ | 
					
						
							|  |  |  |   uint8_t const bmRequesttype = setup_packet[0]; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DCPCFG_b.DIR = tu_edpt_dir(bmRequesttype) ? 0: 1; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   uint16_t const* p = (uint16_t const*)(uintptr_t)&setup_packet[0]; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->USBREQ  = tu_htole16(p[0]); | 
					
						
							|  |  |  |   RUSB2->USBVAL  = p[1]; | 
					
						
							|  |  |  |   RUSB2->USBINDX = p[2]; | 
					
						
							|  |  |  |   RUSB2->USBLENG = p[3]; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->DCPCTR_b.SUREQ = 1; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:00:01 +07:00
										 |  |  | bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc) | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							|  |  |  |   TU_ASSERT(dev_addr < 6); /* USBa can only handle addresses from 0 to 5. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const unsigned ep_addr = ep_desc->bEndpointAddress; | 
					
						
							|  |  |  |   const unsigned epn     = tu_edpt_number(ep_addr); | 
					
						
							|  |  |  |   const unsigned mps     = tu_edpt_packet_size(ep_desc); | 
					
						
							|  |  |  |   if (0 == epn) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     hcd_devtree_info_t devtree; | 
					
						
							|  |  |  |     hcd_devtree_get_info(dev_addr, &devtree); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     uint16_t volatile *devadd = (uint16_t volatile *)(uintptr_t) &RUSB2->DEVADD[0]; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     devadd += dev_addr; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     while (RUSB2->DCPCTR_b.PBUSY) ; | 
					
						
							|  |  |  |     RUSB2->DCPMAXP = (dev_addr << 12) | mps; | 
					
						
							|  |  |  |     *devadd = (TUSB_SPEED_FULL == devtree.speed) ? RUSB2_DEVADD_USBSPD_FS : RUSB2_DEVADD_USBSPD_LS; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     _hcd.ctl_mps[dev_addr] = mps; | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const unsigned dir_in = tu_edpt_dir(ep_addr); | 
					
						
							|  |  |  |   const unsigned xfer   = ep_desc->bmAttributes.xfer; | 
					
						
							|  |  |  |   if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) { | 
					
						
							|  |  |  |     /* USBa supports up to 256 bytes */ | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const unsigned num = find_pipe(xfer); | 
					
						
							|  |  |  |   if (!num) return false; | 
					
						
							|  |  |  |   _hcd.pipe[num].dev = dev_addr; | 
					
						
							|  |  |  |   _hcd.pipe[num].ep  = ep_addr; | 
					
						
							|  |  |  |   _hcd.ep[dev_addr - 1][dir_in][epn - 1] = num; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* setup pipe */ | 
					
						
							|  |  |  |   hcd_int_disable(rhport); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->PIPESEL = num; | 
					
						
							|  |  |  |   RUSB2->PIPEMAXP = (dev_addr << 12) | mps; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   volatile uint16_t *ctr = get_pipectr(num); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   *ctr = RUSB2_PIPE_CTR_ACLRM_Msk | RUSB2_PIPE_CTR_SQCLR_Msk; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   *ctr = 0; | 
					
						
							|  |  |  |   unsigned cfg = ((1 ^ dir_in) << 4) | epn; | 
					
						
							|  |  |  |   if (xfer == TUSB_XFER_BULK) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     cfg |= RUSB2_PIPECFG_TYPE_BULK | RUSB2_PIPECFG_SHTNAK_Msk | RUSB2_PIPECFG_DBLB_Msk; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } else if (xfer == TUSB_XFER_INTERRUPT) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     cfg |= RUSB2_PIPECFG_TYPE_INT; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     cfg |= RUSB2_PIPECFG_TYPE_ISO | RUSB2_PIPECFG_DBLB_Msk; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->PIPECFG = cfg; | 
					
						
							|  |  |  |   RUSB2->BRDYSTS = 0x1FFu ^ TU_BIT(num); | 
					
						
							|  |  |  |   RUSB2->NRDYENB |= TU_BIT(num); | 
					
						
							|  |  |  |   RUSB2->BRDYENB |= TU_BIT(num); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   if (!dir_in) { | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     *ctr = RUSB2_PIPE_CTR_PID_BUF; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  |   hcd_int_enable(rhport); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bool r; | 
					
						
							|  |  |  |   hcd_int_disable(rhport); | 
					
						
							| 
									
										
										
										
											2023-06-23 14:21:58 +02:00
										 |  |  |   TU_LOG(TU_RUSB2_HCD_DBG, "X %d %x %u\n", dev_addr, ep_addr, buflen); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   r = process_edpt_xfer(dev_addr, ep_addr, buffer, buflen); | 
					
						
							|  |  |  |   hcd_int_enable(rhport); | 
					
						
							|  |  |  |   return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 12:52:26 +07:00
										 |  |  | bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { | 
					
						
							|  |  |  |   (void) rhport; | 
					
						
							|  |  |  |   (void) dev_addr; | 
					
						
							|  |  |  |   (void) ep_addr; | 
					
						
							|  |  |  |   // TODO not implemented yet
 | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint16_t volatile *ctr = addr_to_pipectr(dev_addr, ep_addr); | 
					
						
							|  |  |  |   TU_ASSERT(ctr); | 
					
						
							| 
									
										
										
										
											2021-12-27 22:55:28 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const uint32_t pid = *ctr & 0x3; | 
					
						
							|  |  |  |   if (pid & 2) { | 
					
						
							|  |  |  |     *ctr = pid & 2; | 
					
						
							|  |  |  |     *ctr = 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   *ctr = RUSB2_PIPE_CTR_SQCLR_Msk; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   unsigned const epn = tu_edpt_number(ep_addr); | 
					
						
							|  |  |  |   if (!epn) return true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 22:55:28 +09:00
										 |  |  |   if (!tu_edpt_dir(ep_addr)) { /* OUT */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     *ctr = RUSB2_PIPE_CTR_PID_BUF; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | // ISR
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | void hcd_int_handler(uint8_t rhport) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void)rhport; | 
					
						
							|  |  |  | #if defined(__CCRX__)
 | 
					
						
							|  |  |  |   static const int Mod37BitPosition[] = { | 
					
						
							|  |  |  |     -1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, | 
					
						
							|  |  |  |     7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, | 
					
						
							|  |  |  |     20, 8, 19, 18}; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   unsigned is1 = RUSB2->INTSTS1; | 
					
						
							|  |  |  |   unsigned is0 = RUSB2->INTSTS0; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   /* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   RUSB2->INTSTS1 = ~((RUSB2_INTSTS1_SACK_Msk | RUSB2_INTSTS1_SIGN_Msk | RUSB2_INTSTS1_ATTCH_Msk | RUSB2_INTSTS1_DTCH_Msk) & is1); | 
					
						
							|  |  |  |   RUSB2->INTSTS0 = ~((RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_NRDY_Msk | RUSB2_INTSTS0_BEMP_Msk) & is0); | 
					
						
							| 
									
										
										
										
											2023-06-23 14:21:58 +02:00
										 |  |  |   TU_LOG(TU_RUSB2_HCD_DBG, "IS %04x %04x\n", is0, is1); | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   is1 &= RUSB2->INTENB1; | 
					
						
							|  |  |  |   is0 &= RUSB2->INTENB0; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   if (is1 & RUSB2_INTSTS1_SACK_Msk) { | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     /* Set DATA1 in advance for the next transfer. */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->DCPCTR_b.SQSET = 1; | 
					
						
							|  |  |  |     hcd_event_xfer_complete(RUSB2->DCPMAXP_b.DEVSEL, tu_edpt_addr(0, TUSB_DIR_OUT), 8, XFER_RESULT_SUCCESS, true); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   if (is1 & RUSB2_INTSTS1_SIGN_Msk) { | 
					
						
							|  |  |  |     hcd_event_xfer_complete(RUSB2->DCPMAXP_b.DEVSEL, tu_edpt_addr(0, TUSB_DIR_OUT), 8, XFER_RESULT_FAILED, true); | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   if (is1 & RUSB2_INTSTS1_ATTCH_Msk) { | 
					
						
							|  |  |  |     RUSB2->DVSTCTR0_b.UACT = 1; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     _hcd.need_reset = true; | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->INTENB1 = (RUSB2->INTENB1 & ~RUSB2_INTSTS1_ATTCH_Msk) | RUSB2_INTSTS1_DTCH_Msk; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     hcd_event_device_attach(rhport, true); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   if (is1 & RUSB2_INTSTS1_DTCH_Msk) { | 
					
						
							|  |  |  |     RUSB2->DVSTCTR0_b.UACT = 0; | 
					
						
							|  |  |  |     if (RUSB2->DCPCTR_b.SUREQ) { | 
					
						
							|  |  |  |       RUSB2->DCPCTR_b.SUREQCLR = 1; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:01:24 +07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->INTENB1 = (RUSB2->INTENB1 & ~RUSB2_INTSTS1_DTCH_Msk) | RUSB2_INTSTS1_ATTCH_Msk; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     hcd_event_device_remove(rhport, true); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   if (is0 & RUSB2_INTSTS0_BEMP_Msk) { | 
					
						
							|  |  |  |     const unsigned s = RUSB2->BEMPSTS; | 
					
						
							|  |  |  |     RUSB2->BEMPSTS = 0; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     if (s & 1) { | 
					
						
							|  |  |  |       process_pipe0_bemp(rhport); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   if (is0 & RUSB2_INTSTS0_NRDY_Msk) { | 
					
						
							|  |  |  |     const unsigned m = RUSB2->NRDYENB; | 
					
						
							|  |  |  |     unsigned s = RUSB2->NRDYSTS & m; | 
					
						
							|  |  |  |     RUSB2->NRDYSTS = ~s; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     while (s) { | 
					
						
							|  |  |  | #if defined(__CCRX__)
 | 
					
						
							|  |  |  |       const unsigned num = Mod37BitPosition[(-s & s) % 37]; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |       const unsigned num = __builtin_ctz(s); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |       process_pipe_nrdy(rhport, num); | 
					
						
							|  |  |  |       s &= ~TU_BIT(num); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |   if (is0 & RUSB2_INTSTS0_BRDY_Msk) { | 
					
						
							|  |  |  |     const unsigned m = RUSB2->BRDYENB; | 
					
						
							|  |  |  |     unsigned s = RUSB2->BRDYSTS & m; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     /* clear active bits (don't write 0 to already cleared bits according to the HW manual) */ | 
					
						
							| 
									
										
										
										
											2023-03-16 11:28:10 +07:00
										 |  |  |     RUSB2->BRDYSTS = ~s; | 
					
						
							| 
									
										
										
										
											2021-12-27 01:22:57 +09:00
										 |  |  |     while (s) { | 
					
						
							|  |  |  | #if defined(__CCRX__)
 | 
					
						
							|  |  |  |       const unsigned num = Mod37BitPosition[(-s & s) % 37]; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |       const unsigned num = __builtin_ctz(s); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |       process_pipe_brdy(rhport, num); | 
					
						
							|  |  |  |       s &= ~TU_BIT(num); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |