nxp tdi: hcd_init() reset and set host mode

This commit is contained in:
hathach 2021-02-23 01:27:52 +07:00
parent c5b8980398
commit de95585258
4 changed files with 185 additions and 150 deletions

View File

@ -157,51 +157,12 @@ void board_init(void)
Chip_UART_TXEnable(UART_DEV);
//------------- USB -------------//
enum {
USBMODE_DEVICE = 2,
USBMODE_HOST = 3
};
enum {
USBMODE_VBUS_LOW = 0,
USBMODE_VBUS_HIGH = 1
};
// USB0
#if CFG_TUSB_RHPORT0_MODE
Chip_USB0_Init();
// Host/Device mode can only be set right after controller reset
LPC_USB0->USBCMD_D |= 0x02;
while( LPC_USB0->USBCMD_D & 0x02 ) {}
// Set mode
#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
LPC_USB0->PORTSC1_H |= (1<<24); // FIXME force full speed for debugging
#else // TODO OTG
LPC_USB0->USBMODE_D = USBMODE_DEVICE;
LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
#endif
#endif
// USB1
#if CFG_TUSB_RHPORT1_MODE
Chip_USB1_Init();
// // Reset controller
// LPC_USB1->USBCMD_D |= 0x02;
// while( LPC_USB1->USBCMD_D & 0x02 ) {}
//
// // Set mode
// #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST
// LPC_USB1->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
// #else // TODO OTG
// LPC_USB1->USBMODE_D = USBMODE_DEVICE;
// #endif
//
// // USB1 as fullspeed
// LPC_USB1->PORTSC1_D |= (1<<24);
#endif
}

View File

@ -0,0 +1,136 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef COMMON_TRANSDIMENSION_H_
#define COMMON_TRANSDIMENSION_H_
#ifdef __cplusplus
extern "C" {
#endif
// USBCMD
enum {
USBCMD_RUN_STOP = TU_BIT(0),
USBCMD_RESET = TU_BIT(1),
USBCMD_SETUP_TRIPWIRE = TU_BIT(13),
USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoints linked list. This bit is set and cleared by software during the process of adding a new dTD
// Interrupt Threshold bit 23:16
};
// PORTSC1
#define PORTSC1_PORT_SPEED_POS 26
enum {
PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0),
PORTSC1_FORCE_PORT_RESUME = TU_BIT(6),
PORTSC1_SUSPEND = TU_BIT(7),
PORTSC1_FORCE_FULL_SPEED = TU_BIT(24),
PORTSC1_PORT_SPEED = TU_BIT(26) | TU_BIT(27)
};
// OTGSC
enum {
OTGSC_VBUS_DISCHARGE = TU_BIT(0),
OTGSC_VBUS_CHARGE = TU_BIT(1),
// OTGSC_HWASSIST_AUTORESET = TU_BIT(2),
OTGSC_OTG_TERMINATION = TU_BIT(3), ///< Must set to 1 when OTG go to device mode
OTGSC_DATA_PULSING = TU_BIT(4),
OTGSC_ID_PULLUP = TU_BIT(5),
// OTGSC_HWASSIT_DATA_PULSE = TU_BIT(6),
// OTGSC_HWASSIT_BDIS_ACONN = TU_BIT(7),
OTGSC_ID = TU_BIT(8), ///< 0 = A device, 1 = B Device
OTGSC_A_VBUS_VALID = TU_BIT(9),
OTGSC_A_SESSION_VALID = TU_BIT(10),
OTGSC_B_SESSION_VALID = TU_BIT(11),
OTGSC_B_SESSION_END = TU_BIT(12),
OTGSC_1MS_TOGGLE = TU_BIT(13),
OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14),
};
// USBMode
enum {
USBMODE_CM_DEVICE = 2,
USBMODE_CM_HOST = 3,
USBMODE_SLOM = TU_BIT(3),
USBMODE_SDIS = TU_BIT(4),
USBMODE_VBUS_POWER_SELECT = TU_BIT(5), // Need to be enabled for LPC18XX/43XX in host mode
};
// Device Registers
typedef struct
{
//------------- ID + HW Parameter Registers-------------//
__I uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
//------------- Capability Registers-------------//
__I uint8_t CAPLENGTH; ///< Capability Registers Length
__I uint8_t TU_RESERVED[1];
__I uint16_t HCIVERSION; ///< Host Controller Interface Version
__I uint32_t HCSPARAMS; ///< Host Controller Structural Parameters
__I uint32_t HCCPARAMS; ///< Host Controller Capability Parameters
__I uint32_t TU_RESERVED[5];
__I uint16_t DCIVERSION; ///< Device Controller Interface Version
__I uint8_t TU_RESERVED[2];
__I uint32_t DCCPARAMS; ///< Device Controller Capability Parameters
__I uint32_t TU_RESERVED[6];
//------------- Operational Registers -------------//
__IO uint32_t USBCMD; ///< USB Command Register
__IO uint32_t USBSTS; ///< USB Status Register
__IO uint32_t USBINTR; ///< Interrupt Enable Register
__IO uint32_t FRINDEX; ///< USB Frame Index
__I uint32_t TU_RESERVED;
__IO uint32_t DEVICEADDR; ///< Device Address
__IO uint32_t ENDPTLISTADDR; ///< Endpoint List Address
__I uint32_t TU_RESERVED;
__IO uint32_t BURSTSIZE; ///< Programmable Burst Size
__IO uint32_t TXFILLTUNING; ///< TX FIFO Fill Tuning
uint32_t TU_RESERVED[4];
__IO uint32_t ENDPTNAK; ///< Endpoint NAK
__IO uint32_t ENDPTNAKEN; ///< Endpoint NAK Enable
__I uint32_t TU_RESERVED;
__IO uint32_t PORTSC1; ///< Port Status & Control
__I uint32_t TU_RESERVED[7];
__IO uint32_t OTGSC; ///< On-The-Go Status & control
__IO uint32_t USBMODE; ///< USB Device Mode
__IO uint32_t ENDPTSETUPSTAT; ///< Endpoint Setup Status
__IO uint32_t ENDPTPRIME; ///< Endpoint Prime
__IO uint32_t ENDPTFLUSH; ///< Endpoint Flush
__I uint32_t ENDPTSTAT; ///< Endpoint Status
__IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete
__IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7
} dcd_registers_t;
#ifdef __cplusplus
}
#endif
#endif /* COMMON_TRANSDIMENSION_H_ */

