Browse Source

update(cherryusb): add config for mcxn947 usbdev and usbhost

sakumisu 10 months ago
parent
commit
b462daf57e

+ 28 - 2
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/Kconfig

@@ -27,7 +27,7 @@ menu "On-chip Peripheral Drivers"
             config BSP_USING_UART4
                 bool "Enable UART4"
                 default y
-  
+
             config BSP_USING_UART5
                 bool "Enable UART5"
                 default n
@@ -155,7 +155,7 @@ menu "On-chip Peripheral Drivers"
         select RT_USING_LWIP
         select RT_USING_NETDEV
         select RT_USING_SAL
-        
+
     config BSP_USING_RTC
         bool "Enable RTC"
         select RT_USING_RTC
@@ -184,6 +184,32 @@ menu "On-chip Peripheral Drivers"
                     default y
             endif
 
+    menuconfig BSP_USING_USB
+       bool "Enable USB"
+       default n
+       if BSP_USING_USB
+            config BSP_USING_USB_DEVICE
+                bool "Enable USB Device, default is msc ramdisk"
+                default n
+                select RT_USING_CHERRYUSB
+                select RT_CHERRYUSB_DEVICE
+                select RT_CHERRYUSB_DEVICE_SPEED_HS
+                select RT_CHERRYUSB_DEVICE_CHIPIDEA_MCX
+                select RT_CHERRYUSB_DEVICE_MSC
+                select RT_CHERRYUSB_DEVICE_TEMPLATE_MSC
+            config BSP_USING_USB_HOST
+                bool "Enable USB Host"
+                default n
+                select RT_USING_CHERRYUSB
+                select RT_CHERRYUSB_HOST
+                select RT_CHERRYUSB_HOST_EHCI_MCX
+                select RT_CHERRYUSB_HOST_CDC_ACM
+                select RT_CHERRYUSB_HOST_HID
+                select RT_CHERRYUSB_HOST_MSC
+                select RT_CHERRYUSB_HOST_CDC_RNDIS
+       endif
+
+
 endmenu
 
 

+ 2 - 0
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/SConscript

@@ -5,6 +5,8 @@ cwd = GetCurrentDir()
 # add the general drivers.
 src = Split("""
 board.c
+cherryusb_port.c
+usb_phy.c
 MCUX_Config/board/clock_config.c
 MCUX_Config/board/pin_mux.c
 """)

+ 37 - 0
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/cherryusb_port.c

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024/04/23     sakumisu    first version
+ */
+#include <rtthread.h>
+#include <board.h>
+
+/* low level init here, this has implemented in cherryusb */
+
+/* low level deinit here, this has implemented in cherryusb */
+
+#ifdef RT_CHERRYUSB_DEVICE_TEMPLATE_MSC
+int cherryusb_devinit(void)
+{
+    extern void msc_ram_init(uint8_t busid, uintptr_t reg_base);
+
+    msc_ram_init(0, USBHS1__USBC_BASE);
+    return 0;
+}
+INIT_COMPONENT_EXPORT(cherryusb_devinit);
+#endif
+
+#ifdef RT_CHERRYUSB_HOST
+#include "usbh_core.h"
+
+int cherryusb_hostinit(void)
+{
+    usbh_initialize(0, USBHS1__USBC_BASE);
+    return 0;
+}
+INIT_COMPONENT_EXPORT(cherryusb_hostinit);
+#endif

+ 7 - 0
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/linker_scripts/MCXN947_cm33_core0_flash.ld

@@ -120,6 +120,13 @@ SECTIONS
     __rt_init_start = .;
     KEEP(*(SORT(.rti_fn*)))
     __rt_init_end = .;
+
+    /* section information for usbh class */
+    . = ALIGN(8);
+    __usbh_class_info_start__ = .;
+    KEEP(*(.usbh_class_info))
+    __usbh_class_info_end__ = .;
+
   } > m_text
 
   .ARM.extab :

+ 127 - 0
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/usb.h

