diff --git a/arch/renesas/src/rx65n/Kconfig b/arch/renesas/src/rx65n/Kconfig index 5a96160a3a..bf1759dd7c 100644 --- a/arch/renesas/src/rx65n/Kconfig +++ b/arch/renesas/src/rx65n/Kconfig @@ -610,6 +610,21 @@ config RX65N_RIIC2_RCV_IN_BYTE_UNITS depends on !RX65N_RIIC2_RCV_CONTINUOUS endif #RX65N_RIIC2 + +config RX65N_USBDEV + bool "USB0 Device" + default n + depends on USBDEV + +if RX65N_USBDEV + +config RX65N_TEST_INTEP + bool "Testing RX65N Interrupt endpoint" + default n + depends on SERIAL_IFLOWCONTROL && CDCACM_IFLOWCONTROL + +endif #RX65N_USBDEV + endmenu # RX65N Peripheral Selections endif diff --git a/arch/renesas/src/rx65n/Make.defs b/arch/renesas/src/rx65n/Make.defs index fe45e9b168..1fe6f74c9d 100644 --- a/arch/renesas/src/rx65n/Make.defs +++ b/arch/renesas/src/rx65n/Make.defs @@ -58,6 +58,11 @@ endif ifeq ($(CONFIG_RTC_DRIVER),y) CHIP_CSRCS += rx65n_rtc_lowerhalf.c endif + +ifeq ($(CONFIG_USBDEV),y) +CHIP_CSRCS += rx65n_usbdev.c +endif + ifeq ($(CONFIG_I2C),y) CHIP_CSRCS += rx65n_riic.c endif \ No newline at end of file diff --git a/arch/renesas/src/rx65n/rx65n_cgc.c b/arch/renesas/src/rx65n/rx65n_cgc.c index 79f764c91e..59efbf54cf 100644 --- a/arch/renesas/src/rx65n/rx65n_cgc.c +++ b/arch/renesas/src/rx65n/rx65n_cgc.c @@ -289,10 +289,10 @@ void r_cgc_create(void) while (0 != SYSTEM.OSCOVFSR.BIT.SOOVF); } - SYSTEM.PLLCR.BIT.PLIDIV = 0; - SYSTEM.PLLCR.BIT.PLLSRCSEL = 0; - SYSTEM.PLLCR.BIT.STC = (20 * 2) - 1; - SYSTEM.PLLCR2.BYTE = 0x00; + SYSTEM.PLLCR.WORD = _0000_CGC_PLL_FREQ_DIV_1 | + _0000_CGC_PLL_SOURCE_MAIN | + _2700_CGC_PLL_FREQ_MUL_20_0; + SYSTEM.PLLCR2.BYTE = 0x00; while (0 == SYSTEM.OSCOVFSR.BIT.PLOVF); SYSTEM.ROMWT.BYTE = 0x02; if (0x02 == SYSTEM.ROMWT.BYTE) @@ -300,9 +300,20 @@ void r_cgc_create(void) __asm("nop"); } - SYSTEM.SCKCR.LONG = 0x21c11222; - SYSTEM.SCKCR2.WORD = 0x0011; - SYSTEM.SCKCR3.WORD = 4u << 8; /* BSP_CFG_CLOCK_SOURCE */ + SYSTEM.SCKCR.LONG = _00000002_CGC_PCLKD_DIV_4 | _00000020_CGC_PCLKC_DIV_4 | + _00000200_CGC_PCLKB_DIV_4 | + _00001000_CGC_PCLKA_DIV_2 | + _00010000_CGC_BCLK_DIV_2 | + _00C00000_CGC_PSTOP0_PSTOP1 | + _01000000_CGC_ICLK_DIV_2 | + _20000000_CGC_FCLK_DIV_4; + +#if defined(CONFIG_USBHOST) || defined(CONFIG_USBDEV) + SYSTEM.SCKCR2.WORD = _0040_CGC_UCLK_DIV_5 | _0001_SCKCR2_BIT0; +#else + SYSTEM.SCKCR2.WORD = _0010_CGC_UCLK_DIV_1 | _0001_SCKCR2_BIT0; +#endif + SYSTEM.SCKCR3.WORD = _0400_CGC_CLOCKSOURCE_PLL; /* BSP_CFG_CLOCK_SOURCE */ SYSTEM.LOCOCR.BYTE = 0x01; #else diff --git a/arch/renesas/src/rx65n/rx65n_cgc.h b/arch/renesas/src/rx65n/rx65n_cgc.h index 8c2caac5e9..f5b1269fe6 100644 --- a/arch/renesas/src/rx65n/rx65n_cgc.h +++ b/arch/renesas/src/rx65n/rx65n_cgc.h @@ -77,6 +77,8 @@ #define _00050000_CGC_BCLK_DIV_32 (0x00050000ul) /* x1/32 */ #define _00060000_CGC_BCLK_DIV_64 (0x00060000ul) /* x1/64 */ +#define _00C00000_CGC_PSTOP0_PSTOP1 (0x00c00000) + /* System Clock (ICLK) */ #define _00000000_CGC_ICLK_DIV_1 (0x00000000ul) /* x1 */ @@ -260,6 +262,8 @@ #define _0E_CGC_PRIORITY_LEVEL14 (0x0eu) /* Level 14 */ #define _0F_CGC_PRIORITY_LEVEL15 (0x0fu) /* Level 15 (highest) */ +#define _0001_CGC_LOCO_STOP (0x1) + /* Main clock oscillator wait time */ #define _5C_CGC_MOSCWTCR_VALUE (0x5cu) diff --git a/arch/renesas/src/rx65n/rx65n_definitions.h b/arch/renesas/src/rx65n/rx65n_definitions.h index a15a037f9f..bbb98c1066 100644 --- a/arch/renesas/src/rx65n/rx65n_definitions.h +++ b/arch/renesas/src/rx65n/rx65n_definitions.h @@ -432,7 +432,7 @@ /* Bit: 20: Transmit Descriptor Empty Flag */ -#define ETHD_EESR_TDE (1<20) +#define ETHD_EESR_TDE (1 << 20) /* Ether PSR register */ @@ -450,8 +450,8 @@ /* Transmit Interrupt Setting Register's bit */ -#define ETHD_TRIMD_TIS (1) /* Transmit Interrupt is enabled */ -#define ETHD_TRIMD_TIM (1<<4) /* Write-back complete interrupt mode */ +#define ETHD_TRIMD_TIS (1) /* Transmit Interrupt is enabled */ +#define ETHD_TRIMD_TIM (1 << 4) /* Write-back complete interrupt mode */ /* Receive Method Control Register's bit */ @@ -463,13 +463,13 @@ /* FIFO Depth Register's bit */ -#define ETHD_FDR_RFD (7) /* Receive FIFO Depth */ -#define ETHD_FDR_TFD (7<<8) /* Transmit FIFO Depth */ +#define ETHD_FDR_RFD (7) /* Receive FIFO Depth */ +#define ETHD_FDR_TFD (7 << 8) /* Transmit FIFO Depth */ /* ETHERC/EDMAC Transmit/Receive Status Copy Enable Register's bit */ -#define ETHD_TRSCER_RRFCE (1<<4) /* RRF Flag Copy Enable */ -#define ETHD_TRSCER_RMAFCE (1<<7) /* RMAF Flag Copy Enable */ +#define ETHD_TRSCER_RRFCE (1 << 4) /* RRF Flag Copy Enable */ +#define ETHD_TRSCER_RMAFCE (1 << 7) /* RMAF Flag Copy Enable */ /* Broadcast Frame Receive Count Setting Register's field */ @@ -477,10 +477,10 @@ /* PHY Interface Register's bit and values */ -#define ETH_PIR_MDC (1) /* MII/RMII Management Data Clock */ -#define ETH_PIR_MMD (1<<1) /* MII/RMII Management Mode */ -#define ETH_PIR_MDO (1<<2) /* MII/RMII Management Data-Out */ -#define ETH_PIR_MDI (1<<3) /* MII/RMII Management Data-In */ +#define ETH_PIR_MDC (1) /* MII/RMII Management Data Clock */ +#define ETH_PIR_MMD (1 << 1) /* MII/RMII Management Mode */ +#define ETH_PIR_MDO (1 << 2) /* MII/RMII Management Data-Out */ +#define ETH_PIR_MDI (1 << 3) /* MII/RMII Management Data-In */ #define ETH_PIR_RESET_ALL (0x00000000) /* Reset All Flags of PIR */ #define ETH_PIR_SET_MDC (0x00000001) /* Setting MDC of PIR */ @@ -594,6 +594,855 @@ #define RX65N_SBRAM_BASE 0x000a4000 +/* USB Related definitions */ + +#define RX65N_NUSBHOST 1 + +/* USB Registers */ + +/* USB Peripheral base address */ + +#define RX65N_MSTPCRB_START_STOP_USB (1 << 19) +#define RX65N_USB_BASE (0x000a0000UL) + +/* Different USB registers with corresponding offset */ + +/* USB System Configuration register and its bit fields */ + +#define RX65N_USB_SYSCFG ((volatile short *) (RX65N_USB_BASE + 0x0000UL)) +#define RX65N_USB_SYSCFG_SCKE (1U << 10) +#define RX65N_USB_SYSCFG_DCFM (1U << 6) +#define RX65N_USB_SYSCFG_DRPD (1U << 5) +#define RX65N_USB_SYSCFG_DPRPU (1U << 4) +#define RX65N_USB_SYSCFG_USBE (1U << 0) + +#define RX65N_USB_SYSSTS0 ((volatile short *) (RX65N_USB_BASE + 0x0004UL)) +#define USB_FS_JSTS (0x0001u) /* Full-Speed J State */ +#define USB_LNST (0x0003u) /* b1-0: D+, D- line status */ +#define RX65N_USB_SYSSTS0_LNST (3) +#define RX65N_USB_SYSSTS0_IDMON (1U << 2) +#define RX65N_USB_SYSSTS0_SOFEA (1U << 5) +#define RX65N_USB_SYSSTS0_HTACT (1U << 6) +#define RX65N_USB_SYSSTS0_OVCMON (0xc000U) + +/* SE1 */ + +#define RX65N_USB_SYSSTS0_LNST_SE1 (0x3u) + +/* Full speed K state */ + +#define RX65N_USB_SYSSTS0_LNST_FS_KSTS (0x2u) + +/* Full speed J State */ + +#define RX65N_USB_SYSSTS0_LNST_FS_JSTS (0x1u) + +/* Low speed K state */ + +#define RX65N_USB_SYSSTS0_LNST_LS_KSTS (0x2u) + +/* Low speed J State */ + +#define RX65N_USB_SYSSTS0_LNST_LS_JSTS (0x2u) + +/* SE0 */ + +#define RX65N_USB_SYSSTS0_LNST_SE0 (0x0u) + +#define USB_ATTACH (0x0040) +#define USB_ATTACHL (0x0041) +#define USB_ATTACHF (0x0042) +#define USB_DETACH (0x0043) +#define USB_RESUME (0x0044) +#define USB_SUSPEND (0x0045) + +/* Definitions used to pass on the information from interrupt to worker + * function + */ + +#define USB_PROCESS_ATTACHED_INT (0x0050) +#define USB_PROCESS_DETACHED_INT (0x0051) +#define USB_PROCESS_BRDY_INT (0x0052) +#define USB_PROCESS_BEMP_INT (0x0053) +#define USB_PROCESS_NRDY_INT (0x0054) +#define USB_PROCESS_SACK_INT (0x0055) +#define USB_PROCESS_SIGN_INT (0x0056) + +#define USB_UACTON (1) +#define USB_UACTOFF (0) +#define USB_VBON (1) +#define USB_VBOFF (0) + +#define USB_UNDECID (0x0000U) /* Undecided */ + +/* USB Device State Control register 0 and its bit fields */ + +#define RX65N_USB_DVSTCTR0 ((volatile short *) (RX65N_USB_BASE + 0x0008UL)) +#define RX65N_USB_DVSTCTR0_HNPBTOA (1U << 11) +#define RX65N_USB_DVSTCTR0_EXICEN (1U << 10) +#define RX65N_USB_DVSTCTR0_VBUSEN (1U << 9) +#define RX65N_USB_DVSTCTR0_WKUP (1U << 8) +#define RX65N_USB_DVSTCTR0_RWUPE (1U << 7) +#define RX65N_USB_DVSTCTR0_USBRST (1U << 6) +#define RX65N_USB_DVSTCTR0_RESUME (1U << 5) +#define RX65N_USB_DVSTCTR0_UACT (1U << 4) +#define RX65N_USB_DVSTCTR0_RHST (0x7U) +#define USB_RHST (RX65N_USB_DVSTCTR0_RHST) +#define RX65N_USB_DVSTCTR0_SPEED_LOW (1) +#define RX65N_USB_DVSTCTR0_SPEED_FULL (2) +#define RX65N_USB_DVSTCTR0_RESET_IN_PROGRESS (4) + +/* USB CFIFO Port Register and its bit fields */ + +#define RX65N_USB_CFIFO ((volatile short *) (RX65N_USB_BASE + 0x0014UL)) + +/* USB D0FIFO Port Register and its bit fields */ + +#define RX65N_USB_D0FIFO ((volatile short *) (RX65N_USB_BASE + 0x0018UL)) + +/* USB D1FIFO Port Register and its bit fields */ + +#define RX65N_USB_D1FIFO ((volatile short *) (RX65N_USB_BASE + 0x001cUL)) + +/* USB CFIFO Port Select Register and its bit fields */ + +#define RX65N_USB_CFIFOSEL ((volatile short *) (RX65N_USB_BASE + 0x0020UL)) +#define RX65N_USB_CFIFOSEL_RCNT (1U << 15) +#define USB_RCNT (RX65N_USB_CFIFOSEL_RCNT) +#define RX65N_USB_CFIFOSEL_REW (1U << 14) +#define RX65N_USB_CFIFOSEL_MBW_8 (0U << 10) +#define RX65N_USB_CFIFOSEL_MBW_16 (1U << 10) +#define RX65N_USB_CFIFOSEL_BIGEND (1U << 8) +#define RX65N_USB_CFIFOSEL_ISEL (1U << 5) +#define USB_ISEL (RX65N_USB_CFIFOSEL_ISEL) +#define RX65N_USB_CFIFOSEL_CURPIPE_MASK (0xfU) +#define USB_CURPIPE (RX65N_USB_CFIFOSEL_CURPIPE_MASK) + +/* USB CFIFO Port Control Register */ + +#define RX65N_USB_CFIFOCTR ((volatile short *) (RX65N_USB_BASE + 0x0022UL)) + +/* Common bit field values for CFIFOCTR, D0FIFOCTR and D1FIFOCTR registers */ + +#define RX65N_USB_FIFOCTR_BVAL (1U << 15) +#define USB_BVAL (RX65N_USB_FIFOCTR_BVAL) +#define RX65N_USB_FIFOCTR_BCLR (1U << 14) +#define RX65N_USB_FIFOCTR_FRDY (1U << 13) +#define RX65N_USB_FIFOCTR_DTLN (0xfff) + +/* USB D0FIFO and D1FIFO port select and control registers */ + +#define RX65N_USB_D0FIFOSEL ((volatile short *) (RX65N_USB_BASE + 0x0028UL)) +#define RX65N_USB_D0FIFOSEL_MBW_16 (1U << 10) +#define RX65N_USB_D0FIFOCTR ((volatile short *) (RX65N_USB_BASE + 0x002aUL)) +#define RX65N_USB_D1FIFOSEL ((volatile short *) (RX65N_USB_BASE + 0x002cUL)) +#define RX65N_USB_D1FIFOSEL_MBW_16 (1U << 10) +#define RX65N_USB_D1FIFOCTR ((volatile short *) (RX65N_USB_BASE + 0x002eUL)) + +#define RX65N_USB_USING_CFIFO (0) +#define RX65N_USB_USING_D0FIFO (1) +#define RX65N_USB_USING_D1FIFO (2) + +#define USB_CUSE (RX65N_USB_USING_CFIFO) +#define USB_D0USE (RX65N_USB_USING_D0FIFO) +#define USB_D1USE (RX65N_USB_USING_D1FIFO) + +#define USB_ERROR (0xffUL) +#define RX65N_USB_FIFO_ERROR (0xffUL) +#define USB_TRUE (1UL) +#define USB_FALSE (0UL) +#define USB_YES (1UL) +#define USB_NO (0UL) + +/* FIFO read / write result */ + +#define USB_FIFOERROR (USB_ERROR) /* FIFO not ready */ +#define USB_WRITEEND (0x0000u) /* End of write (but packet may not be outputting) */ +#define USB_WRITESHRT (0x0001u) /* End of write (send short packet) */ +#define USB_WRITING (0x0002u) /* Write continues */ +#define USB_READEND (0x0000u) /* End of read */ +#define USB_READSHRT (0x0001u) /* Insufficient (receive short packet) */ +#define USB_READING (0x0002u) /* Read continues */ +#define USB_READOVER (0x0003u) /* Buffer size over */ + +/* Pipe define table end code */ + +#define USB_PDTBLEND (0xffffu) /* End of table */ + +/* Transfer status Type */ + +#define USB_CTRL_END (0u) +#define USB_DATA_NONE (1u) +#define USB_DATA_WAIT (2u) +#define USB_DATA_OK (3u) +#define USB_DATA_SHT (4u) +#define USB_DATA_OVR (5u) +#define USB_DATA_STALL (6u) +#define USB_DATA_ERR (7u) +#define USB_DATA_STOP (8u) +#define USB_DATA_TMO (9u) +#define USB_CTRL_READING (17u) +#define USB_CTRL_WRITING (18u) +#define USB_DATA_READING (19u) +#define USB_DATA_WRITING (20u) + +/* Utr member (segment) */ + +#define USB_TRAN_CONT (0x00u) +#define USB_TRAN_END (0x80u) + +/* USB common bit fields for D0 and D1 FIFO select register */ + +#define RX65N_USB_DFIFOSEL_RCNT (1U << 15) +#define RX65N_USB_DFIFOSEL_REW (1U << 14) +#define RX65N_USB_DFIFOSEL_DCLRM (1U << 13) +#define RX65N_USB_DFIFOSEL_DREQE (1U << 12) +#define RX65N_USB_DFIFOSEL_MBW_8 (0U << 10) +#define USB_MBW_8 (RX65N_USB_DFIFOSEL_MBW_8) +#define RX65N_USB_DFIFOSEL_MBW_16 (1U << 10) +#define USB_MBW_16 (RX65N_USB_DFIFOSEL_MBW_16) +#define USB0_CFIFO_MBW (USB_MBW_16) +#define USB0_D0FIFO_MBW (USB_MBW_16) +#define USB0_D1FIFO_MBW (USB_MBW_16) +#define RX65N_USB_DFIFOSEL_BIGEND (1U << 8) +#define RX65N_USB_DFIFOSEL_CURPIPE_MASK (0xf) + +/* USB Interrupt Enable Register 0 and its bit fields */ + +#define RX65N_USB_INTENB0 ((volatile short *) (RX65N_USB_BASE + 0x0030UL)) +#define RX65N_USB_INTENB0_BEMPE (1U << 10) +#define RX65N_USB_INTENB0_BRDYE (1U << 8) +#define RX65N_USB_INTENB0_VBSE (1U << 15) +#define RX65N_USB_INTENB0_RSME (1U << 14) +#define RX65N_USB_INTENB0_SOFE (1U << 13) +#define RX65N_USB_INTENB0_DVSE (1U << 12) +#define RX65N_USB_INTENB0_CTRE (1U << 11) +#define RX65N_USB_INTENB0_BEMPE (1U << 10) +#define RX65N_USB_INTENB0_NRDYE (1U << 9) +#define RX65N_USB_INTENB0_BRDYE (1U << 8) + +/* USB Interrupt Enable Register 1 and its bit fields */ + +#define RX65N_USB_INTENB1 ((volatile short *) (RX65N_USB_BASE + 0x0032UL)) +#define RX65N_USB_INTENB1_OVRCRE (1U << 15) +#define RX65N_USB_INTENB1_BCHGE (1U << 14) +#define RX65N_USB_INTENB1_DTCHE (1U << 12) +#define RX65N_USB_INTENB1_ATTCHE (1U << 11) + +#define RX65N_USB_INTENB1_EOFERRE (1U << 6) +#define RX65N_USB_INTENB1_SIGNE (1U << 5) +#define RX65N_USB_INTENB1_SACKE (1U << 4) + +/* BRDY Interrupt Enable Register */ + +#define RX65N_USB_BRDYENB ((volatile short *) (RX65N_USB_BASE + 0x0036UL)) + +/* Bit fields of pipe selection/ control registers. These bit fields are + * generic + */ + +#define USB_PIPE1 (1) +#define USB_PIPE2 (2) +#define USB_PIPE3 (3) +#define USB_PIPE4 (4) +#define USB_PIPE5 (5) +#define USB_PIPE6 (6) +#define USB_PIPE7 (7) +#define USB_PIPE8 (8) +#define USB_PIPE9 (9) +#define USB_MIN_PIPE_NO (1u) +#define USB_MAX_PIPE_NO (9) + +/* Details of pipe number for obtaining the pipe */ + +/* Start Pipe No */ + +#define USB_MIN_PIPE_NUM (1u) + +/* Max device */ +#define USB_MAXPIPE_BULK (5u) +#define USB_MAXPIPE_ISO (2u) +#define USB_MAX_PIPE_NUM (9u) + +#define USB_BULK_PIPE_START (1u) +#define USB_BULK_PIPE_END (5u) +#define USB_INT_PIPE_START (6u) +#define USB_INT_PIPE_END (9u) +#define USB_ISO_PIPE_START (1u) +#define USB_ISO_PIPE_END (2u) + +/* Endpoint Descriptor Define */ +#define USB_EP_IN (0x80u) /* In Endpoint */ +#define USB_EP_OUT (0x00u) /* Out Endpoint */ +#define USB_EP_CTRL (0x00u) +#define USB_EP_ISO (0x01u) /* Isochronous Transfer */ +#define USB_EP_BULK (0x02u) /* Bulk Transfer */ +#define USB_EP_INT (0x03u) /* Interrupt Transfer */ + +#define USB_BITSET(x) ((uint16_t)((uint16_t)1 << (x))) + +/* BRDY Interrupt Enable/Status Register */ + +#define USB_BRDY9 (0x0200u) /* b9: PIPE9 */ +#define USB_BRDY8 (0x0100u) /* b8: PIPE8 */ +#define USB_BRDY7 (0x0080u) /* b7: PIPE7 */ +#define USB_BRDY6 (0x0040u) /* b6: PIPE6 */ +#define USB_BRDY5 (0x0020u) /* b5: PIPE5 */ +#define USB_BRDY4 (0x0010u) /* b4: PIPE4 */ +#define USB_BRDY3 (0x0008u) /* b3: PIPE3 */ +#define USB_BRDY2 (0x0004u) /* b2: PIPE2 */ +#define USB_BRDY1 (0x0002u) /* b1: PIPE1 */ +#define USB_BRDY0 (0x0001u) /* b1: PIPE0 */ + +/* NRDY Interrupt Enable/Status Register */ + +#define USB_NRDY9 (0x0200u) /* b9: PIPE9 */ +#define USB_NRDY8 (0x0100u) /* b8: PIPE8 */ +#define USB_NRDY7 (0x0080u) /* b7: PIPE7 */ +#define USB_NRDY6 (0x0040u) /* b6: PIPE6 */ +#define USB_NRDY5 (0x0020u) /* b5: PIPE5 */ +#define USB_NRDY4 (0x0010u) /* b4: PIPE4 */ +#define USB_NRDY3 (0x0008u) /* b3: PIPE3 */ +#define USB_NRDY2 (0x0004u) /* b2: PIPE2 */ +#define USB_NRDY1 (0x0002u) /* b1: PIPE1 */ +#define USB_NRDY0 (0x0001u) /* b1: PIPE0 */ + +/* BEMP Interrupt Enable/Status Register */ + +#define USB_BEMP9 (0x0200u) /* b9: PIPE9 */ +#define USB_BEMP8 (0x0100u) /* b8: PIPE8 */ +#define USB_BEMP7 (0x0080u) /* b7: PIPE7 */ +#define USB_BEMP6 (0x0040u) /* b6: PIPE6 */ +#define USB_BEMP5 (0x0020u) /* b5: PIPE5 */ +#define USB_BEMP4 (0x0010u) /* b4: PIPE4 */ +#define USB_BEMP3 (0x0008u) /* b3: PIPE3 */ +#define USB_BEMP2 (0x0004u) /* b2: PIPE2 */ +#define USB_BEMP1 (0x0002u) /* b1: PIPE1 */ +#define USB_BEMP0 (0x0001u) /* b0: PIPE0 */ + +/* Control Transfer Stage */ + +#define USB_IDLEST (0u) /* Idle */ +#define USB_SETUPNDC (1u) /* Setup Stage No Data Control */ +#define USB_SETUPWR (2u) /* Setup Stage Control Write */ +#define USB_SETUPRD (3u) /* Setup Stage Control Read */ +#define USB_DATAWR (4u) /* Data Stage Control Write */ +#define USB_DATARD (5u) /* Data Stage Control Read */ +#define USB_STATUSRD (6u) /* Status stage */ +#define USB_STATUSWR (7u) /* Status stage */ +#define USB_SETUPWRCNT (17u) /* Setup Stage Control Write */ +#define USB_SETUPRDCNT (18u) /* Setup Stage Control Read */ +#define USB_DATAWRCNT (19u) /* Data Stage Control Write */ +#define USB_DATARDCNT (20u) /* Data Stage Control Read */ + +#define RX65N_USB_PIPE_ALL (0x3ff) + +/* USB NRDY Interrupt Enable Register */ + +#define RX65N_USB_NRDYENB ((volatile short *) (RX65N_USB_BASE + 0x0038UL)) + +/* USB BEMP Interrupt Enable Register */ + +#define RX65N_USB_BEMPENB ((volatile short *) (RX65N_USB_BASE + 0x003aUL)) + +/* USB SOF Output Configuration Register and its bit fields */ + +#define RX65N_USB_SOFCFG ((volatile short *) (RX65N_USB_BASE + 0x003cUL)) +#define RX65N_USB_SOFCFG_TRNENSEL (1U << 8) +#define RX65N_USB_SOFCFG_BRDYM (1U << 6) +#define USB_SUREQ (0x4000u) /* b14: Send USB request */ + +#define RX65N_USB_SOFCFG_EDGESTS (1U << 4) + +/* USB Interrupt Status Register 0 and its bit fields */ + +#define RX65N_USB_INTSTS0 ((volatile short *) (RX65N_USB_BASE + 0x0040UL)) +#define RX65N_USB_INTSTS0_VBINT (1U << 15) +#define RX65N_USB_INTSTS0_RESM (1U << 14) +#define RX65N_USB_INTSTS0_SOFR (1U << 13) +#define RX65N_USB_INTSTS0_DVST (1U << 12) +#define USB_DVSQ (0x0070u) /* b6-4: Device state */ +#define RX65N_USB_INTSTS0_CTRT (1U << 11) +#define USB_CTSQ (0x0007u) /* b2-0: Control transfer stage */ +#define USB_CS_SQER (0x0006u) /* Sequence error */ +#define USB_CS_WRND (0x0005u) /* Ctrl write nodata status stage */ +#define USB_CS_WRSS (0x0004u) /* Ctrl write status stage */ +#define USB_CS_WRDS (0x0003u) /* Ctrl write data stage */ +#define USB_CS_RDSS (0x0002u) /* Ctrl read status stage */ +#define USB_CS_RDDS (0x0001u) /* Ctrl read data stage */ +#define USB_CS_IDST (0x0000u) /* Idle or setup stage */ +#define USB_DS_SPD_CNFG (0x0070u) /* Suspend Configured */ +#define USB_DS_SPD_ADDR (0x0060u) /* Suspend Address */ +#define USB_DS_SPD_DFLT (0x0050u) /* Suspend Default */ +#define USB_DS_SPD_POWR (0x0040u) /* Suspend Powered */ +#define USB_DS_SUSP (0x0040u) /* Suspend */ +#define USB_DS_CNFG (0x0030u) /* Configured */ +#define USB_DS_ADDS (0x0020u) /* Address */ +#define USB_DS_DFLT (0x0010u) /* Default */ +#define USB_DS_POWR (0x0000u) /* Powered */ + +#define RX65N_USB_INTSTS0_CTRT (1U << 11) +#define RX65N_USB_INTSTS0_BEMP (1U << 10) +#define RX65N_USB_INTSTS0_NRDY (1U << 9) +#define RX65N_USB_INTSTS0_BRDY (1U << 8) +#define RX65N_USB_INTSTS0_VBSTS (1U << 7) +#define RX65N_USB_INTSTS0_VALID (1U << 3) +#define RX65N_USB_INTSTS0_DVSQ_MASK (7U << 4) +#define RX65N_USB_INTSTS0_CTSQ_MASK (7) +#define RX65N_USB_INTSTS0_ALL_CLEAR (0U) +#define INTSTS0_BIT_VALUES_TO_DETECT (0x9d00) +#define USB_DATA_STOP (8u) +#define USB_MIN_PIPE_NO (1u) +#define USB_MAXPIPE_NUM (9u) +#define USB_ACLRM (0x0200u) +#define USB_PID_BUF (0x0001u) /* BUF */ +#define USB_PIPE0 (0x0u) +#define USB_PBUSY (0x0020u) /* b5: pipe busy */ +#define USB_TRENB (0x0200u) +#define USB_TRCLR (0x0100u) +#define USB_NULL (0x0u) +#define USB_RSME (0x4000u) +#define USB_RESM (0x4000u) /* b14: Resume interrupt */ +#define USB_VALID (0x0008u) /* b3: Setup packet detect flag */ +#define USB_BMREQUESTTYPETYPE (0x0060u) /* b6-5: Type */ +#define USB_CLASS (0x0020u) +#define USB_MBW (0x0C00u) /* b10: Maximum bit width for FIFO access */ +#define USB0_CFIFO_MBW (USB_MBW_16) +#define USB_DATA_ERR (7u) +#define USB_DATA_OVR (5u) +#define USB_PID (0x0003u) /* b1-0: Response PID */ +#define USB_CCPL (0x0004u) /* b2: Enable control transfer complete */ +#define USB_BCLR (0x4000u) /* b14: Buffer clear */ +#define USB_FRDY (0x2000u) /* b13: FIFO ready */ +#define USB_MAXP (0x007Fu) /* b6-0: Maxpacket size of default control pipe */ +#define USB_MXPS (0x07FFu) /* b10-0: Maxpacket size */ +#define USB_WRITESHRT (0x0001u) /* End of write (send short packet) */ +#define USB_WRITING (0x0002u) /* Write continues */ +#define USB0_CFIFO8 (USB0.CFIFO.BYTE.L) +#define USB0_D0FIFO8 (USB0.D0FIFO.BYTE.L) +#define USB0_D1FIFO8 (USB0.D1FIFO.BYTE.L) +#define USB0_CFIFO16 (USB0.CFIFO.WORD) +#define USB0_D0FIFO16 (USB0.D0FIFO.WORD) +#define USB0_D1FIFO16 (USB0.D1FIFO.WORD) +#define USB_WRITEEND (0x0000u) +#define USB_CTRL_END (0u) +#define USB_BREQUEST (0xFF00u) +#define USB_BRDY0 (0x0001u) /* b1: PIPE0 */ +#define USB_READEND (0x0000u) /* End of read */ +#define USB_READSHRT (0x0001u) /* Insufficient (receive short packet) */ +#define USB_READING (0x0002u) /* Read continues */ +#define USB_READOVER (0x0003u) /* Buffer size over */ +#define USB_DTLN (0x0FFFu) /* b11-0: FIFO data length */ +#define USB_VENDOR (0x0040u) +#define USB_WRITE (1) +#define USB_QOVR (0xd5) +#define USB_DIRFIELD (0x0010u) /* Transfer direction select */ +#define USB_DIR_H_OUT (0x0010u) +#define USB_BEMP0 (0x0001u) /* b0: PIPE0 */ +#define BEMPSTS_MASK (0x03FFu) /* BEMPSTS Reserved bit mask */ +#define USB_BEMP (0x0400u) /* b10: Buffer empty interrupt */ +#define USB_BUF2FIFO (0x0010u) /* Buffer --> FIFO */ +#define USB_FIFO2BUF (0x0000u) +#define USB_BITSET(x) ((uint16_t)((uint16_t)1 << (x))) +#define USB_READ (0) +#define USB_DATA_STALL (6u) +#define USB_INBUFM (0x4000u) /* b14: IN buffer monitor (Only for PIPE1 to 5) */ +#define USB_DATA_NONE (1u) +#define USB_DATA_OK (3u) +#define USB_DATA_SHT (4u) +#define USB_GS_REMOTEWAKEUP (0x0002u) +#define USB_EPNUMFIELD (0x000Fu) /* Endpoint number select */ +#define USB_GS_HALT (0x0001u) +#define USB_GS_SELFPOWERD (1) +#define USB_GS_BUSPOWERD (0) +#define USB_MAX_EP_NO (15u) /* EP0 EP1 ... EP15 */ +#define USB_ENDPOINT_HALT (0x0000u) +#define USB_OVRN (0x8000u) /* b15: Overrun error */ +#define USB_DREQE (0x1000u) /* b12: DREQ output enable */ + +/* USB Interrupt Status Register 0 and its bit fields */ + +#define RX65N_USB_INTSTS1 ((volatile short *) (RX65N_USB_BASE + 0x0042UL)) +#define RX65N_USB_INTSTS1_OVRCRE (1U << 15) +#define RX65N_USB_INTSTS1_BCHG (1U << 14) +#define RX65N_USB_INTSTS1_DTCH (1U << 12) +#define RX65N_USB_INTSTS1_ATTCH (1U << 11) +#define RX65N_USB_INTSTS1_EOFERR (1U << 6) +#define RX65N_USB_INTSTS1_SIGN (1U << 5) +#define RX65N_USB_INTSTS1_SACK (1U << 4) +#define RX65N_USB_INTSTS1_ALL_CLEAR (0U) + +/* USB DCP Control Register and its bit fields */ + +#define RX65N_USB_DCPCTR ((volatile short *) (RX65N_USB_BASE + 0x0060UL)) +#define RX65N_USB_DCPCTR_BSTS (1U << 15) +#define RX65N_USB_DCPCTR_SUREQ (1U << 14) +#define RX65N_USB_DCPCTR_SUREQCLR (1U << 11) +#define USB_SUREQCLR (RX65N_USB_DCPCTR_SUREQCLR) +#define RX65N_USB_DCPCTR_SQCLR (1U << 8) +#define USB_SQCLR (RX65N_USB_DCPCTR_SQCLR) +#define RX65N_USB_DCPCTR_SQSET (1U << 7) +#define RX65N_USB_DCPCTR_SQMON (1U << 6) +#define RX65N_USB_DCPCTR_PBUSY (1U << 5) +#define RX65N_USB_DCPCTR_CCPL (1U << 2) +#define RX65N_USB_DCPCTR_PID_MASK (3UL) +#define RX65N_USB_DCPCTR_PIDNAK (0UL) +#define RX65N_USB_DCPCTR_PIDBUF (1UL) +#define RX65N_USB_DCPCTR_PIDSTALL (2UL) +#define RX65N_USB_DCPCTR_PIDSTALL2 (3UL) + +/* USB PIPE 1 to 9 Control Registers */ + +#define RX65N_USB_PIPE1CTR ((volatile short *) (RX65N_USB_BASE + 0x0070UL)) +#define RX65N_USB_PIPE2CTR ((volatile short *) (RX65N_USB_BASE + 0x0072UL)) +#define RX65N_USB_PIPE3CTR ((volatile short *) (RX65N_USB_BASE + 0x0074UL)) +#define RX65N_USB_PIPE4CTR ((volatile short *) (RX65N_USB_BASE + 0x0076UL)) +#define RX65N_USB_PIPE5CTR ((volatile short *) (RX65N_USB_BASE + 0x0078UL)) +#define RX65N_USB_PIPE6CTR ((volatile short *) (RX65N_USB_BASE + 0x007aUL)) +#define RX65N_USB_PIPE7CTR ((volatile short *) (RX65N_USB_BASE + 0x007cUL)) +#define RX65N_USB_PIPE8CTR ((volatile short *) (RX65N_USB_BASE + 0x007eUL)) +#define RX65N_USB_PIPE9CTR ((volatile short *) (RX65N_USB_BASE + 0x0080UL)) + +/* USB Pipe 1 to 9 control register bit fields */ + +#define RX65N_USB_PIPECTR_BSTS (1U << 15) +#define RX65N_USB_PIPECTR_INBUFM (1U << 14) +#define RX65N_USB_PIPECTR_ATREPM (1U << 10) +#define RX65N_USB_PIPECTR_ACLRM (1U << 9) +#define RX65N_USB_PIPECTR_SQCLR (1U << 8) +#define RX65N_USB_PIPECTR_SQSET (1U << 7) +#define RX65N_USB_PIPECTR_SQMON (1U << 6) +#define RX65N_USB_PIPECTR_PBUSY (1U << 5) +#define RX65N_USB_PIPECTR_PID_MASK (3) +#define RX65N_USB_PIPECTR_PIDNAK (0) +#define RX65N_USB_PIPECTR_PIDBUF (1) +#define RX65N_USB_PIPECTR_PIDSTALL (2) +#define RX65N_USB_PIPECTR_PIDSTALL2 (3) +#define RX65N_USB_PIPECTR_DATA1 (1U << 7) +#define RX65N_USB_PIPECTR_DATA0 (1U << 8) + +/* USB PIPE 1 to 5 (Transaction Counter Enable) and + * (Transaction Counter Register) Registers + */ + +#define RX65N_USB_PIPE1TRE ((volatile short *) (RX65N_USB_BASE + 0x0090UL)) +#define RX65N_USB_PIPE1TRN ((volatile short *) (RX65N_USB_BASE + 0x0092UL)) +#define RX65N_USB_PIPE2TRE ((volatile short *) (RX65N_USB_BASE + 0x0094UL)) +#define RX65N_USB_PIPE2TRN ((volatile short *) (RX65N_USB_BASE + 0x0096UL)) +#define RX65N_USB_PIPE3TRE ((volatile short *) (RX65N_USB_BASE + 0x0098UL)) +#define RX65N_USB_PIPE3TRN ((volatile short *) (RX65N_USB_BASE + 0x009aUL)) +#define RX65N_USB_PIPE4TRE ((volatile short *) (RX65N_USB_BASE + 0x009cUL)) +#define RX65N_USB_PIPE4TRN ((volatile short *) (RX65N_USB_BASE + 0x009eUL)) +#define RX65N_USB_PIPE5TRE ((volatile short *) (RX65N_USB_BASE + 0x00a0UL)) +#define RX65N_USB_PIPE5TRN ((volatile short *) (RX65N_USB_BASE + 0x00a2UL)) + +/* USB PIPE 1 to 5 Transaction Counter Enable register bit fields */ + +#define RX65N_USB_PIPETRE_TRENB (1U << 9) +#define RX65N_USB_PIPETRE_TRCLR (1U << 8) + +/* USB Device Address 0 to 5 Configuration Register */ + +#define RX65N_USB_DEVADD0 ((volatile short *) (RX65N_USB_BASE + 0x00d0UL)) +#define RX65N_USB_DEVADD1 ((volatile short *) (RX65N_USB_BASE + 0x00d2UL)) +#define RX65N_USB_DEVADD2 ((volatile short *) (RX65N_USB_BASE + 0x00d4UL)) +#define RX65N_USB_DEVADD3 ((volatile short *) (RX65N_USB_BASE + 0x00d6UL)) +#define RX65N_USB_DEVADD4 ((volatile short *) (RX65N_USB_BASE + 0x00d8UL)) +#define RX65N_USB_DEVADD5 ((volatile short *) (RX65N_USB_BASE + 0x00daUL)) +#define RX65N_USB_DEVSPD (3 << 6) + +#define USB_MAXDEVADDR (5u) +#define USB_DEVICE_0 (0x0000u) /* Device address 0 */ +#define USB_DEVICE_1 (0x1000u) /* Device address 1 */ +#define USB_DEVICE_2 (0x2000u) /* Device address 2 */ +#define USB_DEVICE_3 (0x3000u) /* Device address 3 */ +#define USB_DEVICE_4 (0x4000u) /* Device address 4 */ +#define USB_DEVICE_5 (0x5000u) /* Device address 5 */ +#define USB_DEVICE_6 (0x6000u) /* Device address 6 */ +#define USB_DEVICE_7 (0x7000u) /* Device address 7 */ +#define USB_DEVICE_8 (0x8000u) /* Device address 8 */ +#define USB_DEVICE_9 (0x9000u) /* Device address 9 */ +#define USB_DEVICE_A (0xa000u) /* Device address A */ +#define USB_NODEVICE (0xf000u) /* No device */ +#define USB_DEVADDRBIT (12u) + +/* Device Address bit fields */ + +#define RX65N_USB_DEVADD_SPEED_LOW (1U << 6) +#define RX65N_USB_DEVADD_SPEED_FULL (2U << 6) +#define RX65N_USB_DEVADD_SPEED_HIGH (3U << 6) + +/* USB PHY Cross Point Adjustment Register and its bit fields */ + +#define RX65N_USB_PHYSLEW ((volatile int *) (RX65N_USB_BASE + 0x00f0UL)) + +/* PHY Cross Point Adjustment, note that Hardware Manual to be + * updated(0xe->0x5) + */ +#define RX65N_USB_PHYSLEW_SLEW_SLEWR00 (1U << 0) +#define RX65N_USB_PHYSLEW_SLEW_SLEWR01 (1U << 1) +#define RX65N_USB_PHYSLEW_SLEW_SLEWF00 (1U << 2) +#define RX65N_USB_PHYSLEW_SLEW_SLEWF01 (1U << 3) + +/* USB Deep Standby USB Transceiver Control/Pin Monitoring Register */ + +#define RX65N_USB_DPUSR0R ((volatile int *)(RX65N_USB_BASE + 0x0400UL)) + +/* USB Deep Standby USB Suspend/Resume Interrupt Register */ + +#define RX65N_USB_DPUSR1R ((volatile int *)(RX65N_USB_BASE + 0x0404UL)) + +#define RX65N_USB_BRDYENB ((volatile short *) (RX65N_USB_BASE + 0x0036UL)) +#define RX65N_USB_NRDYENB ((volatile short *) (RX65N_USB_BASE + 0x0038UL)) + +/* USB BEMP Interrupt Enable Register */ + +#define RX65N_USB_BEMPENB ((volatile short *) (RX65N_USB_BASE + 0x003aUL)) + +/* USB Frame Number Register and its bit fields */ + +#define RX65N_USB_FRMNUM ((volatile short *) (RX65N_USB_BASE + 0x004cUL)) +#define RX65N_USB_FRMNUM_OVRN (1U << 15) +#define RX65N_USB_FRMNUM_CRCE (1U << 14) +#define RX65N_USB_FRMNUM_FRNM_MASK (0x7ffU) + +/* USB Device State Change Register and its bit fields */ + +#define RX65N_USB_DVCHGR ((volatile short *) (RX65N_USB_BASE + 0x004eUL)) + +#define RX65N_USB_PIPESEL ((volatile short *) (RX65N_USB_BASE + 0x0064UL)) +#define RX65N_USB_PIPESEL_NO_PIPE (0x000fUL) + +#define RX65N_USB_PIPECFG ((volatile short *) (RX65N_USB_BASE + 0x0068UL)) +#define RX65N_USB_PIPECFG_TYPE_MASK (0xc000) +#define RX65N_USB_PIPECFG_TYPE_BIT_USED (0) +#define RX65N_USB_PIPECFG_TYPE_BULK (1U << 14) +#define RX65N_USB_PIPECFG_TYPE_INTERRUPT (2U << 14) +#define RX65N_USB_PIPECFG_TYPE_ISOCHRONOUS (3U << 14) +#define RX65N_USB_PIPECFG_BFRE (1U << 10) +#define RX65N_USB_PIPECFG_DBLB (1U << 9) +#define RX65N_USB_PIPECFG_SHTNAK (1U << 7) +#define RX65N_USB_PIPECFG_DIR (1U << 4) +#define RX65N_USB_PIPECFG_EPNUM_MASK (0xfU) + +#define RX65N_USB_PIPEMAXP ((volatile short *) (RX65N_USB_BASE + 0x006cUL)) +#define RX65N_USB_PIPEMAXP_DEVSELMASK (0xfU << 12) +#define RX65N_USB_PIPEMAXP_DEVSEL_SHIFT (12U) +#define RX65N_USB_PIPEMAXP_MXPSMASK (0x1ff) + +#define RX65N_USB_PIPEPERI ((volatile short *) (RX65N_USB_BASE + 0x006eUL)) + +/* USB BRDY Interrupt Status Register */ + +#define RX65N_USB_BRDYSTS ((volatile short *) (RX65N_USB_BASE + 0x0046UL)) + +/* USB NRDY Interrupt Status Register */ + +#define RX65N_USB_NRDYSTS ((volatile short *) (RX65N_USB_BASE + 0x0048UL)) + +/* USB BEMP Interrupt Status Register */ + +#define RX65N_USB_BEMPSTS ((volatile short *) (RX65N_USB_BASE + 0x004aUL)) + +#define RX65N_USB_DVSTCTR0 ((volatile short *) (RX65N_USB_BASE + 0x0008UL)) +#define USB_HSMODE (0x0003u) /* Hi-Speed mode */ +#define USB_FSMODE (0x0002u) /* Full-Speed mode */ +#define USB_LSMODE (0x0001u) /* Low-Speed mode */ +#define USB_HSPROC (0x0004u) /* HS handshake processing */ +#define USB_HSCONNECT (0x00C0u) /* Hi-Speed connect */ +#define USB_FSCONNECT (0x0080u) /* Full-Speed connect */ +#define USB_LSCONNECT (0x0040u) /* Low-Speed connect */ +#define USB_NOCONNECT (0x0000u) + +#define RX65N_USB_DCPCFG ((volatile short *) (RX65N_USB_BASE + 0x005cUL)) +#define RX65N_USB_DCPCFG_DIR (1U << 4) + +#define RX65N_USB_DCPMAXP ((volatile short *) (RX65N_USB_BASE + 0x005eUL)) +#define RX65N_USB_DCPMAXP_DEVADDR_SHIFT (12U) +#define RX65N_USB_DCPMAXP_DEVADDR_MASK (0xf000U) +#define RX65N_USB_DCPMAXP_MXPS_MASK (0x007fU) + +#define USB_DCPMAXP (64u) + +#define RX65N_USB_USBREQ ((volatile short *) (RX65N_USB_BASE + 0x0054UL)) + +/* USB Request Value Register */ + +#define RX65N_USB_USBVAL ((volatile short *) (RX65N_USB_BASE + 0x0056UL)) + +/* USB Request Index Register */ + +#define RX65N_USB_USBINDX ((volatile short *) (RX65N_USB_BASE + 0x0058UL)) + +/* USB Request Length Register */ + +#define RX65N_USB_USBLENG ((volatile short *) (RX65N_USB_BASE + 0x005aUL)) + +/* Endpoint Descriptor Define */ +#define USB_EP_IN (0x80u) /* In Endpoint */ +#define USB_EP_OUT (0x00u) /* Out Endpoint */ +#define USB_EP_ISO (0x01u) /* Isochronous Transfer */ +#define USB_EP_BULK (0x02u) /* Bulk Transfer */ +#define USB_EP_INT (0x03u) /* Interrupt Transfer */ + +#define USB_PIPE_DIR_IN (0u) +#define USB_PIPE_DIR_OUT (1u) +#define USB_PIPE_DIR_MAX (2u) + +#define USB_CFG_PCDC_BULK_IN (USB_PIPE1) +#define USB_CFG_PCDC_BULK_OUT (USB_PIPE2) +#define USB_CFG_PCDC_INT_IN (USB_PIPE6) + +/* USB pipe number */ +#define USB_PIPE0 (0x0u) + +/* Pipe configuration table define */ +#define USB_EPL (6u) /* Pipe configuration table length */ +#define USB_TYPFIELD (0xC000u) /* Transfer type */ +#define USB_PERIODIC (0x8000u) /* Periodic pipe */ +#define USB_TYPFIELD_ISO (0xC000u) /* Isochronous */ +#define USB_TYPFIELD_INT (0x8000u) /* Interrupt */ +#define USB_TYPFIELD_BULK (0x4000u) /* Bulk */ +#define USB_NOUSE (0x0000u) /* Not configuration */ +#define USB_BFREFIELD (0x0400u) /* Buffer ready interrupt mode select */ +#define USB_BFREON (0x0400u) +#define USB_BFREOFF (0x0000u) +#define USB_DBLBFIELD (0x0200u) /* Double buffer mode select */ +#define USB_CFG_DBLBON (0x0200u) +#define USB_CFG_DBLBOFF (0x0000u) +#define USB_CNTMDFIELD (0x0100u) /* Continuous transfer mode select */ +#define USB_CFG_CNTMDON (0x0100u) +#define USB_CFG_CNTMDOFF (0x0000u) +#define USB_CFG_DBLB (USB_CFG_DBLBON) +#define USB_DIR_P_IN (0x0010u) /* PERI IN */ +#define USB_DIR_H_IN (0x0000u) +#define USB_SHTNAKFIELD (0x0080u) /* Transfer end NAK */ +#define USB_DIR_P_OUT (0x0000u) /* PERI OUT */ +#define USB_BRDY (0x0100u) /* b8: Buffer ready interrupt */ +#define BRDYSTS_MASK (0x03FFu) /* BRDYSTS Reserved bit mask */ +#define RX65N_USB_INTSTS0_NRDY (1U << 9) +#define RX65N_PIPENUM_WRITE (1) +#define RX65N_USB_MAXP (64) +#define RX65N_USBI0_SOURCE (0x3eu) +#define RX65N_USBI0_PRIORITY (0x0f) +#define RX65N_PHYSLEW_VALUE (0x5) + +#define RX65N_USB_PFKUSB_ENABLED (1U << 4) +#define RX65N_USB_PFKUSB_MODE_HOST (1) +#define RX65N_USB_INTERRUPT_STATUS_MASK (0x3ffU) + +/* Supported USBMCLK frequency for S7G2 and S5D9. */ + +#define RX65N_USB_MAIN_OSC_24MHz (24000000U) +#define RX65N_USB_MAIN_OSC_20MHz (20000000U) +#define RX65N_USB_MAIN_OSC_12MHz (12000000U) + +/* Bit fields */ + +#define RX65N_USB_SYSSTS0_LNST_J_STATE_FS (1U) +#define RX65N_USB_SYSSTS0_LNST_J_STATE_LS (2U) +#define RX65N_USB_PLLSTA_PLLLOCK (1U << 0) +#define RX65N_USB_PHYSET_HSEB (1U << 15) +#define RX65N_USB_PHYSET_REPSTART (1U << 11) +#define RX65N_USB_PHYSET_REPSEL (1U << 8) +#define RX65N_USB_PHYSET_CLKSEL_1 (1U << 5) +#define RX65N_USB_PHYSET_CLKSEL_0 (1U << 4) +#define RX65N_USB_PHYSET_CDPEN (1U << 3) +#define RX65N_USB_PHYSET_PLLRESET (1U << 1) +#define RX65N_USB_PHYSET_DIRPD (1U << 0) +#define RX65N_USB_PIPEBUF_SIZEMASK (0x1fU << 10) +#define RX65N_USB_PIPEBUF_BUFNMBMASK (0xffU << 10) +#define RX65N_USB_PIPEBUF_SHIFT (10U) + +/* Possibly below are used for differentiating Control/ D0 or D1 pipe... */ + +#define RX65N_USB_FIFO_D0 (0UL) +#define RX65N_USB_FIFO_D1 (1UL) +#define RX65N_USB_FIFO_C (2UL) +#define RX65N_USB_DEVADD_UPPHUB_SHIFT (11U) +#define RX65N_USB_DEVADD_HUBPORT_SHIFT (8U) +#define RX65N_USB_USBMC_VDCEN (1U << 7) + +/* Define Synergy HCOR command/status bitmaps. */ + +#define RX65N_USB_DCP (0) +#define RX65N_USB_DCPCTR_DATA1 (1U << 7) +#define RX65N_USB_DCPCTR_DATA0 (1U << 8) + +/* Define Synergy fifo definition. */ + +#define RX65N_USB_PIPE0_SIZE (256) +#define RX65N_USB_PIPE_NB_BUFFERS (64) + +/* Define Synergy static definition. */ + +#define RX65N_USB_AVAILABLE_BANDWIDTH (2304UL) + +/* The macro above is used for checking the available bandwidth for periodic + * transfers(Isochronous and Interrupt) + * Maximum bandwidth is calculated as + * {2048byes(2x ISO PIPEs) + 256bytes(4x INT PIPEs)} for high-speed operation + */ +#define RX65N_USB_INIT_DELAY (1000) +#define RX65N_USB_RESET_RETRY (1000) +#define RX65N_USB_RESET_DELAY (10) +#define RX65N_USB_PORT_RESET_RETRY (50) +#define RX65N_USB_FORCE_PORT_RESET_RETRY (50) +#define RX65N_USB_FORCE_PORT_RESET_DELAY (1) +#define RX65N_USB_CHECK_PORT_RESET_RETRY (500) +#define RX65N_USB_PORT_RESET_DELAY (300) +#define RX65N_USB_PORT_RESET_RECOVERY_DELAY (100) + +/* Define Synergy initialization values. */ + +#define RX65N_USB_COMMAND_STATUS_RESET (0) +#define RX65N_USB_INIT_RESET_DELAY (10) +#define RX65N_USB_MAX_BUF_SIZE (64) +#define RX65N_USB_BUF_BLOCK_SIZE (64) +#define RX65N_USB_MAX_BUF_SIZE_PIPE1_to_2_FS (256) +#define RX65N_USB_MAX_BUF_SIZE_PIPE3_to_9_FS (64) +#define RX65N_USB_MAX_BUF_SIZE_PIPE1_to_2_HS (1024) +#define RX65N_USB_MAX_BUF_SIZE_PIPE3_to_5_HS (512) +#define RX65N_USB_MAX_BUF_SIZE_PIPE6_to_9_HS (64) +#define RX65N_USB_MAX_BUF_NUM (135) +#define RX65N_USB_PIPE1_BUF_START_NUM (8) + +/* Define Synergy FIFO write completion code. */ + +#define RX65N_USB_FIFO_WRITING (2) +#define RX65N_USB_FIFO_WRITE_END (3) +#define RX65N_USB_FIFO_WRITE_SHORT (4) +#define RX65N_USB_FIFO_WRITE_DMA (5) +#define RX65N_USB_FIFO_WRITE_ERROR (6) + +/* Define Synergy FIFO read completion code. */ + +#define RX65N_USB_FIFO_READING (2) +#define RX65N_USB_FIFO_READ_END (3) +#define RX65N_USB_FIFO_READ_SHORT (4) +#define RX65N_USB_FIFO_READ_DMA (5) +#define RX65N_USB_FIFO_READ_ERROR (6) +#define RX65N_USB_FIFO_READ_OVER (7) +#define RX65N_USB_ED_BRDY (0x00000001U) +#define RX65N_USB_ED_NRDY (0x00000002U) +#define RX65N_USB_ED_BEMP (0x00000004U) +#define RX65N_USB_ED_EOFERR (0x00000010U) +#define RX65N_USB_ED_SIGN (0x00000020U) +#define RX65N_USB_ED_SACK (0x00000040U) +#define RX65N_USB_ED_TIMEOUT (0x00000080U) +#define RX65N_USB_LPSTS_SUSPENDM (1U << 14) + +/* Define Synergy Root hub states. */ + +#define RX65N_USB_PORT_ENABLED (1) +#define RX65N_USB_PORT_DISABLED (0) +#define RX65N_USB_PORT_INEOFERR (3) + +#define RX65N_USB_FRMNUM_VAL (0x1111111111) + +#define USB_INT_BRDY (0x0001u) +#define USB_BMREQUESTTYPERECIP (0x001Fu) /* b4-0: Recipient */ + /* RIIC related definitions */ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_DRIVER) diff --git a/arch/renesas/src/rx65n/rx65n_irq.c b/arch/renesas/src/rx65n/rx65n_irq.c index cc4f4ca452..0ff09339d2 100644 --- a/arch/renesas/src/rx65n/rx65n_irq.c +++ b/arch/renesas/src/rx65n/rx65n_irq.c @@ -849,9 +849,9 @@ void up_enable_irq(int irq) } #ifdef CONFIG_RX65N_PERIB - if (irq == RX65N_INTB176_IRQ) + if (irq == RX65N_INTB185_IRQ) { - ICU.IER[16].BIT.IEN0 = 1; + ICU.IER[0x17].BIT.IEN1 = 1; } #endif diff --git a/arch/renesas/src/rx65n/rx65n_port.c b/arch/renesas/src/rx65n/rx65n_port.c index 8fd9e77129..8f16a8941a 100644 --- a/arch/renesas/src/rx65n/rx65n_port.c +++ b/arch/renesas/src/rx65n/rx65n_port.c @@ -42,6 +42,9 @@ void r_port_create(void) { led_port_create(); sci_port_create(); +#ifdef CONFIG_USBDEV + r_usbdev_port_enable(); +#endif } #ifdef CONFIG_RX65N_EMAC0 diff --git a/arch/renesas/src/rx65n/rx65n_usbdev.c b/arch/renesas/src/rx65n/rx65n_usbdev.c new file mode 100644 index 0000000000..a0dafcdc71 --- /dev/null +++ b/arch/renesas/src/rx65n/rx65n_usbdev.c @@ -0,0 +1,6262 @@ +/**************************************************************************** + * arch/renesas/src/rx65n/rx65n_usbdev.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "chip.h" +#include "up_arch.h" +#include "up_internal.h" + +#include "rx65n_usbdev.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#if defined(CONFIG_USBHOST) && defined(CONFIG_USBDEV) +# error "Both USB Host & Device cannot be configured" +#endif + +#ifndef CONFIG_USBDEV_MAXPOWER +# define CONFIG_USBDEV_MAXPOWER 100 /* mA */ +#endif + +#define RX65N_NENDPOINTS (8) +#define EP0 (0) +#define EP1 (1) +#define EP2 (2) +#define EP3 (3) +#define EP4 (4) +#define EP5 (5) +#define EP6 (6) +#define EP7 (7) + +#define RX65N_ENDP_BIT(ep) (1 << (ep)) +#define RX65N_ENDP_ALLSET 0xff + +#define RX65N_MAXPACKET_SHIFT (6) +#define RX65N_MAXPACKET_SIZE (1 << (RX65N_MAXPACKET_SHIFT)) +#define RX65N_MAXPACKET_MASK (RX65N_MAXPACKET_SIZE-1) + +#define RX65N_EP0MAXPACKET RX65N_MAXPACKET_SIZE + +#define REQRECIPIENT_MASK (USB_REQ_TYPE_MASK | USB_REQ_RECIPIENT_MASK) + +/* Debug ********************************************************************/ + +/* Trace error codes */ + +#define RX65N_TRACEERR_ALLOCFAIL 0x0001 +#define RX65N_TRACEERR_ATTACHIRQ 0x0002 +#define RX65N_TRACEERR_BINDFAILED 0x0003 +#define RX65N_TRACEERR_DRIVER 0x0004 +#define RX65N_TRACEERR_DRIVERREGISTERED 0x0005 +#define RX65N_TRACEERR_EPREAD 0x0006 +#define RX65N_TRACEERR_EWRITE 0x0007 +#define RX65N_TRACEERR_INVALIDPARMS 0x0008 +#define RX65N_TRACEERR_NOEP 0x0009 +#define RX65N_TRACEERR_NOTCONFIGURED 0x000a +#define RX65N_TRACEERR_NULLPACKET 0x000b +#define RX65N_TRACEERR_NULLREQUEST 0x000c +#define RX65N_TRACEERR_REQABORTED 0x000d +#define RX65N_TRACEERR_STALLEDCLRFEATURE 0x000e +#define RX65N_TRACEERR_STALLEDISPATCH 0x000f +#define RX65N_TRACEERR_STALLEDGETST 0x0010 +#define RX65N_TRACEERR_STALLEDGETSTEP 0x0011 +#define RX65N_TRACEERR_STALLEDGETSTRECIP 0x0012 +#define RX65N_TRACEERR_STALLEDREQUEST 0x0013 +#define RX65N_TRACEERR_STALLEDSETFEATURE 0x0014 +#define RX65N_TRACEERR_BADGETCONFIG 0x0015 +#define RX65N_TRACEERR_IRQREGISTRATION 0x001a +#define RX65N_TRACEERR_DISPATCHSTALL 0x001b +#define RX65N_TRACEERR_INVALIDCTRLREQ 0x001c +#define RX65N_TRACEERR_BADEPTYPE 0x001d +#define RX65N_TRACEERR_BADEPNO 0x001e +#define RX65N_TRACEERR_EPRESERVE 0x001f +#define RX65N_TRACEERR_BADSETCONFIG 0x0020 + +/* Trace interrupt codes */ + +#define RX65N_TRACEINTID_CLEARFEATURE 0x0001 +#define RX65N_TRACEINTID_CONTROL 0x0002 +#define RX65N_TRACEINTID_DISPATCH 0x0003 +#define RX65N_TRACEINTID_GETENDPOINT 0x0004 +#define RX65N_TRACEINTID_GETIFDEV 0x0005 +#define RX65N_TRACEINTID_GETSETDESC 0x0006 +#define RX65N_TRACEINTID_GETSETIFCONFIG 0x0007 +#define RX65N_TRACEINTID_GETSTATUS 0x0008 +#define RX65N_TRACEINTID_RESUME 0x0009 +#define RX65N_TRACEINTID_SETADDRESS 0x000a +#define RX65N_TRACEINTID_SETFEATURE 0x000b +#define RX65N_TRACEINTID_SUSPEND 0x000c +#define RX65N_TRACEINTID_SYNCHFRAME 0x000d +#define RX65N_TRACEINTID_TESTMODE 0x000e +#define RX65N_TRACEINTID_TXFIFOSTALL 0x000f +#define RX65N_TRACEINTID_GETCONFIG 0x0010 +#define RX65N_TRACEINTID_EPINQEMPTY 0x0011 +#define RX65N_TRACEINTID_EPOUTQEMPTY 0x0012 +#define RX65N_TRACEINTID_NOSTDREQ 0x0013 +#define RX65N_TRACEINTID_SETCONFIG 0x0014 +#define RX65N_TRACEINTID_GETSETIF 0x0015 + +/* Hardware interface *******************************************************/ + +/* This driver supports the one interrupt IN, one bulk IN + * and one bulk OUT endpoint. + */ + +/* Hardware dependent sizes and numbers */ + +#define RX65N_BULKMAXPACKET 64 /* Bulk endpoint max packet */ +#define RX65N_INTRMAXPACKET 64 /* Interrupt endpoint max packet */ + +/* Endpoint numbers */ + +#define RX65N_EP0 0 /* Control endpoint */ +#define RX65N_EPBULKIN 1 /* Bulk EP for send to host */ +#define RX65N_EPBULKOUT 2 /* Bulk EP for recv to host */ +#define RX65N_EPINTRIN 3 /* Intr EP for host poll */ + +/* Request queue operations *************************************************/ + +#define rx65n_rqempty(ep) ((ep)->head == NULL) +#define rx65n_rqpeek(ep) ((ep)->head) + +# define LSB 0 +# define MSB 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* A container for a request so that the request make be retained in a list */ + +struct rx65n_req_s +{ + struct usbdev_req_s req; /* Standard USB request */ + struct rx65n_req_s *flink; /* Supports a singly linked list */ +}; + +/* This is the internal representation of an endpoint */ + +struct rx65n_ep_s +{ + /* Common endpoint fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbdev_ep_s + * to struct rx65n_ep_s. + */ + + struct usbdev_ep_s ep; /* Standard endpoint structure */ + + /* RX65N-specific fields */ + + struct rx65n_usbdev_s *dev; /* Reference to private driver data */ + struct rx65n_req_s *head; /* Request list for this endpoint */ + struct rx65n_req_s *tail; + uint8_t epphy; /* Physical EP address/index */ + uint8_t stalled:1; /* Endpoint is halted */ + uint8_t in:1; /* Endpoint is IN only */ + uint8_t txbusy:1; /* 1: TX endpoint FIFO full */ + uint8_t halted:1; /* Endpoint feature halted */ + uint8_t txnullpkt:1; /* Null packet needed at end of transfer */ +}; + +/* This structure encapsulates the overall driver state */ + +struct rx65n_usbdev_s +{ + /* Common device fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbdev_s + * to struct rx65n_usbdev_s. + */ + + struct usbdev_s usbdev; + + /* The bound device class driver */ + + struct usbdevclass_driver_s *driver; + + /* RX65N-specific fields */ + + uint8_t stalled:1; /* 1: Protocol stalled */ +#ifdef CONFIG_USBDEV_SELFPOWERED + uint8_t selfpowered:1; /* 1: Device is self powered */ +#endif + uint8_t epavail; /* Bitset of available endpoints */ + uint8_t paddrset:1; /* 1: Peripheral addr has been set */ + uint8_t attached:1; /* 1: Host attached */ + uint8_t rxpending:1; /* 1: RX pending */ + uint8_t paddr; /* Peripheral address */ + uint8_t ep0state; + + struct work_s rx65n_interrupt_bhalf; + struct usb_ctrlreq_s ctrl; + + /* The endpoint list */ + + struct rx65n_ep_s eplist[RX65N_NENDPOINTS]; +}; + +/* For maintaining tables of endpoint info */ + +struct rx65n_epinfo_s +{ + uint8_t addr; /* Logical endpoint address */ + uint8_t attr; /* Endpoint attributes */ + uint8_t fifo; /* FIFO mx pkt size + dual buffer bits */ +#ifdef CONFIG_USBDEV_HIGHSPEED + uint16_t maxpacket; /* Max packet size */ +#else + uint8_t maxpacket; /* Max packet size */ +#endif +}; + +union wb_u +{ + uint16_t w; + uint8_t b[2]; +}; + +uint16_t g_usb_pstd_req_type; /* Type */ +uint16_t g_usb_pstd_req_value; /* Value */ +uint16_t g_usb_pstd_req_index; /* Index */ +uint16_t g_usb_pstd_req_length; /* Length */ + +uint32_t g_usb_pstd_data_cnt[USB_MAXPIPE_NUM + 1u]; +uint8_t *gp_usb_pstd_data[USB_MAXPIPE_NUM + 1u]; +uint16_t g_usb_pstd_remote_wakeup = USB_FALSE; +uint16_t g_usb_pstd_test_mode_flag = USB_FALSE; /* Test mode flag */ +uint16_t g_usb_pstd_test_mode_select; + +int bytesread = 0; + +struct usb_utr +{ + uint16_t keyword; /* Root port / Device address / Pipe number */ + uint8_t *p_tranadr; /* Transfer data Start address */ + uint32_t tranlen; /* Transfer data length */ +}; + +struct usb_utr *g_p_usb_pstd_pipe[USB_MAXPIPE_NUM + 1u]; +struct usb_utr g_usb_pdata[USB_MAXPIPE_NUM + 1]; +uint16_t g_usb_pstd_stall_pipe[USB_MAX_PIPE_NO + 1u]; +uint8_t g_buffer[64] ; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register operations */ + +# define rx65n_getreg8(addr) getreg8(addr) +# define rx65n_getreg16(addr) getreg16(addr) +# define rx65n_getreg32(addr) getreg32(addr) +# define rx65n_putreg8(val,addr) putreg8(val,addr) +# define rx65n_putreg16(val,addr) putreg16(val,addr) +# define rx65n_putreg32(val,addr) putreg32(val,addr) + +#define rx65n_usbdev_givesem(s) nxsem_post(s); + +/* Request queue operations *************************************************/ + +FAR struct rx65n_req_s *rx65n_rqdequeue(FAR struct rx65n_ep_s + *privep); +static void rx65n_rqenqueue(FAR struct rx65n_ep_s *privep, FAR struct + rx65n_req_s *req); + +/* Low level data transfers and request operations */ + +static void rx65n_epwrite(uint8_t epno, struct rx65n_usbdev_s *priv, + struct rx65n_ep_s *privep, + uint8_t *buf, uint32_t nbytes); +static int rx65n_epread(uint8_t epno, struct rx65n_usbdev_s *priv, + uint8_t *buf, + uint16_t nbytes); +static inline void rx65n_abortrequest(struct rx65n_ep_s *privep, + struct rx65n_req_s *privreq, int16_t result); +static void rx65n_reqcomplete(struct rx65n_ep_s *privep, int16_t result); +static int rx65n_wrrequest(uint8_t epno, struct rx65n_usbdev_s *priv, + struct rx65n_ep_s *privep); +static int rx65n_rdrequest(uint8_t epno, struct rx65n_usbdev_s *priv, + struct rx65n_ep_s *privep); + +/* Interrupt handling */ + +static void rx65n_dispatchrequest(struct rx65n_usbdev_s *priv); +void rx65n_ep0setup(struct rx65n_usbdev_s *priv); +static int rx65n_usbinterrupt(int irq, FAR void *context, FAR void *arg); + +/* Endpoint methods */ + +static int rx65n_epconfigure(FAR struct usbdev_ep_s *ep, + const struct usb_epdesc_s *desc, bool last); +static int rx65n_epdisable(FAR struct usbdev_ep_s *ep); +static FAR struct usbdev_req_s *rx65n_epallocreq(FAR struct usbdev_ep_s *ep); +static void rx65n_epfreereq(FAR struct usbdev_ep_s *ep, + FAR struct usbdev_req_s *req); +static int rx65n_epsubmit(FAR struct usbdev_ep_s *ep, + struct usbdev_req_s + *privreq); +static int rx65n_epcancel(FAR struct usbdev_ep_s *ep, + struct usbdev_req_s + *privreq); +static void rx65n_cancelrequests(struct rx65n_ep_s *privep); + +/* USB device controller methods */ + +static struct usbdev_ep_s *rx65n_allocep(struct usbdev_s *dev, + uint8_t epno, bool in, + uint8_t eptype); +static void rx65n_freeep(FAR struct usbdev_s *dev, FAR struct + usbdev_ep_s *ep); +static int rx65n_getframe(struct usbdev_s *dev); +static int rx65n_wakeup(struct usbdev_s *dev); +static int rx65n_selfpowered(struct usbdev_s *dev, bool selfpowered); +int rx65n_pullup(struct usbdev_s *dev, bool enable); + +/* Interrupt Handler */ + +static int rx65n_usbinterrupt(int irq, FAR void *context, FAR void *arg); + +/* USB Helper Functions */ + +void usb_pstd_attach_process (void); +uint16_t usb_pstd_chk_vbsts (void); +void hw_usb_pclear_dprpu(void); +static void hw_usb_clear_aclrm (uint16_t pipeno); +static void hw_usb_set_aclrm (uint16_t pipeno); +static void usb_cstd_do_aclrm (uint16_t pipe); +static void hw_usb_set_curpipe (uint16_t pipemode, uint16_t pipeno); +static void hw_usb_rmw_fifosel (uint16_t pipemode, + uint16_t data, uint16_t bitptn); +static void usb_cstd_chg_curpipe (uint16_t pipe, + uint16_t fifosel, uint16_t isel); +static void *hw_usb_get_fifosel_adr (uint16_t pipemode); +static uint16_t hw_usb_read_fifosel (uint16_t pipemode); +static void hw_usb_set_trclr (uint16_t pipeno); +static void hw_usb_clear_trenb (uint16_t pipeno); +static void hw_usb_clear_bempenb (uint16_t pipeno); +static void hw_usb_clear_nrdyenb (uint16_t pipeno); +static void hw_usb_clear_brdyenb (uint16_t pipeno); +static uint16_t hw_usb_read_pipectr (uint16_t pipeno); +static void hw_usb_clear_pid (uint16_t pipeno, uint16_t data); +static void usb_cstd_set_nak (uint16_t pipe); +void usb_pstd_forced_termination(uint16_t pipe, uint16_t status); +void usb_pstd_detach_process (void); +static void usb_cstd_clr_stall (uint16_t pipe); +static void hw_usb_write_pipesel (uint16_t data); +static void hw_usb_write_pipecfg (uint16_t data); +static void hw_usb_write_pipemaxp (uint16_t data); +static void hw_usb_write_pipeperi (uint16_t data); +static void hw_usb_set_sqclr (uint16_t pipeno); +static void hw_usb_clear_sts_brdy (uint16_t pipeno); +static void hw_usb_clear_status_nrdy (uint16_t pipeno); +static void hw_usb_clear_status_bemp (uint16_t pipeno); +void usb_pstd_bus_reset (void); +void usb_pstd_suspend_process (void); +uint16_t usb_cstd_port_speed (void); +static void hw_usb_write_dcpcfg (uint16_t data); +static uint16_t hw_usb_read_dvstctr (void); +static int hw_usb_read_syssts (void); +void usb_pstd_save_request(void); +static void hw_usb_set_pid (uint16_t pipeno, uint16_t data); +static void hw_usb_set_mbw (uint16_t pipemode, uint16_t data); +static uint16_t hw_usb_read_dcpmaxp (void); +static uint16_t hw_usb_read_pipemaxp (void); +static void hw_usb_write_dcpmxps (uint16_t data); +uint16_t usb_pstd_pipe2fport(uint16_t pipe); +static uint16_t usb_cstd_get_pid (uint16_t pipe); +static void usb_cstd_clr_transaction_counter (uint16_t trnreg); +static uint16_t hw_usb_read_pipecfg (void); +void usb_pstd_set_stall(uint16_t pipe); +static uint16_t hw_usb_read_frmnum (void); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Endpoint methods */ + +static const struct usbdev_epops_s g_epops = +{ + .configure = rx65n_epconfigure, + .disable = rx65n_epdisable, + .allocreq = rx65n_epallocreq, + .freereq = rx65n_epfreereq, +#ifdef CONFIG_USBDEV_DMA + .allocbuffer = rx65n_epallocbuffer, + .freebuffer = rx65n_epfreebuffer, +#endif + .submit = rx65n_epsubmit, + .cancel = rx65n_epcancel, +}; + +/* USB controller device methods */ + +static const struct usbdev_ops_s g_devops = +{ + .allocep = rx65n_allocep, + .freeep = rx65n_freeep, + .getframe = rx65n_getframe, + .wakeup = rx65n_wakeup, + .selfpowered = rx65n_selfpowered, + .pullup = rx65n_pullup, +}; + +enum rx65n_ep0state_e +{ + EP0STATE_WRREQUEST = 0, /* Write request in progress */ + EP0STATE_RDREQUEST, /* Read request in progress */ + EP0STATE_STALLED +}; + +/* There is only one, single, pre-allocated instance + * of the driver structure + */ + +struct rx65n_usbdev_s g_usbdev; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rx65n_rqdequeue + * + * Description: + * Remove a request from an endpoint request queue + * + ****************************************************************************/ + +FAR struct rx65n_req_s *rx65n_rqdequeue(FAR struct rx65n_ep_s *privep) +{ + struct rx65n_req_s *ret = privep->head; + + if (ret) + { + privep->head = ret->flink; + if (!privep->head) + { + privep->tail = NULL; + } + + ret->flink = NULL; + } + + return ret; +} + +/**************************************************************************** + * Name: rx65n_rqenqueue + * + * Description: + * Add a request from an endpoint request queue + * + ****************************************************************************/ + +static void rx65n_rqenqueue(FAR struct rx65n_ep_s *privep, + FAR struct rx65n_req_s *req) +{ + req->flink = NULL; + if (!privep->head) + { + privep->head = req; + privep->tail = req; + } + else + { + privep->tail->flink = req; + privep->tail = req; + } +} + +/**************************************************************************** + * Name: hw_usb_get_fifoctr_adr + * + * Description: + * Get FIFOCTR Address + * + ****************************************************************************/ + +static void *hw_usb_get_fifoctr_adr (uint16_t pipemode) +{ + void *p_reg = NULL; + + switch (pipemode) + { + case USB_CUSE: + p_reg = (void *)RX65N_USB_CFIFOCTR; + break; + + case USB_D0USE: + p_reg = (void *)RX65N_USB_D0FIFOCTR; + break; + + case USB_D1USE: + p_reg = (void *)RX65N_USB_D1FIFOCTR; + break; + + default: + break; + } + + return p_reg; +} + +/**************************************************************************** + * Name: hw_usb_set_mbw + * + * Description: + * Set MBW bit + * + ****************************************************************************/ + +static void hw_usb_set_mbw (uint16_t pipemode, uint16_t data) +{ + uint16_t *p_reg; + + p_reg = hw_usb_get_fifosel_adr(pipemode); + + (*p_reg) &= (~USB_MBW); + if (0 != data) + { + (*p_reg) |= data; + } +} + +/**************************************************************************** + * Name: hw_usb_set_bclr + * + * Description: + * Set BCLR bit + * + ****************************************************************************/ + +static void hw_usb_set_bclr (uint16_t pipemode) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *) hw_usb_get_fifoctr_adr(pipemode); + + *p_reg = USB_BCLR; +} + +/**************************************************************************** + * Name: hw_usb_read_fifoctr + * + * Description: + * Read FIFOCTR Register + * + ****************************************************************************/ + +static uint16_t hw_usb_read_fifoctr (uint16_t pipemode) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *) hw_usb_get_fifoctr_adr(pipemode); + + return *p_reg; +} + +/**************************************************************************** + * Name: hw_usb_read_syscfg + * + * Description: + * Set Read SYSCFG Register + * + ****************************************************************************/ + +static uint16_t hw_usb_read_syscfg (void) +{ + return (rx65n_getreg16(RX65N_USB_SYSCFG)); +} + +/**************************************************************************** + * Name: usb_cstd_is_set_frdy + * + * Description: + * Set FRDY bit + * + ****************************************************************************/ + +static uint16_t usb_cstd_is_set_frdy (uint16_t pipe, uint16_t fifosel, + uint16_t isel) +{ + uint16_t buf; + uint16_t i; + + /* Changes the FIFO port by the pipe. */ + + usb_cstd_chg_curpipe(pipe, fifosel, isel); + + /* WAIT_LOOP */ + + for (i = 0; i < 4; i++) + { + buf = hw_usb_read_fifoctr(fifosel); + + if (USB_FRDY == (uint16_t) (buf & USB_FRDY)) + { + return (buf); + } + + buf = hw_usb_read_syscfg(); + buf = hw_usb_read_syssts(); + } + + return (USB_ERROR); +} + +/**************************************************************************** + * Name: hw_usb_read_dcpmaxp + * + * Description: + * Read DCPMAXP Register + * + ****************************************************************************/ + +static uint16_t hw_usb_read_dcpmaxp () +{ + return rx65n_getreg16(RX65N_USB_DCPMAXP); +} + +/**************************************************************************** + * Name: hw_usb_read_pipemaxp + * + * Description: + * Read PIPEMAXP Register + * + ****************************************************************************/ + +static uint16_t hw_usb_read_pipemaxp () +{ + return rx65n_getreg16(RX65N_USB_PIPEMAXP); +} + +/**************************************************************************** + * Name: usb_cstd_get_buf_size + * + * Description: + * Get buf size + * + ****************************************************************************/ + +static uint16_t usb_cstd_get_buf_size (uint16_t pipe) +{ + uint16_t size; + uint16_t buf; + + if (USB_PIPE0 == pipe) + { + buf = hw_usb_read_dcpmaxp(); + + /* Max Packet Size */ + + size = (uint16_t) (buf & USB_MAXP); + } + else + { + /* Pipe select */ + + hw_usb_write_pipesel(pipe); + buf = hw_usb_read_pipemaxp(); + + /* Max Packet Size */ + + size = (uint16_t) (buf & USB_MXPS); + } + + return size; +} + +/**************************************************************************** + * Name: usb_cstd_get_maxpacket_size + * + * Description: + * Get maxpacket size + * + ****************************************************************************/ + +static uint16_t usb_cstd_get_maxpacket_size (uint16_t pipe) +{ + uint16_t size; + uint16_t buf; + + if (USB_MAXPIPE_NUM < pipe) + { + return USB_NULL; /* Error */ + } + + if (USB_PIPE0 == pipe) + { + buf = hw_usb_read_dcpmaxp(); + } + else + { + /* Pipe select */ + + hw_usb_write_pipesel(pipe); + buf = hw_usb_read_pipemaxp(); + } + + /* Max Packet Size */ + + size = (uint16_t) (buf & USB_MXPS); + + return size; +} + +/**************************************************************************** + * Name: hw_usb_write_fifo16 + * + * Description: + * Write FIFO16 + * + ****************************************************************************/ + +static void hw_usb_write_fifo16 (uint16_t pipemode, uint16_t data) +{ + switch (pipemode) + { + case USB_CUSE : + USB0_CFIFO16 = data; + break; + case USB_D0USE : + USB0_D0FIFO16 = data; + break; + case USB_D1USE : + USB0_D1FIFO16 = data; + break; + default : + break; + } +} + +/**************************************************************************** + * Name: hw_usb_write_fifo8 + * + * Description: + * Write to FIFO8 + * + ****************************************************************************/ + +static void hw_usb_write_fifo8 (uint16_t pipemode, uint8_t data) +{ + switch (pipemode) + { + case USB_CUSE : + USB0_CFIFO8 = data; + break; + case USB_D0USE : + USB0_D0FIFO8 = data; + break; + case USB_D1USE : + USB0_D1FIFO8 = data; + break; + default : + break; + } +} + +/**************************************************************************** + * Name: usb_pstd_write_fifo + * + * Description: + * Write to FIFO + * + ****************************************************************************/ + +uint8_t *usb_pstd_write_fifo(uint16_t count, uint16_t pipemode, + uint8_t *write_p) +{ + uint16_t even; + + /* WAIT_LOOP */ + + for (even = (uint16_t)(count >> 1); (0 != even); --even) + { + /* 16bit access */ + + hw_usb_write_fifo16(pipemode, *((uint16_t *)write_p)); + + /* Renewal write pointer */ + + write_p += sizeof(uint16_t); + } + + if ((count & (uint16_t)0x0001u) != 0u) + { + /* 8bit access */ + + /* count == odd */ + + /* Change FIFO access width */ + + hw_usb_set_mbw(pipemode, USB_MBW_8); + + /* FIFO write */ + + hw_usb_write_fifo8(pipemode, *write_p); + + /* Return FIFO access width */ + + hw_usb_set_mbw(pipemode, USB_MBW_16); + + /* Renewal write pointer */ + + write_p++; + } + + return write_p; +} + +/**************************************************************************** + * Name: hw_usb_set_bval + * + * Description: + * Set BVAL + * + ****************************************************************************/ + +static void hw_usb_set_bval (uint16_t pipemode) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *) hw_usb_get_fifoctr_adr(pipemode); + + (*p_reg) |= USB_BVAL; +} + +/**************************************************************************** + * Name: usb_pstd_write_data + * + * Description: + * Write Data + * + ****************************************************************************/ + +uint16_t usb_pstd_write_data(uint16_t pipe, uint16_t pipemode) +{ + uint16_t size; + uint16_t count; + uint16_t buf; + uint16_t mxps; + uint16_t end_flag; + + if (USB_MAXPIPE_NUM < pipe) + { + return USB_ERROR; /* Error */ + } + + /* Changes FIFO port by the pipe. */ + + if ((USB_CUSE == pipemode) && (USB_PIPE0 == pipe)) + { + buf = usb_cstd_is_set_frdy(pipe, (uint16_t)USB_CUSE, + (uint16_t)USB_ISEL); + } + else + { + buf = usb_cstd_is_set_frdy(pipe, (uint16_t)pipemode, USB_FALSE); + } + + /* Check error */ + + if (USB_ERROR == buf) + { + /* FIFO access error */ + + buf = usb_cstd_is_set_frdy(pipe, (uint16_t)pipemode, USB_FALSE); + } + + /* Data buffer size */ + + size = usb_cstd_get_buf_size(pipe); + + /* Max Packet Size */ + + mxps = usb_cstd_get_maxpacket_size(pipe); + + if (g_usb_pstd_data_cnt[pipe] <= (uint32_t)size) + { + count = (uint16_t)g_usb_pstd_data_cnt[pipe]; + + /* Data count check */ + + if (0 == count) + { + /* Null Packet is end of write */ + + end_flag = USB_WRITESHRT; + } + + else if (0 != (count % mxps)) + { + /* Short Packet is end of write */ + + end_flag = USB_WRITESHRT; + } + + else + { + if (USB_PIPE0 == pipe) + { + /* Just Send Size */ + + end_flag = USB_WRITING; + } + else + { + /* Write continues */ + + end_flag = USB_WRITEEND; + } + } + } + else + { + /* Write continues */ + + end_flag = USB_WRITING; + count = size; + } + + gp_usb_pstd_data[pipe] = usb_pstd_write_fifo(count, pipemode, + gp_usb_pstd_data[pipe]); + + /* Check data count to remain */ + + if (g_usb_pstd_data_cnt[pipe] < (uint32_t)size) + { + /* Clear data count */ + + g_usb_pstd_data_cnt[pipe] = (uint32_t)0u; + + /* Read CFIFOCTR */ + + buf = hw_usb_read_fifoctr(pipemode); + + /* Check BVAL */ + + if (0u == (buf & USB_BVAL)) + { + /* Short Packet */ + + hw_usb_set_bval(pipemode); + } + } + else + { + /* Total data count - count */ + + g_usb_pstd_data_cnt[pipe] -= count; + } + + /* End or Err or Continue */ + + return end_flag; +} + +/**************************************************************************** + * Name: hw_usb_set_nrdyenb + * + * Description: + * Set NRDYENB + * + ****************************************************************************/ + +static void hw_usb_set_nrdyenb (uint16_t pipeno) +{ + uint16_t regval; + regval = rx65n_getreg16(RX65N_USB_NRDYENB); + regval |= (1 << pipeno); + rx65n_putreg16(regval, RX65N_USB_NRDYENB); +} + +/**************************************************************************** + * Name: usb_cstd_nrdy_enable + * + * Description: + * NRDY Enable + * + ****************************************************************************/ + +static void usb_cstd_nrdy_enable (uint16_t pipe) +{ + if (USB_MAXPIPE_NUM < pipe) + { + return; /* Error */ + } + + /* Enable NRDY */ + + hw_usb_set_nrdyenb(pipe); +} + +/**************************************************************************** + * Name: usb_cstd_set_buf + * + * Description: + * Set Buf + * + ****************************************************************************/ + +static void usb_cstd_set_buf (uint16_t pipe) +{ + if (USB_MAXPIPE_NUM < pipe) + { + return; /* Error */ + } + + /* PIPE control reg set */ + + hw_usb_set_pid(pipe, USB_PID_BUF); +} + +/**************************************************************************** + * Name: hw_usb_set_bempenb + * + * Description: + * Set BEMPENB + * + ****************************************************************************/ + +static void hw_usb_set_bempenb (uint16_t pipeno) +{ + uint16_t regval; + regval = rx65n_getreg16(RX65N_USB_BEMPENB); + regval |= (1 << pipeno); + rx65n_putreg16(regval, RX65N_USB_BEMPENB); +} + +/**************************************************************************** + * Name: hw_usb_set_brdyenb + * + * Description: + * Set BRDYENB + * + ****************************************************************************/ + +static void hw_usb_set_brdyenb (uint16_t pipeno) +{ + uint16_t regval; + regval = rx65n_getreg16(RX65N_USB_BRDYENB); + regval |= (1 << pipeno); + rx65n_putreg16(regval, RX65N_USB_BRDYENB); +} + +/**************************************************************************** + * Name: usb_pstd_ctrl_write + * + * Description: + * CTRL Write + * + ****************************************************************************/ + +void usb_pstd_ctrl_write (uint32_t bsize, uint8_t *table) +{ + g_usb_pstd_data_cnt[USB_PIPE0] = bsize; + gp_usb_pstd_data[USB_PIPE0] = table; + + usb_cstd_chg_curpipe((uint16_t) USB_PIPE0, + (uint16_t) USB_CUSE, USB_FALSE); + + /* Buffer clear */ + + hw_usb_set_bclr(USB_CUSE); + + /* Interrupt enable */ + + /* Enable ready interrupt */ + + hw_usb_set_brdyenb((uint16_t) USB_PIPE0); + + /* Enable not ready interrupt */ + + usb_cstd_nrdy_enable((uint16_t) USB_PIPE0); + + /* Set PID=BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); +} + +/**************************************************************************** + * Name: usb_ctrl_read + * + * Description: + * CTRL Read + * + ****************************************************************************/ + +uint16_t usb_ctrl_read (uint32_t bsize, uint8_t *table) +{ + usb_pstd_ctrl_write(bsize, table); + return OK; +} + +/**************************************************************************** + * Name: usb_pstd_ctrl_read + * + * Description: + * CTRL Read invoked from class driver + * + ****************************************************************************/ + +uint16_t usb_pstd_ctrl_read (uint32_t bsize, uint8_t *table) +{ + uint16_t end_flag; + g_usb_pstd_data_cnt[USB_PIPE0] = bsize; + gp_usb_pstd_data[USB_PIPE0] = table; + usb_cstd_chg_curpipe((uint16_t) USB_PIPE0, (uint16_t) USB_CUSE, + (uint16_t) USB_ISEL); + + /* Buffer clear */ + + hw_usb_set_bclr(USB_CUSE); + + hw_usb_clear_status_bemp(USB_PIPE0); + + /* Peripheral Control sequence */ + + end_flag = usb_pstd_write_data(USB_PIPE0, USB_CUSE); + + /* Peripheral control sequence */ + + switch (end_flag) + { + /* End of data write */ + + case USB_WRITESHRT : + + /* Enable not ready interrupt */ + + usb_cstd_nrdy_enable((uint16_t) USB_PIPE0); + + /* Set PID=BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + break; + + /* End of data write (not null) */ + + case USB_WRITEEND : + + /* Continue */ + + /* Continue of data write */ + + case USB_WRITING : + + /* Enable empty interrupt */ + + hw_usb_set_bempenb((uint16_t) USB_PIPE0); + + /* Enable not ready interrupt */ + + usb_cstd_nrdy_enable((uint16_t) USB_PIPE0); + + /* Set PID=BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + break; + + /* FIFO access error */ + + case USB_ERROR : + break; + default : + break; + } + + return (end_flag); /* End or error or continue */ +} + +/**************************************************************************** + * Name: usb_pstd_buf_to_fifo + * + * Description: + * Buf to FIFO data write + * + ****************************************************************************/ + +void usb_pstd_buf_to_fifo(uint16_t pipe, uint16_t useport) +{ + uint16_t end_flag; + + if (USB_MAXPIPE_NUM < pipe) + { + return; /* Error */ + } + + /* Disable Ready Interrupt */ + + hw_usb_clear_brdyenb(pipe); + hw_usb_clear_bempenb(pipe); + + end_flag = usb_pstd_write_data(pipe, useport); + + /* Check FIFO access sequence */ + + switch (end_flag) + { + case USB_WRITING: + + /* Continue of data write */ + + /* Enable Ready Interrupt */ + + hw_usb_set_brdyenb(pipe); + + /* Enable Not Ready Interrupt */ + + usb_cstd_nrdy_enable(pipe); + break; + + case USB_WRITEEND: + + /* End of data write */ + + /* continue */ + + case USB_WRITESHRT: + + /* End of data write */ + + /* Enable Empty Interrupt */ + + hw_usb_set_bempenb(pipe); + + /* Enable Not Ready Interrupt */ + + usb_cstd_nrdy_enable(pipe); + break; + + case USB_ERROR: + + /* FIFO access error */ + + usb_pstd_forced_termination(pipe, (uint16_t)USB_DATA_ERR); + break; + + default: + usb_pstd_forced_termination(pipe, (uint16_t)USB_DATA_ERR); + break; + } +} + +/**************************************************************************** + * Name: usb_pstd_data_end + * + * Description: + * Data End transfer + * + ****************************************************************************/ + +void usb_pstd_data_end(uint16_t pipe, uint16_t status) +{ + uint16_t useport; + + if (USB_MAXPIPE_NUM < pipe) + { + return; /* Error */ + } + + /* PID = NAK */ + + /* Set NAK */ + + usb_cstd_set_nak(pipe); + + /* Pipe number to FIFO port select */ + + useport = USB_CUSE; + + /* Disable Interrupt */ + + /* Disable Ready Interrupt */ + + hw_usb_clear_brdyenb(pipe); + + /* Disable Not Ready Interrupt */ + + hw_usb_clear_nrdyenb(pipe); + + /* Disable Empty Interrupt */ + + hw_usb_clear_bempenb(pipe); + + /* Disable Transaction count */ + + usb_cstd_clr_transaction_counter(pipe); + + /* Check use FIFO */ + + switch (useport) + { + /* CFIFO use */ + + case USB_CUSE: + break; + + default: + break; + } +} + +/**************************************************************************** + * Name: usb_pstd_send_start + * + * Description: + * Send start + * + ****************************************************************************/ + +void usb_pstd_send_start(uint16_t pipe, uint8_t *buf, uint32_t size) +{ + uint16_t useport; + + /* Select NAK */ + + usb_cstd_set_nak(pipe); + + /* Set data count */ + + g_usb_pstd_data_cnt[pipe] = size; + + /* Set data pointer */ + + gp_usb_pstd_data[pipe] = buf; + + /* BEMP Status Clear */ + + hw_usb_clear_status_bemp(pipe); + + /* BRDY Status Clear */ + + hw_usb_clear_sts_brdy(pipe); + + /* Pipe number to FIFO port select */ + + useport = USB_CUSE; + + usb_cstd_chg_curpipe(pipe, useport, USB_FALSE); + + /* Buffer to FIFO data write */ + + usb_pstd_buf_to_fifo(pipe, useport); + + /* Set BUF */ + + usb_cstd_set_buf(pipe); +} + +/**************************************************************************** + * Name: hw_usb_read_pipecfg + * + * Description: + * Read Pipecfg + * + ****************************************************************************/ + +static uint16_t hw_usb_read_pipecfg () +{ + return rx65n_getreg16(RX65N_USB_PIPECFG); +} + +/**************************************************************************** + * Name: usb_cstd_get_pipe_dir + * + * Description: + * Get pipe direction + * + ****************************************************************************/ + +static uint16_t usb_cstd_get_pipe_dir (uint16_t pipe) +{ + uint16_t buf; + + if (USB_MAXPIPE_NUM < pipe) + { + return USB_NULL; /* Error */ + } + + /* Pipe select */ + + hw_usb_write_pipesel(pipe); + + /* Read Pipe direction */ + + buf = hw_usb_read_pipecfg(); + return (uint16_t) (buf & USB_DIRFIELD); +} + +/**************************************************************************** + * Name: usb_cstd_get_pipe_type + * + * Description: + * Get pipe type + * + ****************************************************************************/ + +static uint16_t usb_cstd_get_pipe_type (uint16_t pipe) +{ + uint16_t buf; + + if (USB_MAXPIPE_NUM < pipe) + { + return USB_NULL; /* Error */ + } + + /* Pipe select */ + + hw_usb_write_pipesel(pipe); + + /* Read Pipe direction */ + + buf = hw_usb_read_pipecfg(); + return (uint16_t) (buf & USB_TYPFIELD); +} + +/**************************************************************************** + * Name: usb_pstd_chk_configured + * + * Description: + * Check Configured + * + ****************************************************************************/ + +uint16_t usb_pstd_chk_configured(void) +{ + uint16_t buf; + + buf = rx65n_getreg16(RX65N_USB_INTSTS0); + + /* Device Status - Configured check */ + + if (USB_DS_CNFG == (buf & USB_DVSQ)) + { + /* Configured */ + + return USB_TRUE; + } + else + { + /* not Configured */ + + return USB_FALSE; + } +} + +/**************************************************************************** + * Name: hw_usb_set_trenb + * + * Description: + * Set TRENB + * + ****************************************************************************/ + +static void hw_usb_set_trenb (uint16_t pipeno) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *)RX65N_USB_PIPE1TRE + ((pipeno - 1) * 2); + + (*p_reg) |= USB_TRENB; +} + +/**************************************************************************** + * Name: hw_usb_write_pipetrn + * + * Description: + * Write to PIPETRN + * + ****************************************************************************/ + +static void hw_usb_write_pipetrn (uint16_t pipeno, uint16_t data) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *)RX65N_USB_PIPE1TRN + ((pipeno - 1) * 2); + + *p_reg = data; +} + +/**************************************************************************** + * Name: usb_cstd_set_transaction_counter + * + * Description: + * Set transaction counter + * + ****************************************************************************/ + +static void usb_cstd_set_transaction_counter (uint16_t trnreg, + uint16_t trncnt) +{ + hw_usb_set_trclr(trnreg); + hw_usb_write_pipetrn(trnreg, trncnt); + hw_usb_set_trenb(trnreg); +} + +/**************************************************************************** + * Name: usb_pstd_receive_start + * + * Description: + * Receive start + * + ****************************************************************************/ + +void usb_pstd_receive_start(uint16_t pipe) +{ + struct usb_utr *pp; + uint32_t length; + uint16_t mxps; + uint16_t useport; + + /* Evacuation pointer */ + + pp = g_p_usb_pstd_pipe[pipe]; + length = pp->tranlen; + + /* Select NAK */ + + usb_cstd_set_nak(pipe); + + /* Set data pointer */ + + gp_usb_pstd_data[pipe] = (uint8_t *)pp->p_tranadr; + + /* Pipe number to FIFO port select */ + + useport = USB_CUSE; + + /* Check use FIFO access */ + + switch (useport) + { + /* CFIFO use */ + + case USB_CUSE: + + /* Changes the FIFO port by the pipe. */ + + usb_cstd_chg_curpipe(pipe, useport, USB_FALSE); + + /* Max Packet Size */ + + mxps = usb_cstd_get_maxpacket_size(pipe); + if ((uint32_t)0u != length) + { + /* Data length check */ + + if ((uint32_t)0u == (length % mxps)) + { + /* Set Transaction counter */ + + usb_cstd_set_transaction_counter(pipe, (uint16_t)(length / + mxps)); + } + else + { + /* Set Transaction counter */ + + usb_cstd_set_transaction_counter(pipe, (uint16_t)((length + / mxps) + (uint32_t)1u)); + } + } + + /* Set BUF */ + + usb_cstd_set_buf(pipe); + + /* Enable Ready Interrupt */ + + hw_usb_set_brdyenb(pipe); + + /* Enable Not Ready Interrupt */ + + usb_cstd_nrdy_enable(pipe); + break; + + default: + usb_pstd_forced_termination(pipe, (uint16_t)USB_DATA_ERR); + break; + } +} + +/**************************************************************************** + * Name: usb_pstd_set_submitutr + * + * Description: + * Set Submit Request + * + ****************************************************************************/ + +void usb_pstd_set_submitutr (struct usb_utr *utrmsg) +{ + uint16_t pipenum; + + pipenum = utrmsg->keyword; + g_p_usb_pstd_pipe[pipenum] = utrmsg; + + /* Check state (Configured) */ + + if (USB_TRUE == usb_pstd_chk_configured()) + { + if (USB_DIR_P_OUT == usb_cstd_get_pipe_dir(pipenum)) + { + usb_pstd_receive_start(pipenum); /* Out transfer */ + } + else + { + /* In transfer */ + + usb_pstd_send_start(pipenum, NULL, 0); + } + } +} + +/**************************************************************************** + * Name: usb_pstd_transfer_start + * + * Description: + * Transfer start + * + ****************************************************************************/ + +uint8_t usb_pstd_transfer_start(struct usb_utr *ptr) +{ + usb_pstd_set_submitutr(ptr); + return OK; +} + +/**************************************************************************** + * Name: usb_data_write + * + * Description: + * Data write + * + ****************************************************************************/ + +long usb_data_write (uint8_t epno, uint8_t *buf, uint32_t size) +{ + uint8_t pipe; + if (epno == BULK_IN_EPNUM) + { + pipe = BULK_IN_PIPE; + } + + if (epno == INT_IN_EPNUM) + { + pipe = INT_IN_PIPE; + } + + if (USB_TRUE == usb_pstd_chk_configured()) + { + if (USB_DIR_P_OUT == usb_cstd_get_pipe_dir(pipe)) + { + usb_pstd_receive_start(pipe); /* Out transfer */ + } + else + { + /* In transfer */ + + usb_pstd_send_start(pipe, buf, size); + } + } + + return OK; +} + +/**************************************************************************** + * Name: usb_data_read + * + * Description: + * Data read + * + ****************************************************************************/ + +void usb_data_read(uint8_t *buf, uint32_t size) +{ + uint8_t pipe = BULK_OUT_PIPE; + struct usb_utr *p_tran_data; + memset((void *)&g_usb_pdata, 0, ((USB_MAXPIPE_NUM + 1) * + sizeof(struct usb_utr))); + p_tran_data = (struct usb_utr *)&g_usb_pdata[pipe]; + p_tran_data->p_tranadr = buf; /* Data address */ + p_tran_data->tranlen = size; /* Data Size */ + p_tran_data->keyword = pipe; + usb_pstd_transfer_start(p_tran_data); +} + +/**************************************************************************** + * Name: rx65n_epwrite + * + * Description: + * Endpoint write (IN) + * + ****************************************************************************/ + +static void rx65n_epwrite(uint8_t epno, struct rx65n_usbdev_s *priv, + struct rx65n_ep_s *privep, + uint8_t *buf, uint32_t nbytes) +{ + uint8_t type; + uint8_t g_buf[RX65N_USB_MAXP]; + type = MSBYTE(rx65n_getreg16(RX65N_USB_USBREQ)); + + if (epno == 0) + { + if ((type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) + { + if (type == ACM_GET_LINE_CODING) + { + usb_pstd_ctrl_read(nbytes, buf); + usb_cstd_set_buf((uint16_t) USB_PIPE0); + usb_data_read(g_buf, RX65N_USB_MAXP); + } + else + { + usb_pstd_ctrl_read(nbytes, buf); + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + } + else + { + usb_pstd_ctrl_read(nbytes, buf); + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + } + + if (epno > 0) + { + usb_data_write(epno, buf, nbytes); + } +} + +/**************************************************************************** + * Name: rx65n_epread + * + * Description: + * Endpoint read (OUT) + * + ****************************************************************************/ + +static int rx65n_epread(uint8_t epno, struct rx65n_usbdev_s *priv, + uint8_t *buf, uint16_t nbytes) +{ + if (epno == EP0) + { + usb_ctrl_read(CDC_CLASS_DATA_LENGTH, buf); + } + else + { + usb_data_read(buf, nbytes); + if (bytesread != 0) + { + return bytesread; + } + } + + return OK; +} + +/**************************************************************************** + * Name: rx65n_abortrequest + * + * Description: + * Discard a request + * + ****************************************************************************/ + +static inline void rx65n_abortrequest(struct rx65n_ep_s *privep, + struct rx65n_req_s *privreq, + int16_t result) +{ + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_REQABORTED), + (uint16_t)USB_EPNO(privep->ep.eplog)); + + /* Save the result in the request structure */ + + privreq->req.result = result; + + /* Callback to the request completion handler */ + + privreq->req.callback(&privep->ep, &privreq->req); +} + +/**************************************************************************** + * Name: rx65n_reqcomplete + * + * Description: + * Handle termination of a request. + * + ****************************************************************************/ + +static void rx65n_reqcomplete(struct rx65n_ep_s *privep, int16_t result) +{ + struct rx65n_req_s *privreq; + irqstate_t flags; + + /* Remove the completed request at the head of the endpoint request list */ + + flags = enter_critical_section(); + privreq = rx65n_rqdequeue(privep); + leave_critical_section(flags); + + if (privreq) + { + /* If endpoint 0, temporarily reflect the state of protocol stalled + * in the callback. + */ + + bool stalled = privep->stalled; + if (USB_EPNO(privep->ep.eplog) == EP0) + { + privep->stalled = privep->dev->stalled; + } + + /* Save the result in the request structure */ + + privreq->req.result = result; + + /* Callback to the request completion handler */ + + privreq->flink = NULL; + privreq->req.callback(&privep->ep, &privreq->req); + + /* Restore the stalled indication */ + + privep->stalled = stalled; + } +} + +/**************************************************************************** + * Name: rx65n_wrrequest + * + * Description: + * Send from the next queued write request + * + * Returned Value: + * 0:not finished; 1:completed; <0:error + * + ****************************************************************************/ + +static int rx65n_wrrequest(uint8_t epno, struct rx65n_usbdev_s *priv, + struct rx65n_ep_s *privep) +{ + struct rx65n_req_s *privreq; + uint8_t *buf = NULL; + int nbytes; + int bytesleft; + + /* We get here when an IN endpoint interrupt occurs. So now we know that + * there is no TX transfer in progress. + */ + + privep->txbusy = false; + + /* Check the request from the head of the endpoint request queue */ + + privreq = rx65n_rqpeek(privep); + if (!privreq) + { + /* There is no TX transfer in progress and no new pending TX + * requests to send. + */ + + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_EPINQEMPTY), 0); + return -ENOENT; + } + + epno = USB_EPNO(privep->ep.eplog); + uinfo("epno=%d req=%p: len=%d xfrd=%d nullpkt=%d\n", + epno, privreq, privreq->req.len, privreq->req.xfrd, + privep->txnullpkt); + + /* Get the number of bytes left to be sent in the packet */ + + for (; ; ) + { + bytesleft = privreq->req.len - privreq->req.xfrd; + nbytes = bytesleft; + + /* Either (1) we are committed to sending the null packet + * (because txnullpkt == 1 && nbytes == 0), or + * (2) we have not yet send the last packet (nbytes > 0). + * In either case, it is appropriate to clearn txnullpkt now. + */ + + privep->txnullpkt = 0; + + /* If we are not sending a NULL packet, then clip the size + * to maxpacket + * and check if we need to send a following NULL packet. + */ + + if (nbytes > 0) + { + /* Either send the maxpacketsize or all of the + * remaining data in request + */ + + if (nbytes >= privep->ep.maxpacket) + { + nbytes = privep->ep.maxpacket; + + /* Handle the case where this packet is exactly the + * maxpacketsize. Do we need to send a zero-length packet + * in this case? + */ + + if (bytesleft == privep->ep.maxpacket && + (privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0) + { + privep->txnullpkt = 1; + } + } + } + + /* Send the packet (might be a null packet nbytes == 0) */ + + buf = privreq->req.buf + privreq->req.xfrd; + + rx65n_epwrite(epno, priv, privep, buf, nbytes); + + /* Update for the next data IN interrupt */ + + privreq->req.xfrd += nbytes; + bytesleft = privreq->req.len - privreq->req.xfrd; + + /* If all of the bytes were sent (including any final null packet) + * then we are finished with the request buffer). + */ + + if (bytesleft == 0) + { + /* Return the write request to the class driver */ + + usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), + privreq->req.xfrd); + privep->txnullpkt = 0; + rx65n_reqcomplete(privep, OK); + return OK; + } + } + + return OK; +} + +/**************************************************************************** + * Name: rx65n_rdrequest + * + * Description: + * Receive to the next queued read request + * + ****************************************************************************/ + +static int rx65n_rdrequest(uint8_t epno, struct rx65n_usbdev_s *priv, + struct rx65n_ep_s *privep) +{ + struct rx65n_req_s *privreq; + uint8_t *buf; + int nbytesread; + + /* Check the request from the head of the endpoint request queue */ + + privreq = rx65n_rqpeek(privep); + if (!privreq) + { + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_EPOUTQEMPTY), 0); + return OK; + } + + uinfo("len=%d xfrd=%d nullpkt=%d\n", + privreq->req.len, privreq->req.xfrd, privep->txnullpkt); + + usbtrace(TRACE_READ(privep->epphy), privreq->req.xfrd); + + /* Receive the next packet */ + + buf = privreq->req.buf + privreq->req.xfrd; + nbytesread = rx65n_epread(epno, priv, buf, privep->ep.maxpacket); + if (nbytesread < 0) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_EPREAD), nbytesread); + return ERROR; + } + + /* If the receive buffer is full or if the last packet was not full + * then we are finished with the transfer. + */ + + privreq->req.xfrd += nbytesread; + if (privreq->req.xfrd >= privreq->req.len || + nbytesread < privep->ep.maxpacket) + { + usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd); + rx65n_reqcomplete(privep, OK); + } + + return OK; +} + +/**************************************************************************** + * Name: rx65n_dispatchrequest + * + * Description: + * Provide unhandled setup actions to the class driver + * + ****************************************************************************/ + +static void rx65n_dispatchrequest(struct rx65n_usbdev_s *priv) +{ + int ret; + + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_DISPATCH), 0); + if (priv && priv->driver) + { + /* Forward to the control request to the class driver implementation */ + + ret = CLASS_SETUP(priv->driver, &priv->usbdev, &priv->ctrl, + NULL, 0); + if (ret < 0) + { + /* Stall on failure */ + + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_DISPATCHSTALL), 0); + priv->stalled = 1; + } + } +} + +/**************************************************************************** + * Name: usb_pstd_get_current_power + * + * Description: + * Get the power type + * + ****************************************************************************/ + +uint8_t usb_pstd_get_current_power (void) +{ + uint8_t currentpower; + +#ifdef CONFIG_USBDEV_SELFPOWERED + currentpower = USB_GS_SELFPOWERD; +#else + currentpower = USB_GS_BUSPOWERD; +#endif + + return currentpower; +} + +/**************************************************************************** + * Name: usb_pstd_epadr2pipe + * + * Description: + * Get the endpoint addr to pipe number + * + ****************************************************************************/ + +uint16_t usb_pstd_epadr2pipe(uint16_t dir_ep) +{ + uint16_t i; + uint16_t direp; + uint16_t tmp; + + /* Peripheral */ + + /* Get PIPE Number from Endpoint address */ + + direp = (uint16_t)(((dir_ep & 0x80) >> 3) | (dir_ep & 0x0f)); + + /* EP table loop */ + + /* WAIT_LOOP */ + + for (i = USB_MIN_PIPE_NO; i < (USB_MAXPIPE_NUM +1); i++) + { + /* PIPECFG register will be set if PIPESEL register is set first */ + + /* Check if PIPESEL register is set before reading PIPECFG */ + + tmp = (rx65n_getreg16(RX65N_USB_PIPECFG)) & + (USB_DIRFIELD | USB_EPNUMFIELD); + + /* EP table endpoint dir check */ + + if (direp == tmp) + { + return i; + } + } + + return USB_ERROR; +} + +/**************************************************************************** + * Name: hw_usb_read_dcpctr + * + * Description: + * Read DCPCTR register + * + ****************************************************************************/ + +uint16_t hw_usb_read_dcpctr(void) +{ + return rx65n_getreg16(RX65N_USB_DCPCTR); +} + +/**************************************************************************** + * Name: usb_pstd_set_stall_pipe0 + * + * Description: + * Set stall pipe + * + ****************************************************************************/ + +void usb_pstd_set_stall_pipe0(void) +{ + /* PIPE control reg set */ + + hw_usb_set_pid(USB_PIPE0, USB_PID_STALL); +} + +/**************************************************************************** + * Name: rx65n_ep0setup + * + * Description: + * USB Ctrl EP Setup Event + * + ****************************************************************************/ + +void rx65n_ep0setup(struct rx65n_usbdev_s *priv) +{ + struct rx65n_ep_s *ep0 = &priv->eplist[EP0]; + struct rx65n_req_s *privreq = rx65n_rqpeek(ep0); + union wb_u value; + union wb_u index; + union wb_u len; + uint8_t epno; + uint8_t tbl[2]; + uint16_t ep; + uint16_t buf; + uint16_t pipe; + + /* Starting a control request? */ + + if (priv->usbdev.speed == USB_SPEED_UNKNOWN) + { + priv->usbdev.speed = USB_SPEED_FULL; + } + + /* Terminate any pending requests */ + + while (!rx65n_rqempty(ep0)) + { + int16_t result = OK; + if (privreq->req.xfrd != privreq->req.len) + { + result = -EPROTO; + } + + usbtrace(TRACE_COMPLETE(ep0->epphy), privreq->req.xfrd); + rx65n_reqcomplete(ep0, result); + } + + /* Assume NOT stalled */ + + ep0->stalled = 0; + priv->stalled = 0; + + /* And extract the little-endian 16-bit values to host order */ + + priv->ctrl.type = LSBYTE(rx65n_getreg16(RX65N_USB_USBREQ)); + priv->ctrl.req = MSBYTE(rx65n_getreg16(RX65N_USB_USBREQ)); + priv->ctrl.value[0] = LSBYTE(rx65n_getreg16(RX65N_USB_USBVAL)); + priv->ctrl.value[1] = MSBYTE(rx65n_getreg16(RX65N_USB_USBVAL)); + priv->ctrl.index[0] = LSBYTE(rx65n_getreg16(RX65N_USB_USBINDX)); + priv->ctrl.index[1] = MSBYTE(rx65n_getreg16(RX65N_USB_USBINDX)); + priv->ctrl.len[0] = LSBYTE(rx65n_getreg16(RX65N_USB_USBLENG)); + priv->ctrl.len[1] = MSBYTE(rx65n_getreg16(RX65N_USB_USBLENG)); + + uinfo("SETUP: type=%02x req=%02x value[0]=%02x value[1] =%02x \ + index[0]=%02x index[1] =%02x len[0]=%02x len[1]=%02x\n", + priv->ctrl.type, priv->ctrl.req, priv->ctrl.value[0], + priv->ctrl.value[1], priv->ctrl.index[0], + priv->ctrl.index[1], priv->ctrl.len[0], + priv->ctrl.len[1]); + + /* And extract the little-endian 16-bit values to host order */ + + value.w = GETUINT16(priv->ctrl.value); + index.w = GETUINT16(priv->ctrl.index); + len.w = GETUINT16(priv->ctrl.len); + + uinfo("value=%x index=%x len=%x\n", value.w, index.w, len.w); + + /* Dispatch any non-standard requests */ + + if ((priv->ctrl.type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) + { + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_NOSTDREQ), priv->ctrl.type); + + /* Let the class implementation handle all non-standar requests */ + + priv->ctrl.req = MSBYTE(rx65n_getreg16(RX65N_USB_USBREQ)); + priv->ctrl.type = LSBYTE(rx65n_getreg16(RX65N_USB_USBREQ)); + + if (priv->ctrl.req == ACM_SET_LINE_CODING || + priv->ctrl.req == ACM_SET_CTRL_LINE_STATE) + { + priv->ep0state = EP0STATE_RDREQUEST; + rx65n_dispatchrequest(priv); + } + + priv->ep0state = EP0STATE_WRREQUEST; + rx65n_dispatchrequest(priv); + } + + /* Handle standard request. Pick off the things of interest to the + * USB device controller driver; pass what is left to the class driver + */ + + switch (priv->ctrl.req) + { + case USB_REQ_GETSTATUS: + { + /* type: device-to-host; recipient = device, interface, endpoint + * value: 0 + * index: zero interface endpoint + * len: 2; data = status + */ + + if ((0 == value.w) && (2 == len.w)) + { + tbl[0] = 0; + tbl[1] = 0; + + /* Check request type */ + + switch (priv->ctrl.type & USB_REQ_RECIPIENT_MASK) + { + case USB_REQ_RECIPIENT_ENDPOINT: + { + /* Endpoint number */ + + ep = (uint16_t) (index.w & USB_EPNUMFIELD); + + /* Endpoint 0 */ + + if (0 == ep) + { + buf = hw_usb_read_dcpctr(); + if ((uint16_t) 0 != (buf & USB_PID_STALL)) + { + /* Halt set */ + + tbl[0] = USB_GS_HALT; + } + + /* Control read start */ + + usb_pstd_ctrl_read((uint32_t) 2, tbl); + } + + /* EP1 to max */ + + else if (ep <= USB_MAX_EP_NO) + { + if (USB_TRUE == usb_pstd_chk_configured()) + { + pipe = usb_pstd_epadr2pipe(g_usb_pstd_req_index); + if (USB_ERROR == pipe) + { + /* Set pipe USB_PID_STALL */ + + usb_pstd_set_stall_pipe0(); + } + else + { + buf = usb_cstd_get_pid(pipe); + if ((uint16_t) 0 != (buf & USB_PID_STALL)) + { + /* Halt set */ + + tbl[0] = USB_GS_HALT; + } + + /* Control read start */ + + usb_pstd_ctrl_read((uint32_t) 2, tbl); + } + } + else + { + /* Set pipe USB_PID_STALL */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Set pipe USB_PID_STALL */ + + usb_pstd_set_stall_pipe0(); + } + break; + + case USB_REQ_RECIPIENT_DEVICE: + { + if (0 == index.w) + { + /* Self powered / Bus powered */ + + tbl[0] = usb_pstd_get_current_power(); + + /* Support remote wakeup ? */ + + if (USB_TRUE == g_usb_pstd_remote_wakeup) + { + tbl[0] |= USB_GS_REMOTEWAKEUP; + } + + /* Control read start */ + + usb_pstd_ctrl_read((uint32_t) 2, tbl); + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + } + break; + + case USB_REQ_RECIPIENT_INTERFACE: + { + if (USB_TRUE == usb_pstd_chk_configured()) + { + /* 2 is number of interfaces, + * as configured by class driver + */ + + if (g_usb_pstd_req_index < 2) + + { + /* Control read start */ + + usb_pstd_ctrl_read((uint32_t) 2, tbl); + } + else + { + /* Request error (not exist interface) */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + } + break; + + default: + { + usb_pstd_set_stall_pipe0(); + } + break; + } + } + } + } + break; + case USB_REQ_CLEARFEATURE: + { + /* type: host-to-device; recipient = device, interface or endpoint + * value: feature selector + * index: zero interface endpoint; + * len: zero, data = none + */ + + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_CLEARFEATURE), + priv->ctrl.type); + if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) != + USB_REQ_RECIPIENT_ENDPOINT) + { + /* Let the class implementation handle all recipients + * (except for the endpoint recipient) + */ + + rx65n_dispatchrequest(priv); + } + else + { + /* Endpoint recipient */ + + epno = USB_EPNO(index.b[LSB]); + if (USB_ENDPOINT_HALT == value.w) + { + /* EP0 */ + + if (0 == epno) + { + /* Stall clear */ + + usb_cstd_clr_stall((uint16_t) USB_PIPE0); + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + + /* EP1 to max */ + + else if (epno <= USB_MAX_EP_NO) + { + pipe = usb_pstd_epadr2pipe(index.w); + if (USB_ERROR == pipe) + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + else + { + if (USB_PID_BUF == usb_cstd_get_pid(pipe)) + { + usb_cstd_set_nak(pipe); + + /* SQCLR=1 */ + + hw_usb_set_sqclr(pipe); + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf(pipe); + } + else + { + usb_cstd_clr_stall(pipe); + + /* SQCLR=1 */ + + hw_usb_set_sqclr(pipe); + } + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + } + } + } + break; + + case USB_REQ_SETFEATURE: + { + /* type: host-to-device; recipient = device, interface, endpoint + * value: feature selector + * index: zero interface endpoint; + * len: 0; data = none + */ + + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_SETFEATURE), + priv->ctrl.type); + if (((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_DEVICE) && value.w == USB_FEATURE_TESTMODE) + { + /* Special case recipient=device test mode */ + + uinfo("test mode: %d\n", index.w); + } + else if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) != + USB_REQ_RECIPIENT_ENDPOINT) + { + /* The class driver handles all recipients + * except recipient=endpoint + */ + + rx65n_dispatchrequest(priv); + } + else + { + /* Handler recipient=endpoint */ + + epno = USB_EPNO(index.b[LSB]); + if (USB_ENDPOINT_HALT == value.w) + { + /* EP0 */ + + if (0 == epno) + { + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + + /* EP1 to max */ + + else if (epno <= USB_MAX_EP_NO) + { + pipe = usb_pstd_epadr2pipe(index.w); + if (USB_ERROR == pipe) + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + else + { + /* Set pipe USB_PID_STALL */ + + usb_pstd_set_stall(pipe); + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + } + } + break; + + case USB_REQ_SETADDRESS: + { + /* type: host-to-device; recipient = device + * value: device address + * index: 0 + * len: 0; data = none + */ + + if ((0 == index.w) && (0 == len.w)) + { + if (value.w <= 127) + { + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + } + break; + + case USB_REQ_GETDESCRIPTOR: + case USB_REQ_SETDESCRIPTOR: + /* type: host-to-device; recipient = device + * value: descriptor type and index + * index: 0 or language ID; + * len: descriptor len; data = descriptor + */ + + { + uinfo("Get Descriptor Request Got from Host"); + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_GETCONFIG), + priv->ctrl.type); + /* The request seems valid... let the class + * implementation handle it + */ + + rx65n_dispatchrequest(priv); + } + break; + + case USB_REQ_GETCONFIGURATION: + + /* type: device-to-host; recipient = device + * value: 0; + * index: 0; + * len: 1; data = configuration value + */ + + case USB_REQ_SETCONFIGURATION: + + /* type: host-to-device; recipient = device + * value: configuration value + * index: 0; + * len: 0; data = none + */ + + { + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_SETCONFIG), 0); + if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_DEVICE) + { + rx65n_dispatchrequest(priv); + } + else + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_BADSETCONFIG), 0); + priv->stalled = 1; + } + } + break; + + case USB_REQ_GETINTERFACE: + + /* type: device-to-host; recipient = interface + * value: 0 + * index: interface; + * len: 1; data = alt interface + */ + + case USB_REQ_SETINTERFACE: + + /* type: host-to-device; recipient = interface + * value: alternate setting + * index: interface; + * len: 0; data = none + */ + + { + /* Let the class implementation handle the request */ + + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_GETSETIF), + priv->ctrl.type); + rx65n_dispatchrequest(priv); + } + break; + + case USB_REQ_SYNCHFRAME: + + /* type: device-to-host; recipient = endpoint + * value: 0 + * index: endpoint; + * len: 2; data = frame number + */ + + { + usbtrace(TRACE_INTDECODE(RX65N_TRACEINTID_SYNCHFRAME), 0); + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDCTRLREQ), + priv->ctrl.req); + priv->ep0state = EP0STATE_STALLED; + } + break; + } +} + +/**************************************************************************** + * Name: usb_pstd_pipe2fport + * + * Description: + * Get Pipe Number to FIFO port address + * + ****************************************************************************/ + +uint16_t usb_pstd_pipe2fport(uint16_t pipe) +{ + uint16_t fifo_mode = USB_CUSE; + + if (USB_MAXPIPE_NUM < pipe) + { + return USB_NULL; /* Error */ + } + + return fifo_mode; +} + +/**************************************************************************** + * Name: hw_usb_write_pipeperi + * + * Description: + * Write to PIPE PERI register + * + ****************************************************************************/ + +static void hw_usb_write_pipeperi (uint16_t data) +{ + rx65n_putreg16(data, RX65N_USB_PIPEPERI); +} + +/**************************************************************************** + * Name: usb_cstd_pipe_init + * + * Description: + * Pipe initialization + * + ****************************************************************************/ + +static void usb_cstd_pipe_init (uint16_t pipe, uint16_t pipe_cfg, + uint16_t maxpacket) +{ + uint16_t pipe_peri = 0; + + /* Interrupt Disable */ + + /* Ready Int Disable */ + + hw_usb_clear_brdyenb(pipe); + + /* NotReady Int Disable */ + + hw_usb_clear_nrdyenb(pipe); + + /* Empty/SizeErr Int Disable */ + + hw_usb_clear_bempenb(pipe); + + /* PID=NAK & clear STALL */ + + usb_cstd_clr_stall(pipe); + + /* PIPE Configuration */ + + hw_usb_write_pipesel(pipe); + + hw_usb_write_pipecfg(pipe_cfg); + + hw_usb_write_pipemaxp(maxpacket); + hw_usb_write_pipeperi(pipe_peri); + + /* FIFO buffer DATA-PID initialized */ + + hw_usb_write_pipesel(USB_PIPE0); + + /* SQCLR */ + + hw_usb_set_sqclr(pipe); + + /* ACLRM */ + + usb_cstd_do_aclrm(pipe); + + /* Interrupt status clear */ + + /* Ready Int Clear */ + + hw_usb_clear_sts_brdy(pipe); + + /* NotReady Int Clear */ + + hw_usb_clear_status_nrdy(pipe); + + /* Empty/SizeErr Int Clear */ + + hw_usb_clear_status_bemp(pipe); +} + +/**************************************************************************** + * Name: usb_pstd_set_pipe_reg + * + * Description: + * Set Pipe Register + * + ****************************************************************************/ + +void usb_pstd_set_pipe_reg (uint16_t pipe_no, uint16_t pipe_cfgint, + uint16_t pipe_cfgbulkin, + uint16_t pipe_cfgbulkout, uint16_t maxpacket) +{ + /* Search use pipe block */ + + /* WAIT_LOOP */ + + /* Initialization of registers associated with specified pipe. */ + + if (pipe_no == BULK_IN_PIPE) + { + usb_cstd_pipe_init (pipe_no, pipe_cfgbulkin, maxpacket); + } + + if (pipe_no == INT_IN_PIPE) + { + usb_cstd_pipe_init (pipe_no, pipe_cfgint, maxpacket); + } + + if (pipe_no == BULK_OUT_PIPE) + { + usb_cstd_pipe_init (pipe_no, pipe_cfgbulkout, maxpacket); + } +} + +/**************************************************************************** + * Endpoint Methods + ****************************************************************************/ + +/**************************************************************************** + * Name: rx65n_epconfigure + * + * Description: + * Configure endpoint, making it usable + * + * Input Parameters: + * ep - the struct usbdev_ep_s instance obtained from allocep() + * desc - A struct usb_epdesc_s instance describing the endpoint + * last - true if this this last endpoint to be configured. Some hardware + * needs to take special action when all of the endpoints have been + * configured. + * + ****************************************************************************/ + +static int rx65n_epconfigure(FAR struct usbdev_ep_s *ep, + FAR const struct usb_epdesc_s *desc, + bool last) +{ + uint16_t maxpacket; + uint8_t epno; + uint16_t pipe_no = 0 ; + uint16_t pipe_cfg_int = 0; + uint16_t pipe_cfg_bulkin = 0; + uint16_t pipe_cfg_bulkout = 0; + +#ifdef CONFIG_DEBUG_FEATURES + if (!ep || !desc) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + printf("ERROR: ep=%p desc=%p\n"); + return -EINVAL; + } +#endif + + /* Get the unadorned endpoint address */ + + epno = USB_EPNO(desc->addr); + + usbtrace(TRACE_EPCONFIGURE, (uint16_t)epno); + DEBUGASSERT(epno == USB_EPNO(ep->eplog)); + + /* Set the requested type */ + + switch (desc->attr & USB_EP_ATTR_XFERTYPE_MASK) + { + case USB_EP_ATTR_XFER_INT: /* Interrupt endpoint */ + if (USB_ISEPIN(desc->addr) && epno == INT_IN_EPNUM) + { + /* The full, logical EP number includes direction */ + + ep->eplog = USB_EPIN(epno); + pipe_no = INT_IN_PIPE; + pipe_cfg_int = (uint16_t)(USB_TYPFIELD_INT | USB_DIR_P_IN | epno); + } + + if (USB_ISEPOUT(desc->addr)) + { + /* The full, logical EP number includes direction */ + + ep->eplog = USB_EPOUT(epno); + pipe_no = INT_OUT_PIPE; + pipe_cfg_int = (uint16_t)(USB_TYPFIELD_INT | USB_DIR_P_OUT | epno); + } + break; + + case USB_EP_ATTR_XFER_BULK: /* Bulk endpoint */ + if (USB_ISEPIN(desc->addr) && epno == BULK_IN_EPNUM) + { + /* The full, logical EP number includes direction */ + + ep->eplog = USB_EPIN(epno); + pipe_no = BULK_IN_PIPE; + pipe_cfg_bulkin = (uint16_t)(USB_TYPFIELD_BULK | USB_CFG_DBLB | + USB_DIR_P_IN | epno); + } + + if (USB_ISEPOUT(desc->addr)) + { + /* The full, logical EP number includes direction */ + + ep->eplog = USB_EPOUT(epno); + pipe_no = BULK_OUT_PIPE; + pipe_cfg_bulkout = (uint16_t)(USB_TYPFIELD_BULK | USB_CFG_DBLB | + USB_SHTNAKFIELD | USB_DIR_P_OUT | epno); + } + + break; + + case USB_EP_ATTR_XFER_ISOC: /* Isochronous endpoint */ + + /* Not Supported */ + + break; + + case USB_EP_ATTR_XFER_CONTROL: /* Control endpoint */ + hw_usb_write_dcpcfg(0); + hw_usb_write_dcpmxps(USB_DCPMAXP); + break; + + default: + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_BADEPTYPE), + (uint16_t)desc->type); + return -EINVAL; + } + + maxpacket = GETUINT16(desc->mxpacketsize); + hw_usb_write_pipemaxp(maxpacket); + ep->maxpacket = maxpacket; + + hw_usb_write_dcpmxps(USB_DCPMAXP); + + usb_pstd_set_pipe_reg(pipe_no, pipe_cfg_int, pipe_cfg_bulkin, + pipe_cfg_bulkout, maxpacket); + + return OK; +} + +/**************************************************************************** + * Name: rx65n_epdisable + * + * Description: + * The endpoint will no longer be used + * + ****************************************************************************/ + +static int rx65n_epdisable(struct usbdev_ep_s *ep) +{ + struct rx65n_ep_s *privep = (struct rx65n_ep_s *)ep; + irqstate_t flags; + +#ifdef CONFIG_DEBUG_FEATURES + if (!ep) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + uerr("ERROR: ep=%p\n", ep); + return -EINVAL; + } +#endif + + /* Cancel any ongoing activity */ + + flags = enter_critical_section(); + rx65n_cancelrequests(privep); + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: rx65n_epallocreq + * + * Description: + * Allocate an I/O request + * + ****************************************************************************/ + +static FAR struct usbdev_req_s *rx65n_epallocreq(FAR struct usbdev_ep_s *ep) +{ + struct rx65n_req_s *privreq; + +#ifdef CONFIG_DEBUG_FEATURES + if (!ep) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + return NULL; + } + +#endif + usbtrace(TRACE_EPALLOCREQ, USB_EPNO(ep->eplog)); + + privreq = (struct rx65n_req_s *)kmm_malloc(sizeof(struct rx65n_req_s)); + if (!privreq) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_ALLOCFAIL), 0); + return NULL; + } + + memset(privreq, 0, sizeof(struct rx65n_req_s)); + return &privreq->req; +} + +/**************************************************************************** + * Name: rx65n_epfreereq + * + * Description: + * Free an I/O request + * + ****************************************************************************/ + +static void rx65n_epfreereq(FAR struct usbdev_ep_s *ep, FAR struct + usbdev_req_s *req) +{ + struct rx65n_req_s *privreq = (struct rx65n_req_s *)req; +#ifdef CONFIG_DEBUG_FEATURES + if (!ep || !req) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + return; + } + +#endif + usbtrace(TRACE_EPFREEREQ, USB_EPNO(ep->eplog)); + kmm_free(privreq); +} + +/**************************************************************************** + * Name: rx65n_epsubmit + * + * Description: + * Submit an I/O request to the endpoint + * + ****************************************************************************/ + +static int rx65n_epsubmit(FAR struct usbdev_ep_s *ep, FAR struct + usbdev_req_s *req) +{ + struct rx65n_req_s *privreq = (struct rx65n_req_s *)req; + struct rx65n_ep_s *privep = (struct rx65n_ep_s *)ep; + struct rx65n_usbdev_s *priv; + irqstate_t flags; + uint8_t epno; + int ret = OK; + +#ifdef CONFIG_DEBUG_FEATURES + if (!req || !req->callback || !req->buf || !ep) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + printf("ERROR: req=%p callback=%p buf=%p ep=%p\n", + req, req->callback, req->buf, ep); + return -EINVAL; + } +#endif + + usbtrace(TRACE_EPSUBMIT, USB_EPNO(ep->eplog)); + priv = privep->dev; + +#ifdef CONFIG_DEBUG_FEATURES + if (!priv->driver) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_NOTCONFIGURED), + priv->usbdev.speed); + printf("ERROR: driver=%p\n", priv->driver); + return -ESHUTDOWN; + } +#endif + + /* Handle the request from the class driver */ + + epno = USB_EPNO(ep->eplog); + req->result = -EINPROGRESS; + req->xfrd = 0; + flags = enter_critical_section(); + + /* If we are stalled, then drop all requests on the floor */ + + if (privep->stalled) + { + rx65n_abortrequest(privep, privreq, -EBUSY); + printf("ERROR: stalled\n"); + ret = -EBUSY; + } + + /* Handle IN (device-to-host) requests. NOTE: If the class device is + * using the bi-directional EP0, then we assume that they intend the EP0 + * IN functionality. + */ + + else if (epno == EP0) + { + /* Add the new request to the request queue for the IN endpoint */ + + usbtrace(TRACE_INREQQUEUED(epno), req->len); + rx65n_rqenqueue(privep, privreq); + + if (priv->ep0state == EP0STATE_RDREQUEST) + { + privreq->req.len = CDC_CLASS_DATA_LENGTH; + rx65n_rdrequest(epno, priv, privep); + return OK; + } + + /* If the IN endpoint FIFO is available, then transfer the data now */ + + if (!privep->txbusy) + { + ret = rx65n_wrrequest(epno, priv, privep); + return OK; + } + } + + else if (USB_ISEPIN(ep->eplog) || epno == EP0) + { + /* Add the new request to the request queue for the IN endpoint */ + + usbtrace(TRACE_INREQQUEUED(epno), req->len); + rx65n_rqenqueue(privep, privreq); + if (priv->ep0state == EP0STATE_RDREQUEST) + { + rx65n_rdrequest(epno, priv, privep); + return OK; + } + + /* If the IN endpoint FIFO is available, then transfer the data now */ + + if (!privep->txbusy) + { + ret = rx65n_wrrequest(epno, priv, privep); + } + } + + /* Handle OUT (host-to-device) requests */ + + else + { + /* Add the new request to the request queue for the OUT endpoint */ + + privep->txnullpkt = 0; + rx65n_rqenqueue(privep, privreq); + usbtrace(TRACE_OUTREQQUEUED(epno), req->len); + + /* This there a incoming data pending the availability of a request? */ + + /* This there a incoming data pending the availability of a request? */ + + if (priv->rxpending > 0) + { + ret = rx65n_rdrequest(epno, priv, privep); + priv->rxpending--; + } + } + + leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Name: rx65n_cancelrequests + ****************************************************************************/ + +static void rx65n_cancelrequests(struct rx65n_ep_s *privep) +{ + while (!rx65n_rqempty(privep)) + { + usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), + (rx65n_rqpeek(privep))->req.xfrd); + rx65n_reqcomplete(privep, -ESHUTDOWN); + } +} + +/**************************************************************************** + * Name: rx65n_epcancel + * + * Description: + * Cancel an I/O request previously sent to an endpoint + * + ****************************************************************************/ + +static int rx65n_epcancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req) +{ + struct rx65n_ep_s *privep = (struct rx65n_ep_s *)ep; + irqstate_t flags; + +#ifdef CONFIG_DEBUG_USB + if (!ep || !req) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } + +#endif + usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog)); + + flags = enter_critical_section(); + rx65n_cancelrequests(privep); + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: rx65n_epreserve + ****************************************************************************/ + +static inline struct rx65n_ep_s * +rx65n_epreserve(struct rx65n_usbdev_s *priv, uint8_t epset) +{ + struct rx65n_ep_s *privep = NULL; + irqstate_t flags; + int epndx = 0; + + flags = enter_critical_section(); + epset &= priv->epavail; + if (epset) + { + /* Select the lowest bit in the set of matching, available endpoints + * (skipping EP0) + */ + + for (epndx = 1; epndx < RX65N_NENDPOINTS; epndx++) + { + uint8_t bit = RX65N_ENDP_BIT(epndx); + if ((epset & bit) != 0) + { + /* Mark the endpoint no longer available */ + + priv->epavail &= ~bit; + + /* And return the pointer to the standard endpoint structure */ + + privep = &priv->eplist[epndx]; + break; + } + } + } + + leave_critical_section(flags); + return privep; +} + +/**************************************************************************** + * Device Methods + ****************************************************************************/ + +/**************************************************************************** + * Name: rx65n_allocep + * + * Description: + * Allocate an endpoint matching the parameters + * + * Input Parameters: + * eplog - 7-bit logical endpoint number (direction bit ignored). + * Zero means that any endpoint matching the other requirements + * will suffice. The assigned endpoint can be found in + * the eplog field. in - true: IN (device-to-host) + * endpoint requested eptype - Endpoint type. One of + * {USB_EP_ATTR_XFER_ISOC, USB_EP_ATTR_XFER_BULK, + * USB_EP_ATTR_XFER_INT} + * + ****************************************************************************/ + +static FAR struct usbdev_ep_s *rx65n_allocep(FAR struct usbdev_s *dev, + uint8_t epno, bool in, + uint8_t eptype) +{ + struct rx65n_usbdev_s *priv = (struct rx65n_usbdev_s *)dev; + struct rx65n_ep_s *privep = NULL; + uint8_t epset = RX65N_ENDP_ALLSET; + + usbtrace(TRACE_DEVALLOCEP, (uint16_t)epno); +#ifdef CONFIG_DEBUG_USB + if (!dev) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + return NULL; + } +#endif + + /* Ignore any direction bits in the logical address */ + + epno = USB_EPNO(epno); + + /* A logical address of 0 means that any endpoint will do */ + + if (epno > 0) + { + /* Otherwise, we will return the endpoint structure only + * for the requested 'logical' endpoint. All of the other + * checks will still be performed. + * + * First, verify that the logical endpoint is in + * the range supported by + * by the hardware. + */ + + if (epno >= RX65N_NENDPOINTS) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_BADEPNO), (uint16_t)epno); + return NULL; + } + + /* Convert the logical address to a physical OUT endpoint address and + * remove all of the candidate endpoints from the bitset except for the + * the IN/OUT pair for this logical address. + */ + + epset = RX65N_ENDP_BIT(epno); + } + + /* Check if the selected endpoint number is available */ + + privep = rx65n_epreserve(priv, epset); + if (!privep) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_EPRESERVE), (uint16_t)epset); + goto errout; + } + + return &privep->ep; + +errout: + return NULL; +} + +/**************************************************************************** + * Name: rx65n_epunreserve + ****************************************************************************/ + +static inline void +rx65n_epunreserve(struct rx65n_usbdev_s *priv, + struct rx65n_ep_s *privep) +{ + irqstate_t flags = enter_critical_section(); + priv->epavail |= RX65N_ENDP_BIT(USB_EPNO(privep->ep.eplog)); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: rx65n_freeep + * + * Description: + * Free the previously allocated endpoint + * + ****************************************************************************/ + +static void rx65n_freeep(FAR struct usbdev_s *dev, FAR struct + usbdev_ep_s *ep) +{ + struct rx65n_usbdev_s *priv; + struct rx65n_ep_s *privep; + +#ifdef CONFIG_DEBUG_USB + if (!dev || !ep) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + return; + } +#endif + + priv = (struct rx65n_usbdev_s *)dev; + privep = (struct rx65n_ep_s *)ep; + usbtrace(TRACE_DEVFREEEP, (uint16_t)USB_EPNO(ep->eplog)); + + if (priv && privep) + { + /* Mark the endpoint as available */ + + rx65n_epunreserve(priv, privep); + } +} + +/**************************************************************************** + * Name: rx65n_getframe + * + * Description: + * Returns the current frame number + * + ****************************************************************************/ + +static int rx65n_getframe(struct usbdev_s *dev) +{ + int regval; + regval = (rx65n_getreg16(RX65N_USB_FRMNUM) & RX65N_USB_FRMNUM_VAL); + return regval; +} + +/**************************************************************************** + * Name: rx65n_wakeup + * + * Description: + * Tries to wake up the host connected to this device + * + ****************************************************************************/ + +static int rx65n_wakeup(struct usbdev_s *dev) +{ + uint16_t regval; + regval = rx65n_getreg16 (RX65N_USB_INTENB0); + regval |= RX65N_USB_INTENB0_RSME; + rx65n_putreg16(regval, RX65N_USB_INTENB0); + return OK; +} + +/**************************************************************************** + * Name: rx65n_selfpowered + * + * Description: + * Sets/clears the device selfpowered feature + * + ****************************************************************************/ + +static int rx65n_selfpowered(struct usbdev_s *dev, bool selfpowered) +{ +#ifdef CONFIG_USBDEV_SELFPOWERED + struct rx65n_usbdev_s *priv = (struct rx65n_usbdev_s *)dev; + + usbtrace(TRACE_DEVSELFPOWERED, (uint16_t)selfpowered); + +#ifdef CONFIG_DEBUG_USB + if (!dev) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + return -ENODEV; + } +#endif + + priv->selfpowered = selfpowered; + + return OK; +#else + /* Do Nothing for bus powered configuration */ + + return OK; + +#endif +} + +/**************************************************************************** + * Name: rx65n_pullup + * + * Description: + * Software-controlled connect to/disconnect from USB host + * + ****************************************************************************/ + +int rx65n_pullup(struct usbdev_s *dev, bool enable) +{ + uint16_t regval; + + /* Disable DRPD bit in SYSCFG register */ + + regval = rx65n_getreg16 (RX65N_USB_SYSCFG); + regval &= ~(RX65N_USB_SYSCFG_DRPD); + rx65n_putreg16(regval, RX65N_USB_SYSCFG); + + return OK; +} + +/**************************************************************************** + * Name: usb_pstd_attach_process + * + * Description: + * Set the DPRPU bit + * + ****************************************************************************/ + +void usb_pstd_attach_process (void) +{ + uint16_t regval; + + regval = rx65n_getreg16 (RX65N_USB_SYSCFG); + regval |= (RX65N_USB_SYSCFG_DPRPU); + rx65n_putreg16(regval, RX65N_USB_SYSCFG); +} + +/**************************************************************************** + * Name: hw_usb_pclear_dprpu + * + * Description: + * Clear the DPRPU bit + * + ****************************************************************************/ + +void hw_usb_pclear_dprpu(void) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_SYSCFG); + regval &= ~(RX65N_USB_SYSCFG_DPRPU); + rx65n_putreg16(regval, RX65N_USB_SYSCFG); +} + +/**************************************************************************** + * Name: hw_usb_clear_aclrm + * + * Description: + * Clear ACLRM bit + * + ****************************************************************************/ + +static void hw_usb_clear_aclrm (uint16_t pipeno) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *)(RX65N_USB_PIPE1CTR) + (pipeno - 1); + + (*p_reg) &= (~USB_ACLRM); +} + +/**************************************************************************** + * Name: hw_usb_set_aclrm + * + * Description: + * Set ACLRM bit + * + ****************************************************************************/ + +static void hw_usb_set_aclrm (uint16_t pipeno) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *)(RX65N_USB_PIPE1CTR) + (pipeno - 1); + + (*p_reg) |= USB_ACLRM; +} + +/**************************************************************************** + * Name: usb_cstd_do_aclrm + * + * Description: + * Control ACLRM bit + * + ****************************************************************************/ + +static void usb_cstd_do_aclrm (uint16_t pipe) +{ + if (USB_MAXPIPE_NUM < pipe) + { + return; /* Error */ + } + + /* Control ACLRM */ + + hw_usb_set_aclrm(pipe); + + hw_usb_clear_aclrm(pipe); +} + +/**************************************************************************** + * Name: hw_usb_set_curpipe + * + * Description: + * Set Current Pipe + * + ****************************************************************************/ + +static void hw_usb_set_curpipe (uint16_t pipemode, uint16_t pipeno) +{ + uint16_t *p_reg; + uint16_t reg; + + p_reg = hw_usb_get_fifosel_adr(pipemode); + reg = *p_reg; + + if ((USB_D0USE == pipemode) || (USB_D1USE == pipemode)) + { + reg &= (~USB_DREQE); + } + + reg &= (~USB_CURPIPE); + *p_reg = reg; + + /* WAIT_LOOP */ + + while (0 != ((*p_reg) & USB_CURPIPE)) + { + /* Wait Clear CURPIPE */ + } + + reg |= pipeno; + + *p_reg = reg; +} + +/**************************************************************************** + * Name: hw_usb_rmw_fifosel + * + * Description: + * Clear FIFOSEL bit + * + ****************************************************************************/ + +static void hw_usb_rmw_fifosel (uint16_t pipemode, + uint16_t data, uint16_t bitptn) +{ + uint16_t buf; + uint16_t *p_reg; + + p_reg = (uint16_t *) hw_usb_get_fifosel_adr(pipemode); + + buf = *p_reg; + buf &= (~bitptn); + buf |= (data & bitptn); + *p_reg = buf; +} + +/**************************************************************************** + * Name: usb_cstd_chg_curpipe + * + * Description: + * Current Pipe Check + * + ****************************************************************************/ + +static void usb_cstd_chg_curpipe (uint16_t pipe, + uint16_t fifosel, uint16_t isel) +{ + uint16_t buf; + + /* Select FIFO */ + + switch (fifosel) + { + /* CFIFO use */ + + case USB_CUSE : + + /* ISEL=1, CURPIPE=0 */ + + hw_usb_rmw_fifosel(USB_CUSE, ((USB_RCNT | isel) | pipe), + ((USB_RCNT | USB_ISEL) | USB_CURPIPE)); + break; + + /* D0FIFO use */ + + case USB_D0USE : + + /* D1FIFO use */ + + case USB_D1USE : + + /* DxFIFO pipe select */ + + hw_usb_set_curpipe (fifosel, pipe); + + /* WAIT_LOOP */ + + do + { + buf = hw_usb_read_fifosel (fifosel); + } + while ((uint16_t)(buf & USB_CURPIPE) != pipe); + break; + + default : + break; + } +} + +/**************************************************************************** + * Name: hw_usb_get_fifosel_adr + * + * Description: + * Get FIFOSEL register address + * + ****************************************************************************/ + +static void *hw_usb_get_fifosel_adr (uint16_t pipemode) +{ + void *p_reg = NULL; + + switch (pipemode) + { + case USB_CUSE: + p_reg = (void *)RX65N_USB_CFIFOSEL; + break; + + case USB_D0USE: + p_reg = (void *)RX65N_USB_D0FIFOSEL; + break; + + case USB_D1USE: + p_reg = (void *)RX65N_USB_D1FIFOSEL; + break; + + default: + break; + } + + return p_reg; +} + +/**************************************************************************** + * Name: hw_usb_read_fifosel + * + * Description: + * Read FIFOSEL Register + * + ****************************************************************************/ + +static uint16_t hw_usb_read_fifosel (uint16_t pipemode) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *) hw_usb_get_fifosel_adr(pipemode); + + return *p_reg; +} + +/**************************************************************************** + * Name: hw_usb_set_trclr + * + * Description: + * Set Transaction Clear bit + * + ****************************************************************************/ + +static void hw_usb_set_trclr (uint16_t pipeno) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *)(RX65N_USB_PIPE1CTR) + ((pipeno - 1) * 2); + + (*p_reg) |= USB_TRCLR; +} + +/**************************************************************************** + * Name: hw_usb_clear_trenb + * + * Description: + * Clear Transaction Enable + * + ****************************************************************************/ + +static void hw_usb_clear_trenb (uint16_t pipeno) +{ + uint16_t *p_reg; + + p_reg = (uint16_t *)(RX65N_USB_PIPE1CTR) + ((pipeno - 1) * 2); + (*p_reg) &= (~USB_TRENB); +} + +/**************************************************************************** + * Name: usb_cstd_clr_transaction_counter + * + * Description: + * Clear Transaction Counter + * + ****************************************************************************/ + +static void usb_cstd_clr_transaction_counter (uint16_t trnreg) +{ + hw_usb_clear_trenb(trnreg); + hw_usb_set_trclr(trnreg); +} + +/**************************************************************************** + * Name: hw_usb_clear_bempenb + * + * Description: + * Clear BEMPENB + * + ****************************************************************************/ + +static void hw_usb_clear_bempenb (uint16_t pipeno) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_BEMPENB); + regval &= (~(1 << pipeno)); + rx65n_putreg16(regval, RX65N_USB_BEMPENB); +} + +/**************************************************************************** + * Name: hw_usb_clear_nrdyenb + * + * Description: + * Clear NRDYENB + * + ****************************************************************************/ + +static void hw_usb_clear_nrdyenb (uint16_t pipeno) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_NRDYENB); + regval &= (~(1 << pipeno)); + rx65n_putreg16(regval, RX65N_USB_NRDYENB); +} + +/**************************************************************************** + * Name: hw_usb_clear_brdyenb + * + * Description: + * Clear BRDYENB + * + ****************************************************************************/ + +static void hw_usb_clear_brdyenb (uint16_t pipeno) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_BRDYENB); + regval &= (~(1 << pipeno)); + rx65n_putreg16(regval, RX65N_USB_BRDYENB); +} + +/**************************************************************************** + * Name: hw_usb_read_pipectr + * + * Description: + * Read PIPECTR + * + ****************************************************************************/ + +static uint16_t hw_usb_read_pipectr (uint16_t pipeno) +{ + uint16_t *p_reg; + + if (USB_PIPE0 == pipeno) + { + p_reg = (uint16_t *)RX65N_USB_DCPCTR; + } + else + { + p_reg = (uint16_t *)(RX65N_USB_PIPE1CTR) + (pipeno - 1); + } + + return *p_reg; +} + +/**************************************************************************** + * Name: hw_usb_clear_pid + * + * Description: + * Clear pid + * + ****************************************************************************/ + +static void hw_usb_clear_pid (uint16_t pipeno, uint16_t data) +{ + uint16_t *p_reg; + + if (USB_PIPE0 == pipeno) + { + p_reg = (uint16_t *)RX65N_USB_DCPCTR; + } + else + { + p_reg = (uint16_t *)(RX65N_USB_PIPE1CTR) + (pipeno - 1); + } + + (*p_reg) &= (~data); +} + +/**************************************************************************** + * Name: usb_cstd_set_nak + * + * Description: + * Set NAK + * + ****************************************************************************/ + +static void usb_cstd_set_nak (uint16_t pipe) +{ + uint16_t buf; + uint16_t n; + + /* Set NAK */ + + hw_usb_clear_pid(pipe, (uint16_t) USB_PID_BUF); + + /* The state of PBUSY continues while transmitting + * the packet when it is a detach. + */ + + /* 1ms comes off when leaving because the packet + * duration might not exceed 1ms. + */ + + /* Whether it is PBUSY release or + * 1ms passage can be judged. + */ + + /* WAIT_LOOP */ + + for (n = 0; n < 0xffff; ++n) + { + /* PIPE control reg read */ + + buf = hw_usb_read_pipectr(pipe); + if (0 == (uint16_t) (buf & USB_PBUSY)) + { + n = 0xfffe; + } + } +} + +/**************************************************************************** + * Name: usb_pstd_forced_termination + * + * Description: + * Clear the buffer data + * + ****************************************************************************/ + +void usb_pstd_forced_termination(uint16_t pipe, uint16_t status) +{ + uint16_t buf; + + /* PID = NAK */ + + /* Set NAK */ + + usb_cstd_set_nak(pipe); + + /* Disable Interrupt */ + + /* Disable Ready Interrupt */ + + hw_usb_clear_brdyenb(pipe); + + /* Disable Not Ready Interrupt */ + + hw_usb_clear_nrdyenb(pipe); + + /* Disable Empty Interrupt */ + + hw_usb_clear_bempenb(pipe); + + usb_cstd_clr_transaction_counter(pipe); + + /* Clear CFIFO-port */ + + buf = hw_usb_read_fifosel(USB_CUSE); + + if ((buf & USB_CURPIPE) == pipe) + { + /* Changes the FIFO port by the pipe. */ + + usb_cstd_chg_curpipe((uint16_t) USB_PIPE0, + (uint16_t) USB_CUSE, USB_FALSE); + } + + /* Do Aclr */ + + usb_cstd_do_aclrm(pipe); +} + +/**************************************************************************** + * Name: usb_cstd_clr_stall + * + * Description: + * Clear Stall + * + ****************************************************************************/ + +static void usb_cstd_clr_stall (uint16_t pipe) +{ + if (USB_MAXPIPE_NUM < pipe) + { + return; /* Error */ + } + + /* Set NAK */ + + usb_cstd_set_nak(pipe); + + /* Clear STALL */ + + hw_usb_clear_pid(pipe, USB_PID_STALL); +} + +/**************************************************************************** + * Name: hw_usb_write_pipesel + * + * Description: + * Write to PIPESEL register + * + ****************************************************************************/ + +static void hw_usb_write_pipesel (uint16_t data) +{ + rx65n_putreg16(data, RX65N_USB_PIPESEL); +} + +/**************************************************************************** + * Name: hw_usb_write_pipecfg + * + * Description: + * Write to PIPECFG register + * + ****************************************************************************/ + +static void hw_usb_write_pipecfg (uint16_t data) +{ + rx65n_putreg16(data, RX65N_USB_PIPECFG); +} + +/**************************************************************************** + * Name: hw_usb_write_pipemaxp + * + * Description: + * Write to PIPEMAXP register + * + ****************************************************************************/ + +static void hw_usb_write_pipemaxp (uint16_t data) +{ + rx65n_putreg16(data, RX65N_USB_PIPEMAXP); +} + +/**************************************************************************** + * Name: hw_usb_write_pipeperi + * + * Description: + * Write to PIPEPERI register + * + ****************************************************************************/ + +/**************************************************************************** + * Name: hw_usb_set_sqclr + * + * Description: + * Write to SQCLR register + * + ****************************************************************************/ + +static void hw_usb_set_sqclr (uint16_t pipeno) +{ + uint16_t *p_reg; + uint16_t regval; + + if (USB_PIPE0 == pipeno) + { + regval = rx65n_getreg16(RX65N_USB_DCPCTR); + regval |= USB_SQCLR; + rx65n_putreg16(regval, RX65N_USB_DCPCTR); + } + else + { + p_reg = ((uint16_t *)RX65N_USB_PIPE1CTR + (pipeno - 1)); + (*p_reg) |= USB_SQCLR; + } +} + +/**************************************************************************** + * Name: hw_usb_clear_sts_brdy + * + * Description: + * Clear BRDY status + * + ****************************************************************************/ + +static void hw_usb_clear_sts_brdy (uint16_t pipeno) +{ + rx65n_putreg16((~(1 << pipeno)) & RX65N_USB_PIPE_ALL, + RX65N_USB_BRDYSTS); +} + +/**************************************************************************** + * Name: hw_usb_clear_status_nrdy + * + * Description: + * Clear NRDY status + * + ****************************************************************************/ + +static void hw_usb_clear_status_nrdy (uint16_t pipeno) +{ + rx65n_putreg16((~(1 << pipeno)) & RX65N_USB_PIPE_ALL, + RX65N_USB_NRDYSTS); +} + +/**************************************************************************** + * Name: usb_cstd_clr_pipe_cnfg + * + * Description: + * Clear pipe configuration + * + ****************************************************************************/ + +static void usb_cstd_clr_pipe_cnfg (uint16_t pipe_no) +{ + /* PID=NAK & clear STALL */ + + usb_cstd_clr_stall(pipe_no); + + /* Interrupt disable */ + + /* Ready Int Disable */ + + hw_usb_clear_brdyenb(pipe_no); + + /* NotReady Int Disable */ + + hw_usb_clear_nrdyenb(pipe_no); + + /* Empty/SizeErr Int Disable */ + + hw_usb_clear_bempenb(pipe_no); + + /* PIPE Configuration */ + + usb_cstd_chg_curpipe((uint16_t) USB_PIPE0, (uint16_t) USB_CUSE, USB_FALSE); + hw_usb_write_pipesel(pipe_no); + hw_usb_write_pipecfg(0); + + hw_usb_write_pipemaxp(0); + hw_usb_write_pipeperi(0); + hw_usb_write_pipesel(0); + + /* FIFO buffer DATA-PID initialized */ + + /* SQCLR */ + + hw_usb_set_sqclr(pipe_no); + + /* ACLRM */ + + usb_cstd_do_aclrm(pipe_no); + usb_cstd_clr_transaction_counter(pipe_no); + + /* Interrupt status clear */ + + /* Ready Int Clear */ + + hw_usb_clear_sts_brdy(pipe_no); + + /* NotReady Int Clear */ + + hw_usb_clear_status_nrdy(pipe_no); + + /* Empty/SizeErr Int Clear */ + + hw_usb_clear_status_bemp(pipe_no); +} + +/**************************************************************************** + * Name: hw_usb_clear_status_bemp + * + * Description: + * Clear BEMP status + * + ****************************************************************************/ + +static void hw_usb_clear_status_bemp (uint16_t pipeno) +{ + rx65n_putreg16((~(1 << pipeno)) & RX65N_USB_PIPE_ALL, + RX65N_USB_BEMPSTS); +} + +/**************************************************************************** + * Name: usb_pstd_detach_process + * + * Description: + * Set the DPRPU bit + * + ****************************************************************************/ + +void usb_pstd_detach_process (void) +{ + int i; + + /* Pull-up disable */ + + hw_usb_pclear_dprpu(); + for (i = USB_MIN_PIPE_NO; i < (USB_MAXPIPE_NUM +1); i++) + { + usb_pstd_forced_termination(i, (uint16_t) USB_DATA_STOP); + usb_cstd_clr_pipe_cnfg(i); + } + + usb_pstd_forced_termination(i, (uint16_t) USB_DATA_STOP); + usb_cstd_clr_pipe_cnfg(i); +} + +/**************************************************************************** + * Name: usb_pstd_chk_vbsts + * + * Description: + * USB VBUS Status check + * + ****************************************************************************/ + +uint16_t usb_pstd_chk_vbsts (void) +{ + uint16_t buf1; + uint16_t buf2; + uint16_t buf3; + uint16_t connect_info; + + /* VBUS chattering cut */ + + /* WAIT_LOOP */ + + do + { + buf1 = rx65n_getreg16(RX65N_USB_INTSTS0); + up_udelay(10); + buf2 = rx65n_getreg16(RX65N_USB_INTSTS0); + up_udelay(10); + buf3 = rx65n_getreg16(RX65N_USB_INTSTS0); + } + while (((buf1 & RX65N_USB_INTSTS0_VBSTS) != + (buf2 & RX65N_USB_INTSTS0_VBSTS)) || + ((buf2 & RX65N_USB_INTSTS0_VBSTS) != + (buf3 & RX65N_USB_INTSTS0_VBSTS))); + + if ((uint16_t) 0 != (buf1 & RX65N_USB_INTSTS0_VBSTS)) + { + /* Attach */ + + connect_info = USB_ATTACH; + } + + else + { + /* Detach */ + + connect_info = USB_DETACH; + } + + return connect_info; +} + +/**************************************************************************** + * Name: hw_usb_read_dvstctr + * + * Description: + * Read DVSTCTR register + * + ****************************************************************************/ + +static uint16_t hw_usb_read_dvstctr () +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_DVSTCTR0); + + return regval; +} + +/**************************************************************************** + * Name: usb_cstd_port_speed + * + * Description: + * Set Port Speed for USB device + * + ****************************************************************************/ + +uint16_t usb_cstd_port_speed () +{ + uint16_t buf; + uint16_t conn_inf; + + buf = hw_usb_read_dvstctr(); + + /* Reset handshake status get */ + + buf = (uint16_t) (buf & USB_RHST); + + switch (buf) + { + /* Get port speed */ + + case USB_HSMODE : + conn_inf = USB_HSCONNECT; + break; + case USB_FSMODE : + conn_inf = USB_FSCONNECT; + break; + case USB_LSMODE : + conn_inf = USB_LSCONNECT; + break; + case USB_HSPROC : + conn_inf = USB_NOCONNECT; + break; + default : + conn_inf = USB_NOCONNECT; + break; + } + + return (conn_inf); +} + +/**************************************************************************** + * Name: hw_usb_write_dcpcfg + * + * Description: + * Write to DCPCFG register + * + ****************************************************************************/ + +static void hw_usb_write_dcpcfg (uint16_t data) +{ + rx65n_putreg16(data, RX65N_USB_DCPCFG); +} + +/**************************************************************************** + * Name: hw_usb_write_dcpmxps + * + * Description: + * Write to DCPMAXP register + * + ****************************************************************************/ + +static void hw_usb_write_dcpmxps (uint16_t data) +{ + rx65n_putreg16(data, RX65N_USB_DCPMAXP); +} + +/**************************************************************************** + * Name: usb_pstd_bus_reset + * + * Description: + * Bus Reset + * + ****************************************************************************/ + +void usb_pstd_bus_reset (void) +{ + struct rx65n_usbdev_s *priv = &g_usbdev; + priv->usbdev.speed = USB_SPEED_FULL; + + /* DCP configuration register (0x5C) */ + + hw_usb_write_dcpcfg(0); + hw_usb_write_dcpmxps(USB_DCPMAXP); +} + +/**************************************************************************** + * Name: hw_usb_pset_enb_rsme + * + * Description: + * Enable Resume Interrupt + * + ****************************************************************************/ + +void hw_usb_pset_enb_rsme(void) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_INTENB0); + regval |= USB_RSME; + rx65n_putreg16(regval, RX65N_USB_INTENB0); +} + +/**************************************************************************** + * Name: hw_usb_read_syssts + * + * Description: + * Read System Status Register + * + ****************************************************************************/ + +static int hw_usb_read_syssts () +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_SYSSTS0); + + return regval; +} + +/**************************************************************************** + * Name: hw_usb_pclear_enb_rsme + * + * Description: + * Disable Resume Interrupt + * + ****************************************************************************/ + +void hw_usb_pclear_enb_rsme(void) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_INTENB0); + regval &= (~USB_RSME); + rx65n_putreg16(regval, RX65N_USB_INTENB0); +} + +/**************************************************************************** + * Name: hw_usb_pclear_sts_resm + * + * Description: + * Clear Resume state + * + ****************************************************************************/ + +void hw_usb_pclear_sts_resm(void) +{ + uint16_t regval; + regval = (uint16_t)(~USB_RESM); + rx65n_putreg16(regval, RX65N_USB_INTSTS0); +} + +/**************************************************************************** + * Name: usb_pstd_suspend_process + * + * Description: + * Handle Suspend State of USB + * + ****************************************************************************/ + +void usb_pstd_suspend_process (void) +{ + /* Resume interrupt enable */ + + hw_usb_pset_enb_rsme(); + hw_usb_pclear_sts_resm(); + + /* RESM interrupt disable */ + + hw_usb_pclear_enb_rsme(); +} + +/**************************************************************************** + * Name: hw_usb_pclear_sts_valid + * + * Description: + * Clear Valid Ststus bit + * + ****************************************************************************/ + +void hw_usb_pclear_sts_valid(void) +{ + uint16_t regval; + + regval = (uint16_t)~USB_VALID; + rx65n_putreg16(regval, RX65N_USB_INTSTS0); +} + +/**************************************************************************** + * Name: hw_usb_read_usbreq + * + * Description: + * Read USBREQ + * + ****************************************************************************/ + +uint16_t hw_usb_read_usbreq(void) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_USBREQ); + + return regval; +} + +/**************************************************************************** + * Name: hw_usb_read_usbval + * + * Description: + * Read USBVAL + * + ****************************************************************************/ + +uint16_t hw_usb_read_usbval(void) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_USBVAL); + + return regval; +} + +/**************************************************************************** + * Name: hw_usb_read_usbindx + * + * Description: + * Read USBINDX + * + ****************************************************************************/ + +uint16_t hw_usb_read_usbindx(void) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_USBINDX); + + return regval; +} + +/**************************************************************************** + * Name: hw_usb_read_usbleng + * + * Description: + * Read USBLENG + * + ****************************************************************************/ + +uint16_t hw_usb_read_usbleng(void) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_USBLENG); + + return regval; +} + +/**************************************************************************** + * Name: usb_pstd_save_request + * + * Description: + * Save the request + * + ****************************************************************************/ + +void usb_pstd_save_request(void) +{ + /* Valid clear */ + + hw_usb_pclear_sts_valid(); + + g_usb_pstd_req_type = hw_usb_read_usbreq(); + g_usb_pstd_req_value = hw_usb_read_usbval(); + g_usb_pstd_req_index = hw_usb_read_usbindx(); + g_usb_pstd_req_length = hw_usb_read_usbleng(); +} + +/**************************************************************************** + * Name: usb_pstd_set_stall + * + * Description: + * Set Stall status + * + ****************************************************************************/ + +void usb_pstd_set_stall(uint16_t pipe) +{ + /* PIPE control reg set */ + + hw_usb_set_pid(pipe, USB_PID_STALL); +} + +/**************************************************************************** + * Name: hw_usb_set_pid + * + * Description: + * Set PID + * + ****************************************************************************/ + +static void hw_usb_set_pid (uint16_t pipeno, uint16_t data) +{ + uint16_t *p_reg; + + if (USB_PIPE0 == pipeno) + { + p_reg = ((uint16_t *)(RX65N_USB_DCPCTR)); + } + else + { + p_reg = ((uint16_t *)(RX65N_USB_PIPE1CTR)) + ((pipeno - 1)); + } + + (*p_reg) &= (~USB_PID); + (*p_reg) |= data; +} + +/**************************************************************************** + * Name: hw_usb_pset_ccpl + * + * Description: + * Set CCPL + * + ****************************************************************************/ + +void hw_usb_pset_ccpl(void) +{ + uint16_t regval; + + regval = rx65n_getreg16(RX65N_USB_DCPCTR); + regval |= USB_CCPL; + rx65n_putreg16(regval, RX65N_USB_DCPCTR); +} + +/**************************************************************************** + * Name: usb_pstd_ctrl_end + * + * Description: + * CTRL End + * + ****************************************************************************/ + +void usb_pstd_ctrl_end (uint16_t status) +{ + /* Interrupt disable */ + + /* BEMP0 disable */ + + hw_usb_clear_bempenb((uint16_t) USB_PIPE0); + + /* BRDY0 disable */ + + hw_usb_clear_brdyenb((uint16_t) USB_PIPE0); + + /* NRDY0 disable */ + + hw_usb_clear_nrdyenb((uint16_t) USB_PIPE0); + + hw_usb_set_mbw(USB_CUSE, USB0_CFIFO_MBW); + + if ((USB_DATA_ERR == status) || (USB_DATA_OVR == status)) + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + + else if (USB_DATA_STOP == status) + { + /* Pipe stop */ + + usb_cstd_set_nak((uint16_t) USB_PIPE0); + } + + else + { + /* Set CCPL bit */ + + hw_usb_pset_ccpl(); + } +} + +/**************************************************************************** + * Name: usb_pstd_set_feature3 + * + * Description: + * Handles the set feature request + * + ****************************************************************************/ + +static void usb_pstd_set_feature3 (void) +{ + uint16_t pipe; + uint16_t ep; + + if (0 == g_usb_pstd_req_length) + { + /* check request type */ + + switch ((g_usb_pstd_req_type & USB_BMREQUESTTYPERECIP)) + { + case USB_DEVICE : + switch (g_usb_pstd_req_value) + { + case USB_DEV_REMOTE_WAKEUP : + if (0 == g_usb_pstd_req_index) + { + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + break; + case USB_TEST_MODE : + if (USB_HSCONNECT == usb_cstd_port_speed()) + { + if ((g_usb_pstd_req_index < USB_TEST_RESERVED) + || (USB_TEST_VSTMODES <= g_usb_pstd_req_index)) + { + g_usb_pstd_test_mode_flag = USB_TRUE; + g_usb_pstd_test_mode_select = g_usb_pstd_req_index; + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + break; + default : + usb_pstd_set_stall_pipe0(); + break; + } + break; + case USB_INTERFACE : + + /* Set pipe USB_PID_STALL */ + + usb_pstd_set_stall_pipe0(); + break; + case USB_ENDPOINT : + + /* Endpoint number */ + + ep = (uint16_t) (g_usb_pstd_req_index & USB_EPNUMFIELD); + if (USB_ENDPOINT_HALT == g_usb_pstd_req_value) + { + /* EP0 */ + + if (0 == ep) + { + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + + /* EP1 to max */ + + else if (ep <= USB_MAX_EP_NO) + { + pipe = usb_pstd_epadr2pipe(g_usb_pstd_req_index); + if (USB_ERROR == pipe) + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + else + { + /* Set pipe USB_PID_STALL */ + + usb_pstd_set_stall(pipe); + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + break; + + default : + + /* Request error */ + + usb_pstd_set_stall_pipe0(); + break; + } + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } +} + +/**************************************************************************** + * Name: usb_pstd_clr_feature3 + * + * Description: + * Handles the clear feature request + * + ****************************************************************************/ + +static void usb_pstd_clr_feature3 (void) +{ + uint16_t pipe; + uint16_t ep; + + if (0 == g_usb_pstd_req_length) + { + /* check request type */ + + switch ((g_usb_pstd_req_type & USB_BMREQUESTTYPERECIP)) + { + case USB_DEVICE : + if ((USB_DEV_REMOTE_WAKEUP == g_usb_pstd_req_value) + && (0 == g_usb_pstd_req_index)) + { + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + break; + case USB_INTERFACE : + + /* Request error */ + + usb_pstd_set_stall_pipe0(); + break; + + case USB_ENDPOINT : + + /* Endpoint number */ + + ep = (uint16_t) (g_usb_pstd_req_index & USB_EPNUMFIELD); + if (USB_ENDPOINT_HALT == g_usb_pstd_req_value) + { + /* EP0 */ + + if (0 == ep) + { + /* Stall clear */ + + usb_cstd_clr_stall((uint16_t) USB_PIPE0); + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + + /* EP1 to max */ + + else if (ep <= USB_MAX_EP_NO) + { + pipe = usb_pstd_epadr2pipe(g_usb_pstd_req_index); + if (USB_ERROR == pipe) + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + else + { + if (USB_PID_BUF == usb_cstd_get_pid(pipe)) + { + usb_cstd_set_nak(pipe); + + /* SQCLR=1 */ + + hw_usb_set_sqclr(pipe); + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf(pipe); + } + else + { + usb_cstd_clr_stall(pipe); + + /* SQCLR=1 */ + + hw_usb_set_sqclr(pipe); + } + + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + if (USB_TRUE == g_usb_pstd_stall_pipe[pipe]) + { + g_usb_pstd_stall_pipe[pipe] = USB_FALSE; + } + } + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } + break; + default : + usb_pstd_set_stall_pipe0(); + break; + } + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } +} + +/**************************************************************************** + * Name: usb_pstd_set_address3 + * + * Description: + * Handles the Set Address request + * + ****************************************************************************/ + +static void usb_pstd_set_address3 (void) +{ + if (USB_DEVICE == (g_usb_pstd_req_type & USB_BMREQUESTTYPERECIP)) + { + if ((0 == g_usb_pstd_req_index) && (0 == g_usb_pstd_req_length)) + { + if (g_usb_pstd_req_value <= 127) + { + /* Set pipe PID_BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Not specification */ + + usb_pstd_set_stall_pipe0(); + } + } + else + { + /* Request error */ + + usb_pstd_set_stall_pipe0(); + } +} + +/**************************************************************************** + * Name: usb_pstd_stand_req3 + * + * Description: + * Handle standard request + * + ****************************************************************************/ + +void usb_pstd_stand_req3 (void) +{ + uint16_t regval; + struct rx65n_usbdev_s *priv = &g_usbdev; + regval = MSBYTE(g_usb_pstd_req_type); + + switch (regval) + { + case USB_REQ_CLEARFEATURE : + usb_pstd_clr_feature3(); + break; + + case USB_REQ_SETFEATURE : + usb_pstd_set_feature3(); + break; + + case USB_REQ_SETADDRESS : + usb_pstd_set_address3(); + break; + + case USB_REQ_SETCONFIGURATION : + usb_cstd_set_buf((uint16_t) USB_PIPE0); /* SetConfiguration3 */ + break; + + case USB_REQ_SETINTERFACE : + /* Let the class implementation handle + * as it requires access and updation of + * Configuration descriptor + */ + + rx65n_dispatchrequest(priv); + break; + + default : + break; + } + + usb_pstd_ctrl_end((uint16_t) USB_CTRL_END); /* Control transfer stop(end) */ +} + +/**************************************************************************** + * Name: usb_pstd_stand_req4 + * + * Description: + * Handle standard request + * + ****************************************************************************/ + +void usb_pstd_stand_req4 (void) +{ + uint16_t regval; + + regval = MSBYTE(g_usb_pstd_req_type); + switch (regval) + { + case USB_REQ_GETSTATUS : + usb_cstd_set_buf((uint16_t) USB_PIPE0); /* GetStatus4 */ + break; + + case USB_REQ_GETDESCRIPTOR : + usb_cstd_set_buf((uint16_t) USB_PIPE0); /* GetDescriptor4 */ + break; + + case USB_REQ_GETCONFIGURATION : + usb_cstd_set_buf((uint16_t) USB_PIPE0); /* GetConfiguration4 */ + break; + + case USB_REQ_GETINTERFACE : + usb_cstd_set_buf((uint16_t) USB_PIPE0); /* GetInterface4 */ + break; + + case USB_REQ_SYNCHFRAME : + usb_cstd_set_buf((uint16_t) USB_PIPE0); /* SynchFrame4 */ + break; + + default : + break; + } + + usb_pstd_ctrl_end((uint16_t) USB_CTRL_END); +} + +/**************************************************************************** + * Name: usb_peri_class_request + * + * Description: + * Handle Class Request + * + ****************************************************************************/ + +void usb_peri_class_request(uint8_t type, uint16_t ctsq) +{ + if ((USB_CLASS == (type & USB_BMREQUESTTYPETYPE)) || + (USB_VENDOR == (type & USB_BMREQUESTTYPETYPE))) + { + switch (ctsq) + { + case USB_CS_IDST : + case USB_CS_RDDS : + case USB_CS_WRDS : + + /* Do Nothing */ + + break; + case USB_CS_WRND : + usb_pstd_ctrl_end((uint16_t) USB_CTRL_END); /* class request (control write nodata status stage) */ + break; + + case USB_CS_RDSS : + usb_cstd_set_buf((uint16_t) USB_PIPE0); + usb_pstd_ctrl_end((uint16_t) USB_CTRL_END); /* class request (control read status stage) */ + break; + + case USB_CS_WRSS : + usb_cstd_set_buf((uint16_t) USB_PIPE0); + usb_pstd_ctrl_end((uint16_t) USB_CTRL_END); /* class request (control write status stage) */ + break; + + case USB_CS_SQER : + usb_pstd_ctrl_end((uint16_t) USB_DATA_ERR); /* End control transfer. */ + break; + + default : + usb_pstd_ctrl_end((uint16_t) USB_DATA_ERR); /* End control transfer. */ + break; + } + } +} + +/**************************************************************************** + * Name: hw_usb_read_fifo16 + * + * Description: + * Read FIFO16 + * + ****************************************************************************/ + +static uint16_t hw_usb_read_fifo16 (uint16_t pipemode) +{ + uint16_t data = 0; + switch (pipemode) + { + case USB_CUSE: + data = USB0.CFIFO.WORD; + break; + + default: + break; + } + + return data; +} + +/**************************************************************************** + * Name: usb_pstd_read_fifo + * + * Description: + * Read FIFO + * + ****************************************************************************/ + +uint8_t *usb_pstd_read_fifo(uint16_t count, uint16_t pipemode, + uint8_t *read_p) +{ + uint16_t even; + uint32_t odd_byte_data_temp; + + /* WAIT_LOOP */ + + for (even = (uint16_t)(count >> 1); (0 != even); --even) + { + /* 16bit FIFO access */ + + *(uint16_t *)read_p = hw_usb_read_fifo16(pipemode); + + /* Renewal read pointer */ + + read_p += sizeof(uint16_t); + } + + if ((count & (uint16_t)0x0001) != 0) + { + /* 16bit FIFO access */ + + odd_byte_data_temp = hw_usb_read_fifo16(pipemode); + + *read_p = LSBYTE(odd_byte_data_temp); + + /* Renewal read pointer */ + + read_p += sizeof(uint8_t); + } + + return read_p; +} + +/**************************************************************************** + * Name: usb_pstd_read_data + * + * Description: + * Read data + * + ****************************************************************************/ + +uint16_t usb_pstd_read_data(uint16_t pipe, uint16_t pipemode) +{ + uint16_t count; + uint16_t buf; + uint16_t mxps; + uint16_t dtln; + uint16_t end_flag; + + if (USB_MAXPIPE_NUM < pipe) + { + return USB_ERROR; /* Error */ + } + + /* Changes FIFO port by the pipe. */ + + buf = usb_cstd_is_set_frdy(pipe, (uint16_t)pipemode, USB_FALSE); + + if (USB_ERROR == buf) + { + /* FIFO access error */ + + return (USB_ERROR); + } + + dtln = (uint16_t)(buf & USB_DTLN); + + /* Max Packet Size */ + + mxps = usb_cstd_get_maxpacket_size(pipe); + + g_usb_pstd_data_cnt[pipe] = RX65N_MAXPACKET_SIZE; + + if (g_usb_pstd_data_cnt[pipe] < dtln) + { + /* Buffer Over ? */ + + end_flag = USB_READOVER; + + /* Set NAK */ + + usb_cstd_set_nak(pipe); + count = (uint16_t)g_usb_pstd_data_cnt[pipe]; + g_usb_pstd_data_cnt[pipe] = dtln; + } + else if (g_usb_pstd_data_cnt[pipe] == dtln) + { + /* Just Receive Size */ + + count = dtln; + if ((USB_PIPE0 == pipe) && (0 == (dtln % mxps))) + { + /* Just Receive Size */ + + /* Peripheral Function */ + + end_flag = USB_READING; + } + else + { + end_flag = USB_READEND; + + /* Set NAK */ + + usb_cstd_set_nak(pipe); + } + } + else + { + /* Continuous Receive data */ + + count = dtln; + end_flag = USB_READING; + if (0 == count) + { + /* Null Packet receive */ + + end_flag = USB_READSHRT; + + /* Select NAK */ + + usb_cstd_set_nak(pipe); + } + + if (0 != (count % mxps)) + { + /* Null Packet receive */ + + end_flag = USB_READSHRT; + + /* Select NAK */ + + usb_cstd_set_nak(pipe); + } + } + + if (0 == dtln) + { + /* 0 length packet */ + + /* Clear BVAL */ + + hw_usb_set_bclr(pipemode); + } + else + { + gp_usb_pstd_data[2] = g_buffer; + gp_usb_pstd_data[pipe] = usb_pstd_read_fifo(count, pipemode, + gp_usb_pstd_data[pipe]); + } + + g_usb_pstd_data_cnt[pipe] -= count; + + /* End or Err or Continue */ + + return (end_flag); +} + +/**************************************************************************** + * Name: usb_pstd_fifo_to_buf + * + * Description: + * FIFO to BUF + * + ****************************************************************************/ + +void usb_pstd_fifo_to_buf(uint16_t pipe, uint16_t useport) +{ + uint16_t end_flag; + + end_flag = USB_ERROR; + + if (USB_MAXPIPE_NUM < pipe) + { + return; /* Error */ + } + + end_flag = usb_pstd_read_data(pipe, useport); + + /* Check FIFO access sequence */ + + switch (end_flag) + { + case USB_READING: + + /* Continue of data read */ + + break; + + case USB_READEND: + + /* End of data read */ + + usb_pstd_data_end(pipe, (uint16_t)USB_DATA_OK); + break; + + case USB_READSHRT: + + /* End of data read */ + + usb_pstd_data_end(pipe, (uint16_t)USB_DATA_SHT); + break; + + case USB_READOVER: + + /* Buffer over */ + + usb_pstd_forced_termination(pipe, (uint16_t)USB_DATA_OVR); + break; + + case USB_ERROR: + + /* FIFO access error */ + + usb_pstd_forced_termination(pipe, (uint16_t)USB_DATA_ERR); + break; + + default: + usb_pstd_forced_termination(pipe, (uint16_t)USB_DATA_ERR); + break; + } +} + +/**************************************************************************** + * Name: usb_pstd_brdy_pipe_process + * + * Description: + * Handle BRDY Pipe for Data + * + ****************************************************************************/ + +void usb_pstd_brdy_pipe_process(uint16_t bitsts) +{ + uint16_t useport; + uint16_t i; + + /* WAIT_LOOP */ + + for (i = USB_MIN_PIPE_NO; i <= USB_MAXPIPE_NUM; i++) + { + if (0u != (bitsts & USB_BITSET(i))) + { + /* Interrupt check */ + + hw_usb_clear_sts_brdy (i); + hw_usb_clear_status_bemp(i); + + if (USB_NULL != g_p_usb_pstd_pipe[i]) + { + /* Pipe number to FIFO port select */ + + useport = usb_pstd_pipe2fport(i); + + if (USB_CUSE == useport) + { + if (USB_BUF2FIFO == usb_cstd_get_pipe_dir(i)) + { + /* Buffer to FIFO data write */ + + usb_pstd_buf_to_fifo(i, useport); + } + else + { + /* FIFO to Buffer data read */ + + usb_pstd_fifo_to_buf(i, useport); + } + } + } + } + } +} + +/**************************************************************************** + * Name: usb_pstd_brdy_pipe + * + * Description: + * Handle BRDY Interupt + * + ****************************************************************************/ + +void usb_pstd_brdy_pipe (uint16_t bitsts, struct rx65n_usbdev_s *priv, + struct rx65n_ep_s *privep, uint16_t epno) +{ + uint32_t nbytes; + + if (USB_BRDY0 == (rx65n_getreg16(RX65N_USB_BRDYSTS) & USB_BRDY0)) + { + hw_usb_clear_sts_brdy (USB_PIPE0); + g_usb_pstd_data_cnt[0] = CDC_CLASS_DATA_LENGTH; + + switch (usb_pstd_read_data(USB_PIPE0, USB_CUSE)) + { + /* End of data read */ + + case USB_READEND : + + /* Continue */ + + /* End of data read */ + + case USB_READSHRT : + hw_usb_clear_brdyenb((uint16_t) USB_PIPE0); + break; + + /* Continue of data read */ + + case USB_READING : + + /* PID = BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + break; + + /* FIFO access error */ + + case USB_READOVER : + + /* Clear BVAL */ + + hw_usb_set_bclr(USB_CUSE); + + /* Control transfer stop(end) */ + + usb_pstd_ctrl_end((uint16_t) USB_DATA_OVR); + break; + + /* FIFO access error */ + + case USB_ERROR : + + /* Control transfer stop(end) */ + + usb_pstd_ctrl_end((uint16_t) USB_DATA_ERR); + break; + default : + break; + } + } + else + { + /* not PIPE0 */ + + usb_pstd_brdy_pipe_process(bitsts); + epno = BULK_IN_EPNUM; + nbytes = (RX65N_USB_MAXP) - g_usb_pstd_data_cnt[BULK_OUT_PIPE]; + usb_data_write(epno, g_buffer, nbytes); + rx65n_putreg16(0, RX65N_USB_BRDYSTS); + privep->head->req.buf = g_buffer; + + /* EP3 is passed, because for read(), + * the endpoint list should + * always point to bulk out endpoint + */ + + privep = &priv->eplist[EP3]; + usb_data_read(g_buffer, RX65N_MAXPACKET_SIZE); + bytesread = nbytes; + + /* The rx65n_rdrequest() function is invoked here + * to handle application specific read() + * and invoke the reqcomplete() function + * which further, unblocks the semaphore waiting + * on read() + * Failing to invoke this function will result, + * in failiure of application specific read + * + */ + + rx65n_rdrequest(epno, priv, privep); + bytesread = 0; + } +} + +/**************************************************************************** + * Name: usb_cstd_get_pid + * + * Description: + * Get PID + * + ****************************************************************************/ + +static uint16_t usb_cstd_get_pid (uint16_t pipe) +{ + uint16_t buf; + + if (USB_MAXPIPE_NUM < pipe) + { + return USB_NULL; /* Error */ + } + + /* PIPE control reg read */ + + buf = hw_usb_read_pipectr(pipe); + return (uint16_t) (buf & USB_PID); +} + +/**************************************************************************** + * Name: usb_pstd_bemp_pipe_process + * + * Description: + * BEMP Interrupt Handling for Pipe + * + ****************************************************************************/ + +void usb_pstd_bemp_pipe_process(uint16_t bitsts) +{ + uint16_t buf; + uint16_t i; + + /* WAIT_LOOP */ + + for (i = USB_MIN_PIPE_NO; i <= USB_PIPE5; i++) + { + if (0 != (bitsts & USB_BITSET(i))) + { + hw_usb_clear_status_bemp (i); + + /* Interrupt check */ + + if ((USB_NULL != g_p_usb_pstd_pipe[i])) + { + buf = usb_cstd_get_pid(i); + + /* MAX packet size error ? */ + + if (USB_PID_STALL == (buf & USB_PID_STALL)) + { + usb_pstd_forced_termination(i, (uint16_t)USB_DATA_STALL); + } + else + { + if (USB_INBUFM != (hw_usb_read_pipectr(i) & USB_INBUFM)) + { + usb_pstd_data_end(i, (uint16_t)USB_DATA_NONE); + } + else + { + /* set BEMP enable */ + + hw_usb_set_bempenb(i); + } + } + } + } + } + + /* WAIT_LOOP */ + + for (i = USB_PIPE6; i <= USB_MAXPIPE_NUM; i++) + { + /* Interrupt check */ + + if (0 != (bitsts & USB_BITSET(i))) + { + if (USB_NULL != g_p_usb_pstd_pipe[i]) + { + buf = usb_cstd_get_pid(i); + + /* MAX packet size error ? */ + + if (USB_PID_STALL == (buf & USB_PID_STALL)) + { + usb_pstd_forced_termination(i, (uint16_t)USB_DATA_STALL); + } + else + { + /* End of data transfer */ + + usb_pstd_data_end(i, (uint16_t)USB_DATA_NONE); + } + } + } + } +} + +/**************************************************************************** + * Name: usb_pstd_bemp_pipe + * + * Description: + * BEMP Interrupt Handling + * + ****************************************************************************/ + +void usb_pstd_bemp_pipe (uint16_t bitsts) +{ + if (USB_BEMP0 == (bitsts & USB_BEMP0)) + { + switch (usb_pstd_write_data(USB_PIPE0, USB_CUSE)) + { + /* End of data write (not null) */ + + case USB_WRITEEND : + + /* Continue */ + + /* End of data write */ + + case USB_WRITESHRT : + + /* Enable empty interrupt */ + + hw_usb_clear_bempenb((uint16_t) USB_PIPE0); + break; + + /* Continue of data write */ + + case USB_WRITING : + + /* PID = BUF */ + + usb_cstd_set_buf((uint16_t) USB_PIPE0); + break; + + /* FIFO access error */ + + case USB_ERROR : + + /* Control transfer stop(end) */ + + usb_pstd_ctrl_end((uint16_t) USB_DATA_ERR); + break; + + default : + break; + } + } + else + { + /* BEMP interrupt */ + + usb_pstd_bemp_pipe_process(bitsts); + } +} + +/**************************************************************************** + * Name: hw_usb_read_frmnum + * + * Description: + * Read Framenum + * + ****************************************************************************/ + +static uint16_t hw_usb_read_frmnum () +{ + return rx65n_getreg16(RX65N_USB_FRMNUM); +} + +/**************************************************************************** + * Name: usb_pstd_nrdy_pipe_process + * + * Description: + * NRDY Pipe Prrocess + * + ****************************************************************************/ + +void usb_pstd_nrdy_pipe_process(uint16_t bitsts) +{ + uint16_t buf; + uint16_t i; + + /* WAIT_LOOP */ + + for (i = USB_MIN_PIPE_NO; i <= USB_MAXPIPE_NUM; i++) + { + if (0 != (bitsts & USB_BITSET(i))) + { + /* Interrupt check */ + + if (USB_NULL != g_p_usb_pstd_pipe[i]) + { + if (USB_TYPFIELD_ISO == usb_cstd_get_pipe_type(i)) + { + /* Wait for About 60ns */ + + buf = hw_usb_read_frmnum(); + if (USB_OVRN == (buf & USB_OVRN)) + { + /* @1 */ + + /* End of data transfer */ + + usb_pstd_forced_termination(i, (uint16_t)USB_DATA_OVR); + } + else + { + /* @2 */ + + /* End of data transfer */ + + usb_pstd_forced_termination(i, (uint16_t)USB_DATA_ERR); + } + } + else + { + /* Non processing. */ + } + } + } + } +} + +/**************************************************************************** + * Name: rx65n_usbdev_bottomhalf + * + * Description: + * BRDY handler in bottom half + * + ****************************************************************************/ + +static void rx65n_usbdev_bottomhalf (void *arg) +{ + struct rx65n_usbdev_s *priv = &g_usbdev; + uint32_t bottom_half_processing = (uint32_t)arg; + struct rx65n_ep_s *privep ; + + if (bottom_half_processing == USB_INT_BRDY) + { + uint16_t regval; + uint8_t epno; + uint16_t brdysts; + + brdysts = USB0.BRDYSTS.WORD; + regval = rx65n_getreg16(RX65N_USB_PIPECFG); + regval &= USB_EPNUMFIELD; + epno = regval; + privep = &priv->eplist[epno]; + usb_pstd_brdy_pipe(brdysts, priv, privep, epno); + } +} + +/**************************************************************************** + * Name: usb_pstd_nrdy_pipe + * + * Description: + * NRDY Interrupt handler + * + ****************************************************************************/ + +void usb_pstd_nrdy_pipe (uint16_t bitsts) +{ + /* Nrdy Pipe interrupt */ + + usb_pstd_nrdy_pipe_process(bitsts); +} + +/**************************************************************************** + * Name: rx65n_usbinterrupt + * + * Description: + * USB interrupt handler + * + ****************************************************************************/ + +static int rx65n_usbinterrupt(int irq, FAR void *context, FAR void *arg) +{ + struct rx65n_usbdev_s *priv = &g_usbdev; + + uint8_t type; + uint16_t ists0; + uint16_t intenb0; + uint16_t intsts0; + uint16_t stginfo; + uint16_t bempsts; + uint16_t nrdysts; + static uint32_t connected_times = 0; + + intenb0 = rx65n_getreg16(RX65N_USB_INTENB0); + + /* Read Interrupt Status and mask out interrupts that are not enabled. */ + + intsts0 = ((rx65n_getreg16(RX65N_USB_INTSTS0) & intenb0)); + nrdysts = rx65n_getreg16(RX65N_USB_NRDYSTS); + bempsts = rx65n_getreg16(RX65N_USB_BEMPSTS); + + /* Check VBUS */ + + if ((intsts0 & RX65N_USB_INTSTS0_VBINT) == RX65N_USB_INTSTS0_VBINT) + { + rx65n_putreg16 + (((~RX65N_USB_INTSTS0_VBINT) & INTSTS0_BIT_VALUES_TO_DETECT), + RX65N_USB_INTSTS0); + + if (USB_ATTACH == usb_pstd_chk_vbsts()) + { + priv->attached = 1; + connected_times ++; + syslog (LOG_INFO, "NuttX: USB Device Connected. %d\n", + connected_times); + uinfo("Device attached\n"); + usb_pstd_attach_process(); /* USB attach */ + } + else + { + priv->attached = 0; + syslog (LOG_INFO, "NuttX: USB Device Disconnected. %d\n", + connected_times); + usb_pstd_detach_process(); /* USB detach */ + if (priv->driver) + { + CLASS_DISCONNECT(priv->driver, &priv->usbdev); + } + } +} + + intsts0 = (rx65n_getreg16(RX65N_USB_INTSTS0)); + if ((intsts0 & RX65N_USB_INTSTS0_DVST) == RX65N_USB_INTSTS0_DVST) + { + rx65n_putreg16 + (((~RX65N_USB_INTSTS0_DVST) & INTSTS0_BIT_VALUES_TO_DETECT), + RX65N_USB_INTSTS0); + + switch ((uint16_t) (intsts0 & USB_DVSQ)) + { + /* Power state */ + + case USB_DS_POWR : + break; + + /* Default state */ + + case USB_DS_DFLT : + uinfo("USB-reset int peri\n"); + usb_pstd_bus_reset(); + break; + + /* Address state */ + + case USB_DS_ADDS : + break; + + /* Configured state */ + + case USB_DS_CNFG : + uinfo("Device configuration int peri\n"); + break; + + /* Power suspend state */ + + case USB_DS_SPD_POWR : + + /* Continue */ + + /* Default suspend state */ + + case USB_DS_SPD_DFLT : + + /* Continue */ + + /* Address suspend state */ + + case USB_DS_SPD_ADDR : + + /* Continue */ + + /* Configured Suspend state */ + + case USB_DS_SPD_CNFG : + uinfo("SUSPEND int peri\n"); + usb_pstd_suspend_process(); + break; + + /* Error */ + + default : + break; + } + } + + intsts0 = (rx65n_getreg16(RX65N_USB_INTSTS0)); + if ((intsts0 & RX65N_USB_INTSTS0_CTRT) == RX65N_USB_INTSTS0_CTRT) + { + rx65n_putreg16 + (((~RX65N_USB_INTSTS0_CTRT) & INTSTS0_BIT_VALUES_TO_DETECT), + RX65N_USB_INTSTS0); + + stginfo = (uint16_t) ((rx65n_getreg16(RX65N_USB_INTSTS0) & USB_CTSQ)); + + if (((USB_CS_RDDS == stginfo) || (USB_CS_WRDS == stginfo)) + || (USB_CS_WRND == stginfo)) + { + /* Save request register */ + + usb_pstd_save_request(); + } + + if (USB_REQ_TYPE_STANDARD == (g_usb_pstd_req_type & USB_BMREQUESTTYPETYPE)) + { + /* Switch on the control transfer stage (CTSQ). */ + + switch (stginfo) + { + /* Idle or setup stage */ + + uinfo("stginfo =%d\n", stginfo); + case USB_CS_IDST : + case USB_CS_RDDS : + case USB_CS_WRDS : + case USB_CS_WRSS : + + rx65n_ep0setup(priv); + break; + + case USB_CS_RDSS : + usb_pstd_stand_req4(); + break; + + case USB_CS_WRND : + usb_pstd_stand_req3(); + break; + + /* Control sequence error */ + + case USB_CS_SQER : + usb_pstd_ctrl_end((uint16_t) USB_DATA_ERR); + break; + + /* Illegal */ + + default : + usb_pstd_ctrl_end((uint16_t) USB_DATA_ERR); + break; + } + } + else + { + /* Vender Specific */ + + type = LSBYTE(rx65n_getreg16(RX65N_USB_USBREQ)); + rx65n_ep0setup(priv); + usb_peri_class_request(type, stginfo); + } + } + + ists0 = (uint16_t)(intsts0 & intenb0); + + /* BRDY Interrupt Check */ + + if (USB_BRDY == (ists0 & USB_BRDY)) + { + DEBUGVERIFY(work_queue(HPWORK, &g_usbdev.rx65n_interrupt_bhalf, + rx65n_usbdev_bottomhalf, + (void *)USB_INT_BRDY, 0)); + } + + /* BEMP Interrupt Check */ + + if ((USB_BEMP == (ists0 & USB_BEMP))) + { + usb_pstd_bemp_pipe_process(bempsts); + } + + /* NRDY Interrupt Check */ + + if ((((intsts0 & intenb0) & RX65N_USB_INTSTS0_NRDY)) == + RX65N_USB_INTSTS0_NRDY) + { + usb_pstd_nrdy_pipe(nrdysts); + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_usbinitialize + * + * Description: + * Initialize USB hardware + * + ****************************************************************************/ + +void up_usbinitialize(void) +{ + /* For now there is only one USB controller, but we will always refer to + * it using a pointer + */ + + struct rx65n_usbdev_s *priv = &g_usbdev; + uint32_t reg32; + uint16_t regval; + int epno; + usbtrace(TRACE_DEVINIT, 0); + + /* Enable write to System registers */ + + regval = rx65n_getreg16 (RX65N_PRCR_ADDR); + + rx65n_putreg16(RX65N_PRCR_VALUE, RX65N_PRCR_ADDR); + regval = rx65n_getreg16 (RX65N_PRCR_ADDR); + + /* Clear bit 19 - so that USB module is released from stop state */ + + reg32 = getreg32(RX65N_MSTPCRB_ADDR); + reg32 &= (~RX65N_MSTPCRB_START_STOP_USB); + putreg32(reg32, RX65N_MSTPCRB_ADDR); + + memset(priv, 0, sizeof(struct rx65n_usbdev_s)); + priv->usbdev.ops = &g_devops; + priv->usbdev.ep0 = &priv->eplist[EP0].ep; + priv->epavail = RX65N_ENDP_ALLSET & ~RX65N_ENDP_BIT(EP0); + + /* Initialize the endpoint list */ + + for (epno = 0; epno < RX65N_NENDPOINTS; epno++) + { + /* Set endpoint operations, reference to driver structure (not + * really necessary because there is only one controller), and + * the (physical) endpoint number which is just the index to the + * endpoint. + */ + + priv->eplist[epno].ep.ops = &g_epops; + priv->eplist[epno].dev = priv; + priv->eplist[epno].ep.eplog = epno; + + /* We will use a fixed maxpacket size for all endpoints (perhaps + * ISOC endpoints could have larger maxpacket???). A smaller + * packet size can be selected when the endpoint is configured. + */ + + priv->eplist[epno].ep.maxpacket = RX65N_MAXPACKET_SIZE; + } + + /* Select a smaller endpoint size for EP0 */ + +#if RX65N_EP0MAXPACKET < RX65N_MAXPACKET_SIZE + priv->eplist[EP0].ep.maxpacket = RX65N_EP0MAXPACKET; +#endif + + /* Set SCKE bit in SYSCFG Register */ + + regval = rx65n_getreg16 (RX65N_USB_SYSCFG); + regval |= (RX65N_USB_SYSCFG_SCKE); + rx65n_putreg16(regval, RX65N_USB_SYSCFG); + + regval = rx65n_getreg16 (RX65N_USB_PHYSLEW); + regval |= (RX65N_PHYSLEW_VALUE); + rx65n_putreg16(regval, RX65N_USB_PHYSLEW); + + /* Set USBE bit in SYSCFG register */ + + regval = rx65n_getreg16 (RX65N_USB_SYSCFG); + regval |= (RX65N_USB_SYSCFG_USBE); + rx65n_putreg16(regval, RX65N_USB_SYSCFG); + + /* Set MBW bit in CFIFOSEL register */ + + regval = rx65n_getreg16 (RX65N_USB_CFIFOSEL); + regval |= (RX65N_USB_CFIFOSEL_MBW_16); + rx65n_putreg16(regval, RX65N_USB_CFIFOSEL); + + /* Set MBW bit in D0FIFOSEL register */ + + regval = rx65n_getreg16 (RX65N_USB_D0FIFOSEL); + regval |= (RX65N_USB_D0FIFOSEL_MBW_16); + rx65n_putreg16(regval, RX65N_USB_D0FIFOSEL); + + /* Set MBW bit in D1FIFOSEL register */ + + regval = rx65n_getreg16 (RX65N_USB_D1FIFOSEL); + regval |= (RX65N_USB_D1FIFOSEL_MBW_16); + rx65n_putreg16(regval, RX65N_USB_D1FIFOSEL); + + /* Set the Interrupt enable bits in INTENB0 register */ + + regval = rx65n_getreg16 (RX65N_USB_INTENB0); + regval |= (RX65N_USB_INTENB0_BEMPE | RX65N_USB_INTENB0_BRDYE | + RX65N_USB_INTENB0_VBSE | RX65N_USB_INTENB0_DVSE | + RX65N_USB_INTENB0_CTRE); + rx65n_putreg16(regval, RX65N_USB_INTENB0); + + ICU.SLIBR185.BYTE = RX65N_USBI0_SOURCE; + + IPR(PERIB, INTB185) = RX65N_USBI0_PRIORITY; + + if (irq_attach(RX65N_INTB185_IRQ, rx65n_usbinterrupt, NULL) != 0) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_IRQREGISTRATION), + (uint16_t)RX65N_INTB185_IRQ); + } + + priv->usbdev.speed = USB_SPEED_FULL; + + syslog (LOG_INFO, "Debug:USB Device Initialized, Device connected:%s\n", + priv->attached ? "YES" : "NO"); +} + +/**************************************************************************** + * Name: up_usbuninitialize + * Description: + * Initialize the USB driver + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_usbuninitialize(void) +{ + struct rx65n_usbdev_s *priv = &g_usbdev; + + usbtrace(TRACE_DEVUNINIT, 0); + if (priv->driver) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_DRIVERREGISTERED), 0); + usbdev_unregister(priv->driver); + } + + priv->usbdev.speed = USB_SPEED_UNKNOWN; + + /* Disable and detach IRQs */ + + IEN(PERIB, INTB185) = 0U; + + irq_detach(RX65N_INTB185_IRQ); +} + +/**************************************************************************** + * Name: usbdevclass_register + * + * Description: + * Register a USB device class driver. The class driver's + * bind() method will be + * called to bind it to a USB device driver. + * + ****************************************************************************/ + +int usbdev_register(FAR struct usbdevclass_driver_s *driver) +{ + int ret; + + usbtrace(TRACE_DEVREGISTER, 0); + +#ifdef CONFIG_DEBUG_USB + if (!driver || !driver->ops->bind || !driver->ops->unbind || + !driver->ops->disconnect || !driver->ops->setup) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } + + if (g_usbdev.driver) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_DRIVER), 0); + return -EBUSY; + } +#endif + + /* First hook up the driver */ + + g_usbdev.driver = driver; + + /* Then bind the class driver */ + + ret = CLASS_BIND(driver, &g_usbdev.usbdev); + if (ret) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_BINDFAILED), (uint16_t)-ret); + g_usbdev.driver = NULL; + } + else + { + /* Enable USB controller interrupts */ + + IEN(PERIB, INTB185) = 1U; + } + + return ret; +} + +/**************************************************************************** + * Name: usbdev_unregister + * + * Description: + * Un-register usbdev class driver.If the USB device is connected + * to a USB host, it will first disconnect(). The driver is + * also requested to unbind() and clean + * up any device state, before this procedure finally returns. + * + ****************************************************************************/ + +int usbdev_unregister(FAR struct usbdevclass_driver_s *driver) +{ + usbtrace(TRACE_DEVUNREGISTER, 0); + +#ifdef CONFIG_DEBUG_FEATURES + if (driver != g_usbdev.driver) + { + usbtrace(TRACE_DEVERROR(RX65N_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + + /* Unbind the class driver */ + + CLASS_UNBIND(driver, &g_usbdev.usbdev); + + /* Disable IRQs */ + + IEN(PERIB, INTB185) = 0U; + + /* Unhook the driver */ + + g_usbdev.driver = NULL; + return OK; +} diff --git a/arch/renesas/src/rx65n/rx65n_usbdev.h b/arch/renesas/src/rx65n/rx65n_usbdev.h new file mode 100644 index 0000000000..485108c5f6 --- /dev/null +++ b/arch/renesas/src/rx65n/rx65n_usbdev.h @@ -0,0 +1,94 @@ +/**************************************************************************** + * arch/renesas/src/rx65n/rx65n_usbdev.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RENESAS_SRC_RX65N_USBDEV_H +#define __ARCH_RENESAS_SRC_RX65N_USBDEV_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "rx65n_definitions.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CDC_CLASS_DATA_LENGTH (7) +#define RW_DATA_LEN (1) +#define BULK_IN_PIPE (1) +#define INT_IN_PIPE (6) +#define INT_OUT_PIPE (7) +#define BULK_OUT_PIPE (2) + +/* The below endpoint numbers are assigned by + * NuttX Class Driver, during endpoint + * initialization. + * + */ + +#define BULK_IN_EPNUM (2) +#define INT_IN_EPNUM (1) +#define BULK_OUT_EPNUM (3) +#define INT_OUT_EPNUM (4) + +/* USB_BMREQUESTTYPERECIP 0x001Fu(b4-0) */ +#define USB_DEVICE (0x0000u) +#define USB_INTERFACE (0x0001u) +#define USB_ENDPOINT (0x0002u) +#define USB_OTHER (0x0003u) + +#define USB_DEV_REMOTE_WAKEUP (0x0001u) +#define USB_TEST_MODE (0x0002u) +#define USB_TEST_RESERVED (0x4000u) /* Reserved */ +#define USB_TEST_VSTMODES (0xC000u) /* VendorSpecific test modes */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* #if defined(CONFIG_USBHOST) && defined(RX65N_NUSBHOST) > 0 */ diff --git a/boards/renesas/rx65n/rx65n-grrose/README.txt b/boards/renesas/rx65n/rx65n-grrose/README.txt index 447a8c7219..01c3a99fc6 100644 --- a/boards/renesas/rx65n/rx65n-grrose/README.txt +++ b/boards/renesas/rx65n/rx65n-grrose/README.txt @@ -11,35 +11,10 @@ Contents - Serial Console - LEDs - Networking - - IPv6 Integration - - HTTP Server Integration on IPv4 - - DHCP Client Integration on IPv4 - - DHCP Server Integration on IPv4 - - FTP Server Integration on IPv4 - - FTP Client Integration on IPv4 - - TFTP Client Integration on IPv4 - - Telnet Server Integration on IPv4 - - Telnet Client Integration on IPv4 - - Ustream Socket Integration on IPv4 - - Udgram Socket Integration on IPv4 - - SMTP Client Integration on IPv4 - - Raw Socket Integration - - Custom User Socket Integration - - IGMPv2 Integration - - Inherit telnet server Integration - - VNC Server Integration - - PPPD Integration - - HTTP Client Integration - - NTP Client Integration - - NFS Client Integration - - MLD Integration - - ICMPv6 AutoConfig Integration - - IP Forwarding Integration for IPv4 - - DNS Name Resolution Integration for IPv4 - - LINK MONITOR Integration + - Contents - RTC - - File Systems - - Standby RAM + - USB Device + - Debugging - Debugging Board Features @@ -61,12 +36,6 @@ See the RX65N GRROSE website for further information about this board: - http://gadget.renesas.com/en/product/rose.html -Status/Open Issues -================== -Ethernet ---------- - - Serial Console ============== RX65N GRROSE supports 12 serial ports (SCI0 - SCI12), however only 5 ports can be tested(SCI0, SCI1, SCI2, @@ -262,6 +231,26 @@ The following configurations are to be enabled as part of testing RTC examples. CONFIG_EXAMPLES_ALARM CONFIG_EXAMPLES_PERIODIC CONFIG_EXAMPLES_CARRY + +USB Device Configurations +-------------------------- +The following configurations need to be enabled for USB Device + +CONFIG_USBDEV +CONFIG_CDCACM +CONFIG_STDIO_BUFFER_SIZE=64 +CONFIG_STDIO_LINEBUFFER + +USB Device Testing +------------------------ +The following testing is executed as part of USB Device testing on RX65N target for GRROSE board + +echo "This is a test for USB Device" > /dev/ttyACM0 + +xd 0 0x20000 > /dev/ttyACM0 + +The output of the commands mentioned above should be seen on the USB Device COM port on teraterm + Debugging ========== @@ -295,8 +284,3 @@ endif Select Motorola SREC format. 4. Download Renesas flash programmer tool from https://www.renesas.com/in/en/products/software-tools/tools/programmer/renesas-flash-programmer-programming-gui.html#downloads 5. Refer to the user manual document, for steps to flash NuttX binary using RFP tool. -Changes Made in NuttX 8.2 Code -================================ -1. In wd_start.c file, in function wd_expiration(), typecasting is done when the signal handler nxsig_timeout() is invoked. -2. In rtc.c, (drivers/timers/rtc.c) file, in function rtc_periodic_callback(), alarminfo->active = false is commented. -The reason being, periodic interrupt should not be disabled. Uncommenting the above mentioned line (alarminfo->active = false), will make the periodic interrupt come only once. diff --git a/boards/renesas/rx65n/rx65n-grrose/include/rx65n_gpio.h b/boards/renesas/rx65n/rx65n-grrose/include/rx65n_gpio.h index b5690540b7..a42bc121b0 100644 --- a/boards/renesas/rx65n/rx65n-grrose/include/rx65n_gpio.h +++ b/boards/renesas/rx65n/rx65n-grrose/include/rx65n_gpio.h @@ -103,6 +103,24 @@ void led_port_create(void); void r_ether_pheriperal_enable(void); #endif +/**************************************************************************** + * Name: r_usbdev_port_enable + * + * Description: + * USB device port settings + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV +void r_usbdev_port_enable(void); +#endif + /**************************************************************************** * Name: sci0_init_port * diff --git a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c index b366487ce4..a3712c0d7c 100644 --- a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c +++ b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c @@ -43,6 +43,10 @@ # include "rx65n_rtc.h" #endif +#ifdef CONFIG_CDCACM +# include +#endif + #ifdef HAVE_RIIC_DRIVER # include # include "rx65n_riic.h" @@ -136,6 +140,19 @@ int rx65n_bringup(void) (void)rx65n_sbram_int(); #endif + +#if defined(CONFIG_CDCACM) && !defined(CONFIG_CDCACM_CONSOLE) + /* Initialize CDCACM */ + + syslog(LOG_INFO, "Initialize CDCACM device\n"); + + ret = cdcacm_initialize(0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cdcacm_initialize failed: %d\n", ret); + } +#endif /* CONFIG_CDCACM & !CONFIG_CDCACM_CONSOLE */ + #ifdef HAVE_RIIC_DRIVER FAR struct i2c_master_s *i2c; diff --git a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_gpio.c b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_gpio.c index ef81b5926f..0b8a15f8c9 100644 --- a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_gpio.c +++ b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_gpio.c @@ -161,6 +161,23 @@ void r_ether_pheriperal_enable(void) } #endif +/**************************************************************************** + * Name: r_usbdev_port_enable + * + * Description: + * USB Device enabling + ****************************************************************************/ + +#ifdef CONFIG_USBDEV +void r_usbdev_port_enable(void) +{ + /* Set USB0_VBUS pin */ + + MPC.P16PFS.BYTE = 0x11; + PORT1.PMR.BIT.B6 = 1; +} +#endif + /**************************************************************************** * Name: sci0_init_port * diff --git a/boards/renesas/rx65n/rx65n-rsk2mb/README.txt b/boards/renesas/rx65n/rx65n-rsk2mb/README.txt index 8a181a78ee..4942279826 100644 --- a/boards/renesas/rx65n/rx65n-rsk2mb/README.txt +++ b/boards/renesas/rx65n/rx65n-rsk2mb/README.txt @@ -11,35 +11,8 @@ Contents - Serial Console - LEDs - Networking - - IPv6 Integration - - HTTP Server Integration on IPv4 - - DHCP Client Integration on IPv4 - - DHCP Server Integration on IPv4 - - FTP Server Integration on IPv4 - - FTP Client Integration on IPv4 - - TFTP Client Integration on IPv4 - - Telnet Server Integration on IPv4 - - Telnet Client Integration on IPv4 - - Ustream Socket Integration on IPv4 - - Udgram Socket Integration on IPv4 - - SMTP Client Integration on IPv4 - - Raw Socket Integration - - Custom User Socket Integration - - IGMPv2 Integration - - Inherit telnet server Integration - - VNC Server Integration - - PPPD Integration - - HTTP Client Integration - - NTP Client Integration - - NFS Client Integration - - MLD Integration - - ICMPv6 AutoConfig Integration - - IP Forwarding Integration for IPv4 - - DNS Name Resolution Integration for IPv4 - - LINK MONITOR Integration - RTC - - Standby RAM - - File Systems + - USB Device - Debugging Board Features @@ -59,14 +32,6 @@ See the RX65N RSK2MB website for further information about this board: - https://www.renesas.com/br/en/products/software-tools/boards-and-kits/starter-kits/renesas-starter-kitplus-for-rx65n-2mb.html -Status/Open Issues -================== -Ethernet ---------- -1.Observed instability in Link Management, due to difference in hardware design.(No Separate Interrupt line for PHY) -2.Currently tested only ping and udpblaster application. -3. Executed long run ping and udpblaster stress test for 12 hrs. Code is able to execute for 12hrs without any breakage. - Serial Console ============== RX65N RSK2MB supports 12 serial ports (SCI0 - SCI12), however only 1 port can be tested(SCI8, which is the serial console). Only SCI8 port can be tested which is connected to USB Serial port. @@ -146,6 +111,15 @@ Ethernet Connections P71 ET0_MDIO P54 ET0_LINKSTA ------ --------- + +USB Device +----------- + +For the RX65N RSK2MB board, to be used as USB Device, the following Jumper settings need to be done + +J7 Short Pin 2 & Pin 3 +J16 Short Pin 1 & Pin 2 + NuttX Configurations -------------------- The following configurations, need to be enabled for network. @@ -223,6 +197,25 @@ CONFIG_EXAMPLES_ALARM CONFIG_EXAMPLES_PERIODIC CONFIG_EXAMPLES_CARRY +USB Device Configurations +-------------------------- +The following configurations need to be enabled for USB Device + +CONFIG_USBDEV +CONFIG_CDCACM +CONFIG_STDIO_BUFFER_SIZE=64 +CONFIG_STDIO_LINEBUFFER + +USB Device Testing +------------------------ +The following testing is executed as part of USB Device testing on RX65N target for GRROSE board + +echo "This is a test for USB Device" > /dev/ttyACM0 + +xd 0 0x20000 > /dev/ttyACM0 + +The output of the commands mentioned above should be seen on the USB Device COM port on teraterm + Debugging ========== 1. NuttX needs to be compiled in Cygwin environment on Windows. diff --git a/boards/renesas/rx65n/rx65n-rsk2mb/include/rx65n_gpio.h b/boards/renesas/rx65n/rx65n-rsk2mb/include/rx65n_gpio.h index 16b336e3b0..40a87ece04 100644 --- a/boards/renesas/rx65n/rx65n-rsk2mb/include/rx65n_gpio.h +++ b/boards/renesas/rx65n/rx65n-rsk2mb/include/rx65n_gpio.h @@ -103,6 +103,24 @@ void led_port_create(void); void r_ether_pheriperal_enable(void); #endif +/**************************************************************************** + * Name: r_usbdev_port_enable + * + * Description: + * USB device port settings + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV +void r_usbdev_port_enable(void); +#endif + /**************************************************************************** * Name: sci1_init_port * diff --git a/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c index 25030f5c98..e9916fcdf8 100644 --- a/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c +++ b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c @@ -43,6 +43,10 @@ # include "rx65n_rtc.h" #endif +#ifdef CONFIG_CDCACM +# include +#endif + #ifdef HAVE_RIIC_DRIVER # include # include "rx65n_riic.h" @@ -136,6 +140,19 @@ int rx65n_bringup(void) (void)rx65n_sbram_int(); #endif + +#if defined(CONFIG_CDCACM) && !defined(CONFIG_CDCACM_CONSOLE) + /* Initialize CDCACM */ + + syslog(LOG_INFO, "Initialize CDCACM device\n"); + + ret = cdcacm_initialize(0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cdcacm_initialize failed: %d\n", ret); + } +#endif /* CONFIG_CDCACM & !CONFIG_CDCACM_CONSOLE */ + #ifdef HAVE_RIIC_DRIVER FAR struct i2c_master_s *i2c; diff --git a/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_gpio.c b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_gpio.c index c9d35ffbdb..7f2858302f 100644 --- a/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_gpio.c +++ b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_gpio.c @@ -197,6 +197,23 @@ void r_ether_pheriperal_enable(void) MPC.P34PFS.BYTE = 0x11u; PORT3.PMR.BIT.B4 = 1u; } + +#endif +/**************************************************************************** + * Name: r_usbdev_port_enable + * + * Description: + * USB Device enabling + ****************************************************************************/ + +#ifdef CONFIG_USBDEV +void r_usbdev_port_enable(void) +{ + /* Set USB0_VBUS pin */ + + MPC.P16PFS.BYTE = 0x11; + PORT1.PMR.BIT.B6 = 1; +} #endif /****************************************************************************