View File

@ -32,9 +32,6 @@
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#include "common/tusb_common.h"
#include "device/dcd.h"
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
#include "fsl_device_registers.h"
#else
@ -42,6 +39,10 @@
#include "chip.h"
#endif
#include "common/tusb_common.h"
#include "device/dcd.h"
#include "common_transdimension.h"
#if defined(__CORTEX_M) && __CORTEX_M == 7 && __DCACHE_PRESENT == 1
#define CleanInvalidateDCache_by_Addr SCB_CleanInvalidateDCache_by_Addr
#else
@ -60,15 +61,6 @@ enum {
ENDPTCTRL_ENABLE = TU_BIT(7)
};
// USBCMD
enum {
USBCMD_RUN_STOP = TU_BIT(0),
USBCMD_RESET = TU_BIT(1),
USBCMD_SETUP_TRIPWIRE = TU_BIT(13),
USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoints linked list. This bit is set and cleared by software during the process of adding a new dTD
};
// Interrupt Threshold bit 23:16
// USBSTS, USBINTR
enum {
INTR_USB = TU_BIT(0),
@ -80,96 +72,6 @@ enum {
INTR_NAK = TU_BIT(16)
};
// PORTSC1
#define PORTSC1_PORT_SPEED_POS 26
enum {
PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0),
PORTSC1_FORCE_PORT_RESUME = TU_BIT(6),
PORTSC1_SUSPEND = TU_BIT(7),
PORTSC1_FORCE_FULL_SPEED = TU_BIT(24),
PORTSC1_PORT_SPEED = TU_BIT(26) | TU_BIT(27)
};
// OTGSC
enum {
OTGSC_VBUS_DISCHARGE = TU_BIT(0),
OTGSC_VBUS_CHARGE = TU_BIT(1),
// OTGSC_HWASSIST_AUTORESET = TU_BIT(2),
OTGSC_OTG_TERMINATION = TU_BIT(3), ///< Must set to 1 when OTG go to device mode
OTGSC_DATA_PULSING = TU_BIT(4),
OTGSC_ID_PULLUP = TU_BIT(5),
// OTGSC_HWASSIT_DATA_PULSE = TU_BIT(6),
// OTGSC_HWASSIT_BDIS_ACONN = TU_BIT(7),
OTGSC_ID = TU_BIT(8), ///< 0 = A device, 1 = B Device
OTGSC_A_VBUS_VALID = TU_BIT(9),
OTGSC_A_SESSION_VALID = TU_BIT(10),
OTGSC_B_SESSION_VALID = TU_BIT(11),
OTGSC_B_SESSION_END = TU_BIT(12),
OTGSC_1MS_TOGGLE = TU_BIT(13),
OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14),
};
// USBMode
enum {
USBMODE_CM_DEVICE = 2,
USBMODE_CM_HOST = 3,
USBMODE_SLOM = TU_BIT(3),
USBMODE_SDIS = TU_BIT(4),
USBMODE_VBUS_POWER_SELCT = TU_BIT(5), // Enable for LPC18XX/43XX in host most only
};
// Device Registers
typedef struct
{
//------------- ID + HW Parameter Registers-------------//
__I uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
//------------- Capability Registers-------------//
__I uint8_t CAPLENGTH; ///< Capability Registers Length
__I uint8_t TU_RESERVED[1];
__I uint16_t HCIVERSION; ///< Host Controller Interface Version
__I uint32_t HCSPARAMS; ///< Host Controller Structural Parameters
__I uint32_t HCCPARAMS; ///< Host Controller Capability Parameters
__I uint32_t TU_RESERVED[5];
__I uint16_t DCIVERSION; ///< Device Controller Interface Version
__I uint8_t TU_RESERVED[2];
__I uint32_t DCCPARAMS; ///< Device Controller Capability Parameters
__I uint32_t TU_RESERVED[6];
//------------- Operational Registers -------------//
__IO uint32_t USBCMD; ///< USB Command Register
__IO uint32_t USBSTS; ///< USB Status Register
__IO uint32_t USBINTR; ///< Interrupt Enable Register
__IO uint32_t FRINDEX; ///< USB Frame Index
__I uint32_t TU_RESERVED;
__IO uint32_t DEVICEADDR; ///< Device Address
__IO uint32_t ENDPTLISTADDR; ///< Endpoint List Address
__I uint32_t TU_RESERVED;
__IO uint32_t BURSTSIZE; ///< Programmable Burst Size
__IO uint32_t TXFILLTUNING; ///< TX FIFO Fill Tuning
uint32_t TU_RESERVED[4];
__IO uint32_t ENDPTNAK; ///< Endpoint NAK
__IO uint32_t ENDPTNAKEN; ///< Endpoint NAK Enable
__I uint32_t TU_RESERVED;
__IO uint32_t PORTSC1; ///< Port Status & Control
__I uint32_t TU_RESERVED[7];
__IO uint32_t OTGSC; ///< On-The-Go Status & control
__IO uint32_t USBMODE; ///< USB Device Mode
__IO uint32_t ENDPTSETUPSTAT; ///< Endpoint Setup Status
__IO uint32_t ENDPTPRIME; ///< Endpoint Prime
__IO uint32_t ENDPTFLUSH; ///< Endpoint Flush
__I uint32_t ENDPTSTAT; ///< Endpoint Status
__IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete
__IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7
} dcd_registers_t;
// Queue Transfer Descriptor
typedef struct
{
@ -279,7 +181,7 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048)
static dcd_data_t _dcd_data;
//--------------------------------------------------------------------+
// CONTROLLER API
// Controller API
//--------------------------------------------------------------------+
/// follows LPC43xx User Manual 23.10.3