@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __USB_H__
+#define __USB_H__
+
+#include <stdint.h>
+#include <stdio.h>
+
+/*!
+ * @addtogroup usb_drv
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*! @brief Defines USB stack major version */
+#define USB_STACK_VERSION_MAJOR (2UL)
+/*! @brief Defines USB stack minor version */
+#define USB_STACK_VERSION_MINOR (10UL)
+/*! @brief Defines USB stack bugfix version */
+#define USB_STACK_VERSION_BUGFIX (0U)
+
+/*! @brief USB stack version definition */
+#define USB_MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
+
+/*! @brief USB stack component version definition, changed with component in yaml together */
+#define USB_STACK_COMPONENT_VERSION \
+    MAKE_VERSION(USB_STACK_VERSION_MAJOR, USB_STACK_VERSION_MINOR, USB_STACK_VERSION_BUGFIX)
+
+/*
+ * Component ID used by tools
+ *
+ * FSL_COMPONENT_ID "middleware.usb.stack_common"
+ */
+
+/*! @brief USB error code */
+typedef enum _usb_status
+{
+    kStatus_USB_Success = 0x00U, /*!< Success */
+    kStatus_USB_Error,           /*!< Failed */
+
+    kStatus_USB_Busy,                       /*!< Busy */
+    kStatus_USB_InvalidHandle,              /*!< Invalid handle */
+    kStatus_USB_InvalidParameter,           /*!< Invalid parameter */
+    kStatus_USB_InvalidRequest,             /*!< Invalid request */
+    kStatus_USB_ControllerNotFound,         /*!< Controller cannot be found */
+    kStatus_USB_InvalidControllerInterface, /*!< Invalid controller interface */
+
+    kStatus_USB_NotSupported,   /*!< Configuration is not supported */
+    kStatus_USB_Retry,          /*!< Enumeration get configuration retry */
+    kStatus_USB_TransferStall,  /*!< Transfer stalled */
+    kStatus_USB_TransferFailed, /*!< Transfer failed */
+    kStatus_USB_AllocFail,      /*!< Allocation failed */
+    kStatus_USB_LackSwapBuffer, /*!< Insufficient swap buffer for KHCI */
+    kStatus_USB_TransferCancel, /*!< The transfer cancelled */
+    kStatus_USB_BandwidthFail,  /*!< Allocate bandwidth failed */
+    kStatus_USB_MSDStatusFail,  /*!< For MSD, the CSW status means fail */
+    kStatus_USB_EHCIAttached,
+    kStatus_USB_EHCIDetached,
+    kStatus_USB_DataOverRun, /*!< The amount of data returned by the endpoint exceeded
+                                  either the size of the maximum data packet allowed
+                                  from the endpoint or the remaining buffer size. */
+} usb_status_t;
+
+/*! @brief USB host handle type define */
+typedef void *usb_host_handle;
+
+/*! @brief USB device handle type define. For device stack it is the whole device handle; for host stack it is the
+ * attached device instance handle*/
+typedef void *usb_device_handle;
+
+/*! @brief USB OTG handle type define */
+typedef void *usb_otg_handle;
+
+/*! @brief USB controller ID */
+typedef enum _usb_controller_index
+{
+    kUSB_ControllerKhci0 = 0U, /*!< KHCI 0U */
+    kUSB_ControllerKhci1 = 1U, /*!< KHCI 1U, Currently, there are no platforms which have two KHCI IPs, this is reserved
+                                  to be used in the future. */
+    kUSB_ControllerEhci0 = 2U, /*!< EHCI 0U */
+    kUSB_ControllerEhci1 = 3U, /*!< EHCI 1U */
+
+    kUSB_ControllerLpcIp3511Fs0 = 4U, /*!< LPC USB IP3511 FS controller 0 */
+    kUSB_ControllerLpcIp3511Fs1 = 5U, /*!< LPC USB IP3511 FS controller 1, there are no platforms which have two IP3511
+                                        IPs, this is reserved to be used in the future. */
+
+    kUSB_ControllerLpcIp3511Hs0 = 6U, /*!< LPC USB IP3511 HS controller 0 */
+    kUSB_ControllerLpcIp3511Hs1 = 7U, /*!< LPC USB IP3511 HS controller 1, there are no platforms which have two IP3511
+                                        IPs, this is reserved to be used in the future. */
+
+    kUSB_ControllerOhci0 = 8U, /*!< OHCI 0U */
+    kUSB_ControllerOhci1 = 9U, /*!< OHCI 1U, Currently, there are no platforms which have two OHCI IPs, this is reserved
+                                  to be used in the future. */
+
+    kUSB_ControllerIp3516Hs0 = 10U, /*!< IP3516HS 0U */
+    kUSB_ControllerIp3516Hs1 = 11U, /*!< IP3516HS 1U, Currently, there are no platforms which have two IP3516HS IPs,
+                                  this is reserved to be used in the future. */
+    kUSB_ControllerDwc30 = 12U,     /*!< DWC3 0U */
+    kUSB_ControllerDwc31 = 13U, /*!< DWC3 1U Currently, there are no platforms which have two Dwc IPs, this is reserved
+                              to be used in the future.*/
+} usb_controller_index_t;
+
+/**
+ * @brief USB stack version fields
+ */
+typedef struct _usb_version
+{
+    uint8_t major;  /*!< Major */
+    uint8_t minor;  /*!< Minor */
+    uint8_t bugfix; /*!< Bug fix */
+} usb_version_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*! @} */
+
+#endif /* __USB_H__ */

+ 278 - 0
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/usb_config.h

@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef CHERRYUSB_CONFIG_H
+#define CHERRYUSB_CONFIG_H
+
+#include <rtthread.h>
+
+/* ================ USB common Configuration ================ */
+
+#define CONFIG_USB_PRINTF(...) rt_kprintf(__VA_ARGS__)
+
+#ifndef CONFIG_USB_DBG_LEVEL
+#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
+#endif
+
+/* Enable print with color */
+#define CONFIG_USB_PRINTF_COLOR_ENABLE
+
+/* data align size when use dma */
+#ifndef CONFIG_USB_ALIGN_SIZE
+#define CONFIG_USB_ALIGN_SIZE 4
+#endif
+
+/* attribute data into no cache ram */
+#define USB_NOCACHE_RAM_SECTION __attribute__((section(".NonCacheable")))
+
+/* ================= USB Device Stack Configuration ================ */
+
+/* Ep0 in and out transfer buffer */
+#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN
+#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
+#endif
+
+/* Setup packet log for debug */
+// #define CONFIG_USBDEV_SETUP_LOG_PRINT
+
+/* Send ep0 in data from user buffer instead of copying into ep0 reqdata
+ * Please note that user buffer must be aligned with CONFIG_USB_ALIGN_SIZE
+*/
+// #define CONFIG_USBDEV_EP0_INDATA_NO_COPY
+
+/* Check if the input descriptor is correct */
+// #define CONFIG_USBDEV_DESC_CHECK
+
+/* Enable test mode */
+// #define CONFIG_USBDEV_TEST_MODE
+
+#ifndef CONFIG_USBDEV_MSC_MAX_LUN
+#define CONFIG_USBDEV_MSC_MAX_LUN 1
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
+#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 512
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
+#define CONFIG_USBDEV_MSC_MANUFACTURER_STRING ""
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_PRODUCT_STRING
+#define CONFIG_USBDEV_MSC_PRODUCT_STRING ""
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_VERSION_STRING
+#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
+#endif
+
+/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */
+// #define CONFIG_USBDEV_MSC_POLLING
+
+/* move msc read & write from isr to thread */
+// #define CONFIG_USBDEV_MSC_THREAD
+
+#ifndef CONFIG_USBDEV_MSC_PRIO
+#define CONFIG_USBDEV_MSC_PRIO 4
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_STACKSIZE
+#define CONFIG_USBDEV_MSC_STACKSIZE 2048
+#endif
+
+#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
+#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
+#endif
+
+/* rndis transfer buffer size, must be a multiple of (1536 + 44)*/
+#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
+#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
+#endif
+
+#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID
+#define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff
+#endif
+
+#ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC
+#define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB"
+#endif
+
+#define CONFIG_USBDEV_RNDIS_USING_LWIP
+
+/* ================ USB HOST Stack Configuration ================== */
+
+#define CONFIG_USBHOST_MAX_RHPORTS          1
+#define CONFIG_USBHOST_MAX_EXTHUBS          1
+#define CONFIG_USBHOST_MAX_EHPORTS          4
+#define CONFIG_USBHOST_MAX_INTERFACES       8
+#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
+#define CONFIG_USBHOST_MAX_ENDPOINTS        4
+
+#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
+#define CONFIG_USBHOST_MAX_HID_CLASS     4
+#define CONFIG_USBHOST_MAX_MSC_CLASS     2
+#define CONFIG_USBHOST_MAX_AUDIO_CLASS   1
+#define CONFIG_USBHOST_MAX_VIDEO_CLASS   1
+
+#define CONFIG_USBHOST_DEV_NAMELEN 16
+
+#ifndef CONFIG_USBHOST_PSC_PRIO
+#define CONFIG_USBHOST_PSC_PRIO 0
+#endif
+#ifndef CONFIG_USBHOST_PSC_STACKSIZE
+#define CONFIG_USBHOST_PSC_STACKSIZE 2048
+#endif
+
+//#define CONFIG_USBHOST_GET_STRING_DESC
+
+// #define CONFIG_USBHOST_MSOS_ENABLE
+#ifndef CONFIG_USBHOST_MSOS_VENDOR_CODE
+#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
+#endif
+
+/* Ep0 max transfer buffer */
+#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN
+#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
+#endif
+
+#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
+#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
+#endif
+
+#ifndef CONFIG_USBHOST_MSC_TIMEOUT
+#define CONFIG_USBHOST_MSC_TIMEOUT 5000
+#endif
+
+/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
+ * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
+ */
+#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE
+#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
+#endif
+
+/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
+#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE
+#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
+#endif
+
+/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
+ * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
+ */
+#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE
+#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE (2048)
+#endif
+/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
+#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE
+#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE (2048)
+#endif
+
+/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
+ * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
+ */
+#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE
+#define CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE (2048)
+#endif
+/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
+#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE
+#define CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE (2048)
+#endif
+
+/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
+ * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
+ */
+#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE
+#define CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE (2048)
+#endif
+/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
+#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE
+#define CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE (2048)
+#endif
+
+#define CONFIG_USBHOST_BLUETOOTH_HCI_H4
+// #define CONFIG_USBHOST_BLUETOOTH_HCI_LOG
+
+#ifndef CONFIG_USBHOST_BLUETOOTH_TX_SIZE
+#define CONFIG_USBHOST_BLUETOOTH_TX_SIZE 2048
+#endif
+#ifndef CONFIG_USBHOST_BLUETOOTH_RX_SIZE
+#define CONFIG_USBHOST_BLUETOOTH_RX_SIZE 2048
+#endif
+
+/* ================ USB Device Port Configuration ================*/
+
+#ifndef CONFIG_USBDEV_MAX_BUS
+#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
+#endif
+
+#ifndef CONFIG_USBDEV_EP_NUM
+#define CONFIG_USBDEV_EP_NUM 6
+#endif
+
+/* ---------------- FSDEV Configuration ---------------- */
+//#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference
+
+/* ---------------- DWC2 Configuration ---------------- */
+/* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for
+ * status information) + (2 * number of OUT endpoints) + 1 for Global NAK
+ */
+// #define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
+/* IN Endpoints Max packet Size / 4 */
+// #define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
+// #define CONFIG_USB_DWC2_TX1_FIFO_SIZE (512 / 4)
+// #define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
+// #define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
+// #define CONFIG_USB_DWC2_TX4_FIFO_SIZE (0 / 4)
+// #define CONFIG_USB_DWC2_TX5_FIFO_SIZE (0 / 4)
+// #define CONFIG_USB_DWC2_TX6_FIFO_SIZE (0 / 4)
+// #define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
+// #define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
+
+/* ---------------- MUSB Configuration ---------------- */
+// #define CONFIG_USB_MUSB_SUNXI
+
+/* ================ USB Host Port Configuration ==================*/
+#ifndef CONFIG_USBHOST_MAX_BUS
+#define CONFIG_USBHOST_MAX_BUS 1
+#endif
+
+#ifndef CONFIG_USBHOST_PIPE_NUM
+#define CONFIG_USBHOST_PIPE_NUM 10
+#endif
+
+/* ---------------- EHCI Configuration ---------------- */
+
+#define CONFIG_USB_EHCI_HCCR_OFFSET     (0x100)
+#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
+#define CONFIG_USB_EHCI_QH_NUM          CONFIG_USBHOST_PIPE_NUM
+#define CONFIG_USB_EHCI_QTD_NUM         3
+#define CONFIG_USB_EHCI_ITD_NUM         20
+// #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
+// #define CONFIG_USB_EHCI_CONFIGFLAG
+// #define CONFIG_USB_EHCI_ISO
+// #define CONFIG_USB_EHCI_WITH_OHCI
+
+/* ---------------- OHCI Configuration ---------------- */
+#define CONFIG_USB_OHCI_HCOR_OFFSET (0x0)
+
+/* ---------------- XHCI Configuration ---------------- */
+#define CONFIG_USB_XHCI_HCCR_OFFSET (0x0)
+
+/* ---------------- DWC2 Configuration ---------------- */
+/* largest non-periodic USB packet used / 4 */
+// #define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (512 / 4)
+/* largest periodic USB packet used / 4 */
+// #define CONFIG_USB_DWC2_PTX_FIFO_SIZE (1024 / 4)
+/*
+ * (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
+ * 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
+ */
+// #define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE) / 4)
+
+/* ---------------- MUSB Configuration ---------------- */
+// #define CONFIG_USB_MUSB_SUNXI
+
+#define CONFIG_USB_EHCI_NXP         (1)
+
+#endif