View File

@ -31,6 +31,9 @@
#if TUSB_OPT_HOST_ENABLED && \
(CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
#include "fsl_device_registers.h"
#else
@ -38,9 +41,17 @@
#include "chip.h"
#endif
#include "common/tusb_common.h"
#include "common_transdimension.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
// TODO can be merged with dcd_controller_t
typedef struct
{
uint32_t regs_addr; // registers base
uint32_t regs_base; // registers base
const IRQn_Type irqnum; // IRQ number
}hcd_controller_t;
@ -49,27 +60,49 @@ typedef struct
{
// RT1010 and RT1020 only has 1 USB controller
#if FSL_FEATURE_SOC_USBHS_COUNT == 1
{ .regs_addr = (uint32_t) &USB->USBCMD , .irqnum = USB_OTG1_IRQn }
{ .regs_base = USB_BASE , .irqnum = USB_OTG1_IRQn }
#else
{ .regs_addr = (uint32_t) &USB1->USBCMD, .irqnum = USB_OTG1_IRQn },
{ .regs_addr = (uint32_t) &USB2->USBCMD, .irqnum = USB_OTG2_IRQn }
{ .regs_base = USB1_BASE, .irqnum = USB_OTG1_IRQn },
{ .regs_base = USB2_BASE, .irqnum = USB_OTG2_IRQn }
#endif
};
#else
static const hcd_controller_t _hcd_controller[] =
{
{ .regs_addr = (uint32_t) &LPC_USB0->USBCMD_H, .irqnum = USB0_IRQn },
{ .regs_addr = (uint32_t) &LPC_USB1->USBCMD_H, .irqnum = USB1_IRQn }
{ .regs_base = LPC_USB0_BASE, .irqnum = USB0_IRQn },
{ .regs_base = LPC_USB1_BASE, .irqnum = USB1_IRQn }
};
#endif
// TODO better prototype later
extern bool hcd_ehci_init (uint8_t rhport); // from ehci.c
//--------------------------------------------------------------------+
// Controller API
//--------------------------------------------------------------------+
bool hcd_init(uint8_t rhport)
{
dcd_registers_t* dcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base;
// Reset controller
dcd_reg->USBCMD |= USBCMD_RESET;
while( dcd_reg->USBCMD & USBCMD_RESET ) {}
// Set mode to device, must be set immediately after reset
#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
// LPC18XX/43XX need to set VBUS Power Select to HIGH
// RHPORT1 is fullspeed only (need external PHY for Highspeed)
dcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
if (rhport == 1) dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
#else
dcd_reg->USBMODE = USBMODE_CM_HOST;
#endif
// FIXME force full speed, still have issue with Highspeed enumeration
dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
return hcd_ehci_init(rhport);
}
@ -85,7 +118,10 @@ void hcd_int_disable(uint8_t rhport)
uint32_t hcd_ehci_register_addr(uint8_t rhport)
{
return _hcd_controller[rhport].regs_addr;
dcd_registers_t* hcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base;
// EHCI USBCMD has same address within dcd_register_t
return (uint32_t) &hcd_reg->USBCMD;
}
#endif