+ 275 - 0
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/usb_phy.c

@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016 - 2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "usb.h"
+#include "fsl_device_registers.h"
+
+#include "usb_phy.h"
+
+void *USB_EhciPhyGetBase(uint8_t controllerId)
+{
+    void *usbPhyBase = NULL;
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+#if defined(USBPHY_STACK_BASE_ADDRS)
+    uint32_t usbphy_base[] = USBPHY_STACK_BASE_ADDRS;
+#else
+    uint32_t usbphy_base[] = USBPHY_BASE_ADDRS;
+#endif
+    uint32_t *temp;
+    if (controllerId < (uint8_t)kUSB_ControllerEhci0)
+    {
+        return NULL;
+    }
+
+    if ((controllerId == (uint8_t)kUSB_ControllerEhci0) || (controllerId == (uint8_t)kUSB_ControllerEhci1))
+    {
+        controllerId = controllerId - (uint8_t)kUSB_ControllerEhci0;
+    }
+    else if ((controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs0) ||
+             (controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs1))
+    {
+        controllerId = controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0;
+    }
+    else if ((controllerId == (uint8_t)kUSB_ControllerIp3516Hs0) || (controllerId == (uint8_t)kUSB_ControllerIp3516Hs1))
+    {
+        controllerId = controllerId - (uint8_t)kUSB_ControllerIp3516Hs0;
+    }
+    else
+    {
+        return NULL;
+    }
+
+    if (controllerId < (sizeof(usbphy_base) / sizeof(usbphy_base[0])))
+    {
+        temp       = (uint32_t *)usbphy_base[controllerId];
+        usbPhyBase = (void *)temp;
+    }
+    else
+    {
+        return NULL;
+    }
+#endif
+    return usbPhyBase;
+}
+
+/*!
+ * @brief ehci phy initialization.
+ *
+ * This function initialize ehci phy IP.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] freq            the external input clock.
+ *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
+ *
+ * @retval kStatus_USB_Success      cancel successfully.
+ * @retval kStatus_USB_Error        the freq value is incorrect.
+ */
+uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return (uint8_t)kStatus_USB_Error;
+    }
+
+#if ((defined FSL_FEATURE_SOC_ANATOP_COUNT) && (FSL_FEATURE_SOC_ANATOP_COUNT > 0U))
+    ANATOP->HW_ANADIG_REG_3P0.RW =
+        (ANATOP->HW_ANADIG_REG_3P0.RW &
+         (~(ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x1F) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_ILIMIT_MASK))) |
+        ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x17) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_LINREG_MASK;
+    ANATOP->HW_ANADIG_USB2_CHRG_DETECT.SET =
+        ANATOP_HW_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B_MASK | ANATOP_HW_ANADIG_USB2_CHRG_DETECT_EN_B_MASK;
+#endif
+
+#if (defined USB_ANALOG)
+    USB_ANALOG->INSTANCE[controllerId - (uint8_t)kUSB_ControllerEhci0].CHRG_DETECT_SET =
+        USB_ANALOG_CHRG_DETECT_CHK_CHRG_B(1) | USB_ANALOG_CHRG_DETECT_EN_B(1);
+#endif
+
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+
+    usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
+#endif
+    usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
+    usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
+    /* PWD register provides overall control of the PHY power state */
+    usbPhyBase->PWD = 0U;
+    if (((uint8_t)kUSB_ControllerIp3516Hs0 == controllerId) || ((uint8_t)kUSB_ControllerIp3516Hs1 == controllerId) ||
+        ((uint8_t)kUSB_ControllerLpcIp3511Hs0 == controllerId) ||
+        ((uint8_t)kUSB_ControllerLpcIp3511Hs1 == controllerId))
+    {
+        usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_CLKGATE_MASK;
+        usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_PHY_PWD_MASK;
+    }
+    if (NULL != phyConfig)
+    {
+        /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
+        usbPhyBase->TX =
+            ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
+             (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
+              USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
+    }
+#endif
+
+    return (uint8_t)kStatus_USB_Success;
+}
+
+/*!
+ * @brief ehci phy initialization for suspend and resume.
+ *
+ * This function initialize ehci phy IP for suspend and resume.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] freq            the external input clock.
+ *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
+ *
+ * @retval kStatus_USB_Success      cancel successfully.
+ * @retval kStatus_USB_Error        the freq value is incorrect.
+ */
+uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return (uint8_t)kStatus_USB_Error;
+    }
+
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+    usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
+#endif
+
+#if ((defined USBPHY_CTRL_AUTORESUME_EN_MASK) && (USBPHY_CTRL_AUTORESUME_EN_MASK > 0U))
+    usbPhyBase->CTRL_CLR |= USBPHY_CTRL_AUTORESUME_EN_MASK;
+#else
+    usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTO_PWRON_PLL_MASK;
+#endif
+    usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK;
+    usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
+    usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
+    /* PWD register provides overall control of the PHY power state */
+    usbPhyBase->PWD = 0U;
+#if (defined USBPHY_ANACTRL_PFD_CLKGATE_MASK)
+    /* now the 480MHz USB clock is up, then configure fractional divider after PLL with PFD
+     * pfd clock = 480MHz*18/N, where N=18~35
+     * Please note that USB1PFDCLK has to be less than 180MHz for RUN or HSRUN mode
+     */
+    usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_FRAC(24);   /* N=24 */
+    usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_CLK_SEL(1); /* div by 4 */
+
+    usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_DEV_PULLDOWN_MASK;
+    usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;
+    while (0U == (usbPhyBase->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK))
+    {
+    }
+#endif
+    if (NULL != phyConfig)
+    {
+        /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
+        usbPhyBase->TX =
+            ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
+             (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
+              USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
+    }
+#endif
+
+    return (uint8_t)kStatus_USB_Success;
+}
+
+/*!
+ * @brief ehci phy de-initialization.
+ *
+ * This function de-initialize ehci phy IP.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ */
+void USB_EhciPhyDeinit(uint8_t controllerId)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return;
+    }
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+    usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK;       /* power down PLL */
+    usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* disable USB clock output from USB PHY PLL */
+#endif
+    usbPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* set to 1U to gate clocks */
+#endif
+}
+
+/*!
+ * @brief ehci phy disconnect detection enable or disable.
+ *
+ * This function enable/disable host ehci disconnect detection.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] enable
+ *            1U - enable;
+ *            0U - disable;
+ */
+void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return;
+    }
+
+    if (0U != enable)
+    {
+        usbPhyBase->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK;
+    }
+    else
+    {
+        usbPhyBase->CTRL &= (~USBPHY_CTRL_ENHOSTDISCONDETECT_MASK);
+    }
+#endif
+}
+
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+#if ((defined FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE) && (FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE > 0U))
+void USB_PhyDeviceForceEnterFSMode(uint8_t controllerId, uint8_t enable)
+{
+    USBPHY_Type *usbPhyBase;
+
+    usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+    if (NULL == usbPhyBase)
+    {
+        return;
+    }
+
+    if (0U != enable)
+    {
+        uint32_t delay         = 1000000;
+        usbPhyBase->DEBUG0_CLR = USBPHY_DEBUG0_CLKGATE_MASK;
+        while ((0U != (usbPhyBase->USB1_VBUS_DET_STAT & USBPHY_USB1_VBUS_DET_STAT_VBUS_VALID_3V_MASK)) && (0U != delay))
+        {
+            delay--;
+        }
+        usbPhyBase->USB1_LOOPBACK_SET = USBPHY_USB1_LOOPBACK_UTMI_TESTSTART_MASK;
+    }
+    else
+    {
+        usbPhyBase->DEBUG0_CLR        = USBPHY_DEBUG0_CLKGATE_MASK;
+        usbPhyBase->USB1_LOOPBACK_CLR = USBPHY_USB1_LOOPBACK_UTMI_TESTSTART_MASK;
+    }
+}
+#endif
+#endif

+ 105 - 0
bsp/nxp/mcx/mcxn/frdm-mcxn947/board/usb_phy.h

@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016 - 2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __USB_PHY_H__
+#define __USB_PHY_H__
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+typedef struct _usb_phy_config_struct
+{
+    uint8_t D_CAL;     /* Decode to trim the nominal 17.78mA current source */
+    uint8_t TXCAL45DP; /* Decode to trim the nominal 45-Ohm series termination resistance to the USB_DP output pin */
+    uint8_t TXCAL45DM; /* Decode to trim the nominal 45-Ohm series termination resistance to the USB_DM output pin */
+} usb_phy_config_struct_t;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+/*!
+ * @brief EHCI PHY get USB phy bass address.
+ *
+ * This function is used to get USB phy bass address.
+ *
+ * @param[in] controllerId    EHCI controller ID; See the #usb_controller_index_t.
+ *
+ * @retval USB phy bass address.
+ */
+extern void *USB_EhciPhyGetBase(uint8_t controllerId);
+
+/*!
+ * @brief EHCI PHY initialization.
+ *
+ * This function initializes the EHCI PHY IP.
+ *
+ * @param[in] controllerId    EHCI controller ID; See the #usb_controller_index_t.
+ * @param[in] freq            The external input clock.
+ *
+ * @retval kStatus_USB_Success      Cancel successfully.
+ * @retval kStatus_USB_Error        The freq value is incorrect.
+ */
+extern uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig);
+
+/*!
+ * @brief ehci phy initialization for suspend and resume.
+ *
+ * This function initialize ehci phy IP for suspend and resume.
+ *
+ * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] freq            the external input clock.
+ *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
+ *
+ * @retval kStatus_USB_Success      cancel successfully.
+ * @retval kStatus_USB_Error        the freq value is incorrect.
+ */
+extern uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig);
+
+/*!
+ * @brief EHCI PHY deinitialization.
+ *
+ * This function deinitializes the EHCI PHY IP.
+ *
+ * @param[in] controllerId   EHCI controller ID; See #usb_controller_index_t.
+ */
+extern void USB_EhciPhyDeinit(uint8_t controllerId);
+
+/*!
+ * @brief EHCI PHY disconnect detection enable or disable.
+ *
+ * This function enable/disable the host EHCI disconnect detection.
+ *
+ * @param[in] controllerId   EHCI controller ID; See #usb_controller_index_t.
+ * @param[in] enable
+ *            1U - enable;
+ *            0U - disable;
+ */
+extern void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable);
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+#if ((defined FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE) && (FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE > 0U))
+/*!
+ * @brief Force the PHY enter FS Mode
+ *
+ * on RT500 and RT600, the device doesn't enter FS Mode after vbus is invalide and the controller works as HS.
+ *
+ * @param[in] controllerId   EHCI controller ID; See #usb_controller_index_t.
+ * @param[in] enable
+ *            1U - enable;
+ *            0U - disable;
+ */
+extern void USB_PhyDeviceForceEnterFSMode(uint8_t controllerId, uint8_t enable);
+#endif
+#endif
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __USB_PHY_H__ */