forked from xuos/xiuos
merge 5g_usb
This commit is contained in:
commit
02f6a412de
|
@ -15,10 +15,21 @@
|
|||
#define SPSR_EL2_VALUE (7 << 6) | (5 << 0)
|
||||
#define SCTLR_EL1_VALUE (0x30D00800)
|
||||
|
||||
/* Macros for MAIR setting. */
|
||||
#define MAIR(attr, mt) ((attr) << ((mt) * 8))
|
||||
#define MT_DEVICE_nGnRnE 0
|
||||
#define MT_DEVICE_nGnRE 1
|
||||
#define MT_DEVICE_GRE 2
|
||||
#define MT_NORMAL_NC 3
|
||||
#define MT_NORMAL 4
|
||||
#define MT_NORMAL_WT 5
|
||||
|
||||
.section ".text", "ax"
|
||||
.global _boot_start
|
||||
.global primary_cpu_init
|
||||
.global el2_setup
|
||||
/* The function for setting memory types and MAIR registers. */
|
||||
.global __cpu_mair_setup
|
||||
|
||||
_boot_start:
|
||||
bl el2_setup
|
||||
|
@ -53,6 +64,7 @@ _boot_start:
|
|||
mov x5, x2
|
||||
cmp x5, #0
|
||||
beq primary_cpu_init
|
||||
bl __cpu_mair_setup
|
||||
bl bootmain // for secondary cpus, jump to argument function pointer passed in by ROM
|
||||
|
||||
bl .
|
||||
|
@ -68,6 +80,7 @@ primary_cpu_init:
|
|||
stp x3, x3, [x1], #16
|
||||
b.lt 1b
|
||||
|
||||
bl __cpu_mair_setup
|
||||
bl bootmain
|
||||
|
||||
.func el2_setup
|
||||
|
@ -117,4 +130,39 @@ el2_setup:
|
|||
eret
|
||||
.endfunc
|
||||
|
||||
.func __cpu_mair_setup
|
||||
__cpu_mair_setup:
|
||||
tlbi vmalle1 // Invalidate local TLB
|
||||
dsb nsh
|
||||
|
||||
// mov x0, #3 << 20
|
||||
// msr cpacr_el1, x0 // Enable FP/ASIMD
|
||||
// mov x0, #1 << 12 // Reset mdscr_el1 and disable
|
||||
// msr mdscr_el1, x0 // access to the DCC from EL0
|
||||
isb // Unmask debug exceptions now,
|
||||
// enable_dbg // since this is per-cpu
|
||||
/*
|
||||
* Memory region attributes for LPAE:
|
||||
*
|
||||
* n = AttrIndx[2:0]
|
||||
* n MAIR
|
||||
* DEVICE_nGnRnE 000 00000000
|
||||
* DEVICE_nGnRE 001 00000100
|
||||
* DEVICE_GRE 010 00001100
|
||||
* NORMAL_NC 011 01000100
|
||||
* NORMAL 100 11111111
|
||||
* NORMAL_WT 101 10111011
|
||||
*/
|
||||
ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \
|
||||
MAIR(0x04, MT_DEVICE_nGnRE) | \
|
||||
MAIR(0x0c, MT_DEVICE_GRE) | \
|
||||
MAIR(0x44, MT_NORMAL_NC) | \
|
||||
MAIR(0xff, MT_NORMAL) | \
|
||||
MAIR(0xbb, MT_NORMAL_WT)
|
||||
msr mair_el1, x5
|
||||
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
.end
|
|
@ -70,7 +70,12 @@ static void _cpu_irq_disable(void)
|
|||
|
||||
static void _single_irq_enable(int irq, int cpu, int prio)
|
||||
{
|
||||
gic_setup_ppi((uint32_t)cpu, (uint32_t)irq);
|
||||
if (irq < 32) {
|
||||
gic_setup_ppi((uint32_t)cpu, (uint32_t)irq);
|
||||
}
|
||||
else {
|
||||
gic_setup_spi((uint32_t)cpu, (uint32_t)irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void _single_irq_disable(int irq, int cpu)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
SRC_DIR := fs shell lib boards drivers semaphore tools app
|
||||
SRC_DIR := fs shell lib boards semaphore drivers tools net app
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -43,9 +43,9 @@ INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \
|
|||
-I$(KERNEL_ROOT)/services/app
|
||||
|
||||
ifeq ($(BOARD), imx6q-sabrelite)
|
||||
all: test_fault simple_client simple_server shell fs_server semaphore_server test_sleep test_semaphore test_ipc_null test_thread test_irq_hdlr test_irq_block test_irq_send eth_driver epit_server readme.txt | bin
|
||||
all: test_fault simple_client simple_server shell fs_server semaphore_server test_semaphore test_ipc_null test_thread test_irq_hdlr test_irq_block test_irq_send eth_driver epit_server test_net lwip readme.txt | bin
|
||||
else
|
||||
all: test_fault simple_client simple_server shell fs_server semaphore_server test_sleep test_ipc_null test_thread test_semaphore test_net lwip readme.txt eth_hal | bin
|
||||
all: test_fault simple_client simple_server shell fs_server semaphore_server test_ipc_null test_thread test_semaphore test_net lwip readme.txt eth_hal usb_driver_service | bin
|
||||
endif
|
||||
../tools/mkfs/mkfs ./fs.img $^
|
||||
@mv $(filter-out readme.txt, $^) bin
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
SRC_DIR := hal
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,62 @@
|
|||
ifeq ($(BOARD), imx6q-sabrelite)
|
||||
toolchain ?= arm-none-eabi-
|
||||
user_ldflags = --specs=nosys.specs -Wl,-Map=user.map,-cref -N
|
||||
cflags = -std=c11 -O2 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
|
||||
endif
|
||||
|
||||
ifeq ($(BOARD), zynq7000-zc702)
|
||||
toolchain ?= arm-xilinx-eabi-
|
||||
user_ldflags = -Wl,--start-group,-lgcc,-lc,--end-group -N
|
||||
cflags = -std=c11 -O2 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
|
||||
board_specs = stub.o
|
||||
#cflags = -Wall -g -std=c11
|
||||
endif
|
||||
|
||||
ifeq ($(BOARD), ok1028a-c)
|
||||
toolchain ?= aarch64-none-elf-
|
||||
user_ldflags = -N -Ttext 0
|
||||
cflags = -g -std=c11 -mtune=cortex-a72 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -Werror -ggdb -Wno-unused -fno-omit-frame-pointer -fno-stack-protector -fno-pie
|
||||
board_specs = stub.o
|
||||
endif
|
||||
|
||||
ifeq ($(BOARD), 3568)
|
||||
toolchain ?= aarch64-none-elf-
|
||||
user_ldflags = -N -Ttext 0
|
||||
cflags = -Wall -g -std=c11 -mtune=cortex-a55 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
|
||||
board_specs = $(KERNEL_ROOT)/services/app/stub.o
|
||||
endif
|
||||
|
||||
cc = ${toolchain}gcc
|
||||
ld = ${toolchain}g++
|
||||
objdump = ${toolchain}objdump
|
||||
c_useropts = -O2
|
||||
# c_useropts = -O0
|
||||
|
||||
INC_DIR = -I$(KERNEL_ROOT)/services/app \
|
||||
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
|
||||
-I$(KERNEL_ROOT)/services/lib/serial \
|
||||
-I$(KERNEL_ROOT)/services/drivers/3568/include \
|
||||
-I$(KERNEL_ROOT)/services/lib/usyscall \
|
||||
-I$(KERNEL_ROOT)/services/lib/ipc \
|
||||
-I$(KERNEL_ROOT)/services/lib/memory
|
||||
|
||||
|
||||
objs = hal_gmac.o \
|
||||
hal_gmac_3568.o \
|
||||
test_gmac.o \
|
||||
hal_base.o \
|
||||
hal_bsp.o \
|
||||
hal_pinctrl_v2.o \
|
||||
hal_cru.o \
|
||||
hal_gpio.o \
|
||||
hal_timer.o \
|
||||
hal_cru_rk3568.o \
|
||||
hal_debug.o \
|
||||
system_rk3568.o \
|
||||
|
||||
all: ${objs}
|
||||
@mv $^ $(KERNEL_ROOT)/services/app
|
||||
|
||||
%.o: %.c
|
||||
@echo "cc $^"
|
||||
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^
|
|
@ -0,0 +1,454 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_base.h"
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup HAL_BASE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_BASE_How_To_Use How To Use
|
||||
* @{
|
||||
|
||||
HAL system support is including delay system, HAL tick system and global system clock,
|
||||
|
||||
HAL system tick setting:
|
||||
|
||||
- Attach HAL_IncTick() to system tick interrupt handler;
|
||||
- Notify the HAL system the system's tick frequency by calling HAL_SetTickFreq() unless
|
||||
it is the same as default value HAL_TICK_FREQ_1KHZ;
|
||||
- If you need a more accurate delay system, specify SYS_TIMER in hal_conf.h.
|
||||
|
||||
Init HAL system:
|
||||
|
||||
- Initialize the HAL system by calling HAL_Init():
|
||||
|
||||
Reset when SOC system is changed:
|
||||
|
||||
- Update system with new core clock and new SysTick clock source by calling HAL_SystemCoreClockUpdate();
|
||||
|
||||
APIs:
|
||||
|
||||
- Get system time by calling HAL_GetTick().
|
||||
- Delay for a certain length of time, HAL_DelayMs(), HAL_DelayUs(), and HAL_CPUDelayUs().
|
||||
- Blocking for a certain period of time to continuously query HW status, use HAL_GetTick()
|
||||
to do timeout, this will be more accurate.
|
||||
- Get current cpu usage by calling HAL_GetCPUUsage().
|
||||
|
||||
@} */
|
||||
|
||||
/** @defgroup HAL_BASE_Private_Definition Private Definition
|
||||
* @{
|
||||
*/
|
||||
/********************* Private MACRO Definition ******************************/
|
||||
|
||||
#define HAL_TICK_FREQ_DEFAULT HAL_TICK_FREQ_1KHZ
|
||||
|
||||
/********************* Private Structure Definition **************************/
|
||||
|
||||
/********************* Private Variable Definition ***************************/
|
||||
|
||||
static __IO uint32_t uwTick;
|
||||
static eHAL_tickFreq uwTickFreq = HAL_TICK_FREQ_DEFAULT;
|
||||
|
||||
/********************* Private Function Definition ***************************/
|
||||
#if defined(__CORTEX_A) || defined(__CORTEX_M)
|
||||
#if __CORTEX_M == 0U || !defined(__GNUC__)
|
||||
static void CPUCycleLoop(uint32_t cycles)
|
||||
{
|
||||
uint32_t count;
|
||||
|
||||
if (cycles < 100U) {
|
||||
return;
|
||||
}
|
||||
|
||||
count = cycles / 3;
|
||||
while (count-- > 0) {
|
||||
__asm volatile ("nop");
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void CPUCycleLoop(uint32_t cycles)
|
||||
{
|
||||
__ASM volatile (
|
||||
"mov r0, %0\n\t"
|
||||
"adds r0, r0, #2\n\t" // 1 2 Round to the nearest multiple of 4.
|
||||
"lsrs r0, r0, #2\n\t" // 1 2 Divide by 4 and set flags.
|
||||
"beq 2f\n\t" // 2 2 Skip if 0.
|
||||
".align 4\n\t"
|
||||
"1:\n\t"
|
||||
"adds r0, r0, #1\n\t" // 1 2 Increment the counter.
|
||||
"subs r0, r0, #2\n\t" // 1 2 Decrement the counter by 2.
|
||||
"bne 1b\n\t" // (1)2 2 2 CPU cycles (if branch is taken).
|
||||
"nop\n\t" // 1 2 Loop alignment padding.
|
||||
"2:"
|
||||
: : "r" (cycles)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#elif defined(__RISC_V)
|
||||
static void CPUCycleLoop(uint32_t cycles)
|
||||
{
|
||||
asm volatile (
|
||||
"mv a0, %0\n\t"
|
||||
"addi a0, a0, 2\n\t" // 1 2 Round to the nearest multiple of 4.
|
||||
"li a1, 4\n\t"
|
||||
"div a0, a0, a1\n\t" // 1 2 Divide by 4 and set flags.
|
||||
"li a1, 2\n\t"
|
||||
"bnez a0, 1f\n\t" // 2 2 Skip if 0.
|
||||
"j 2f\n\t"
|
||||
".align 6\n\t"
|
||||
"1:\n\t"
|
||||
"addi a0, a0, 1\n\t" // 1 2 Increment the counter.
|
||||
"sub a0, a0, a1\n\t" // 1 2 Decrement the counter by 2.
|
||||
"bnez a0, 1b\n\t" // (1)2 2 2 CPU cycles (if branch is taken).
|
||||
"nop\n\t" // 1 2 Loop alignment padding.
|
||||
"2:"
|
||||
: : "r" (cycles)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
|
||||
__attribute__((always_inline)) static inline HAL_Status TimerDelayUs(uint32_t us)
|
||||
{
|
||||
uint64_t count, from, now, pass;
|
||||
|
||||
from = HAL_TIMER_GetCount(SYS_TIMER);
|
||||
count = PLL_INPUT_OSC_RATE / 1000000 * us;
|
||||
do {
|
||||
now = HAL_TIMER_GetCount(SYS_TIMER);
|
||||
pass = now > from ? now - from : from - now;
|
||||
} while (pass < count);
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/********************* Public Function Definition ***************************/
|
||||
/** @defgroup HAL_BASE_Exported_Functions_Group4 Init and DeInit Functions
|
||||
|
||||
This section provides functions allowing to init and deinit the module:
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Init HAL driver basic code.
|
||||
* @return HAL_OK.
|
||||
*/
|
||||
HAL_Status HAL_Init(void)
|
||||
{
|
||||
#ifdef __CORTEX_M
|
||||
#ifdef HAL_NVIC_MODULE_ENABLED
|
||||
/* Set Interrupt Group Priority */
|
||||
HAL_NVIC_Init();
|
||||
|
||||
/* Set Interrupt Group Priority */
|
||||
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_DEFAULT);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
|
||||
HAL_TIMER_SysTimerInit(SYS_TIMER);
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PINCTRL_MODULE_ENABLED
|
||||
HAL_PINCTRL_Init();
|
||||
#endif
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HAL system update with new core clock and systick clock source.
|
||||
* @param hz: new core clock.
|
||||
* @param clkSource: new systick clock source.
|
||||
* @return HAL_OK.
|
||||
*/
|
||||
HAL_Status HAL_SystemCoreClockUpdate(uint32_t hz, eHAL_systickClkSource clkSource)
|
||||
{
|
||||
uint32_t rate = hz;
|
||||
HAL_Status ret = HAL_OK;
|
||||
|
||||
#if defined(__CORTEX_M) && defined(HAL_SYSTICK_MODULE_ENABLED)
|
||||
ret = HAL_SYSTICK_CLKSourceConfig(clkSource);
|
||||
if (ret == HAL_OK && clkSource == HAL_SYSTICK_CLKSRC_EXT) {
|
||||
rate = PLL_INPUT_OSC_RATE;
|
||||
}
|
||||
HAL_SYSTICK_Config(rate / (1000 / HAL_GetTickFreq()));
|
||||
ret = HAL_OK;
|
||||
#endif
|
||||
|
||||
if (ret == HAL_OK) {
|
||||
SystemCoreClock = rate; /* Update global SystemCoreClock */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HAL deinit.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
*/
|
||||
HAL_Status HAL_DeInit(void)
|
||||
{
|
||||
/* TO-DO */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup HAL_BASE_Exported_Functions_Group5 Other Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Count plus tickFreq when interrupt occurs.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
*/
|
||||
HAL_Status HAL_IncTick(void)
|
||||
{
|
||||
uwTick += uwTickFreq;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provides tick value in millisecond.
|
||||
* @return uint32_t: tick value in millisecond.
|
||||
* @attention this API allow direct use in the HAL layer.
|
||||
*/
|
||||
uint32_t HAL_GetTick(void)
|
||||
{
|
||||
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
|
||||
uint64_t tick = HAL_TIMER_GetCount(SYS_TIMER);
|
||||
uint32_t base = PLL_INPUT_OSC_RATE / 1000;
|
||||
|
||||
if (tick >> 62) {
|
||||
tick = ~tick;
|
||||
}
|
||||
|
||||
return (uint32_t)HAL_DivU64(tick, base);
|
||||
#else
|
||||
|
||||
return uwTick;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provides system timer count.
|
||||
* @return uint64_t: timer count.
|
||||
* @attention this API allow direct use in the HAL layer.
|
||||
*/
|
||||
uint64_t HAL_GetSysTimerCount(void)
|
||||
{
|
||||
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
|
||||
uint64_t count = HAL_TIMER_GetCount(SYS_TIMER);
|
||||
if (count >> 62) {
|
||||
count = ~count;
|
||||
}
|
||||
|
||||
return count;
|
||||
#else
|
||||
|
||||
return 0LLU;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set new tick frequency.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_SetTickFreq(eHAL_tickFreq freq)
|
||||
{
|
||||
HAL_ASSERT(IS_TICKFREQ(freq));
|
||||
|
||||
uwTickFreq = freq;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return tick frequency.
|
||||
* @return uint32_t: tick period in Hz.
|
||||
* @attention this API allow direct use in the HAL layer.
|
||||
*/
|
||||
eHAL_tickFreq HAL_GetTickFreq(void)
|
||||
{
|
||||
return uwTickFreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SysTick mdelay.
|
||||
* @param ms: mdelay count.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
* @attention this API allow direct use in the HAL layer. Blocking for a
|
||||
* certain period of time to continuously query HW status, use HAL_GetTick
|
||||
* to do timeout, that will be more accurate.
|
||||
*/
|
||||
__attribute__((weak)) HAL_Status HAL_DelayMs(uint32_t ms)
|
||||
{
|
||||
for (uint32_t i = 0; i < ms; i++) {
|
||||
HAL_DelayUs(1000);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SysTick udelay.
|
||||
* @param us: udelay count.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
* @attention this API allow direct use in the HAL layer. The longer the delay,
|
||||
* the more accurate. Actual delay is greater than the parameter.
|
||||
*/
|
||||
HAL_Status HAL_DelayUs(uint32_t us)
|
||||
{
|
||||
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
|
||||
|
||||
return TimerDelayUs(us);
|
||||
#else
|
||||
return HAL_CPUDelayUs(us);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CPU loop udelay.
|
||||
* @param us: udelay count.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
* @attention this API allow direct use in the HAL layer. The longer the delay,
|
||||
* the more accurate. Actual delay is greater than the parameter.
|
||||
* During delay, CPU rate change result in delay imprecise, so call it in
|
||||
* following case:
|
||||
* 1.IRQ disable
|
||||
* 2.CRU code
|
||||
*/
|
||||
HAL_Status HAL_CPUDelayUs(uint32_t us)
|
||||
{
|
||||
volatile uint32_t cycles;
|
||||
|
||||
#if (__CORTEX_M == 0)
|
||||
cycles = (uint32_t)HAL_DivU64((uint64_t)SystemCoreClock, 1000000) * us; /* Add few cycles penalty */
|
||||
#else
|
||||
cycles = SystemCoreClock / 1000000 * us; /* Add few cycles penalty */
|
||||
#endif
|
||||
|
||||
CPUCycleLoop(cycles);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if defined(HAL_CPU_USAGE_ENABLED)
|
||||
static uint64_t g_last_enter_idle_time = 0; /* Last time current CPU entered the idle state. */
|
||||
static uint64_t g_total_idle_time = 0; /* Total time for current CPU to enter idle state. */
|
||||
static uint64_t g_last_elapsed_time = 0; /* Last elapsed time for current CPU. */
|
||||
|
||||
/**
|
||||
* @brief Get current CPU usage.
|
||||
* @return 0-100
|
||||
* @attention The cpu usage function depends on HAL_CPUEnterIdle function.
|
||||
*/
|
||||
uint32_t HAL_GetCPUUsage(void)
|
||||
{
|
||||
uint64_t elapsed_time, active_time, current_time;
|
||||
uint32_t usage;
|
||||
|
||||
current_time = HAL_GetSysTimerCount();
|
||||
elapsed_time = current_time - g_last_elapsed_time;
|
||||
|
||||
/* Prevent the risk of dividing by 0 caused by repeated calls for a short time. */
|
||||
if (!elapsed_time) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_ASSERT(elapsed_time > g_total_idle_time);
|
||||
active_time = elapsed_time - g_total_idle_time;
|
||||
usage = (active_time * 100) / elapsed_time;
|
||||
g_total_idle_time = 0;
|
||||
g_last_elapsed_time = current_time;
|
||||
|
||||
return usage;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CPU enter idle.
|
||||
*/
|
||||
void HAL_CPU_EnterIdle(void)
|
||||
{
|
||||
#if defined(HAL_CPU_USAGE_ENABLED)
|
||||
uint64_t idle_time;
|
||||
|
||||
__disable_irq();
|
||||
g_last_enter_idle_time = HAL_GetSysTimerCount();
|
||||
#endif
|
||||
|
||||
// __asm__ volatile ("wfi");
|
||||
|
||||
#if defined(HAL_CPU_USAGE_ENABLED)
|
||||
idle_time = HAL_GetSysTimerCount() - g_last_enter_idle_time;
|
||||
g_total_idle_time += idle_time;
|
||||
__enable_irq();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
/********************* Public Function Definition ***************************/
|
||||
/** @defgroup HAL_BASE_EX_Exported_Functions_Group5 Other Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief uint64_t numerator / uint32_t denominator with remainder
|
||||
* @param numerator
|
||||
* @param denominator
|
||||
* @param pRemainder [out] pointer to unsigned 32bit remainder
|
||||
* @return uint64_t result. sets *pRemainder if pRemainder is not null
|
||||
*/
|
||||
uint64_t HAL_DivU64Rem(uint64_t numerator, uint32_t denominator, uint32_t *pRemainder)
|
||||
{
|
||||
uint64_t remainder = numerator;
|
||||
uint64_t b = denominator;
|
||||
uint64_t result;
|
||||
uint64_t d = 1;
|
||||
uint32_t high = numerator >> 32;
|
||||
|
||||
result = 0;
|
||||
if (high >= denominator) {
|
||||
high /= denominator;
|
||||
result = (uint64_t)high << 32;
|
||||
remainder -= (uint64_t)(high * denominator) << 32;
|
||||
}
|
||||
|
||||
while ((int64_t)b > 0 && b < remainder) {
|
||||
b = b + b;
|
||||
d = d + d;
|
||||
}
|
||||
|
||||
do {
|
||||
if (remainder >= b) {
|
||||
remainder -= b;
|
||||
result += d;
|
||||
}
|
||||
b >>= 1;
|
||||
d >>= 1;
|
||||
} while (d);
|
||||
|
||||
if (pRemainder) {
|
||||
*pRemainder = remainder;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,420 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_bsp.h"
|
||||
|
||||
#ifdef HAL_PL330_MODULE_ENABLED
|
||||
struct HAL_PL330_DEV g_pl330Dev0 =
|
||||
{
|
||||
.pReg = DMA0,
|
||||
.peripReqType = BURST,
|
||||
.irq[0] = DMAC0_IRQn,
|
||||
.irq[1] = DMAC0_ABORT_IRQn,
|
||||
.pd = 0,
|
||||
};
|
||||
|
||||
struct HAL_PL330_DEV g_pl330Dev1 =
|
||||
{
|
||||
.pReg = DMA1,
|
||||
.peripReqType = BURST,
|
||||
.irq[0] = DMAC1_IRQn,
|
||||
.irq[1] = DMAC1_ABORT_IRQn,
|
||||
.pd = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
const struct HAL_SPI_DEV g_spi0Dev = {
|
||||
.base = SPI0_BASE,
|
||||
.clkId = CLK_SPI0,
|
||||
.clkGateID = CLK_SPI0_GATE,
|
||||
.pclkGateID = PCLK_SPI0_GATE,
|
||||
.irqNum = SPI0_IRQn,
|
||||
.isSlave = false,
|
||||
.txDma = {
|
||||
.channel = DMA_REQ_SPI0_TX,
|
||||
.direction = DMA_MEM_TO_DEV,
|
||||
.addr = SPI0_BASE + 0x400,
|
||||
.dmac = DMA0,
|
||||
},
|
||||
.rxDma = {
|
||||
.channel = DMA_REQ_SPI0_RX,
|
||||
.direction = DMA_DEV_TO_MEM,
|
||||
.addr = SPI0_BASE + 0x800,
|
||||
.dmac = DMA0,
|
||||
},
|
||||
};
|
||||
|
||||
const struct HAL_SPI_DEV g_spi1Dev = {
|
||||
.base = SPI1_BASE,
|
||||
.clkId = CLK_SPI1,
|
||||
.clkGateID = CLK_SPI1_GATE,
|
||||
.pclkGateID = PCLK_SPI1_GATE,
|
||||
.irqNum = SPI1_IRQn,
|
||||
.isSlave = false,
|
||||
.txDma = {
|
||||
.channel = DMA_REQ_SPI1_TX,
|
||||
.direction = DMA_MEM_TO_DEV,
|
||||
.addr = SPI1_BASE + 0x400,
|
||||
.dmac = DMA0,
|
||||
},
|
||||
.rxDma = {
|
||||
.channel = DMA_REQ_SPI1_RX,
|
||||
.direction = DMA_DEV_TO_MEM,
|
||||
.addr = SPI1_BASE + 0x800,
|
||||
.dmac = DMA0,
|
||||
},
|
||||
};
|
||||
|
||||
const struct HAL_SPI_DEV g_spi2Dev = {
|
||||
.base = SPI2_BASE,
|
||||
.clkId = CLK_SPI2,
|
||||
.clkGateID = CLK_SPI2_GATE,
|
||||
.pclkGateID = PCLK_SPI2_GATE,
|
||||
.irqNum = SPI2_IRQn,
|
||||
.isSlave = false,
|
||||
.txDma = {
|
||||
.channel = DMA_REQ_SPI2_TX,
|
||||
.direction = DMA_MEM_TO_DEV,
|
||||
.addr = SPI2_BASE + 0x400,
|
||||
.dmac = DMA0,
|
||||
},
|
||||
.rxDma = {
|
||||
.channel = DMA_REQ_SPI2_RX,
|
||||
.direction = DMA_DEV_TO_MEM,
|
||||
.addr = SPI2_BASE + 0x800,
|
||||
.dmac = DMA0,
|
||||
},
|
||||
};
|
||||
|
||||
const struct HAL_SPI_DEV g_spi3Dev = {
|
||||
.base = SPI3_BASE,
|
||||
.clkId = CLK_SPI3,
|
||||
.clkGateID = CLK_SPI3_GATE,
|
||||
.pclkGateID = PCLK_SPI3_GATE,
|
||||
.irqNum = SPI3_IRQn,
|
||||
.isSlave = false,
|
||||
.txDma = {
|
||||
.channel = DMA_REQ_SPI3_TX,
|
||||
.direction = DMA_MEM_TO_DEV,
|
||||
.addr = SPI3_BASE + 0x400,
|
||||
.dmac = DMA0,
|
||||
},
|
||||
.rxDma = {
|
||||
.channel = DMA_REQ_SPI3_RX,
|
||||
.direction = DMA_DEV_TO_MEM,
|
||||
.addr = SPI3_BASE + 0x800,
|
||||
.dmac = DMA0,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
const struct HAL_UART_DEV g_uart0Dev =
|
||||
{
|
||||
.pReg = UART0,
|
||||
.sclkID = CLK_UART0,
|
||||
.irqNum = UART0_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart1Dev =
|
||||
{
|
||||
.pReg = UART1,
|
||||
.sclkID = CLK_UART1,
|
||||
.sclkGateID = SCLK_UART1_GATE,
|
||||
.pclkGateID = PCLK_UART1_GATE,
|
||||
.irqNum = UART1_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart2Dev =
|
||||
{
|
||||
.pReg = UART2,
|
||||
.sclkID = CLK_UART2,
|
||||
.sclkGateID = SCLK_UART2_GATE,
|
||||
.pclkGateID = PCLK_UART2_GATE,
|
||||
.irqNum = UART2_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart3Dev =
|
||||
{
|
||||
.pReg = UART3,
|
||||
.sclkID = CLK_UART3,
|
||||
.sclkGateID = SCLK_UART3_GATE,
|
||||
.pclkGateID = PCLK_UART3_GATE,
|
||||
.irqNum = UART3_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart4Dev =
|
||||
{
|
||||
.pReg = UART4,
|
||||
.sclkID = CLK_UART4,
|
||||
.sclkGateID = SCLK_UART4_GATE,
|
||||
.pclkGateID = PCLK_UART4_GATE,
|
||||
.irqNum = UART4_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart5Dev =
|
||||
{
|
||||
.pReg = UART5,
|
||||
.sclkID = CLK_UART5,
|
||||
.sclkGateID = SCLK_UART5_GATE,
|
||||
.pclkGateID = PCLK_UART5_GATE,
|
||||
.irqNum = UART5_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart6Dev =
|
||||
{
|
||||
.pReg = UART6,
|
||||
.sclkID = CLK_UART6,
|
||||
.sclkGateID = SCLK_UART6_GATE,
|
||||
.pclkGateID = PCLK_UART6_GATE,
|
||||
.irqNum = UART6_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart7Dev =
|
||||
{
|
||||
.pReg = UART7,
|
||||
.sclkID = CLK_UART7,
|
||||
.sclkGateID = SCLK_UART7_GATE,
|
||||
.pclkGateID = PCLK_UART7_GATE,
|
||||
.irqNum = UART7_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart8Dev =
|
||||
{
|
||||
.pReg = UART8,
|
||||
.sclkID = CLK_UART8,
|
||||
.sclkGateID = SCLK_UART8_GATE,
|
||||
.pclkGateID = PCLK_UART8_GATE,
|
||||
.irqNum = UART8_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
|
||||
const struct HAL_UART_DEV g_uart9Dev =
|
||||
{
|
||||
.pReg = UART9,
|
||||
.sclkID = CLK_UART9,
|
||||
.sclkGateID = SCLK_UART9_GATE,
|
||||
.pclkGateID = PCLK_UART9_GATE,
|
||||
.irqNum = UART9_IRQn,
|
||||
.isAutoFlow = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
const struct HAL_I2C_DEV g_i2c0Dev =
|
||||
{
|
||||
.pReg = I2C0,
|
||||
.irqNum = I2C0_IRQn,
|
||||
.clkID = CLK_I2C,
|
||||
.clkGateID = CLK_I2C0_GATE,
|
||||
.pclkGateID = PCLK_I2C0_GATE,
|
||||
.runtimeID = PM_RUNTIME_ID_I2C0,
|
||||
};
|
||||
|
||||
const struct HAL_I2C_DEV g_i2c1Dev =
|
||||
{
|
||||
.pReg = I2C1,
|
||||
.irqNum = I2C1_IRQn,
|
||||
.clkID = CLK_I2C,
|
||||
.clkGateID = CLK_I2C1_GATE,
|
||||
.pclkGateID = PCLK_I2C1_GATE,
|
||||
.runtimeID = PM_RUNTIME_ID_I2C1,
|
||||
};
|
||||
|
||||
const struct HAL_I2C_DEV g_i2c2Dev =
|
||||
{
|
||||
.pReg = I2C2,
|
||||
.irqNum = I2C2_IRQn,
|
||||
.clkID = CLK_I2C,
|
||||
.clkGateID = CLK_I2C2_GATE,
|
||||
.pclkGateID = PCLK_I2C2_GATE,
|
||||
.runtimeID = PM_RUNTIME_ID_I2C2,
|
||||
};
|
||||
|
||||
const struct HAL_I2C_DEV g_i2c3Dev =
|
||||
{
|
||||
.pReg = I2C3,
|
||||
.irqNum = I2C3_IRQn,
|
||||
.clkID = CLK_I2C,
|
||||
.clkGateID = CLK_I2C3_GATE,
|
||||
.pclkGateID = PCLK_I2C3_GATE,
|
||||
.runtimeID = PM_RUNTIME_ID_I2C3,
|
||||
};
|
||||
|
||||
const struct HAL_I2C_DEV g_i2c4Dev =
|
||||
{
|
||||
.pReg = I2C4,
|
||||
.irqNum = I2C4_IRQn,
|
||||
.clkID = CLK_I2C,
|
||||
.clkGateID = CLK_I2C4_GATE,
|
||||
.pclkGateID = PCLK_I2C4_GATE,
|
||||
.runtimeID = PM_RUNTIME_ID_I2C4,
|
||||
};
|
||||
|
||||
const struct HAL_I2C_DEV g_i2c5Dev =
|
||||
{
|
||||
.pReg = I2C5,
|
||||
.irqNum = I2C5_IRQn,
|
||||
.clkID = CLK_I2C,
|
||||
.clkGateID = CLK_I2C5_GATE,
|
||||
.pclkGateID = PCLK_I2C5_GATE,
|
||||
.runtimeID = PM_RUNTIME_ID_I2C5,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAL_FSPI_MODULE_ENABLED
|
||||
struct HAL_FSPI_HOST g_fspi0Dev =
|
||||
{
|
||||
.instance = FSPI,
|
||||
.sclkGate = SCLK_SFC_GATE,
|
||||
.hclkGate = HCLK_SFC_GATE,
|
||||
.xipClkGate = 0,
|
||||
.sclkID = 0,
|
||||
.irqNum = FSPI0_IRQn,
|
||||
.xipMemCode = 0,
|
||||
.xipMemData = 0,
|
||||
.xmmcDev[0] =
|
||||
{
|
||||
.type = 0,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAL_CANFD_MODULE_ENABLED
|
||||
const struct HAL_CANFD_DEV g_can0Dev =
|
||||
{
|
||||
.pReg = CAN0,
|
||||
.sclkID = CLK_CAN0,
|
||||
.sclkGateID = CLK_CAN0_GATE,
|
||||
.pclkGateID = PCLK_CAN0_GATE,
|
||||
.irqNum = CAN0_IRQn,
|
||||
};
|
||||
|
||||
const struct HAL_CANFD_DEV g_can1Dev =
|
||||
{
|
||||
.pReg = CAN1,
|
||||
.sclkID = CLK_CAN1,
|
||||
.sclkGateID = CLK_CAN1_GATE,
|
||||
.pclkGateID = PCLK_CAN1_GATE,
|
||||
.irqNum = CAN1_IRQn,
|
||||
};
|
||||
|
||||
const struct HAL_CANFD_DEV g_can2Dev =
|
||||
{
|
||||
.pReg = CAN2,
|
||||
.sclkID = CLK_CAN2,
|
||||
.sclkGateID = CLK_CAN2_GATE,
|
||||
.pclkGateID = PCLK_CAN2_GATE,
|
||||
.irqNum = CAN2_IRQn,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GMAC_MODULE_ENABLED
|
||||
// const struct HAL_GMAC_DEV g_gmac0Dev =
|
||||
// {
|
||||
// .pReg = GMAC0,
|
||||
// .clkID = CLK_MAC0_2TOP,
|
||||
// .clkGateID = CLK_MAC0_2TOP_GATE,
|
||||
// .pclkID = PCLK_PHP,
|
||||
// .pclkGateID = PCLK_GMAC0_GATE,
|
||||
// .irqNum = GMAC0_IRQn,
|
||||
// };
|
||||
const struct HAL_GMAC_DEV g_gmac0Dev =
|
||||
{
|
||||
.pReg = GMAC0,
|
||||
.clkID125M = CLK_MAC0_2TOP,
|
||||
.clkID50M = CLK_MAC0_2TOP,
|
||||
.clkGateID125M = CLK_MAC0_2TOP_GATE,
|
||||
.clkGateID50M = CLK_MAC0_2TOP_GATE,
|
||||
.pclkID = PCLK_PHP,
|
||||
.pclkGateID = PCLK_GMAC0_GATE,
|
||||
.irqNum = GMAC0_IRQn,
|
||||
};
|
||||
|
||||
// const struct HAL_GMAC_DEV g_gmac1Dev =
|
||||
// {
|
||||
// .pReg = GMAC1,
|
||||
// .clkID = CLK_MAC1_2TOP,
|
||||
// .clkGateID = CLK_MAC1_2TOP_GATE,
|
||||
// .pclkID = PCLK_USB,
|
||||
// .pclkGateID = PCLK_GMAC1_GATE,
|
||||
// .irqNum = GMAC1_IRQn,
|
||||
// };
|
||||
const struct HAL_GMAC_DEV g_gmac1Dev =
|
||||
{
|
||||
.pReg = GMAC1,
|
||||
.clkID125M = CLK_MAC1_2TOP,
|
||||
.clkID50M = CLK_MAC1_2TOP,
|
||||
.clkGateID125M = CLK_MAC1_2TOP_GATE,
|
||||
.clkGateID50M = CLK_MAC1_2TOP_GATE,
|
||||
.pclkID = PCLK_USB,
|
||||
.pclkGateID = PCLK_GMAC1_GATE,
|
||||
.irqNum = GMAC1_IRQn,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PCIE_MODULE_ENABLED
|
||||
struct HAL_PCIE_DEV g_pcieDev =
|
||||
{
|
||||
.apbBase = PCIE3X2_APB_BASE,
|
||||
.dbiBase = PCIE3X2_DBI_BASE,
|
||||
.cfgBase = 0xF0000000,
|
||||
.lanes = 2,
|
||||
.gen = 3,
|
||||
.firstBusNo = 0x20,
|
||||
.legacyIrqNum = PCIE30x2_LEGACY_IRQn,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PWM_MODULE_ENABLED
|
||||
const struct HAL_PWM_DEV g_pwm0Dev =
|
||||
{
|
||||
.pReg = PWM0,
|
||||
.clkID = 0,
|
||||
.clkGateID = CLK_PWM0_GATE,
|
||||
.pclkGateID = PCLK_PWM0_GATE,
|
||||
.irqNum = PWM_PMU_IRQn,
|
||||
};
|
||||
|
||||
const struct HAL_PWM_DEV g_pwm1Dev =
|
||||
{
|
||||
.pReg = PWM1,
|
||||
.clkID = CLK_PWM1,
|
||||
.clkGateID = CLK_PWM1_GATE,
|
||||
.pclkGateID = PCLK_PWM1_GATE,
|
||||
.irqNum = PWM1_IRQn,
|
||||
};
|
||||
|
||||
const struct HAL_PWM_DEV g_pwm2Dev =
|
||||
{
|
||||
.pReg = PWM2,
|
||||
.clkID = CLK_PWM2,
|
||||
.clkGateID = CLK_PWM2_GATE,
|
||||
.pclkGateID = PCLK_PWM2_GATE,
|
||||
.irqNum = PWM2_IRQn,
|
||||
};
|
||||
|
||||
const struct HAL_PWM_DEV g_pwm3Dev =
|
||||
{
|
||||
.pReg = PWM3,
|
||||
.clkID = CLK_PWM3,
|
||||
.clkGateID = CLK_PWM3_GATE,
|
||||
.pclkGateID = PCLK_PWM3_GATE,
|
||||
.irqNum = PWM3_IRQn,
|
||||
};
|
||||
#endif
|
||||
|
||||
void BSP_Init(void)
|
||||
{
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,227 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup DEBUG
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup DEBUG_How_To_Use How To Use
|
||||
* @{
|
||||
|
||||
The DEBUG driver can be used as follows:
|
||||
|
||||
Implement DBG hook:
|
||||
|
||||
- printf func: define new HAL_SYSLOG in hal_conf.h or use HAL_DBG_Printf() in default;
|
||||
- assert func: redefine AssertFailed().
|
||||
|
||||
Define debug level in hal_conf.h:
|
||||
|
||||
- HAL_DBG_ON: print master switch;
|
||||
- HAL_DBG_INFO_ON: information printing switch;
|
||||
- HAL_DBG_WRN_ON: information printing switch;
|
||||
- HAL_DBG_ERR_ON: information printing switch;
|
||||
- HAL_ASSERT_ON: Support assert.
|
||||
|
||||
APIS:
|
||||
|
||||
- printf information by calling HAL_DBG();
|
||||
- printf warning by calling HAL_DBG_WRN();
|
||||
- printf error by calling HAL_DBG_ERR();
|
||||
- do assert by calling HAL_ASSERT().
|
||||
|
||||
@} */
|
||||
|
||||
#include "hal_base.h"
|
||||
|
||||
/** @defgroup DEBUG_Private_Definition Private Definition
|
||||
* @{
|
||||
*/
|
||||
/********************* Private MACRO Definition ******************************/
|
||||
|
||||
/********************* Private Structure Definition **************************/
|
||||
|
||||
/********************* Private Variable Definition ***************************/
|
||||
|
||||
/********************* Private Function Definition ***************************/
|
||||
|
||||
/** @} */
|
||||
/********************* Public Function Definition ****************************/
|
||||
|
||||
/** @defgroup DEBUG_Exported_Functions_Group5 Other Functions
|
||||
|
||||
This section provides functions allowing to init and deinit module as follows:
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reports the name of the source file and the source line number
|
||||
* where the HAL_ASSERT error has occurred.
|
||||
* @param file: pointer to the source file name
|
||||
* @param line: HAL_ASSERT error line source number
|
||||
*/
|
||||
__attribute__((weak)) void HAL_AssertFailed(const char *file, uint32_t line)
|
||||
{
|
||||
HAL_DBG_ERR("assert failed at %s %lu\n", file, line);
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief format hex print.
|
||||
* @param s: head tag for every new line.
|
||||
* @param buf: buffer for printing.
|
||||
* @param width: every single printed object width.
|
||||
* @param len: the number of printed objects.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
* sum = width * len (BYTE).
|
||||
*/
|
||||
HAL_Status HAL_DBG_HEX(char *s, void *buf, uint32_t width, uint32_t len)
|
||||
{
|
||||
#ifdef HAL_DBG_ON
|
||||
uint32_t i, j;
|
||||
unsigned char *p8 = (unsigned char *)buf;
|
||||
unsigned short *p16 = (unsigned short *)buf;
|
||||
uint32_t *p32 = (uint32_t *)buf;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (j == 0) {
|
||||
HAL_SYSLOG("[HAL_DBG_HEX] %s %p + 0x%lx:", s, buf, i * width);
|
||||
}
|
||||
|
||||
if (width == 4) {
|
||||
HAL_SYSLOG("0x%08lx,", p32[i]);
|
||||
} else if (width == 2) {
|
||||
HAL_SYSLOG("0x%04x,", p16[i]);
|
||||
} else {
|
||||
HAL_SYSLOG("0x%02x,", p8[i]);
|
||||
}
|
||||
|
||||
if (++j >= 16) {
|
||||
j = 0;
|
||||
HAL_SYSLOG("\n");
|
||||
}
|
||||
}
|
||||
HAL_SYSLOG("\n");
|
||||
#endif
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#ifdef HAL_DBG_USING_HAL_PRINTF
|
||||
static void reverse(char *start, char *end)
|
||||
{
|
||||
while (start < end) {
|
||||
char temp = *start;
|
||||
*start = *end;
|
||||
*end = temp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
extern int _write(int fd, char *ptr, int len);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief format and print data
|
||||
* @param format: format printf param. only support: \%d, \%s, \%ld, \%lld
|
||||
* @return int32_t.
|
||||
*/
|
||||
__attribute__((weak)) int32_t HAL_DBG_Printf(const char *format, ...)
|
||||
{
|
||||
static char g_printf_buf[HAL_PRINTF_BUF_SIZE];
|
||||
char *str = g_printf_buf;
|
||||
int32_t len = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
while (*format != '\0') {
|
||||
if (*format == '%') {
|
||||
format++;
|
||||
if (*format == 'd') {
|
||||
int i = va_arg(args, int);
|
||||
char *start = str;
|
||||
do {
|
||||
*str++ = '0' + (i % 10);
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
reverse(start, str - 1);
|
||||
} else if (*format == 's') {
|
||||
char *s = va_arg(args, char *);
|
||||
while (*s) {
|
||||
*str++ = *s++;
|
||||
}
|
||||
} else if (*format == 'l') {
|
||||
format++;
|
||||
if (*format == 'd') {
|
||||
long i = va_arg(args, long);
|
||||
char *start = str;
|
||||
do {
|
||||
*str++ = '0' + (i % 10);
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
reverse(start, str - 1);
|
||||
} else if (*format == 'l') {
|
||||
format++;
|
||||
if (*format == 'd') {
|
||||
long long int i = va_arg(args, long long int);
|
||||
char *start = str;
|
||||
do {
|
||||
*str++ = '0' + (i % 10);
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
reverse(start, str - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*str++ = *format;
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
*str = '\0';
|
||||
|
||||
va_end(args);
|
||||
len = str - g_printf_buf;
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
return _write(2, g_printf_buf, len);
|
||||
#else
|
||||
for (int i = 0; i < len; i++) {
|
||||
fputc(g_printf_buf[i], stdout);
|
||||
}
|
||||
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* @brief format and print data
|
||||
* @param format: format printf param.
|
||||
* @return int32_t.
|
||||
*/
|
||||
__attribute__((weak)) int32_t HAL_DBG_Printf(const char *format, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAL_DBG_USING_HAL_PRINTF */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,205 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_base.h"
|
||||
|
||||
#if defined(SOC_RK3568) && defined(HAL_GMAC_MODULE_ENABLED)
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup GMAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup GMAC_Private_Definition Private Definition
|
||||
* @{
|
||||
*/
|
||||
/********************* Private MACRO Definition ******************************/
|
||||
|
||||
#define HIWORD_UPDATE(val, mask, shift) \
|
||||
((val) << (shift) | (mask) << ((shift) + 16))
|
||||
|
||||
#define GRF_BIT(nr) (1 << (nr) | 1 << (nr+16))
|
||||
#define GRF_CLR_BIT(nr) (1 << (nr+16))
|
||||
|
||||
#define DELAY_ENABLE(soc, tx, rx) \
|
||||
(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \
|
||||
((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
|
||||
|
||||
#define RK3568_GRF_GMAC0_CON0 0X0380
|
||||
#define RK3568_GRF_GMAC0_CON1 0X0384
|
||||
#define RK3568_GRF_GMAC1_CON0 0X0388
|
||||
#define RK3568_GRF_GMAC1_CON1 0X038c
|
||||
|
||||
/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
|
||||
#define RK3568_GMAC_GMII_MODE GRF_BIT(7)
|
||||
#define RK3568_GMAC_PHY_INTF_SEL_RGMII \
|
||||
(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
|
||||
#define RK3568_GMAC_PHY_INTF_SEL_RMII \
|
||||
(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
|
||||
#define RK3568_GMAC_FLOW_CTRL GRF_BIT(3)
|
||||
#define RK3568_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3)
|
||||
#define RK3568_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1)
|
||||
#define RK3568_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(1)
|
||||
#define RK3568_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0)
|
||||
#define RK3568_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0)
|
||||
|
||||
/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
|
||||
#define RK3568_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
|
||||
#define RK3568_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
||||
|
||||
/********************* Private Structure Definition **************************/
|
||||
|
||||
/********************* Private Variable Definition ***************************/
|
||||
|
||||
/********************* Private Function Definition ***************************/
|
||||
|
||||
/** @} */
|
||||
/********************* Public Function Definition ****************************/
|
||||
|
||||
/** @defgroup GMAC_Exported_Functions_Group5 Other Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set RGMII Mode.
|
||||
* @param pGMAC: pointer to a GMAC_HANDLE structure that contains
|
||||
* the information for GMAC module.
|
||||
* @param txDelay: RGMII tx delayline
|
||||
* @param rxDelay: RGMII rx delayline
|
||||
*/
|
||||
void HAL_GMAC_SetToRGMII(struct GMAC_HANDLE *pGMAC,
|
||||
int32_t txDelay, int32_t rxDelay)
|
||||
{
|
||||
uint32_t *con0, *con1;
|
||||
|
||||
con0 = (uint32_t *)((pGMAC->pReg == GMAC1) ? &(GRF->MAC1_CON0) :
|
||||
&(GRF->MAC0_CON0));
|
||||
con1 = (uint32_t *)((pGMAC->pReg == GMAC1) ? &(GRF->MAC1_CON1) :
|
||||
&(GRF->MAC0_CON1));
|
||||
|
||||
WRITE_REG(*con1,
|
||||
RK3568_GMAC_PHY_INTF_SEL_RGMII |
|
||||
RK3568_GMAC_RXCLK_DLY_ENABLE |
|
||||
RK3568_GMAC_TXCLK_DLY_ENABLE);
|
||||
|
||||
WRITE_REG(*con0,
|
||||
RK3568_GMAC_CLK_RX_DL_CFG(rxDelay) |
|
||||
RK3568_GMAC_CLK_TX_DL_CFG(txDelay));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RMII Mode.
|
||||
* @param pGMAC: pointer to a GMAC_HANDLE structure that contains
|
||||
* the information for GMAC module.
|
||||
*/
|
||||
void HAL_GMAC_SetToRMII(struct GMAC_HANDLE *pGMAC)
|
||||
{
|
||||
uint32_t *con1, *cruCon, val;
|
||||
|
||||
con1 = (uint32_t *)((pGMAC->pReg == GMAC1) ? &(GRF->MAC1_CON1) :
|
||||
&(GRF->MAC0_CON1));
|
||||
|
||||
WRITE_REG(*con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
|
||||
|
||||
cruCon = (uint32_t *)((pGMAC->pReg == GMAC1) ? &(CRU->CRU_CLKSEL_CON[33]) :
|
||||
&(CRU->CRU_CLKSEL_CON[31]));
|
||||
/* RMII mode */
|
||||
val = HIWORD_UPDATE(0x1, 0x3, 0);
|
||||
/* clock from io if it was */
|
||||
/* val |= HIWORD_UPDATE(0x1, 0x1, 2); */
|
||||
/* ref clock sel 50M */
|
||||
val |= HIWORD_UPDATE(0x1, 0x3, 8);
|
||||
/* clock speed 25M */
|
||||
val |= HIWORD_UPDATE(0x1, 0x1, 3);
|
||||
WRITE_REG(*cruCon, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set external clock source select.
|
||||
* @param pGMAC: pointer to a GMAC_HANDLE structure that contains
|
||||
* the information for GMAC module.
|
||||
* @param extClk: 0: select clk_mac as the clock of mac
|
||||
* 1: select external phy clock as the clock of mac
|
||||
*/
|
||||
void HAL_GMAC_SetExtclkSrc(struct GMAC_HANDLE *pGMAC, bool extClk)
|
||||
{
|
||||
uint32_t *cruCon, val;
|
||||
uint32_t clksel = 0;
|
||||
|
||||
cruCon = (uint32_t *)((pGMAC->pReg == GMAC1) ? &(CRU->CRU_CLKSEL_CON[33]) :
|
||||
&(CRU->CRU_CLKSEL_CON[31]));
|
||||
|
||||
if (extClk) {
|
||||
clksel = 1;
|
||||
}
|
||||
|
||||
val = HIWORD_UPDATE(clksel, 0x1, 2);
|
||||
WRITE_REG(*cruCon, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RGMII speed.
|
||||
* @param pGMAC: pointer to a GMAC_HANDLE structure that contains
|
||||
* the information for GMAC module.
|
||||
* @param speed: RGMII speed 10/100/1000
|
||||
*/
|
||||
void HAL_GMAC_SetRGMIISpeed(struct GMAC_HANDLE *pGMAC, int32_t speed)
|
||||
{
|
||||
eCLOCK_Name clkID;
|
||||
uint32_t rate;
|
||||
int32_t ret;
|
||||
|
||||
switch (speed) {
|
||||
case 10:
|
||||
rate = 2500000;
|
||||
break;
|
||||
case 100:
|
||||
rate = 25000000;
|
||||
break;
|
||||
case 1000:
|
||||
rate = 125000000;
|
||||
break;
|
||||
default:
|
||||
HAL_DBG_ERR("unknown speed value for GMAC speed=%ld", speed);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (pGMAC->phyStatus.interface == PHY_INTERFACE_MODE_RMII) {
|
||||
clkID = (pGMAC->pReg == GMAC1) ? SCLK_GMAC1_RMII_SPEED :
|
||||
SCLK_GMAC0_RMII_SPEED;
|
||||
} else {
|
||||
clkID = (pGMAC->pReg == GMAC1) ? SCLK_GMAC1_RGMII_SPEED :
|
||||
SCLK_GMAC0_RGMII_SPEED;
|
||||
}
|
||||
|
||||
ret = HAL_CRU_ClkSetFreq(clkID, rate);
|
||||
if (ret) {
|
||||
HAL_DBG_ERR("%s: set clk_mac_speed rate %ld failed %ld\n",
|
||||
__func__, rate, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RGMII speed.
|
||||
* @param pGMAC: pointer to a GMAC_HANDLE structure that contains
|
||||
* the information for GMAC module.
|
||||
* @param speed: RGMII speed 10/100
|
||||
*/
|
||||
void HAL_GMAC_SetRMIISpeed(struct GMAC_HANDLE *pGMAC, int32_t speed)
|
||||
{
|
||||
HAL_GMAC_SetRGMIISpeed(pGMAC, speed);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* SOC_RK3568 && HAL_GMAC_MODULE_ENABLED */
|
|
@ -0,0 +1,606 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_base.h"
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup GPIO
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup GPIO_How_To_Use How To Use
|
||||
* @{
|
||||
|
||||
The GPIO driver can be used as follows:
|
||||
|
||||
APIs for GPIO io read write:
|
||||
|
||||
1. HAL_GPIO_GetPinLevel() to get EXT port level.
|
||||
2. HAL_GPIO_SetPinLevel() to set io level.
|
||||
3. HAL_GPIO_SetPinDirection() to set io direction.
|
||||
|
||||
APIs for GPIO IRQ:
|
||||
|
||||
1. HAL_GPIO_EnableIRQ() to enable a GPIO IRQ.
|
||||
2. HAL_GPIO_DisableIRQ() to disable a GPIO IRQ.
|
||||
3. HAL_GPIO_IRQHandler() to handle GPIO IRQ isr.
|
||||
4. HAL_GPIO_IRQDispatch() to dispatch GPIO IRQ, should be implemented by User.
|
||||
|
||||
Please open the macro definition HAL_GPIO_VIRTUAL_MODEL_FEATURE_ENABLED to support
|
||||
|
||||
APIs for GPIO virtual model:
|
||||
|
||||
1. HAL_GPIO_EnableVirtualModel() to enable a GPIO virtual model.
|
||||
2. HAL_GPIO_DisableVirtualModel() to disable a GPIO virtual model.
|
||||
3. HAL_GPIO_SetVirtualModel() to configure GPIO pins virtual model.
|
||||
|
||||
@} */
|
||||
|
||||
/** @defgroup GPIO_Private_Definition Private Definition
|
||||
* @{
|
||||
*/
|
||||
/********************* Private MACRO Definition ******************************/
|
||||
#define UNUSED(X) (void)(X) /* To avoid gcc/g++ warnings */
|
||||
|
||||
/********************* Private Function Definition ***************************/
|
||||
|
||||
/**
|
||||
* @brief Set the GPIO IRQ end of interrupt(EOI).
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
*/
|
||||
static void GPIO_SetEOI(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
|
||||
{
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
if (IS_GPIO_HIGH_PIN(pin)) {
|
||||
pin &= 0xFFFF0000;
|
||||
pGPIO->PORT_EOI_H = pin | (pin >> 16);
|
||||
} else {
|
||||
pin &= 0x0000FFFF;
|
||||
pGPIO->PORT_EOI_L = pin | (pin << 16);
|
||||
}
|
||||
#else
|
||||
{
|
||||
pGPIO->PORTA_EOI = pin;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get GPIO all pins irq type.
|
||||
* @param pGPIO: the GPIO struct.
|
||||
* @return uint32_t: type value.
|
||||
*/
|
||||
static uint32_t GPIO_GetIntType(struct GPIO_REG *pGPIO)
|
||||
{
|
||||
uint32_t type;
|
||||
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
type = (pGPIO->INT_TYPE_L & 0xffff);
|
||||
type |= ((pGPIO->INT_TYPE_H & 0xffff) << 16);
|
||||
type |= (pGPIO->INT_BOTHEDGE_L & 0xffff);
|
||||
type |= ((pGPIO->INT_BOTHEDGE_H & 0xffff) << 16);
|
||||
#else
|
||||
type = pGPIO->INTTYPE_LEVEL;
|
||||
#ifdef GPIO_INT_BOTHEDGE_OFFSET
|
||||
type |= pGPIO->INT_BOTHEDGE;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get GPIO all pins irq status.
|
||||
* @param pGPIO: the GPIO struct.
|
||||
* @return uint32_t: status value.
|
||||
*/
|
||||
static uint32_t GPIO_GetIntStatus(struct GPIO_REG *pGPIO)
|
||||
{
|
||||
return pGPIO->INT_STATUS;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
/********************* Public Function Definition ***************************/
|
||||
|
||||
/** @defgroup GPIO_Exported_Functions_Group1 State and Errors Functions
|
||||
|
||||
This section provides functions allowing to get the status of the module:
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief GPIO Configure IRQ trigger type.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @param mode: The value defined in @ref eGPIO_intType.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_GPIO_SetIntType(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_intType mode)
|
||||
{
|
||||
uint32_t both = 0, type = 0, plar = 0;
|
||||
|
||||
UNUSED(both);
|
||||
|
||||
switch (mode) {
|
||||
case GPIO_INT_TYPE_EDGE_RISING:
|
||||
type = 1;
|
||||
plar = 1;
|
||||
both = 0;
|
||||
break;
|
||||
case GPIO_INT_TYPE_EDGE_FALLING:
|
||||
type = 1;
|
||||
plar = 0;
|
||||
both = 0;
|
||||
break;
|
||||
case GPIO_INT_TYPE_LEVEL_HIGH:
|
||||
type = 0;
|
||||
plar = 1;
|
||||
both = 0;
|
||||
break;
|
||||
case GPIO_INT_TYPE_LEVEL_LOW:
|
||||
type = 0;
|
||||
plar = 0;
|
||||
both = 0;
|
||||
break;
|
||||
case GPIO_INT_TYPE_EDGE_BOTH:
|
||||
type = 0;
|
||||
plar = 0;
|
||||
both = 1;
|
||||
break;
|
||||
default:
|
||||
|
||||
return HAL_INVAL;
|
||||
}
|
||||
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
if (IS_GPIO_HIGH_PIN(pin)) {
|
||||
pin &= 0xFFFF0000;
|
||||
pGPIO->INT_TYPE_H = (type) ? (pin | (pin >> 16)) : (pin);
|
||||
pGPIO->INT_POLARITY_H = (plar) ? (pin | (pin >> 16)) : (pin);
|
||||
pGPIO->INT_BOTHEDGE_H = (both) ? (pin | (pin >> 16)) : (pin);
|
||||
} else {
|
||||
pin &= 0x0000FFFF;
|
||||
pGPIO->INT_TYPE_L = (type) ? (pin | (pin << 16)) : (pin << 16);
|
||||
pGPIO->INT_POLARITY_L = (plar) ? (pin | (pin << 16)) : (pin << 16);
|
||||
pGPIO->INT_BOTHEDGE_L = (both) ? (pin | (pin << 16)) : (pin << 16);
|
||||
}
|
||||
#else
|
||||
{
|
||||
pGPIO->INTTYPE_LEVEL = (type) ? (pin) : (pGPIO->INTTYPE_LEVEL & ~(pin));
|
||||
pGPIO->INT_POLARITY = (plar) ? (pin) : (pGPIO->INT_POLARITY & ~(pin));
|
||||
#ifdef GPIO_INT_BOTHEDGE_OFFSET
|
||||
pGPIO->INT_BOTHEDGE = (both) ? (pin) : (pGPIO->INT_BOTHEDGE & ~(pin));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set GPIO direction.
|
||||
* @param pGPIO: the GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @param direction: direction value defined in @ref eGPIO_pinDirection.
|
||||
* @return HAL_Status: HAL_OK if success.
|
||||
*/
|
||||
HAL_Status HAL_GPIO_SetPinDirection(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_pinDirection direction)
|
||||
{
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
if (IS_GPIO_HIGH_PIN(pin)) {
|
||||
pin &= 0xFFFF0000;
|
||||
pGPIO->SWPORT_DDR_H = (direction == GPIO_OUT) ? (pin | (pin >> 16)) : (pin);
|
||||
} else {
|
||||
pin &= 0x0000FFFF;
|
||||
pGPIO->SWPORT_DDR_L = (direction == GPIO_OUT) ? (pin | (pin << 16)) : (pin << 16);
|
||||
}
|
||||
#else
|
||||
if (direction == GPIO_OUT) {
|
||||
pGPIO->SWPORTA_DDR |= pin;
|
||||
} else {
|
||||
pGPIO->SWPORTA_DDR &= ~pin;
|
||||
}
|
||||
#endif
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set GPIO direction.
|
||||
* @param pGPIO: the GPIO struct.
|
||||
* @param mPins: The pins defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @param direction: value defined in @ref eGPIO_pinDirection.
|
||||
* @return HAL_Status: HAL_OK if success.
|
||||
*/
|
||||
HAL_Status HAL_GPIO_SetPinsDirection(struct GPIO_REG *pGPIO, uint32_t mPins, eGPIO_pinDirection direction)
|
||||
{
|
||||
uint8_t pin;
|
||||
HAL_Status rc;
|
||||
|
||||
HAL_ASSERT(IS_GPIO_INSTANCE(pGPIO));
|
||||
|
||||
for (pin = 0; pin < 32; pin++) {
|
||||
if (mPins & (1 << pin)) {
|
||||
rc = HAL_GPIO_SetPinDirection(pGPIO, (1 << pin), direction);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get GPIO Pin data direction value.
|
||||
* @param pGPIO: the GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @retval eGPIO_pinDirection: data direction value.
|
||||
*/
|
||||
eGPIO_pinDirection HAL_GPIO_GetPinDirection(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
|
||||
{
|
||||
eGPIO_pinDirection direction;
|
||||
uint32_t value;
|
||||
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
value = IS_GPIO_HIGH_PIN(pin) ? (pGPIO->SWPORT_DDR_H & (pin >> 16)) : (pGPIO->SWPORT_DDR_L & pin);
|
||||
#else
|
||||
value = pGPIO->SWPORTA_DDR & pin;
|
||||
#endif
|
||||
|
||||
if (value != (uint32_t)GPIO_IN) {
|
||||
direction = GPIO_OUT;
|
||||
} else {
|
||||
direction = GPIO_IN;
|
||||
}
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set GPIO pin level.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @param level: The level defined in @ref eGPIO_pinLevel.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_GPIO_SetPinLevel(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_pinLevel level)
|
||||
{
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
if (IS_GPIO_HIGH_PIN(pin)) {
|
||||
pin &= 0xFFFF0000;
|
||||
pGPIO->SWPORT_DR_H = (level == GPIO_HIGH) ? (pin | (pin >> 16)) : (pin);
|
||||
} else {
|
||||
pin &= 0x0000FFFF;
|
||||
pGPIO->SWPORT_DR_L = (level == GPIO_HIGH) ? (pin | (pin << 16)) : (pin << 16);
|
||||
}
|
||||
#else
|
||||
if (level == GPIO_HIGH) {
|
||||
pGPIO->SWPORTA_DR |= pin;
|
||||
} else {
|
||||
pGPIO->SWPORTA_DR &= ~pin;
|
||||
}
|
||||
#endif
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set GPIO pin level.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @param mPins: The pins defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @param level: The level defined in @ref eGPIO_pinLevel.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_GPIO_SetPinsLevel(struct GPIO_REG *pGPIO, uint32_t mPins, eGPIO_pinLevel level)
|
||||
{
|
||||
uint8_t pin;
|
||||
HAL_Status rc;
|
||||
|
||||
HAL_ASSERT(IS_GPIO_INSTANCE(pGPIO));
|
||||
|
||||
for (pin = 0; pin < 32; pin++) {
|
||||
if (mPins & (1 << pin)) {
|
||||
rc = HAL_GPIO_SetPinLevel(pGPIO, (1 << pin), level);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup GPIO_Exported_Functions_Group2 IO Functions
|
||||
|
||||
This section provides functions allowing to IO controlling:
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get GPIO Pin data value.
|
||||
* @param pGPIO: the GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @retval eGPIO_pinLevel: data value.
|
||||
*/
|
||||
eGPIO_pinLevel HAL_GPIO_GetPinData(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
|
||||
{
|
||||
eGPIO_pinLevel level;
|
||||
uint32_t value;
|
||||
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
value = IS_GPIO_HIGH_PIN(pin) ? (pGPIO->SWPORT_DR_H & (pin >> 16)) : (pGPIO->SWPORT_DR_L & pin);
|
||||
#else
|
||||
value = pGPIO->SWPORTA_DR & pin;
|
||||
#endif
|
||||
|
||||
if (value != (uint32_t)GPIO_LOW) {
|
||||
level = GPIO_HIGH;
|
||||
} else {
|
||||
level = GPIO_LOW;
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get GPIO Pin ext bank level.
|
||||
* @param pGPIO: the GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @retval GPIO_PinState: ext bank value.
|
||||
*/
|
||||
eGPIO_pinLevel HAL_GPIO_GetPinLevel(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
value = (pGPIO->EXT_PORT & pin);
|
||||
#else
|
||||
value = (pGPIO->EXT_PORTA & pin);
|
||||
#endif
|
||||
|
||||
return (value == (uint32_t)GPIO_LOW) ? GPIO_LOW : GPIO_HIGH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get GPIO Pin ext bank level.
|
||||
* @param pGPIO: the GPIO struct.
|
||||
* @retval uint32_t: ext bank value.
|
||||
*/
|
||||
uint32_t HAL_GPIO_GetBankLevel(struct GPIO_REG *pGPIO)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
value = (pGPIO->EXT_PORT);
|
||||
#else
|
||||
value = (pGPIO->EXT_PORTA);
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** @defgroup GPIO_Exported_Functions_Group3 Other Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set GPIO irq enable.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
*/
|
||||
void HAL_GPIO_EnableIRQ(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
|
||||
{
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
if (IS_GPIO_HIGH_PIN(pin)) {
|
||||
pin &= 0xFFFF0000;
|
||||
#ifndef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
|
||||
pGPIO->INT_MASK_H = pin;
|
||||
#endif
|
||||
pGPIO->INT_EN_H = pin | (pin >> 16);
|
||||
} else {
|
||||
pin &= 0x0000FFFF;
|
||||
#ifndef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
|
||||
pGPIO->INT_MASK_L = pin << 16;
|
||||
#endif
|
||||
pGPIO->INT_EN_L = pin | (pin << 16);
|
||||
}
|
||||
#else
|
||||
{
|
||||
pGPIO->INTEN |= pin;
|
||||
pGPIO->INTMASK &= ~pin;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set GPIO irq disable.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @param pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
*/
|
||||
void HAL_GPIO_DisableIRQ(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
|
||||
{
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
if (IS_GPIO_HIGH_PIN(pin)) {
|
||||
pin &= 0xFFFF0000;
|
||||
pGPIO->INT_EN_H = pin;
|
||||
#ifndef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
|
||||
pGPIO->INT_MASK_H = pin | (pin >> 16);
|
||||
#endif
|
||||
} else {
|
||||
pin &= 0x0000FFFF;
|
||||
pGPIO->INT_EN_L = pin << 16;
|
||||
#ifndef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
|
||||
pGPIO->INT_MASK_L = pin | (pin << 16);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
{
|
||||
pGPIO->INTEN &= ~pin;
|
||||
pGPIO->INTMASK |= pin;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO IRQ callbacks.
|
||||
* @param bank: The bank id.
|
||||
* @param pin: The true pin index, 0~31.
|
||||
* NOTE: This function Should not be modified, when the callback is needed,
|
||||
* the HAL_GPIO_IRQDispatch could be implemented in the user file.
|
||||
*/
|
||||
__attribute__((weak)) void HAL_GPIO_IRQDispatch(eGPIO_bankId bank, uint32_t pin)
|
||||
{
|
||||
UNUSED(bank);
|
||||
UNUSED(pin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO IRQ hanlder.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @param bank: The bank id.
|
||||
*/
|
||||
void HAL_GPIO_IRQHandler(struct GPIO_REG *pGPIO, eGPIO_bankId bank)
|
||||
{
|
||||
uint32_t stat, type, clear;
|
||||
uint32_t i;
|
||||
uint32_t pin;
|
||||
|
||||
stat = GPIO_GetIntStatus(pGPIO);
|
||||
type = GPIO_GetIntType(pGPIO);
|
||||
|
||||
/* Then process each pending GPIO interrupt */
|
||||
for (i = 0x0U; i < PIN_NUMBER_PER_BANK && stat != 0; i++) {
|
||||
clear = 0x1U << i;
|
||||
pin = HAL_BIT(i);
|
||||
|
||||
if ((stat & clear) != 0x0U) {
|
||||
/* If gpio is Edge-sensitive triggered, clear eoi */
|
||||
if (type & clear) {
|
||||
GPIO_SetEOI(pGPIO, pin);
|
||||
}
|
||||
|
||||
/* Remove the pending interrupt bit from the clear */
|
||||
stat &= ~clear;
|
||||
|
||||
/* And disptach the GPIO interrupt to the handler */
|
||||
HAL_GPIO_IRQDispatch(bank, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAL_GPIO_VIRTUAL_MODEL_FEATURE_ENABLED
|
||||
|
||||
/**
|
||||
* @brief GPIO virtual model enable.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_GPIO_EnableVirtualModel(struct GPIO_REG *pGPIO)
|
||||
{
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
pGPIO->GPIO_VIRTUAL_EN = 0x10001;
|
||||
|
||||
return HAL_OK;
|
||||
#endif
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO virtual model disable.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_GPIO_DisableVirtualModel(struct GPIO_REG *pGPIO)
|
||||
{
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
pGPIO->GPIO_VIRTUAL_EN = 0x10000;
|
||||
|
||||
return HAL_OK;
|
||||
#endif
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO Configure pins for virtual model.
|
||||
* @param pGPIO: The pointer of GPIO struct.
|
||||
* @param pins: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @param vmode: The value defined in @ref eGPIO_VirtualModel.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_GPIO_SetVirtualModel(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_VirtualModel vmodel)
|
||||
{
|
||||
#if (GPIO_VER_ID >= 0x01000C2BU)
|
||||
uint32_t lowPins, highPins;
|
||||
|
||||
lowPins = pin & 0x0000ffff;
|
||||
highPins = (pin & 0xffff0000) >> 16;
|
||||
|
||||
#if defined(GPIO0_EXP)
|
||||
/* Support OS_A and OS_B */
|
||||
if (vmodel == GPIO_VIRTUAL_MODEL_OS_B) {
|
||||
pGPIO->GPIO_REG_GROUP_L = lowPins << 16;
|
||||
pGPIO->GPIO_REG_GROUP_H = highPins << 16;
|
||||
} else {
|
||||
pGPIO->GPIO_REG_GROUP_L = lowPins | (lowPins << 16);
|
||||
pGPIO->GPIO_REG_GROUP_H = highPins | (highPins << 16);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
#elif defined(GPIO0_EXP3)
|
||||
/* Support 4 OS */
|
||||
switch (vmodel) {
|
||||
case GPIO_VIRTUAL_MODEL_OS_A:
|
||||
pGPIO->GPIO_REG_GROUP_L = lowPins | (lowPins << 16);
|
||||
pGPIO->GPIO_REG_GROUP_H = highPins | (highPins << 16);
|
||||
break;
|
||||
case GPIO_VIRTUAL_MODEL_OS_B:
|
||||
pGPIO->GPIO_REG_GROUP1_L = lowPins | (lowPins << 16);
|
||||
pGPIO->GPIO_REG_GROUP1_H = highPins | (highPins << 16);
|
||||
break;
|
||||
case GPIO_VIRTUAL_MODEL_OS_C:
|
||||
pGPIO->GPIO_REG_GROUP2_L = lowPins | (lowPins << 16);
|
||||
pGPIO->GPIO_REG_GROUP2_H = highPins | (highPins << 16);
|
||||
break;
|
||||
case GPIO_VIRTUAL_MODEL_OS_D:
|
||||
pGPIO->GPIO_REG_GROUP3_L = lowPins | (lowPins << 16);
|
||||
pGPIO->GPIO_REG_GROUP3_H = highPins | (highPins << 16);
|
||||
break;
|
||||
default:
|
||||
HAL_DBG("unknown gpio virtual model-%d\n", vmodel);
|
||||
break;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
#else
|
||||
#error missing GPIO EXP register definition!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
#endif /* HAL_GPIO_VIRTUAL_MODEL_FEATURE_ENABLED */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
|
@ -0,0 +1,565 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_base.h"
|
||||
|
||||
#if defined(HAL_PINCTRL_MODULE_ENABLED) && (defined(SOC_RV1126) || defined(SOC_SWALLOW) || defined(SOC_RK3568) || defined(RKMCU_RK2106))
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup PINCTRL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PINCTRL_How_To_Use How To Use
|
||||
* @{
|
||||
|
||||
The pinctrl setting registers actually is bus grf registers, which include
|
||||
iomux, drive strength, pull mode, slew rate and schmitt trigger.
|
||||
|
||||
The pinctrl driver provides APIs:
|
||||
- HAL_PINCTRL_SetIOMUX() to set pin iomux
|
||||
- HAL_PINCTRL_SetParam() to set pin iomux/drive/pull/slewrate/schmitt/ie
|
||||
|
||||
Example:
|
||||
|
||||
HAL_PINCTRL_SetIOMUX(GPIO_BANK0,
|
||||
GPIO_PIN_A0 | // I2S_IN_SCLK
|
||||
GPIO_PIN_A1 | // I2S_IN_LRCK
|
||||
GPIO_PIN_A2 | // I2S_IN_SDI0
|
||||
GPIO_PIN_A3, // I2S_IN_SDI1
|
||||
PIN_CONFIG_MUX_FUNC2);
|
||||
|
||||
HAL_PINCTRL_SetParam(GPIO_BANK0,
|
||||
GPIO_PIN_A0 | // I2S_IN_SCLK
|
||||
GPIO_PIN_A1 | // I2S_IN_LRCK
|
||||
GPIO_PIN_A2 | // I2S_IN_SDI0
|
||||
GPIO_PIN_A3, // I2S_IN_SDI1
|
||||
PIN_CONFIG_MUX_FUNC2 |
|
||||
PIN_CONFIG_PUL_DOWN |
|
||||
PIN_CONFIG_DRV_LEVEL2 |
|
||||
PIN_CONFIG_SRT_FAST |
|
||||
PIN_CONFIG_SMT_ENABLE);
|
||||
@} */
|
||||
|
||||
/** @defgroup PINCTRL_Private_Definition Private Definition
|
||||
* @{
|
||||
*/
|
||||
/********************* Private MACRO Definition ******************************/
|
||||
|
||||
#define _TO_MASK(w) ((1U << (w)) - 1U)
|
||||
#define _TO_OFFSET(p, w) ((p) * (w))
|
||||
#define RK_GEN_VAL(p, v, w) ((_TO_MASK(w) << (_TO_OFFSET(p, w) + 16)) | (((v) & _TO_MASK(w)) << _TO_OFFSET(p, w)))
|
||||
|
||||
/*
|
||||
* Use HAL_DBG("pinctrl: write val = 0x%lx to register %p\n", VAL, ®);
|
||||
* and HAL_DBG("pinctrl: readback register %p = 0x%lx\n", ®, REG);
|
||||
* for debug
|
||||
*/
|
||||
#define _PINCTRL_WRITE(REG, DATA) \
|
||||
{ \
|
||||
REG = DATA; \
|
||||
}
|
||||
|
||||
#if defined(GRF_GPIO0A_IOMUX_OFFSET)
|
||||
#define IOMUX_BIT_PER_PIN (2)
|
||||
#define IOMUX_PIN_PER_REG (16 / IOMUX_BIT_PER_PIN)
|
||||
#define IOMUX_0(__B, __P) (GRF->GPIO##__B##__P##_IOMUX)
|
||||
#define SET_IOMUX_0(_B, _P, p, v, w) _PINCTRL_WRITE(IOMUX_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_IOMUX_0(B, P, p, v) SET_IOMUX_0(B, P, p % IOMUX_PIN_PER_REG, v, IOMUX_BIT_PER_PIN)
|
||||
#define SET_IOMUX(_GPIO, _PORT, pin, val) RK_SET_IOMUX_0(_GPIO, _PORT, pin, val)
|
||||
|
||||
#elif defined(GRF_GPIO0A_IOMUX_H_OFFSET)
|
||||
#define IOMUX_BIT_PER_PIN (4)
|
||||
#define IOMUX_PIN_PER_REG (16 / IOMUX_BIT_PER_PIN)
|
||||
#define IOMUX_0(__B, __P) (GRF->GPIO##__B##__P##_IOMUX_L)
|
||||
#define IOMUX_1(__B, __P) (GRF->GPIO##__B##__P##_IOMUX_H)
|
||||
#define SET_IOMUX_0(_B, _P, p, v, w) _PINCTRL_WRITE(IOMUX_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_IOMUX_1(_B, _P, p, v, w) _PINCTRL_WRITE(IOMUX_1(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_IOMUX_0(B, P, p, v) SET_IOMUX_0(B, P, p % IOMUX_PIN_PER_REG, v, IOMUX_BIT_PER_PIN)
|
||||
#define RK_SET_IOMUX_1(B, P, p, v) SET_IOMUX_1(B, P, p % IOMUX_PIN_PER_REG, v, IOMUX_BIT_PER_PIN)
|
||||
#define SET_IOMUX(_GPIO, _PORT, pin, val) \
|
||||
{ \
|
||||
if ((pin % 8) < 4) { \
|
||||
RK_SET_IOMUX_0(_GPIO, _PORT, pin, val); \
|
||||
} else { \
|
||||
RK_SET_IOMUX_1(_GPIO, _PORT, pin, val); \
|
||||
} \
|
||||
}
|
||||
|
||||
#elif defined(GRF_GPIO0A_IOMUX_0_OFFSET)
|
||||
#define IOMUX_BIT_PER_PIN (8)
|
||||
#define IOMUX_PIN_PER_REG (16 / IOMUX_BIT_PER_PIN)
|
||||
#define IOMUX_0(__B, __P) (GRF->GPIO##__B##__P##_IOMUX_0)
|
||||
#define IOMUX_1(__B, __P) (GRF->GPIO##__B##__P##_IOMUX_1)
|
||||
#define IOMUX_2(__B, __P) (GRF->GPIO##__B##__P##_IOMUX_2)
|
||||
#define IOMUX_3(__B, __P) (GRF->GPIO##__B##__P##_IOMUX_3)
|
||||
#define SET_IOMUX_0(_B, _P, p, v, w) _PINCTRL_WRITE(IOMUX_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_IOMUX_1(_B, _P, p, v, w) _PINCTRL_WRITE(IOMUX_1(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_IOMUX_2(_B, _P, p, v, w) _PINCTRL_WRITE(IOMUX_2(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_IOMUX_3(_B, _P, p, v, w) _PINCTRL_WRITE(IOMUX_3(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_IOMUX_0(B, P, p, v) SET_IOMUX_0(B, P, p % IOMUX_PIN_PER_REG, v, IOMUX_BIT_PER_PIN)
|
||||
#define RK_SET_IOMUX_1(B, P, p, v) SET_IOMUX_1(B, P, p % IOMUX_PIN_PER_REG, v, IOMUX_BIT_PER_PIN)
|
||||
#define RK_SET_IOMUX_2(B, P, p, v) SET_IOMUX_2(B, P, p % IOMUX_PIN_PER_REG, v, IOMUX_BIT_PER_PIN)
|
||||
#define RK_SET_IOMUX_3(B, P, p, v) SET_IOMUX_3(B, P, p % IOMUX_PIN_PER_REG, v, IOMUX_BIT_PER_PIN)
|
||||
#define SET_IOMUX(_GPIO, _PORT, pin, val) \
|
||||
{ \
|
||||
if ((pin % 8) < 2) { \
|
||||
RK_SET_IOMUX_0(_GPIO, _PORT, pin, val); \
|
||||
} else if ((pin % 8) < 4) { \
|
||||
RK_SET_IOMUX_1(_GPIO, _PORT, pin, val); \
|
||||
} else if ((pin % 8) < 6) { \
|
||||
RK_SET_IOMUX_2(_GPIO, _PORT, pin, val); \
|
||||
} else { \
|
||||
RK_SET_IOMUX_3(_GPIO, _PORT, pin, val); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GRF_GPIO0A_DS_OFFSET)
|
||||
#define DS_BIT_PER_PIN (2)
|
||||
#define DS_PIN_PER_REG (16 / DS_BIT_PER_PIN)
|
||||
#define DS_0(__B, __P) (GRF->GPIO##__B##__P##_DS)
|
||||
#define SET_DS_0(_B, _P, p, v, w) _PINCTRL_WRITE(DS_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_DS_0(B, P, p, v) SET_DS_0(B, P, p % DS_PIN_PER_REG, v, DS_BIT_PER_PIN)
|
||||
#define SET_DS(_GPIO, _PORT, pin, val) RK_SET_DS_0(_GPIO, _PORT, pin, val)
|
||||
|
||||
#elif defined(GRF_GPIO0A_DS_H_OFFSET)
|
||||
#define DS_BIT_PER_PIN (4)
|
||||
#define DS_PIN_PER_REG (16 / DS_BIT_PER_PIN)
|
||||
#define DS_0(__B, __P) (GRF->GPIO##__B##__P##_DS_L)
|
||||
#define DS_1(__B, __P) (GRF->GPIO##__B##__P##_DS_L)
|
||||
#define SET_DS_0(_B, _P, p, v, w) _PINCTRL_WRITE(DS_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_DS_1(_B, _P, p, v, w) _PINCTRL_WRITE(DS_1(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_DS_0(B, P, p, v) SET_DS_0(B, P, p % DS_PIN_PER_REG, v, DS_BIT_PER_PIN)
|
||||
#define RK_SET_DS_1(B, P, p, v) SET_DS_1(B, P, p % DS_PIN_PER_REG, v, DS_BIT_PER_PIN)
|
||||
#define SET_DS(_GPIO, _PORT, pin, val) \
|
||||
{ \
|
||||
if ((pin % 8) < 4) { \
|
||||
RK_SET_DS_0(_GPIO, _PORT, pin, val); \
|
||||
} else { \
|
||||
RK_SET_DS_1(_GPIO, _PORT, pin, val); \
|
||||
} \
|
||||
}
|
||||
|
||||
#elif defined(GRF_GPIO0A_DS_0_OFFSET)
|
||||
#define DS_BIT_PER_PIN (8)
|
||||
#define DS_PIN_PER_REG (16 / DS_BIT_PER_PIN)
|
||||
#define DS_0(__B, __P) (GRF->GPIO##__B##__P##_DS_0)
|
||||
#define DS_1(__B, __P) (GRF->GPIO##__B##__P##_DS_1)
|
||||
#define DS_2(__B, __P) (GRF->GPIO##__B##__P##_DS_2)
|
||||
#define DS_3(__B, __P) (GRF->GPIO##__B##__P##_DS_3)
|
||||
#define SET_DS_0(_B, _P, p, v, w) _PINCTRL_WRITE(DS_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_DS_1(_B, _P, p, v, w) _PINCTRL_WRITE(DS_1(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_DS_2(_B, _P, p, v, w) _PINCTRL_WRITE(DS_2(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_DS_3(_B, _P, p, v, w) _PINCTRL_WRITE(DS_3(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_DS_0(B, P, p, v) SET_DS_0(B, P, p % DS_PIN_PER_REG, v, DS_BIT_PER_PIN)
|
||||
#define RK_SET_DS_1(B, P, p, v) SET_DS_1(B, P, p % DS_PIN_PER_REG, v, DS_BIT_PER_PIN)
|
||||
#define RK_SET_DS_2(B, P, p, v) SET_DS_2(B, P, p % DS_PIN_PER_REG, v, DS_BIT_PER_PIN)
|
||||
#define RK_SET_DS_3(B, P, p, v) SET_DS_3(B, P, p % DS_PIN_PER_REG, v, DS_BIT_PER_PIN)
|
||||
#define SET_DS(_GPIO, _PORT, pin, val) \
|
||||
{ \
|
||||
if ((pin % 8) < 2) { \
|
||||
RK_SET_DS_0(_GPIO, _PORT, pin, val); \
|
||||
} else if ((pin % 8) < 4) { \
|
||||
RK_SET_DS_1(_GPIO, _PORT, pin, val); \
|
||||
} else if ((pin % 8) < 6) { \
|
||||
RK_SET_DS_2(_GPIO, _PORT, pin, val); \
|
||||
} else { \
|
||||
RK_SET_DS_3(_GPIO, _PORT, pin, val); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GRF_GPIO0A_P_OFFSET)
|
||||
#define P_BIT_PER_PIN (2)
|
||||
#define P_PIN_PER_REG (16 / P_BIT_PER_PIN)
|
||||
#define P_0(__B, __P) (GRF->GPIO##__B##__P##_P)
|
||||
#define SET_P_0(_B, _P, p, v, w) _PINCTRL_WRITE(P_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_P_0(B, P, p, v) SET_P_0(B, P, p % P_PIN_PER_REG, v, P_BIT_PER_PIN)
|
||||
#define SET_P(_GPIO, _PORT, pin, val) RK_SET_P_0(_GPIO, _PORT, pin, val)
|
||||
|
||||
#elif defined(GRF_GPIO0A_P_H_OFFSET)
|
||||
#define P_BIT_PER_PIN (4)
|
||||
#define P_PIN_PER_REG (16 / P_BIT_PER_PIN)
|
||||
#define P_0(__B, __P) (GRF->GPIO##__B##__P##_P_L)
|
||||
#define P_1(__B, __P) (GRF->GPIO##__B##__P##_P_L)
|
||||
#define SET_P_0(_B, _P, p, v, w) _PINCTRL_WRITE(P_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_P_1(_B, _P, p, v, w) _PINCTRL_WRITE(P_1(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_P_0(B, P, p, v) SET_P_0(B, P, p % P_PIN_PER_REG, v, P_BIT_PER_PIN)
|
||||
#define RK_SET_P_1(B, P, p, v) SET_P_1(B, P, p % P_PIN_PER_REG, v, P_BIT_PER_PIN)
|
||||
#define SET_P(_GPIO, _PORT, pin, val) \
|
||||
{ \
|
||||
if ((pin % 8) < 4) { \
|
||||
RK_SET_P_0(_GPIO, _PORT, pin, val); \
|
||||
} else { \
|
||||
RK_SET_P_3(_GPIO, _PORT, pin, val); \
|
||||
} \
|
||||
}
|
||||
|
||||
#elif defined(GRF_GPIO0A_P_0_OFFSET)
|
||||
#define P_BIT_PER_PIN (8)
|
||||
#define P_PIN_PER_REG (16 / P_BIT_PER_PIN)
|
||||
#define P_0(__B, __P) (GRF->GPIO##__B##__P##_P_0)
|
||||
#define P_1(__B, __P) (GRF->GPIO##__B##__P##_P_1)
|
||||
#define P_2(__B, __P) (GRF->GPIO##__B##__P##_P_2)
|
||||
#define P_3(__B, __P) (GRF->GPIO##__B##__P##_P_3)
|
||||
#define SET_P_0(_B, _P, p, v, w) _PINCTRL_WRITE(P_0(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_P_1(_B, _P, p, v, w) _PINCTRL_WRITE(P_1(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_P_2(_B, _P, p, v, w) _PINCTRL_WRITE(P_2(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define SET_P_3(_B, _P, p, v, w) _PINCTRL_WRITE(P_3(_B, _P), RK_GEN_VAL(p, v, w))
|
||||
#define RK_SET_P_0(B, P, p, v) SET_P_0(B, P, p % P_PIN_PER_REG, v, P_BIT_PER_PIN)
|
||||
#define RK_SET_P_1(B, P, p, v) SET_P_1(B, P, p % P_PIN_PER_REG, v, P_BIT_PER_PIN)
|
||||
#define RK_SET_P_2(B, P, p, v) SET_P_2(B, P, p % P_PIN_PER_REG, v, P_BIT_PER_PIN)
|
||||
#define RK_SET_P_3(B, P, p, v) SET_P_3(B, P, p % P_PIN_PER_REG, v, P_BIT_PER_PIN)
|
||||
#define SET_P(_GPIO, _PORT, pin, val) \
|
||||
{ \
|
||||
if ((pin % 8) < 2) { \
|
||||
RK_SET_P_0(_GPIO, _PORT, pin, val); \
|
||||
} else if ((pin % 8) < 4) { \
|
||||
RK_SET_P_1(_GPIO, _PORT, pin, val); \
|
||||
} else if ((pin % 8) < 6) { \
|
||||
RK_SET_P_2(_GPIO, _PORT, pin, val); \
|
||||
} else { \
|
||||
RK_SET_P_3(_GPIO, _PORT, pin, val); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SET_IOMUX
|
||||
#define PINCTRL_SET_IOMUX(bank, pin, val) \
|
||||
{ \
|
||||
if (pin < 8) { \
|
||||
SET_IOMUX(bank, A, pin, val); \
|
||||
} else if (pin < 16) { \
|
||||
SET_IOMUX(bank, B, pin, val); \
|
||||
} else if (pin < 24) { \
|
||||
SET_IOMUX(bank, C, pin, val); \
|
||||
} else { \
|
||||
SET_IOMUX(bank, D, pin, val); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SET_DS
|
||||
#define PINCTRL_SET_DS(bank, pin, val) \
|
||||
{ \
|
||||
if (pin < 8) { \
|
||||
SET_DS(bank, A, pin, val); \
|
||||
} else if (pin < 16) { \
|
||||
SET_DS(bank, B, pin, val); \
|
||||
} else if (pin < 24) { \
|
||||
SET_DS(bank, C, pin, val); \
|
||||
} else { \
|
||||
SET_DS(bank, D, pin, val); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SET_P
|
||||
#define PINCTRL_SET_P(bank, pin, val) \
|
||||
{ \
|
||||
if (pin < 8) { \
|
||||
SET_P(bank, A, pin, val); \
|
||||
} else if (pin < 16) { \
|
||||
SET_P(bank, B, pin, val); \
|
||||
} else if (pin < 24) { \
|
||||
SET_P(bank, C, pin, val); \
|
||||
} else { \
|
||||
SET_P(bank, D, pin, val); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************* Private Variable Definition ***************************/
|
||||
|
||||
/********************* Private Function Definition ***************************/
|
||||
|
||||
/**
|
||||
* @brief Private function to set iomux for one pin.
|
||||
* @param bank: pin bank channel.
|
||||
* @param pin: pin index, 0~31.
|
||||
* @param param: value to write.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
static HAL_Status PINCTRL_SetIOMUX(eGPIO_bankId bank, uint8_t pin, uint32_t data)
|
||||
{
|
||||
#ifdef PINCTRL_SET_IOMUX
|
||||
switch (bank) {
|
||||
#ifdef GPIO0
|
||||
case 0:
|
||||
PINCTRL_SET_IOMUX(0, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO1
|
||||
case 1:
|
||||
PINCTRL_SET_IOMUX(1, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO2
|
||||
case 2:
|
||||
PINCTRL_SET_IOMUX(2, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO3
|
||||
case 3:
|
||||
PINCTRL_SET_IOMUX(3, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO4
|
||||
case 4:
|
||||
#ifdef SOC_RV1126
|
||||
if (pin < 2) {
|
||||
GRF->GPIO4A_IOMUX_L = RK_GEN_VAL(pin % IOMUX_PIN_PER_REG, data, IOMUX_BIT_PER_PIN);
|
||||
}
|
||||
#else
|
||||
PINCTRL_SET_IOMUX(4, pin, data);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
HAL_DBG("unknown gpio%d\n", bank);
|
||||
break;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
#else
|
||||
|
||||
return HAL_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Private function to set drive strength for one pin.
|
||||
* @param bank: pin bank channel.
|
||||
* @param pin: pin index, 0~31.
|
||||
* @param param: value to write.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
static HAL_Status PINCTRL_SetDS(eGPIO_bankId bank, uint8_t pin, uint32_t data)
|
||||
{
|
||||
#ifdef PINCTRL_SET_DS
|
||||
switch (bank) {
|
||||
#ifdef GPIO0
|
||||
case 0:
|
||||
PINCTRL_SET_DS(0, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO1
|
||||
case 1:
|
||||
PINCTRL_SET_DS(1, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO2
|
||||
case 2:
|
||||
PINCTRL_SET_DS(2, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO3
|
||||
case 3:
|
||||
PINCTRL_SET_DS(3, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO4
|
||||
case 4:
|
||||
#ifdef SOC_RV1126
|
||||
if (pin < 2) {
|
||||
GRF->GPIO4A_DS_L = RK_GEN_VAL(pin % DS_PIN_PER_REG, data, DS_BIT_PER_PIN);
|
||||
}
|
||||
#else
|
||||
PINCTRL_SET_DS(4, pin, data);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
HAL_DBG("unknown gpio%d\n", bank);
|
||||
break;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
#else
|
||||
|
||||
return HAL_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Private function to set pupd for one pin.
|
||||
* @param bank: pin bank channel.
|
||||
* @param pin: pin index, 0~31.
|
||||
* @param param: value to write.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
static HAL_Status PINCTRL_SetPUPD(eGPIO_bankId bank, uint8_t pin, uint32_t data)
|
||||
{
|
||||
#ifdef PINCTRL_SET_P
|
||||
switch (bank) {
|
||||
#ifdef GPIO0
|
||||
case 0:
|
||||
#ifdef SOC_RV1126
|
||||
if (pin < 8) {
|
||||
SET_P(0, A, pin, data);
|
||||
} else if (pin < 16) {
|
||||
SET_P(0, B, pin, data);
|
||||
} else if (pin < 20) {
|
||||
GRF->GPIO0C_P_L = RK_GEN_VAL(pin % P_PIN_PER_REG, data, P_BIT_PER_PIN);
|
||||
} else if (pin < 24) {
|
||||
GRF->GPIO0C_P_H = RK_GEN_VAL(pin % P_PIN_PER_REG, data, P_BIT_PER_PIN);
|
||||
} else {
|
||||
SET_P(0, D, pin, data);
|
||||
}
|
||||
#else
|
||||
PINCTRL_SET_P(0, pin, data);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO1
|
||||
case 1:
|
||||
PINCTRL_SET_P(1, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO2
|
||||
case 2:
|
||||
PINCTRL_SET_P(2, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO3
|
||||
case 3:
|
||||
PINCTRL_SET_P(3, pin, data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GPIO4
|
||||
case 4:
|
||||
#ifdef SOC_RV1126
|
||||
if (pin < 2) {
|
||||
GRF->GPIO4A_P = RK_GEN_VAL(pin % P_PIN_PER_REG, data, P_BIT_PER_PIN);
|
||||
}
|
||||
#else
|
||||
PINCTRL_SET_P(4, pin, data);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
HAL_DBG("unknown gpio%d\n", bank);
|
||||
break;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
#else
|
||||
|
||||
return HAL_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Private function to configure one pin.
|
||||
* @param bank: pin bank channel defined in @ref eGPIO_bankId.
|
||||
* @param pin: pin index, 0~31.
|
||||
* @param param: multi params defined in @ref ePINCTRL_configParam,
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
static HAL_Status PINCTRL_SetPinParam(eGPIO_bankId bank, uint8_t pin, uint32_t param)
|
||||
{
|
||||
HAL_Status rc = HAL_OK;
|
||||
|
||||
if (param & FLAG_MUX) {
|
||||
rc |= PINCTRL_SetIOMUX(bank, pin, (uint8_t)((param & MASK_MUX) >> SHIFT_MUX));
|
||||
}
|
||||
|
||||
if (param & FLAG_PUL) {
|
||||
rc |= PINCTRL_SetPUPD(bank, pin, (uint8_t)((param & MASK_PUL) >> SHIFT_PUL));
|
||||
}
|
||||
|
||||
if (param & FLAG_DRV) {
|
||||
rc |= PINCTRL_SetDS(bank, pin, (uint8_t)((param & MASK_DRV) >> SHIFT_DRV));
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/********************* Public Function Definition ****************************/
|
||||
|
||||
/** @defgroup PINCTRL_Exported_Functions_Group1 Suspend and Resume Functions
|
||||
|
||||
This section provides functions allowing to suspend and resume the module:
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup PINCTRL_Exported_Functions_Group2 Init and DeInit Functions
|
||||
|
||||
This section provides functions allowing to init and deinit the module:
|
||||
|
||||
* @{
|
||||
*/
|
||||
HAL_Status HAL_PINCTRL_Init(void)
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_Status HAL_PINCTRL_DeInit(void)
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** @defgroup PINCTRL_Exported_Functions_Group3 IO Functions
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Public function to configure for multi pins.
|
||||
* @param bank: pin bank channel defined in eGPIO_bankId.
|
||||
* @param mPins: multi pins defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @param param: multi params defined in @ref ePINCTRL_configParam.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_PINCTRL_SetParam(eGPIO_bankId bank, uint32_t mPins, ePINCTRL_configParam param)
|
||||
{
|
||||
uint8_t pin;
|
||||
HAL_Status rc;
|
||||
|
||||
HAL_ASSERT(bank < GPIO_BANK_NUM);
|
||||
|
||||
if (!(param & (FLAG_MUX | FLAG_PUL | FLAG_DRV | FLAG_SRT | FLAG_SMT))) {
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
for (pin = 0; pin < 32; pin++) {
|
||||
if (mPins & (1 << pin)) {
|
||||
rc = PINCTRL_SetPinParam(bank, pin, param);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Public function to set iomux for multi pins.
|
||||
* @param bank: pin bank channel defined in eGPIO_bankId.
|
||||
* @param mPins: multi pins defined in @ref ePINCTRL_GPIO_PINS.
|
||||
* @param param: multi params defined in @ref ePINCTRL_configParam.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_PINCTRL_SetIOMUX(eGPIO_bankId bank, uint32_t mPins, ePINCTRL_configParam param)
|
||||
{
|
||||
return HAL_PINCTRL_SetParam(bank, mPins, param);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* HAL_PINCTRL_MODULE_ENABLED */
|
|
@ -0,0 +1,307 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_base.h"
|
||||
|
||||
#ifdef HAL_TIMER_MODULE_ENABLED
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup TIMER
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup TIMER_How_To_Use How To Use
|
||||
* @{
|
||||
|
||||
The TIMER driver can be used as follows:
|
||||
|
||||
- IT mode: Resgister TIMER handler.
|
||||
- Initialize the TIMER by calling HAL_TIMER_Init():
|
||||
- Set TIMER count by calling HAL_TIMER_SetCount().
|
||||
- Start the TIMER by calling HAL_TIMER_Start() or HAL_TIMER_Start_IT().
|
||||
- Stop the TIMER by calling HAL_TIMER_Stop() or HAL_TIMER_Stop_IT().
|
||||
|
||||
SYS_TIMER
|
||||
|
||||
- SYS_TIMER is a rk timer fixed to serve the delay system. Invoke HAL_TIMER_SysTimerInit() to init.
|
||||
|
||||
@} */
|
||||
|
||||
/** @defgroup TIMER_Private_Definition Private Definition
|
||||
* @{
|
||||
*/
|
||||
/********************* Private MACRO Definition ******************************/
|
||||
#define TIMER_CONTROLREG_TIMER_MODE_FREE_RUNNING (0x0U << TIMER_CONTROLREG_TIMER_MODE_SHIFT)
|
||||
|
||||
#define TIMER_CONTROLREG_TIMER_ENABLE_ENABLED (0x1U << TIMER_CONTROLREG_TIMER_ENABLE_SHIFT)
|
||||
#define TIMER_CONTROLREG_TIMER_ENABLE_DISABLED (0x0U << TIMER_CONTROLREG_TIMER_ENABLE_SHIFT)
|
||||
|
||||
#define TIMER_CONTROLREG_TIMER_INT_MASK_UNMASK (0x1U << TIMER_CONTROLREG_TIMER_INT_MASK_SHIFT)
|
||||
|
||||
/********************* Private Structure Definition **************************/
|
||||
|
||||
/********************* Private Variable Definition ***************************/
|
||||
|
||||
/********************* Private Function Definition ***************************/
|
||||
|
||||
/** @} */
|
||||
/********************* Public Function Definition ****************************/
|
||||
|
||||
/** @defgroup TIMER_Exported_Functions_Group4 Init and DeInit Functions
|
||||
|
||||
This section provides functions allowing to init and deinit module as follows:
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Timer init.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @param mode: Choose TIMER mode.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_Init(struct TIMER_REG *pReg, eTIMER_MODE mode)
|
||||
{
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
#ifdef SYS_TIMER
|
||||
if (pReg == SYS_TIMER) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
WRITE_REG(pReg->CONTROLREG, mode << TIMER_CONTROLREG_TIMER_MODE_SHIFT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System Timer init.
|
||||
* @return HAL_Status.
|
||||
* @attention this API allow direct use in the HAL layer. SYS_TTIMER is used for delay system.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_SysTimerInit(struct TIMER_REG *pReg)
|
||||
{
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
|
||||
if (READ_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK)) {
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
WRITE_REG(pReg->CONTROLREG, TIMER_FREE_RUNNING);
|
||||
pReg->LOAD_COUNT[0] = 0xFFFFFFFFU;
|
||||
pReg->LOAD_COUNT[1] = 0xFFFFFFFFU;
|
||||
CLEAR_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_INT_MASK_MASK);
|
||||
SET_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Timer deinit.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_DeInit(struct TIMER_REG *pReg)
|
||||
{
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
#ifdef SYS_TIMER
|
||||
if (pReg == SYS_TIMER) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
WRITE_REG(pReg->CONTROLREG, 0);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TIMER_Exported_Functions_Group5 Other Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Start TIMER counter.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_Start(struct TIMER_REG *pReg)
|
||||
{
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
#ifdef SYS_TIMER
|
||||
if (pReg == SYS_TIMER) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLEAR_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_INT_MASK_MASK);
|
||||
SET_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop TIMER counter.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @return HAL_Status.
|
||||
* Just disable TIMER, and keep TIMER configuration.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_Stop(struct TIMER_REG *pReg)
|
||||
{
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
#ifdef SYS_TIMER
|
||||
if (pReg == SYS_TIMER) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLEAR_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start TIMER counter in interrupt mode.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_Start_IT(struct TIMER_REG *pReg)
|
||||
{
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
#ifdef SYS_TIMER
|
||||
if (pReg == SYS_TIMER) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
SET_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_ENABLED | TIMER_CONTROLREG_TIMER_INT_MASK_UNMASK);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop TIMER counter in interrupt mode.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @return HAL_Status.
|
||||
* Just disable TIMER, and keep TIMER configuration.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_Stop_IT(struct TIMER_REG *pReg)
|
||||
{
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
#ifdef SYS_TIMER
|
||||
if (pReg == SYS_TIMER) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLEAR_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set TIMER count number.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @param timerCount: TIMER counter loading number.
|
||||
* @return HAL_Status.
|
||||
* Set timer count number.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_SetCount(struct TIMER_REG *pReg, uint64_t timerCount)
|
||||
{
|
||||
uint64_t loadCount = 0;
|
||||
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
#ifdef SYS_TIMER
|
||||
if (pReg == SYS_TIMER) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
loadCount = timerCount;
|
||||
pReg->LOAD_COUNT[0] = (loadCount & 0xffffffff);
|
||||
pReg->LOAD_COUNT[1] = ((loadCount >> 32) & 0xffffffff);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get TIMER count number.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @return uint64_t: Current conut number.
|
||||
*/
|
||||
HAL_SECTION_SRAM_CODE
|
||||
uint64_t HAL_TIMER_GetCount(struct TIMER_REG *pReg)
|
||||
{
|
||||
uint32_t high, low, temp;
|
||||
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
|
||||
do {
|
||||
high = pReg->CURRENT_VALUE[1];
|
||||
low = pReg->CURRENT_VALUE[0];
|
||||
temp = pReg->CURRENT_VALUE[1];
|
||||
} while (high != temp);
|
||||
|
||||
return ((uint64_t)high << 32) | low;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear TIMER interrupt status.
|
||||
* @param pReg: Choose TIMER.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
*/
|
||||
HAL_Status HAL_TIMER_ClrInt(struct TIMER_REG *pReg)
|
||||
{
|
||||
uint32_t timeOut = 1000;
|
||||
|
||||
HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
|
||||
|
||||
pReg->INTSTATUS = 0x1;
|
||||
while (pReg->INTSTATUS && timeOut) {
|
||||
timeOut--;
|
||||
}
|
||||
|
||||
if (timeOut == 0) {
|
||||
return HAL_TIMEOUT;
|
||||
} else {
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIMER0 interrupt handler.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
* Clear interrupt status.
|
||||
*/
|
||||
__attribute__((weak)) HAL_Status HAL_TIMER0_Handler(void)
|
||||
{
|
||||
HAL_TIMER_ClrInt(TIMER0);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIMER1 interrupt handler.
|
||||
* @return HAL_Status: HAL_OK.
|
||||
* Clear interrupt status.
|
||||
*/
|
||||
__attribute__((weak)) HAL_Status HAL_TIMER1_Handler(void)
|
||||
{
|
||||
HAL_TIMER_ClrInt(TIMER1);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* HAL_TIMER_MODULE_ENABLED */
|
|
@ -0,0 +1,91 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_base.h"
|
||||
#include "soc.h"
|
||||
|
||||
/* The frequency of SYSTEM_CLOCK is determined by the previous firmware. */
|
||||
#define SYSTEM_CLOCK 816000000U
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
System Core Clock Variable
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint32_t SystemCoreClock = SYSTEM_CLOCK;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
System Core Clock update function
|
||||
*----------------------------------------------------------------------------*/
|
||||
void SystemCoreClockUpdate (void)
|
||||
{
|
||||
SystemCoreClock = SYSTEM_CLOCK;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
System Initialization
|
||||
*----------------------------------------------------------------------------*/
|
||||
// void SystemInit (void)
|
||||
// {
|
||||
// #if defined(HAL_AP_CORE) && defined(HAL_DCACHE_MODULE_ENABLED)
|
||||
// /* do not use global variables because this function is called before
|
||||
// reaching pre-main. RW section may be overwritten afterwards. */
|
||||
|
||||
// // Invalidate entire Unified TLB
|
||||
// __set_TLBIALL(0);
|
||||
|
||||
// // Invalidate entire branch predictor array
|
||||
// __set_BPIALL(0);
|
||||
// __DSB();
|
||||
// __ISB();
|
||||
|
||||
// // Invalidate instruction cache and flush branch target cache
|
||||
// __set_ICIALLU(0);
|
||||
// __DSB();
|
||||
// __ISB();
|
||||
|
||||
// // Invalidate data cache
|
||||
// L1C_InvalidateDCacheAll();
|
||||
// #endif
|
||||
|
||||
// #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
|
||||
// // Enable FPU
|
||||
// __FPU_Enable();
|
||||
// #endif
|
||||
|
||||
// #if defined(HAL_AP_CORE) && defined(HAL_DCACHE_MODULE_ENABLED)
|
||||
// // Create Translation Table
|
||||
// MMU_CreateTranslationTable();
|
||||
|
||||
// // Enable MMU
|
||||
// MMU_Enable();
|
||||
|
||||
// // Enable Caches
|
||||
// L1C_EnableCaches();
|
||||
// L1C_EnableBTAC();
|
||||
// #endif
|
||||
|
||||
// #if defined(HAL_MCU_CORE) && defined(HAL_INTMUX_MODULE_ENABLED)
|
||||
// HAL_INTMUX_Init();
|
||||
// #endif
|
||||
// }
|
||||
|
||||
// void DataInit (void)
|
||||
// {
|
||||
// #ifdef HAL_AP_CORE
|
||||
|
||||
// typedef struct {
|
||||
// unsigned long* dest;
|
||||
// unsigned long wlen;
|
||||
// } __zero_table_t;
|
||||
|
||||
// extern const __zero_table_t __zero_table_start__;
|
||||
// extern const __zero_table_t __zero_table_end__;
|
||||
|
||||
// for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) {
|
||||
// for (unsigned long i = 0u; i < pTable->wlen; ++i) {
|
||||
// pTable->dest[i] = 0u;
|
||||
// }
|
||||
// }
|
||||
// #endif /* HAL_AP_CORE */
|
||||
// }
|
|
@ -0,0 +1,753 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_bsp.h"
|
||||
#include "hal_base.h"
|
||||
#include "hal_gmac.h"
|
||||
#include "usyscall.h"
|
||||
#if (defined(HAL_GMAC_MODULE_ENABLED) || defined(HAL_GMAC1000_MODULE_ENABLED))
|
||||
|
||||
/*************************** GMAC DRIVER ****************************/
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
|
||||
/***************************** Function Declare ******************************/
|
||||
|
||||
/********************* Private MACRO Definition ******************************/
|
||||
#define GMAC_BUS_MAX 2
|
||||
|
||||
#define ARCH_DMA_MINALIGN 64
|
||||
|
||||
#define GMAC_DESCRIPTOR_SIZE 16
|
||||
#define GMAC_DESCRIPTORS_TX 8
|
||||
#define GMAC_DESCRIPTORS_RX 8
|
||||
#define GMAC_DESC_TX_SIZE HAL_GMAC_ALIGN(GMAC_DESCRIPTORS_TX * GMAC_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN)
|
||||
#define GMAC_DESC_RX_SIZE HAL_GMAC_ALIGN(GMAC_DESCRIPTORS_RX * GMAC_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN)
|
||||
|
||||
#define GMAC_RX_BUFFER_SIZE (GMAC_DESCRIPTORS_RX * HAL_GMAC_MAX_PACKET_SIZE)
|
||||
#define GMAC_TX_BUFFER_SIZE (GMAC_DESCRIPTORS_TX * HAL_GMAC_MAX_PACKET_SIZE)
|
||||
|
||||
/* Basic mode control register. */
|
||||
#define BMCR_RESV 0x003f /* Unused... */
|
||||
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
|
||||
#define BMCR_CTST 0x0080 /* Collision test */
|
||||
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
|
||||
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
|
||||
#define BMCR_ISOLATE 0x0400 /* Isolate data paths from MII */
|
||||
#define BMCR_PDOWN 0x0800 /* Enable low power state */
|
||||
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
|
||||
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
|
||||
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
|
||||
#define BMCR_RESET 0x8000 /* Reset to default state */
|
||||
#define BMCR_SPEED10 0x0000 /* Select 10Mbps */
|
||||
|
||||
#define GMAC_TEST_TIMES 16
|
||||
|
||||
/********************* Private Structure Definition **************************/
|
||||
/* GMAC consumer config data. */
|
||||
struct GMAC_ETH_CONFIG {
|
||||
struct GMAC_HANDLE instance;
|
||||
const struct HAL_GMAC_DEV *halDev;
|
||||
eGMAC_PHY_Interface mode;
|
||||
uint32_t speed;
|
||||
uint32_t maxSpeed;
|
||||
uint16_t phyAddr;
|
||||
|
||||
bool extClk;
|
||||
|
||||
/* phy reset gpio */
|
||||
struct GPIO_REG *resetGpioBank;
|
||||
ePINCTRL_GPIO_PINS resetGpioNum;
|
||||
uint32_t resetDelayMs[3];
|
||||
|
||||
int32_t txDelay;
|
||||
int32_t rxDelay;
|
||||
|
||||
struct GMAC_Desc *txDescs;
|
||||
struct GMAC_Desc *txDescs_dma;
|
||||
struct GMAC_Desc *rxDescs;
|
||||
struct GMAC_Desc *rxDescs_dma;
|
||||
|
||||
uint8_t *txBuff;
|
||||
uint8_t *txBuff_dma;
|
||||
uint8_t *rxBuff;
|
||||
uint8_t *rxBuff_dma;
|
||||
|
||||
/* MAC address info, hw address */
|
||||
uint8_t macAddr[6];
|
||||
};
|
||||
|
||||
/********************* Private Variable Definition ***************************/
|
||||
|
||||
|
||||
static uint8_t dstAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
#if defined(HAL_GMAC_MODULE_ENABLED) && defined(SOC_RK3568)
|
||||
static struct GMAC_ETH_CONFIG ethConfigTable[] =
|
||||
{
|
||||
{
|
||||
.halDev = &g_gmac0Dev,
|
||||
.mode = PHY_INTERFACE_MODE_RGMII,
|
||||
.maxSpeed = 1000,
|
||||
.phyAddr = 1,
|
||||
|
||||
.extClk = false,
|
||||
|
||||
.resetGpioBank = GPIO3,
|
||||
.resetGpioNum = GPIO_PIN_A4,
|
||||
.resetDelayMs = { 0, 20, 100 },
|
||||
|
||||
.txDelay = 0x2f,
|
||||
.rxDelay = 0x00,
|
||||
},
|
||||
|
||||
|
||||
// {
|
||||
// .halDev = &g_gmac1Dev,
|
||||
// .mode = PHY_INTERFACE_MODE_RGMII,
|
||||
// .maxSpeed = 1000,
|
||||
// .phyAddr = 1,
|
||||
|
||||
// .extClk = false,
|
||||
|
||||
// .resetGpioBank = GPIO4,
|
||||
// .resetGpioNum = GPIO_PIN_B6,
|
||||
// .resetDelayMs = { 0, 20, 100 },
|
||||
|
||||
// .txDelay = 0x4f,
|
||||
// .rxDelay = 0x26,
|
||||
// },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/********************* Private Function Definition ***************************/
|
||||
|
||||
static void Dump_Hex(char *message, uint8_t *ptr, uint16_t buflen)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)ptr;
|
||||
int i, j;
|
||||
|
||||
printf("%s package at %p, len: %d: \n", message, ptr, buflen);
|
||||
for (i = 0; i < buflen; i += 16) {
|
||||
printf("%08X: ", i);
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (i + j < buflen) {
|
||||
printf("%02X ", buf[i + j]);
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf(" ");
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (i + j < buflen) {
|
||||
printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void print_desc(struct GMAC_HANDLE *pGMAC)
|
||||
{
|
||||
struct GMAC_Desc *desc;
|
||||
int nIndex;
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (pGMAC->rxDescs) {
|
||||
desc = pGMAC->rxDescs;
|
||||
for (nIndex = 0; nIndex < pGMAC->rxSize; nIndex++) {
|
||||
desc = pGMAC->rxDescs + nIndex;
|
||||
printf("rx_desc[%d]@0x%08lx={0x%lx, 0x%lx, 0x%lx, 0x%lx};\n",
|
||||
nIndex, (uint64_t)desc, desc->des0, desc->des1, desc->des2, desc->des3);
|
||||
}
|
||||
}
|
||||
|
||||
if (pGMAC->txDescs) {
|
||||
desc = pGMAC->txDescs;
|
||||
for (nIndex = 0; nIndex < pGMAC->txSize; nIndex++) {
|
||||
desc = pGMAC->txDescs + nIndex;
|
||||
printf("tx_desc[%d]@0x%08lx={0x%lx, 0x%lx, 0x%lx, 0x%lx};\n",
|
||||
nIndex, (uint64_t)desc, desc->des0, desc->des1, desc->des2, desc->des3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Dump_Regs(struct GMAC_HANDLE *pGMAC)
|
||||
{
|
||||
uint32_t *reg = (uint32_t *)pGMAC->pReg;
|
||||
int i;
|
||||
|
||||
printf("\n");
|
||||
|
||||
for (i = 0; i < (0x200 / 0x4); i++) {
|
||||
printf("offset_0x%08x: %08lx %08lx %08lx %08lx\n", i * 0x10,
|
||||
*((volatile const uint32_t *)(reg + 0x4 * i)), *(volatile const uint32_t *)((reg + 0x4 * i + 1)),
|
||||
*((volatile const uint32_t *)(reg + 0x4 * i + 2)), *((volatile const uint32_t *)(reg + 0x4 * i + 3)));
|
||||
}
|
||||
|
||||
reg = reg + 0x1000 / 4;
|
||||
|
||||
for (i = 0; i < (0x100 / 0x4); i++) {
|
||||
printf("offset_0x%08x: %08lx %08lx %08lx %08lx\n", i * 0x10 + 0x1000,
|
||||
*((volatile const uint32_t *)(reg + 0x4 * i)), *((volatile const uint32_t *)(reg + 0x4 * i + 1)),
|
||||
*((volatile const uint32_t *)(reg + 0x4 * i + 2)), *((volatile const uint32_t *)(reg + 0x4 * i + 3)));
|
||||
}
|
||||
}
|
||||
|
||||
static void PHY_Dump(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC)
|
||||
{
|
||||
int data, i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data = HAL_GMAC_MDIORead(pGMAC, eth->phyAddr, i);
|
||||
if (data < 0) {
|
||||
printf("phy_dump: %d --> faild\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i % 8 == 7) {
|
||||
printf("%d --> %08X\n ", i, data);
|
||||
} else {
|
||||
printf("%d --> %08X\n\n", i, data);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void GMAC_PHY_Reset(struct GMAC_ETH_CONFIG *config)
|
||||
{
|
||||
if (config->resetGpioBank) {
|
||||
HAL_GPIO_SetPinDirection(config->resetGpioBank,
|
||||
config->resetGpioNum,
|
||||
GPIO_OUT);
|
||||
HAL_GPIO_SetPinLevel(config->resetGpioBank,
|
||||
config->resetGpioNum,
|
||||
GPIO_HIGH);
|
||||
HAL_DelayMs(config->resetDelayMs[0]);
|
||||
HAL_GPIO_SetPinLevel(config->resetGpioBank,
|
||||
config->resetGpioNum,
|
||||
GPIO_LOW);
|
||||
HAL_DelayMs(config->resetDelayMs[1]);
|
||||
HAL_GPIO_SetPinLevel(config->resetGpioBank,
|
||||
config->resetGpioNum,
|
||||
GPIO_HIGH);
|
||||
HAL_DelayMs(config->resetDelayMs[2]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void NET_Random_ETHAddr(uint8_t *addr)
|
||||
{
|
||||
addr[0] = 0xe6;
|
||||
addr[1] = 0x47;
|
||||
addr[2] = 0xcd;
|
||||
addr[3] = 0x20;
|
||||
addr[4] = 0xcf;
|
||||
addr[5] = 0xd9;
|
||||
}
|
||||
|
||||
static inline void NET_Random_Package(uint8_t *addr, uint16_t len)
|
||||
{
|
||||
unsigned int seed = HAL_TIMER_GetCount(SYS_TIMER) | 0xffffffff;
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
addr[i] = rand();
|
||||
}
|
||||
}
|
||||
|
||||
static void PHY_Update_Links(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC,
|
||||
uint8_t id)
|
||||
{
|
||||
HAL_Status status;
|
||||
|
||||
status = HAL_GMAC_PHYStartup(pGMAC);
|
||||
if (status) {
|
||||
printf("HAL_PHY_Startup() failed: %d\n", status);
|
||||
|
||||
return;
|
||||
}
|
||||
HAL_DelayMs(10000);
|
||||
|
||||
status = HAL_GMAC_PHYUpdateLink(pGMAC);
|
||||
if (status == HAL_OK) {
|
||||
if (pGMAC->phyStatus.link) {
|
||||
status = HAL_GMAC_PHYParseLink(pGMAC);
|
||||
if (PHY_SPEED_1000M == pGMAC->phyStatus.speed) {
|
||||
printf("Phy%d: 1000M link speed\n", id);
|
||||
} else if (PHY_SPEED_100M == pGMAC->phyStatus.speed) {
|
||||
printf("Phy%d: 100M link speed\n", id);
|
||||
} else {
|
||||
printf("Phy%d: 10M link speed\n", id);
|
||||
}
|
||||
|
||||
if (PHY_DUPLEX_HALF == pGMAC->phyStatus.duplex) {
|
||||
printf("Phy%d: half dumplex\n", id);
|
||||
} else {
|
||||
printf("Phy%d: full dumplex\n", id);
|
||||
}
|
||||
|
||||
if (pGMAC->phyStatus.pause) {
|
||||
printf("Phy%d: flow control rx/tx\n", id);
|
||||
} else {
|
||||
printf("Phy%d: flow control off\n", id);
|
||||
}
|
||||
|
||||
status = HAL_GMAC_AdjustLink(pGMAC, eth->txDelay, eth->rxDelay);
|
||||
if (status != HAL_OK) {
|
||||
printf("HAL_GMAC_AdjustLink() failed: %d\n", status);
|
||||
}
|
||||
|
||||
printf("Phy%d: link up.\n", id);
|
||||
} else {
|
||||
printf("Phy%d: link down.\n", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* interrupt service routine polling */
|
||||
static HAL_Status GMAC_ETH_IRQ(struct GMAC_HANDLE *pGMAC)
|
||||
{
|
||||
HAL_Status status;
|
||||
|
||||
/* enter interrupt */
|
||||
/* rt_interrupt_enter(); */
|
||||
status = HAL_GMAC_IRQHandler(pGMAC);
|
||||
|
||||
if (status & DMA_HANLE_RX) {
|
||||
/* a frame has been received */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* leave interrupt */
|
||||
/* rt_interrupt_leave(); */
|
||||
}
|
||||
|
||||
|
||||
static void *malloc_align(size_t size, size_t align, uintptr_t va, uintptr_t *pa)
|
||||
{
|
||||
void *align_ptr;
|
||||
// void *ptr;
|
||||
size_t align_size;
|
||||
|
||||
/* align the alignment size to 4 byte */
|
||||
align = ((align + 0x03) & ~0x03);
|
||||
|
||||
/* get total aligned size */
|
||||
align_size = ((size + 0x03) & ~0x03);
|
||||
/* allocate memory block from heap */
|
||||
// ptr = malloc(align_size);
|
||||
|
||||
if (naive_mmap(&va, pa, align_size, true) < 0){
|
||||
HAL_DBG("Alloc failed\n");
|
||||
}
|
||||
// printf("%p,%p\n",(void *)va, *pa);
|
||||
// void* ptr = (void *)va;
|
||||
// if (ptr != 0) {
|
||||
// /* the allocated memory block is aligned */
|
||||
// if (((uint64_t)ptr & (align - 1)) == 0) {
|
||||
// align_ptr = (void *)((uint64_t)ptr + align);
|
||||
// } else {
|
||||
// align_ptr = (void *)(((uint64_t)ptr + (align - 1)) & ~(align - 1));
|
||||
// }
|
||||
|
||||
// /* set the pointer before alignment pointer to the real pointer */
|
||||
// *((uint64_t *)((uint64_t)align_ptr - sizeof(void *))) = (uint64_t)ptr;
|
||||
|
||||
// ptr = align_ptr;
|
||||
// }
|
||||
|
||||
return (void *)va;
|
||||
}
|
||||
|
||||
static void free_align(void *ptr)
|
||||
{
|
||||
void *real_ptr;
|
||||
|
||||
real_ptr = (void *)*(uint64_t *)((uint64_t)ptr - sizeof(void *));
|
||||
free(real_ptr);
|
||||
|
||||
}
|
||||
|
||||
/********************* Public Function Definition ****************************/
|
||||
|
||||
static HAL_Status GMAC_Send_Test(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC,
|
||||
uint16_t len)
|
||||
{
|
||||
uint8_t *ptr = NULL;
|
||||
HAL_Status status;
|
||||
|
||||
if (!pGMAC->phyStatus.link) {
|
||||
HAL_DBG("pGMAC->phyStatus.link: %d", pGMAC->phyStatus.link);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check the frame length. */
|
||||
if (len > HAL_GMAC_MAX_FRAME_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = (uint8_t *)HAL_GMAC_GetTXBuffer(pGMAC);
|
||||
HAL_DBG("txPtr:%p\n", ptr);
|
||||
memcpy(ptr, dstAddr, 6);
|
||||
memcpy(ptr + 6, eth->macAddr, 6);
|
||||
ptr[12] = 0x40;
|
||||
ptr[13] = 0x06;
|
||||
ptr[14] = 0x00;
|
||||
ptr[15] = 0x01;
|
||||
NET_Random_Package(ptr + 16, len - 16);
|
||||
|
||||
if (len > 60) {
|
||||
/* index */
|
||||
ptr[50] = pGMAC->txDescIdx;
|
||||
}
|
||||
|
||||
/* dump packages */
|
||||
Dump_Hex("Tx", ptr, len);
|
||||
|
||||
// HAL_DCACHE_CleanByRange((uint64_t)ptr, len);
|
||||
uint8_t * ptr_dma = (uint8_t *)HAL_GMAC_GetTXBufferDMA(pGMAC);
|
||||
status = HAL_GMAC_Send(pGMAC, ptr_dma, len);
|
||||
if (status) {
|
||||
printf("GMAC send failed: %d\n", status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint16_t GMAC_Recv_Test(struct GMAC_HANDLE *pGMAC)
|
||||
{
|
||||
uint8_t *ptr = NULL;
|
||||
HAL_Status status;
|
||||
int32_t size;
|
||||
|
||||
if (!pGMAC->phyStatus.link) {
|
||||
HAL_DBG("pGMAC->phyStatus.link: %d", pGMAC->phyStatus.link);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = GMAC_ETH_IRQ(pGMAC);
|
||||
ptr = HAL_GMAC_Recv(pGMAC, &size);
|
||||
while (status && ptr) {
|
||||
if (size > 0 && ptr) {
|
||||
/* dump packages */
|
||||
Dump_Hex("Rx", ptr, size);
|
||||
// HAL_DCACHE_InvalidateByRange((uint64_t)ptr, size);
|
||||
HAL_GMAC_CleanRX(pGMAC);
|
||||
} else {
|
||||
printf("GMAC recv failed: %ld\n", size);
|
||||
|
||||
return -1;
|
||||
}
|
||||
ptr = HAL_GMAC_Recv(pGMAC, &size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HAL_Status GMAC_Memory_Init(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC)
|
||||
{
|
||||
|
||||
uintptr_t tx_va = 0x1000000000, tx_pa = 0;
|
||||
if (naive_mmap(&tx_va, &tx_pa, GMAC_DESC_TX_SIZE, true) < 0){
|
||||
HAL_DBG("TX Desc alloc failed\n");
|
||||
}
|
||||
eth->txDescs = (struct GMAC_Desc *)0x1000000000;
|
||||
eth->txDescs_dma = (struct GMAC_Desc *)tx_pa;
|
||||
|
||||
uintptr_t rx_va = 0x1000400000, rx_pa = 0;
|
||||
if (naive_mmap(&rx_va, &rx_pa, GMAC_DESC_RX_SIZE, true) < 0){
|
||||
HAL_DBG("RX Desc alloc failed\n");
|
||||
}
|
||||
eth->rxDescs = (struct GMAC_Desc *)0x1000400000;
|
||||
eth->rxDescs_dma = (struct GMAC_Desc *)rx_pa;
|
||||
|
||||
if (!eth->rxDescs || !eth->txDescs_dma ||
|
||||
!eth->txDescs || !eth->txDescs_dma){
|
||||
return -1;
|
||||
}
|
||||
|
||||
HAL_DBG("rx:%p, %p\n",eth->rxDescs, eth->rxDescs_dma);
|
||||
HAL_DBG("tx:%p, %p\n",eth->txDescs, eth->txDescs_dma);
|
||||
|
||||
|
||||
uintptr_t txbuf_va = 0x1000800000, txbuf_pa = 0;
|
||||
eth->txBuff = malloc_align(GMAC_TX_BUFFER_SIZE, ARCH_DMA_MINALIGN, txbuf_va, &txbuf_pa);
|
||||
eth->txBuff = (void *)0x1000800000;
|
||||
eth->txBuff_dma = (void *)txbuf_pa;
|
||||
|
||||
uintptr_t rxbuf_va = 0x1000c00000, rxbuf_pa = 0;
|
||||
eth->rxBuff = malloc_align(GMAC_RX_BUFFER_SIZE, ARCH_DMA_MINALIGN, rxbuf_va, &rxbuf_pa);
|
||||
eth->rxBuff = (void *)0x1000c00000;
|
||||
eth->rxBuff_dma = (void *)rxbuf_pa;
|
||||
|
||||
if (!eth->rxBuff || !eth->txBuff ||
|
||||
!eth->rxBuff_dma || !eth->txBuff_dma){
|
||||
return -1;
|
||||
}
|
||||
HAL_DBG("rx_buff:%p,%p\n",eth->rxBuff, eth->rxBuff_dma);
|
||||
HAL_DBG("tx_buff:%p,%p,\n",eth->txBuff, eth->txBuff_dma);
|
||||
memset(eth->rxDescs, 0, GMAC_DESC_RX_SIZE);
|
||||
memset(eth->txDescs, 0, GMAC_DESC_TX_SIZE);
|
||||
memset(eth->rxBuff, 0, GMAC_RX_BUFFER_SIZE);
|
||||
// HAL_DCACHE_InvalidateByRange((uint64_t)eth->rxBuff, GMAC_RX_BUFFER_SIZE);
|
||||
memset(eth->txBuff, 0, GMAC_TX_BUFFER_SIZE);
|
||||
// HAL_DCACHE_CleanByRange((uint64_t)eth->txBuff, GMAC_TX_BUFFER_SIZE);
|
||||
|
||||
HAL_GMAC_DMARxDescInit(pGMAC, eth->rxDescs, eth->rxDescs_dma, eth->rxBuff, eth->rxBuff_dma, GMAC_DESCRIPTORS_RX);
|
||||
HAL_GMAC_DMATxDescInit(pGMAC, eth->txDescs, eth->txDescs_dma, eth->txBuff, eth->txBuff_dma, GMAC_DESCRIPTORS_TX);
|
||||
|
||||
print_desc(pGMAC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HAL_Status GMAC_Init(uint8_t id)
|
||||
{
|
||||
struct GMAC_ETH_CONFIG *eth;
|
||||
struct GMAC_HANDLE *pGMAC;
|
||||
const struct HAL_GMAC_DEV *gmacDev;
|
||||
struct GMAC_PHY_Config config;
|
||||
eGMAC_PHY_Interface interface;
|
||||
HAL_Status status;
|
||||
uint32_t freq;
|
||||
|
||||
HAL_ASSERT(id < GMAC_BUS_MAX);
|
||||
|
||||
eth = ðConfigTable[id];
|
||||
if (!eth) {
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
pGMAC = ð->instance;
|
||||
gmacDev = eth->halDev;
|
||||
|
||||
/* MAC init */
|
||||
interface = eth->mode;
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_RGMII) {
|
||||
HAL_CRU_ClkSetFreq(gmacDev->clkID125M, 125000000);
|
||||
} else {
|
||||
HAL_CRU_ClkSetFreq(gmacDev->clkID50M, 50000000);
|
||||
}
|
||||
|
||||
freq = HAL_CRU_ClkGetFreq(gmacDev->pclkID);
|
||||
HAL_GMAC_Init(pGMAC, gmacDev->pReg, freq, interface, eth->extClk);
|
||||
|
||||
/* PHY Init */
|
||||
config.speed = eth->speed;
|
||||
config.maxSpeed = eth->maxSpeed;
|
||||
config.duplexMode = PHY_DUPLEX_FULL;
|
||||
config.neg = PHY_AUTONEG_ENABLE;
|
||||
config.interface = interface;
|
||||
config.phyAddress = eth->phyAddr;
|
||||
config.features = 0;
|
||||
status = HAL_GMAC_PHYInit(pGMAC, &config);
|
||||
if (status) {
|
||||
printf("HAL_PHY_Init() failed: %d\n", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* MAC Address */
|
||||
NET_Random_ETHAddr(eth->macAddr);
|
||||
HAL_GMAC_WriteHWAddr(ð->instance, eth->macAddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************** GMAC TEST ****************************/
|
||||
|
||||
#ifdef SOC_RK3568
|
||||
/**
|
||||
* @brief Config iomux for GMAC0
|
||||
*/
|
||||
static void GMAC0_Iomux_Config(void)
|
||||
{
|
||||
/* GMAC0 iomux */
|
||||
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
||||
GPIO_PIN_B6, /* gmac0_rxd0 */
|
||||
PIN_CONFIG_MUX_FUNC1);
|
||||
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
||||
GPIO_PIN_C3 | /* gmac0_mdc */
|
||||
GPIO_PIN_C4 | /* gmac0_mdio */
|
||||
GPIO_PIN_C0 | /* gmac0_rxdvcrs */
|
||||
GPIO_PIN_B7 | /* gmac0_rxd1 */
|
||||
GPIO_PIN_A3 | /* gmac0_rxd2 */
|
||||
GPIO_PIN_A4 | /* gmac0_rxd3 */
|
||||
GPIO_PIN_A6 | /* gmac0_txd2 */
|
||||
GPIO_PIN_A7 | /* gmac0_txd3 */
|
||||
GPIO_PIN_A5, /* gmac0_rxclk */
|
||||
PIN_CONFIG_MUX_FUNC2);
|
||||
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
||||
GPIO_PIN_B3 | /* gmac0_txd0 */
|
||||
GPIO_PIN_B4 | /* gmac0_txd1 */
|
||||
GPIO_PIN_B5, /* gmac0_txen */
|
||||
PIN_CONFIG_MUX_FUNC1 | PIN_CONFIG_DRV_LEVEL2);
|
||||
|
||||
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
||||
GPIO_PIN_A7 | /* gmac0_txd3 */
|
||||
GPIO_PIN_A6, /* gmac0_txd2 */
|
||||
PIN_CONFIG_MUX_FUNC2 | PIN_CONFIG_DRV_LEVEL2);
|
||||
HAL_PINCTRL_SetIOMUX(GPIO_BANK2, /* gmac0_txclk */
|
||||
GPIO_PIN_B0,
|
||||
PIN_CONFIG_MUX_FUNC2 | PIN_CONFIG_DRV_LEVEL1);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void GMAC_Iomux_Config(uint8_t id)
|
||||
{
|
||||
// if (id == 1) {
|
||||
// GMAC1_M1_Iomux_Config();
|
||||
// } else if (id == 0) {
|
||||
GMAC0_Iomux_Config();
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/*************************** GMAC TEST MAIN ****************************/
|
||||
|
||||
#include "usyscall.h"
|
||||
|
||||
// IPC_SERVER_INTERFACE(Ipc_intr, 1);
|
||||
// IPC_SERVER_REGISTER_INTERFACES(IpIntrHandler, 1, Ipc_intr);
|
||||
|
||||
int main() {
|
||||
struct GMAC_ETH_CONFIG *eth;
|
||||
struct GMAC_HANDLE *pGMAC;
|
||||
int32_t bus, num = 0, i;
|
||||
|
||||
HAL_DBG("GMAC Test:\n");
|
||||
|
||||
num = sizeof(ethConfigTable) / sizeof(struct GMAC_ETH_CONFIG);
|
||||
HAL_DBG("GMAC Num: %ld\n", num);
|
||||
for (bus = 0; bus < num; bus++) {
|
||||
eth = ðConfigTable[bus];
|
||||
HAL_DBG("new pGmac\n");
|
||||
if (eth) {
|
||||
pGMAC = ð->instance;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mmap(0x2000000000ULL+ GMAC0_BASE, GMAC0_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap GMAC0(%8x) failed\n", GMAC0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!mmap(0x2000000000ULL + GPIO2_BASE, GPIO2_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap GPIO2(%8x) failed\n", GPIO2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!mmap(0x2000000000ULL + GPIO3_BASE, GPIO3_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap GPIO3(%8x) failed\n", GPIO3);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!mmap(0x2000000000ULL + GRF_BASE, GRF_BASE, 0x50000, true)) {
|
||||
printf("eth_hal: mmap GRF(%8x) failed\n", GRF);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!mmap(0x2000000000ULL + CRU_BASE, CRU_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap CRU(%8x) failed\n", CRU);
|
||||
exit(1);
|
||||
}
|
||||
if (!mmap(0x2000000000ULL + TIMER5_BASE, TIMER5_BASE, 32, true)) {
|
||||
printf("eth_hal: mmap TIMER5(%8x) failed\n", TIMER5);
|
||||
exit(1);
|
||||
}
|
||||
if (!mmap(0x2000000000ULL + PMUCRU_BASE, PMUCRU_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap PMUCRU(%8x) failed\n", PMUCRU);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
HAL_TIMER_SysTimerInit(TIMER5);
|
||||
|
||||
/* ionmux */
|
||||
GMAC_Iomux_Config(bus);
|
||||
HAL_CRU_ClkEnable(eth->halDev->pclkGateID);
|
||||
HAL_CRU_ClkEnable(eth->halDev->clkGateID125M);
|
||||
HAL_CRU_ClkEnable(eth->halDev->clkGateID50M);
|
||||
|
||||
/* Register irq */
|
||||
// register_irq(eth->halDev->irqNum, );
|
||||
/* PHY reset */
|
||||
GMAC_PHY_Reset(eth);
|
||||
|
||||
/* GMAC Init */
|
||||
GMAC_Init(bus);
|
||||
|
||||
GMAC_Memory_Init(eth, pGMAC);
|
||||
|
||||
/* Enable GMAC and DMA transmission and reception */
|
||||
HAL_GMAC_Start(pGMAC, eth->macAddr);
|
||||
|
||||
/* Update links information */
|
||||
PHY_Update_Links(eth, pGMAC, bus);
|
||||
|
||||
/* Dump MAC Regs */
|
||||
Dump_Regs(pGMAC);
|
||||
|
||||
/* Dump PHY Regs */
|
||||
// PHY_Dump(eth, pGMAC);
|
||||
for (i = 0; i < GMAC_TEST_TIMES; i++) {
|
||||
HAL_DBG("TEST %d\n", i);
|
||||
|
||||
/* GMAC Send 64 bytes */
|
||||
HAL_DBG("--------------GMAC_Send_Test START!--------------\n");
|
||||
GMAC_Send_Test(eth, pGMAC, 64);
|
||||
HAL_DBG("--------------GMAC_Send_Test END!--------------\n");
|
||||
|
||||
HAL_DelayMs(1000);
|
||||
print_desc(pGMAC);
|
||||
|
||||
/* GMAC Recv */
|
||||
HAL_DBG("--------------GMAC_Recv_Test START! -------------- \n");
|
||||
GMAC_Recv_Test(pGMAC);
|
||||
HAL_DBG("--------------GMAC_Recv_Test END!!-------------- \n");
|
||||
|
||||
HAL_DelayMs(1000);
|
||||
Dump_Regs(pGMAC);
|
||||
}
|
||||
HAL_CRU_ClkDisable(eth->halDev->pclkGateID);
|
||||
HAL_CRU_ClkDisable(eth->halDev->clkGateID125M);
|
||||
HAL_CRU_ClkDisable(eth->halDev->clkGateID50M);
|
||||
|
||||
// free_align(eth->txBuff);
|
||||
// free_align(eth->rxBuff);
|
||||
HAL_DBG("done\n");
|
||||
}
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// typedef void (*isr_handler_t)(int vector, void *param);
|
||||
// typedef void (*NVIC_IRQHandler)(void);
|
||||
|
||||
// isr_handler_t interrupt_install(int vector,
|
||||
// isr_handler_t handler,
|
||||
// void *param,
|
||||
// const char *name)
|
||||
// {
|
||||
|
||||
// HAL_NVIC_SetIRQHandler(vector, (NVIC_IRQHandler)handler);
|
||||
// return handler;
|
||||
// }
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup HAL_BASE
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HAL_BASE_H_
|
||||
#define _HAL_BASE_H_
|
||||
|
||||
#include "hal_conf.h"
|
||||
#include "hal_driver.h"
|
||||
#include "hal_debug.h"
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
|
||||
/** @defgroup HAL_BASE_Exported_Definition_Group1 Basic Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** enter markrom usb upgrade */
|
||||
#define SYS_UPGRADE_FLAG (0xEF08A53C)
|
||||
/** enter loader usb upgrade */
|
||||
#define LDR_UPGRADE_FLAG (0x5242C301)
|
||||
|
||||
#define IS_TICKFREQ(f) (((f) == HAL_TICK_FREQ_1KHZ) || ((f) == HAL_TICK_FREQ_100HZ) || ((f) == HAL_TICK_FREQ_10HZ))
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
typedef enum {
|
||||
HAL_TICK_FREQ_10HZ = 100U, /**< 10 ticks per second, so it's 100ms/tick */
|
||||
HAL_TICK_FREQ_100HZ = 10U, /**< 100 ticks per second, so it's 10ms/tick */
|
||||
HAL_TICK_FREQ_1KHZ = 1U, /**< 1000 ticks per second, so it's 1ms/tick */
|
||||
HAL_TICK_FREQ_DEFAULT = HAL_TICK_FREQ_1KHZ
|
||||
} eHAL_tickFreq;
|
||||
|
||||
/** @} */
|
||||
|
||||
/***************************** Function Declare ******************************/
|
||||
/** @defgroup HAL_BASE_Public_Function_Declare Public Function Declare
|
||||
* @{
|
||||
*/
|
||||
|
||||
HAL_Status HAL_Init(void);
|
||||
HAL_Status HAL_DeInit(void);
|
||||
HAL_Status HAL_InitTick(uint32_t tickPriority);
|
||||
HAL_Status HAL_IncTick(void);
|
||||
uint32_t HAL_GetTick(void);
|
||||
HAL_Status HAL_SetTickFreq(eHAL_tickFreq freq);
|
||||
eHAL_tickFreq HAL_GetTickFreq(void);
|
||||
|
||||
HAL_Status HAL_DelayUs(uint32_t us);
|
||||
HAL_Status HAL_DelayMs(uint32_t ms);
|
||||
HAL_Status HAL_CPUDelayUs(uint32_t us);
|
||||
HAL_Status HAL_SystemCoreClockUpdate(uint32_t hz, eHAL_systickClkSource clkSource);
|
||||
|
||||
uint64_t HAL_DivU64Rem(uint64_t numerator, uint32_t denominator, uint32_t *pRemainder);
|
||||
uint64_t HAL_GetSysTimerCount(void);
|
||||
|
||||
void HAL_CPU_EnterIdle(void);
|
||||
#if defined(HAL_CPU_USAGE_ENABLED)
|
||||
uint32_t HAL_GetCPUUsage(void);
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/********************* Public Function Definition ***************************/
|
||||
/** @defgroup HAL_BASE_Exported_Functions_Group5 Other Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief uint64_t numerator / uint32_t denominator
|
||||
* @param numerator
|
||||
* @param denominator
|
||||
* @return uint64_t result
|
||||
*/
|
||||
static inline uint64_t HAL_DivU64(uint64_t numerator, uint32_t denominator)
|
||||
{
|
||||
return HAL_DivU64Rem(numerator, denominator, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uint32_t numerator / uint32_t denominator rounded to nearest integer
|
||||
* @param numerator
|
||||
* @param denominator
|
||||
* @return uint32_t result rounded to nearest integer
|
||||
*/
|
||||
static inline uint32_t HAL_DivRoundClosest(uint32_t numerator, uint32_t denominator)
|
||||
{
|
||||
return (numerator + (denominator / 2)) / denominator;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,75 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __BSP_H__
|
||||
#define __BSP_H__
|
||||
|
||||
#include "hal_base.h"
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
#ifdef HAL_PL330_MODULE_ENABLED
|
||||
extern struct HAL_PL330_DEV g_pl330Dev0;
|
||||
extern struct HAL_PL330_DEV g_pl330Dev1;
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
extern const struct HAL_SPI_DEV g_spi0Dev;
|
||||
extern const struct HAL_SPI_DEV g_spi1Dev;
|
||||
extern const struct HAL_SPI_DEV g_spi2Dev;
|
||||
extern const struct HAL_SPI_DEV g_spi3Dev;
|
||||
#endif
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
extern const struct HAL_UART_DEV g_uart0Dev;
|
||||
extern const struct HAL_UART_DEV g_uart1Dev;
|
||||
extern const struct HAL_UART_DEV g_uart2Dev;
|
||||
extern const struct HAL_UART_DEV g_uart3Dev;
|
||||
extern const struct HAL_UART_DEV g_uart4Dev;
|
||||
extern const struct HAL_UART_DEV g_uart5Dev;
|
||||
extern const struct HAL_UART_DEV g_uart6Dev;
|
||||
extern const struct HAL_UART_DEV g_uart7Dev;
|
||||
extern const struct HAL_UART_DEV g_uart8Dev;
|
||||
extern const struct HAL_UART_DEV g_uart9Dev;
|
||||
#endif
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
extern const struct HAL_I2C_DEV g_i2c0Dev;
|
||||
extern const struct HAL_I2C_DEV g_i2c1Dev;
|
||||
extern const struct HAL_I2C_DEV g_i2c2Dev;
|
||||
extern const struct HAL_I2C_DEV g_i2c3Dev;
|
||||
extern const struct HAL_I2C_DEV g_i2c4Dev;
|
||||
extern const struct HAL_I2C_DEV g_i2c5Dev;
|
||||
#endif
|
||||
|
||||
#ifdef HAL_FSPI_MODULE_ENABLED
|
||||
extern struct HAL_FSPI_HOST g_fspi0Dev;
|
||||
#endif
|
||||
#ifdef HAL_CANFD_MODULE_ENABLED
|
||||
extern const struct HAL_CANFD_DEV g_can0Dev;
|
||||
extern const struct HAL_CANFD_DEV g_can1Dev;
|
||||
extern const struct HAL_CANFD_DEV g_can2Dev;
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GMAC_MODULE_ENABLED
|
||||
extern const struct HAL_GMAC_DEV g_gmac0Dev;
|
||||
extern const struct HAL_GMAC_DEV g_gmac1Dev;
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PCIE_MODULE_ENABLED
|
||||
extern struct HAL_PCIE_DEV g_pcieDev;
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PWM_MODULE_ENABLED
|
||||
extern const struct HAL_PWM_DEV g_pwm0Dev;
|
||||
extern const struct HAL_PWM_DEV g_pwm1Dev;
|
||||
extern const struct HAL_PWM_DEV g_pwm2Dev;
|
||||
extern const struct HAL_PWM_DEV g_pwm3Dev;
|
||||
#endif
|
||||
/***************************** Function Declare ******************************/
|
||||
void BSP_Init(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _HAL_CONF_H_
|
||||
#define _HAL_CONF_H_
|
||||
|
||||
/* HAL CPU config */
|
||||
#define SOC_RK3568
|
||||
#define HAL_AP_CORE
|
||||
#define SYS_TIMER TIMER5 /* System timer designation (RK TIMER) */
|
||||
|
||||
/* HAL Driver Config */
|
||||
// #define HAL_CACHE_ECC_MODULE_ENABLED
|
||||
// #define HAL_CPU_TOPOLOGY_MODULE_ENABLED
|
||||
#define HAL_CRU_MODULE_ENABLED
|
||||
// #define HAL_DCACHE_MODULE_ENABLED
|
||||
// #define HAL_DDR_ECC_MODULE_ENABLED
|
||||
// #define HAL_FSPI_MODULE_ENABLED
|
||||
// #define HAL_GIC_MODULE_ENABLED
|
||||
#define HAL_GMAC_MODULE_ENABLED
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
// #define HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
|
||||
// #define HAL_SPINLOCK_MODULE_ENABLED
|
||||
// #define HAL_HWSPINLOCK_MODULE_ENABLED
|
||||
// #define HAL_I2C_MODULE_ENABLED
|
||||
// #define HAL_IRQ_HANDLER_MODULE_ENABLED
|
||||
// #define HAL_MBOX_MODULE_ENABLED
|
||||
// #define HAL_PCIE_MODULE_ENABLED
|
||||
#define HAL_PINCTRL_MODULE_ENABLED
|
||||
// #define HAL_PL330_MODULE_ENABLED
|
||||
// #define HAL_PWM_MODULE_ENABLED
|
||||
// #define HAL_SARADC_MODULE_ENABLED
|
||||
// #define HAL_SMCCC_MODULE_ENABLED
|
||||
// #define HAL_SNOR_MODULE_ENABLED
|
||||
// #define HAL_SPI_MODULE_ENABLED
|
||||
#define HAL_TIMER_MODULE_ENABLED
|
||||
// #define HAL_TSADC_MODULE_ENABLED
|
||||
// #define HAL_UART_MODULE_ENABLED
|
||||
// #define HAL_WDT_MODULE_ENABLED
|
||||
// #define HAL_CANFD_MODULE_ENABLED
|
||||
|
||||
/* HAL_DBG SUB CONFIG */
|
||||
#define HAL_DBG_USING_LIBC_PRINTF
|
||||
#define HAL_DBG_ON
|
||||
#define HAL_DBG_INFO_ON
|
||||
#define HAL_DBG_WRN_ON
|
||||
#define HAL_DBG_ERR_ON
|
||||
#define HAL_ASSERT_ON
|
||||
|
||||
#ifdef HAL_SNOR_MODULE_ENABLED
|
||||
#define HAL_SNOR_FSPI_HOST
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GIC_MODULE_ENABLED
|
||||
#define HAL_GIC_AMP_FEATURE_ENABLED
|
||||
#define HAL_GIC_PREEMPT_FEATURE_ENABLED
|
||||
//#define HAL_GIC_WAIT_LINUX_INIT_ENABLED
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#define HAL_GPIO_IRQ_DISPATCH_FEATURE_ENABLED
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
|
||||
#define HAL_GPIO_IRQ_GROUP_PRIO_LEVEL_MAX (3)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,500 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_conf.h"
|
||||
|
||||
#ifdef HAL_CRU_MODULE_ENABLED
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup CRU
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HAL_CRU_H_
|
||||
#define _HAL_CRU_H_
|
||||
|
||||
#include "hal_def.h"
|
||||
|
||||
/*************************** MACRO Definition ****************************/
|
||||
/** @defgroup CRU_Exported_Definition_Group1 Basic Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_CRU_DBG_ON
|
||||
#define HAL_CRU_DBG(fmt, arg...) HAL_SYSLOG("[HAL CRU] " fmt, ##arg)
|
||||
#else
|
||||
#define HAL_CRU_DBG(fmt, arg...) do { if (0) HAL_SYSLOG("[HAL CRU] " fmt, ##arg); } while (0)
|
||||
#endif
|
||||
|
||||
#define MHZ 1000000
|
||||
#define KHZ 1000
|
||||
|
||||
#ifndef PLL_INPUT_OSC_RATE
|
||||
#define PLL_INPUT_OSC_RATE (24 * MHZ)
|
||||
#endif
|
||||
|
||||
#define GENVAL_D16(x, h, l) ((uint32_t)(((x) & HAL_GENMASK(h, l)) / 16))
|
||||
#define GENVAL_D16_REM(x, h, l) ((uint32_t)(((x) & HAL_GENMASK(h, l)) % 16))
|
||||
#define WIDTH_TO_MASK(w) ((1 << (w)) - 1)
|
||||
|
||||
/*
|
||||
* RESET/GATE fields:
|
||||
* [31:16]: reserved
|
||||
* [15:12]: bank
|
||||
* [11:0]: id
|
||||
*/
|
||||
#define CLK_RESET_GET_REG_OFFSET(x) GENVAL_D16(x, 11, 0)
|
||||
#define CLK_RESET_GET_BITS_SHIFT(x) GENVAL_D16_REM(x, 11, 0)
|
||||
#define CLK_RESET_GET_REG_BANK(x) HAL_GENVAL(x, 15, 12)
|
||||
|
||||
#define CLK_GATE_GET_REG_OFFSET(x) CLK_RESET_GET_REG_OFFSET(x)
|
||||
#define CLK_GATE_GET_BITS_SHIFT(x) CLK_RESET_GET_BITS_SHIFT(x)
|
||||
#define CLK_GATE_GET_REG_BANK(x) CLK_RESET_GET_REG_BANK(x)
|
||||
|
||||
/*
|
||||
* MUX/DIV fields:
|
||||
* [31:24]: width
|
||||
* [23:16]: shift
|
||||
* [15:12]: reserved
|
||||
* [11:8]: bank
|
||||
* [7:0]: reg
|
||||
*/
|
||||
#define CLK_MUX_GET_REG_OFFSET(x) HAL_GENVAL(x, 7, 0)
|
||||
#define CLK_MUX_GET_BANK(x) HAL_GENVAL(x, 11, 8)
|
||||
#define CLK_MUX_GET_BITS_SHIFT(x) HAL_GENVAL(x, 23, 16)
|
||||
#define CLK_MUX_GET_WIDTH(x) HAL_GENVAL(x, 31, 24)
|
||||
#define CLK_MUX_GET_MASK(x) (WIDTH_TO_MASK(CLK_MUX_GET_WIDTH(x)) << CLK_MUX_GET_BITS_SHIFT(x))
|
||||
|
||||
#define CLK_DIV_GET_REG_OFFSET(x) CLK_MUX_GET_REG_OFFSET(x)
|
||||
#define CLK_DIV_GET_BANK(x) CLK_MUX_GET_BANK(x)
|
||||
#define CLK_DIV_GET_BITS_SHIFT(x) CLK_MUX_GET_BITS_SHIFT(x)
|
||||
#define CLK_DIV_GET_WIDTH(x) CLK_MUX_GET_WIDTH(x)
|
||||
#define CLK_DIV_GET_MASK(x) CLK_MUX_GET_MASK(x)
|
||||
#define CLK_DIV_GET_MAXDIV(x) ((1 << CLK_DIV_GET_WIDTH(x)) - 1)
|
||||
|
||||
/*
|
||||
* v64 mux = v32 | bank(in bit[35:32])
|
||||
* v64 div = v32 | bank(in bit[39:36])
|
||||
*/
|
||||
#ifdef CRU_CLK_USE_CON_BANK
|
||||
#define CLK_GET_MUX(v64) ((uint32_t)(((v64) & 0xFFFFFFFF00000000) >> 32))
|
||||
#define CLK_GET_DIV(v64) ((uint32_t)((v64) & 0x00000000FFFFFFFF))
|
||||
#else
|
||||
#define CLK_GET_MUX(v32) ((uint32_t)((v32) & 0x0F0F00FFU))
|
||||
#define CLK_GET_DIV(v32) ((uint32_t)((((v32) & 0x0000FF00U) >> 8) | \
|
||||
(((v32) & 0xF0F00000U) >> 4)))
|
||||
#endif
|
||||
|
||||
#define RK_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, \
|
||||
_frac) \
|
||||
{ \
|
||||
.rate = _rate##U, .fbDiv = _fbdiv, .postDiv1 = _postdiv1, \
|
||||
.refDiv = _refdiv, .postDiv2 = _postdiv2, .dsmpd = _dsmpd, \
|
||||
.frac = _frac, \
|
||||
}
|
||||
|
||||
#define RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \
|
||||
{ \
|
||||
.rate = _rate##U, .p = _p, .m = _m, \
|
||||
.s = _s, .k = _k, \
|
||||
}
|
||||
|
||||
#define CRU_BANK_CFG_FLAGS(reg, sel, gate, soft) \
|
||||
{ \
|
||||
.cruBase = reg, \
|
||||
.selOffset = sel, \
|
||||
.gateOffset = gate, \
|
||||
.softOffset = soft, \
|
||||
}
|
||||
|
||||
struct PLL_CONFIG {
|
||||
uint32_t rate;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t fbDiv;
|
||||
uint32_t postDiv1;
|
||||
uint32_t refDiv;
|
||||
uint32_t postDiv2;
|
||||
uint32_t dsmpd;
|
||||
uint32_t frac;
|
||||
};
|
||||
struct {
|
||||
uint32_t m;
|
||||
uint32_t p;
|
||||
uint32_t s;
|
||||
uint32_t k;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct PLL_SETUP {
|
||||
__IO uint32_t *conOffset0;
|
||||
__IO uint32_t *conOffset1;
|
||||
__IO uint32_t *conOffset2;
|
||||
__IO uint32_t *conOffset3;
|
||||
__IO uint32_t *conOffset6;
|
||||
__IO uint32_t *modeOffset;
|
||||
__I uint32_t *stat0;
|
||||
uint32_t modeShift;
|
||||
uint32_t lockShift;
|
||||
uint32_t modeMask;
|
||||
const struct PLL_CONFIG *rateTable;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GLB_SRST_FST = 0xfdb9,
|
||||
GLB_SRST_SND = 0xeca8,
|
||||
} eCRU_GlbSrstType;
|
||||
|
||||
typedef enum {
|
||||
GLB_RST_FST_WDT0 = 0U,
|
||||
GLB_RST_SND_WDT0,
|
||||
GLB_RST_FST_WDT1,
|
||||
GLB_RST_SND_WDT1,
|
||||
GLB_RST_FST_WDT2,
|
||||
GLB_RST_SND_WDT2,
|
||||
GLB_RST_FST_WDT3,
|
||||
GLB_RST_SND_WDT3,
|
||||
GLB_RST_FST_WDT4,
|
||||
GLB_RST_SND_WDT4,
|
||||
|
||||
} eCRU_WdtRstType;
|
||||
|
||||
struct CRU_BANK_INFO {
|
||||
uint32_t cruBase;
|
||||
uint32_t selOffset;
|
||||
uint32_t gateOffset;
|
||||
uint32_t softOffset;
|
||||
};
|
||||
|
||||
struct HAL_CRU_DEV {
|
||||
const struct CRU_BANK_INFO *banks;
|
||||
uint8_t banksNum;
|
||||
};
|
||||
|
||||
extern const struct HAL_CRU_DEV g_cruDev;
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
|
||||
/** @} */
|
||||
/***************************** Function Declare ******************************/
|
||||
/** @defgroup CRU_Private_Function_Declare Private Function Declare
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define _MHZ(n) ((n) * 1000000)
|
||||
#define DIV_NO_REM(pFreq, freq, maxDiv) \
|
||||
((!((pFreq) % (freq))) && ((pFreq) / (freq) <= (maxDiv)))
|
||||
|
||||
int HAL_CRU_FreqGetMux4(uint32_t freq, uint32_t freq0, uint32_t freq1,
|
||||
uint32_t freq2, uint32_t freq3);
|
||||
int HAL_CRU_FreqGetMux3(uint32_t freq, uint32_t freq0, uint32_t freq1,
|
||||
uint32_t freq2);
|
||||
int HAL_CRU_FreqGetMux2(uint32_t freq, uint32_t freq0, uint32_t freq1);
|
||||
int HAL_CRU_FreqGetMuxArray(uint32_t freq, uint32_t *table, int num);
|
||||
|
||||
uint32_t HAL_CRU_MuxGetFreq4(uint32_t muxName, uint32_t freq0, uint32_t freq1,
|
||||
uint32_t freq2, uint32_t freq3);
|
||||
uint32_t HAL_CRU_MuxGetFreq3(uint32_t muxName, uint32_t freq0, uint32_t freq1,
|
||||
uint32_t freq2);
|
||||
uint32_t HAL_CRU_MuxGetFreq2(uint32_t muxName, uint32_t freq0, uint32_t freq1);
|
||||
uint32_t HAL_CRU_MuxGetFreqArray(uint32_t muxName, uint32_t *table, int num);
|
||||
|
||||
int HAL_CRU_RoundFreqGetMux4(uint32_t freq, uint32_t pFreq0, uint32_t pFreq1,
|
||||
uint32_t pFreq2, uint32_t pFreq3, uint32_t *pFreqOut);
|
||||
int HAL_CRU_RoundFreqGetMux3(uint32_t freq, uint32_t pFreq0, uint32_t pFreq1,
|
||||
uint32_t pFreq2, uint32_t *pFreqOut);
|
||||
int HAL_CRU_RoundFreqGetMux2(uint32_t freq, uint32_t pFreq0, uint32_t pFreq1,
|
||||
uint32_t *pFreqOut);
|
||||
int HAL_CRU_RoundFreqGetMuxArray(uint32_t freq, uint32_t *table, int num, uint32_t *pFreqOut, bool is_div);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup CRU_Public_Function_Declare Public Function Declare
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get pll freq.
|
||||
* @param pSetup: Contains PLL register parameters
|
||||
* @return pll rate.
|
||||
*/
|
||||
uint32_t HAL_CRU_GetPllFreq(struct PLL_SETUP *pSetup);
|
||||
|
||||
/**
|
||||
* @brief Set pll freq.
|
||||
* @param pSetup: Contains PLL register parameters
|
||||
* @param rate: pll set
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_SetPllFreq(struct PLL_SETUP *pSetup, uint32_t rate);
|
||||
|
||||
/**
|
||||
* @brief Set pll power up.
|
||||
* @param pSetup: Contains PLL register parameters
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_SetPllPowerUp(struct PLL_SETUP *pSetup);
|
||||
|
||||
/**
|
||||
* @brief Set pll power down.
|
||||
* @param pSetup: Contains PLL register parameters
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_SetPllPowerDown(struct PLL_SETUP *pSetup);
|
||||
|
||||
/**
|
||||
* @brief Check if clk is enabled
|
||||
* @param clk: clock to check
|
||||
* @return HAL_Check.
|
||||
*/
|
||||
HAL_Check HAL_CRU_ClkIsEnabled(uint32_t clk);
|
||||
|
||||
/**
|
||||
* @brief Enable clk
|
||||
* @param clk: clock to set
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkEnable(uint32_t clk);
|
||||
|
||||
/**
|
||||
* @brief Disable unused clk
|
||||
* @param bank: cru bank id
|
||||
* @param index: gate con offset
|
||||
* @param val: gate value
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkDisableUnused(uint32_t bank, uint32_t index, uint32_t val);
|
||||
|
||||
/**
|
||||
* @brief Disable clk
|
||||
* @param clk: clock to set
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkDisable(uint32_t clk);
|
||||
|
||||
/**
|
||||
* @brief Check if clk is reset
|
||||
* @param clk: clock to check
|
||||
* @return HAL_Check.
|
||||
*/
|
||||
HAL_Check HAL_CRU_ClkIsReset(uint32_t clk);
|
||||
|
||||
/**
|
||||
* @brief Assert the reset to the clk
|
||||
* @param clk: clock to assert
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkResetAssert(uint32_t clk);
|
||||
|
||||
/**
|
||||
* @brief Deassert the reset to the clk
|
||||
* @param clk: clock to deassert
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkResetDeassert(uint32_t clk);
|
||||
|
||||
/**
|
||||
* @brief Sync Assert the resets to the clk
|
||||
* @param numClks: num clocks to assert
|
||||
* @param clks: clocks to assert
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkResetSyncAssert(int numClks, uint32_t *clks);
|
||||
|
||||
/**
|
||||
* @brief Sync Deassert the resets to the clk
|
||||
* @param numClks: num clocks to assert
|
||||
* @param clks: clocks to deassert
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkResetSyncDeassert(int numClks, uint32_t *clks);
|
||||
|
||||
/**
|
||||
* @brief Set frac div
|
||||
* @param fracDivName: frac div id(Contains div offset, shift, mask information)
|
||||
* @param numerator: the numerator to set.
|
||||
* @param denominator: the denominator to set.
|
||||
* @return HAL_Status
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkSetFracDiv(uint32_t fracDivName,
|
||||
uint32_t numerator,
|
||||
uint32_t denominator);
|
||||
|
||||
/**
|
||||
* @brief Get frac div
|
||||
* @param fracDivName: frac div id(Contains div offset, shift, mask information)
|
||||
* @param numerator: the returned numerator.
|
||||
* @param denominator: the returned denominator.
|
||||
* @return HAL_Status
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkGetFracDiv(uint32_t fracDivName,
|
||||
uint32_t *numerator,
|
||||
uint32_t *denominator);
|
||||
|
||||
/**
|
||||
* @brief Set integer div
|
||||
* @param divName: div id(Contains div offset, shift, mask information)
|
||||
* @param divValue: div value
|
||||
* @return NONE
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkSetDiv(uint32_t divName, uint32_t divValue);
|
||||
|
||||
/**
|
||||
* @brief Get integer div
|
||||
* @param divName: div id (Contains div offset, shift, mask information)
|
||||
* @return div value
|
||||
*/
|
||||
uint32_t HAL_CRU_ClkGetDiv(uint32_t divName);
|
||||
|
||||
/**
|
||||
* @brief Set mux
|
||||
* @param muxName: mux id (Contains mux offset, shift, mask information)
|
||||
* @param muxValue: mux value
|
||||
* @return NONE
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkSetMux(uint32_t muxName, uint32_t muxValue);
|
||||
|
||||
/**
|
||||
* @brief Get mux
|
||||
* @param muxName: mux id (Contains mux offset, shift, mask information)
|
||||
* @return mux value
|
||||
*/
|
||||
uint32_t HAL_CRU_ClkGetMux(uint32_t muxName);
|
||||
|
||||
/**
|
||||
* @brief Get frac div config.
|
||||
* @param rateOut: clk out rate.
|
||||
* @param rate: clk src rate.
|
||||
* @param numerator: the returned numerator.
|
||||
* @param denominator: the returned denominator.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_FracdivGetConfig(uint32_t rateOut, uint32_t rate,
|
||||
uint32_t *numerator,
|
||||
uint32_t *denominator);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get frac div config V2(24bit).
|
||||
* @param rateOut: clk out rate.
|
||||
* @param rate: clk src rate.
|
||||
* @param numerator: the returned numerator.
|
||||
* @param denominator: the returned denominator.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_FracdivGetConfigV2(uint32_t rateOut, uint32_t rate,
|
||||
uint32_t *numerator,
|
||||
uint32_t *denominator);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get clk freq.
|
||||
* @param clockName: CLOCK_Name id.
|
||||
* @return rate.
|
||||
* @attention these APIs allow direct use in the HAL layer.
|
||||
*/
|
||||
uint32_t HAL_CRU_ClkGetFreq(eCLOCK_Name clockName);
|
||||
|
||||
/**
|
||||
* @brief Set clk freq.
|
||||
* @param clockName: CLOCK_Name id.
|
||||
* @param rate: clk rate.
|
||||
* @return HAL_Status.
|
||||
* @attention these APIs allow direct use in the HAL layer.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkSetFreq(eCLOCK_Name clockName, uint32_t rate);
|
||||
|
||||
/**
|
||||
* @brief vop dclk enable.
|
||||
* @param gateId: gate id
|
||||
* @return HAL_Status.
|
||||
* @attention these APIs allow direct use in the HAL layer.
|
||||
*/
|
||||
HAL_Status HAL_CRU_VopDclkEnable(uint32_t gateId);
|
||||
|
||||
/**
|
||||
* @brief vop dclk disable.
|
||||
* @param gateId: gate id
|
||||
* @return HAL_Status.
|
||||
* @attention these APIs allow direct use in the HAL layer.
|
||||
*/
|
||||
HAL_Status HAL_CRU_VopDclkDisable(uint32_t gateId);
|
||||
|
||||
/**
|
||||
* @brief Get Np5 best div.
|
||||
* @param clockName: clk id.
|
||||
* @param rate: clk rate.
|
||||
* @param pRate: clk parent rate
|
||||
* @param bestdiv: the returned bestdiv.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_CRU_ClkNp5BestDiv(eCLOCK_Name clockName, uint32_t rate, uint32_t pRate, uint32_t *bestdiv);
|
||||
|
||||
/**
|
||||
* @brief assert CRU global software reset.
|
||||
* @param type: global software reset type.
|
||||
* @return HAL_INVAL if the SoC does not support.
|
||||
*/
|
||||
HAL_Status HAL_CRU_SetGlbSrst(eCRU_GlbSrstType type);
|
||||
|
||||
/**
|
||||
* @brief wdt glbrst enable.
|
||||
* @param wdtType: wdt reset type.
|
||||
* @return HAL_OK.
|
||||
* @attention these APIs allow direct use in the HAL layer.
|
||||
*/
|
||||
HAL_Status HAL_CRU_WdtGlbRstEnable(eCRU_WdtRstType wdtType);
|
||||
|
||||
/**
|
||||
* @brief pll output freq Compensation.
|
||||
* @param clockName: CLOCK_Name id.
|
||||
* @param ppm: Efforts to compensate.
|
||||
* @return HAL_OK.
|
||||
* @attention these APIs allow direct use in the HAL layer.
|
||||
*/
|
||||
HAL_Status HAL_CRU_PllCompensation(eCLOCK_Name clockName, int ppm);
|
||||
|
||||
/**
|
||||
* @brief CRU suspend.
|
||||
* @return HAL_Status.
|
||||
* @attention these APIs allow direct use in the HAL layer.
|
||||
*/
|
||||
HAL_Status HAL_CRU_Suspend(void);
|
||||
|
||||
/**
|
||||
* @brief CRU resume.
|
||||
* @return HAL_Status.
|
||||
* @attention these APIs allow direct use in the HAL layer.
|
||||
*/
|
||||
HAL_Status HAL_CRU_Resume(void);
|
||||
|
||||
#ifdef HAL_CRU_AS_FEATURE_ENABLED
|
||||
/**
|
||||
* @brief it is for AS init.
|
||||
*/
|
||||
void HAL_CRU_AsInit(void);
|
||||
|
||||
/**
|
||||
* @brief it is for AS enable.
|
||||
* @param ch: channel
|
||||
* @param en: 1 is enable, 0 is disable.
|
||||
*/
|
||||
void HAL_CRU_AsEnable(uint8_t ch, uint8_t en);
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* HAL_CRU_MODULE_ENABLED */
|
|
@ -0,0 +1,94 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef _HAL_DEBUG_H_
|
||||
#define _HAL_DEBUG_H_
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup DEBUG
|
||||
* @{
|
||||
*/
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
|
||||
/* Run only for debugging, please refer to how-to-use for the definition of the specification. */
|
||||
//#define HAL_DBG_USING_RTT_SERIAL
|
||||
//#define HAL_DBG_USING_LIBC_PRINTF
|
||||
//#define HAL_DBG_USING_HAL_PRINTF
|
||||
#ifdef HAL_DBG_USING_RTT_SERIAL
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#define HAL_SYSLOG rt_kprintf
|
||||
#elif defined(HAL_DBG_USING_LIBC_PRINTF)
|
||||
#define HAL_SYSLOG printf
|
||||
#elif defined(HAL_DBG_USING_HAL_PRINTF)
|
||||
#define HAL_SYSLOG HAL_DBG_Printf
|
||||
#ifndef HAL_PRINTF_BUF_SIZE
|
||||
#define HAL_PRINTF_BUF_SIZE 128
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** @defgroup DEBUG_Exported_Definition_Group1 Basic Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HAL_SYSLOG
|
||||
#define HAL_SYSLOG HAL_DBG_Printf
|
||||
#endif
|
||||
|
||||
#if defined(HAL_DBG_ON) && defined(HAL_DBG_INFO_ON)
|
||||
#define HAL_DBG(fmt, arg...) HAL_SYSLOG("[HAL INFO] " fmt, ##arg)
|
||||
#else
|
||||
#define HAL_DBG(fmt, arg...) do { if (0) HAL_SYSLOG("[HAL INFO] " fmt, ##arg); } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(HAL_DBG_ON) && defined(HAL_DBG_WRN_ON)
|
||||
#define HAL_DBG_WRN(fmt, arg...) HAL_SYSLOG("[HAL WARNING] " fmt, ##arg)
|
||||
#else
|
||||
#define HAL_DBG_WRN(fmt, arg...) do { if (0) HAL_SYSLOG("[HAL WARNING] " fmt, ##arg); } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(HAL_DBG_ON) && defined(HAL_DBG_ERR_ON)
|
||||
#define HAL_DBG_ERR(fmt, arg...) HAL_SYSLOG("[HAL ERROR] " fmt, ##arg)
|
||||
#else
|
||||
#define HAL_DBG_ERR(fmt, arg...) do { if (0) HAL_SYSLOG("[HAL ERROR] " fmt, ##arg); } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(HAL_DBG_ON) && defined(HAL_ASSERT_ON)
|
||||
#define HAL_ASSERT(expr) \
|
||||
do { \
|
||||
if (!(expr)) \
|
||||
HAL_AssertFailed((const char *)__FILE__, __LINE__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define HAL_ASSERT(expr)
|
||||
#endif
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
|
||||
/** @} */
|
||||
/***************************** Function Declare ******************************/
|
||||
/** @defgroup DEBUG_Public_Function_Declare Public Function Declare
|
||||
* @{
|
||||
*/
|
||||
|
||||
void HAL_AssertFailed(const char *file, uint32_t line);
|
||||
HAL_Status HAL_DBG_HEX(char *s, void *buf, uint32_t width, uint32_t len);
|
||||
#ifdef __GNUC__
|
||||
__attribute__((__format__(printf, 1, 2)))
|
||||
#endif
|
||||
int32_t HAL_DBG_Printf(const char *format, ...);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,205 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup HAL_DEF
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HAL_DEF_H_
|
||||
#define _HAL_DEF_H_
|
||||
|
||||
#include "libserial.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "hal_list.h"
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
/** @defgroup HAL_DEF_Exported_Definition_Group1 Basic Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define SET_BIT(REG, BIT) ((*(volatile uint32_t *)&(REG)) |= (BIT)) /**< Set 1 to the register specific bit field */
|
||||
#define CLEAR_BIT(REG, MASK) ((*(volatile uint32_t *)&(REG)) &= ~(MASK)) /**< Clear the specific bits filed from the register */
|
||||
#define READ_BIT(REG, MASK) ((*(volatile const uint32_t *)&(REG)) & (MASK)) /**< Read the value of a specific bits field from the register */
|
||||
#define CLEAR_REG(REG) ((*(volatile uint32_t *)&(REG)) = (0x0)) /**< Write 0 to the register */
|
||||
#define WRITE_REG(REG, VAL) ((*(volatile uint32_t *)&(REG)) = (VAL)) /**< Write the register */
|
||||
#define READ_REG(REG) ((*(volatile const uint32_t *)&(REG))) /**< Read the register */
|
||||
#define MODIFY_REG(REG, CLEARMASK, SETMASK) \
|
||||
WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) /**< Clear and set the value of a specific bits field from the register */
|
||||
#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL)))
|
||||
|
||||
#if defined(__GNUC__) || defined(__CC_ARM)
|
||||
#define MASK_TO_WE(msk) (__builtin_constant_p(msk) ? ((msk) > 0xFFFFU ? 0 : ((msk) << 16)) : ((msk) << 16))
|
||||
#else
|
||||
#define MASK_TO_WE(msk) ((msk) << 16)
|
||||
#endif
|
||||
#define VAL_MASK_WE(msk, val) ((MASK_TO_WE(msk)) | (val))
|
||||
#define WRITE_REG_MASK_WE(reg, msk, val) WRITE_REG(reg, (VAL_MASK_WE(msk, val)))
|
||||
|
||||
/* Misc OPS Marco */
|
||||
#define HAL_MAX_DELAY 0xFFFFFFFFU
|
||||
|
||||
#define RESET 0
|
||||
#define HAL_IS_BIT_SET(REG, MASK) (((*(volatile uint32_t *)&(REG)) & (MASK)) != RESET) /**< Check if the the specific bits filed from the register is valid */
|
||||
#define HAL_IS_BIT_CLR(REG, MASK) (((*(volatile uint32_t *)&(REG)) & (MASK)) == RESET) /**< Check if the the specific bits filed from the register is isvalid */
|
||||
|
||||
#define HAL_BIT(nr) (1UL << (nr))
|
||||
#define HAL_ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
|
||||
#define HAL_MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define HAL_MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
#define HAL_DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y))
|
||||
|
||||
#define HAL_IS_ALIGNED(x, a) (((x) & (a - 1)) == 0)
|
||||
#ifdef CACHE_LINE_SIZE
|
||||
#define HAL_IS_CACHELINE_ALIGNED(x) HAL_IS_ALIGNED((uint32_t)(x), CACHE_LINE_SIZE)
|
||||
#else
|
||||
#define HAL_IS_CACHELINE_ALIGNED(x) HAL_IS_ALIGNED((uint32_t)(x), 4)
|
||||
#endif
|
||||
|
||||
/* Compiller Macro */
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) || defined(__ICCARM__)
|
||||
#define HAL_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define HAL_UNUSED
|
||||
#endif
|
||||
|
||||
#ifdef CACHE_LINE_SIZE
|
||||
#define HAL_CACHELINE_ALIGNED __ALIGNED(CACHE_LINE_SIZE)
|
||||
#else
|
||||
#define HAL_CACHELINE_ALIGNED
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SRAM_SECTION_ENABLED
|
||||
#define HAL_SECTION_SRAM_CODE __attribute__((section(".sram_code")))
|
||||
#define HAL_SECTION_SRAM_RODATA __attribute__((section(".sram_rodata")))
|
||||
#define HAL_SECTION_SRAM_DATA __attribute__((section(".sram_data")))
|
||||
#define HAL_SECTION_SRAM_BSS __attribute__((section(".sram_bss")))
|
||||
#else
|
||||
#define HAL_SECTION_SRAM_CODE
|
||||
#define HAL_SECTION_SRAM_RODATA
|
||||
#define HAL_SECTION_SRAM_DATA
|
||||
#define HAL_SECTION_SRAM_BSS
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PSRAM_SECTION_ENABLED
|
||||
#define HAL_SECTION_PSRAM_CODE __attribute__((section(".psram_code")))
|
||||
#define HAL_SECTION_PSRAM_RODATA __attribute__((section(".psram_rodata")))
|
||||
#define HAL_SECTION_PSRAM_DATA __attribute__((section(".psram_data")))
|
||||
#define HAL_SECTION_PSRAM_BSS __attribute__((section(".psram_bss")))
|
||||
#else
|
||||
#define HAL_SECTION_PSRAM_CODE
|
||||
#define HAL_SECTION_PSRAM_RODATA
|
||||
#define HAL_SECTION_PSRAM_DATA
|
||||
#define HAL_SECTION_PSRAM_BSS
|
||||
#endif
|
||||
|
||||
#ifdef HAL_XIP_SECTION_ENABLED
|
||||
#define HAL_SECTION_XIP_CODE __attribute__((section(".xip_code")))
|
||||
#define HAL_SECTION_XIP_RODATA __attribute__((section(".xip_rodata")))
|
||||
#else
|
||||
#define HAL_SECTION_XIP_CODE
|
||||
#define HAL_SECTION_XIP_RODATA
|
||||
#endif
|
||||
|
||||
#define HAL_GENMASK(h, l) (((~0U) << (l)) & (~0U >> (32 - 1 - (h))))
|
||||
#define HAL_GENVAL(x, h, l) ((uint32_t)(((x) & HAL_GENMASK(h, l)) >> (l)))
|
||||
#define HAL_GENMASK_ULL(h, l) (((~0ULL) << (l)) & (~0ULL >> (64 - 1 - (h))))
|
||||
#define HAL_GENVAL_ULL(x, h, l) ((uint64_t)(((x) & HAL_GENMASK_ULL(h, l)) >> (l)))
|
||||
|
||||
/** MCU systick clock source */
|
||||
typedef enum {
|
||||
HAL_SYSTICK_CLKSRC_CORE,
|
||||
HAL_SYSTICK_CLKSRC_EXT
|
||||
} eHAL_systickClkSource;
|
||||
|
||||
/** Check if is MCU systick clock source */
|
||||
#define IS_SYSTICK_SOURCE(s) (((s) == HAL_SYSTICK_CLKSRC_CORE) || ((s) == HAL_SYSTICK_CLKSRC_EXT))
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
/** HAL boolean type definition */
|
||||
typedef enum {
|
||||
HAL_FALSE = 0x00U,
|
||||
HAL_TRUE = 0x01U
|
||||
} HAL_Check;
|
||||
|
||||
/** HAL error code definition */
|
||||
typedef enum {
|
||||
HAL_OK = 0x00U,
|
||||
HAL_ERROR = (-1),
|
||||
HAL_BUSY = (-16),
|
||||
HAL_NODEV = (-19),
|
||||
HAL_INVAL = (-22),
|
||||
HAL_NOSYS = (-38),
|
||||
HAL_TIMEOUT = (-110)
|
||||
} HAL_Status;
|
||||
|
||||
/** HAL functional status definition */
|
||||
typedef enum {
|
||||
HAL_DISABLE = 0x00U,
|
||||
HAL_ENABLE = 0x01U
|
||||
} HAL_FuncStatus;
|
||||
|
||||
/** HAL lock structures definition */
|
||||
typedef enum {
|
||||
HAL_UNLOCKED = 0x00U,
|
||||
HAL_LOCKED = 0x01U
|
||||
} HAL_LockStatus;
|
||||
|
||||
/** RK GPIO bank definition */
|
||||
typedef enum {
|
||||
#ifdef GPIO0
|
||||
GPIO_BANK0 = 0,
|
||||
#endif
|
||||
#ifdef GPIO1
|
||||
GPIO_BANK1 = 1,
|
||||
#endif
|
||||
#ifdef GPIO2
|
||||
GPIO_BANK2 = 2,
|
||||
#endif
|
||||
#ifdef GPIO3
|
||||
GPIO_BANK3 = 3,
|
||||
#endif
|
||||
#ifdef GPIO4
|
||||
GPIO_BANK4 = 4,
|
||||
#endif
|
||||
#ifdef GPIO0_EXP
|
||||
GPIO_BANK0_EXP = 5,
|
||||
#endif
|
||||
#ifdef GPIO1_EXP
|
||||
GPIO_BANK1_EXP = 6,
|
||||
#endif
|
||||
#ifdef GPIO2_EXP
|
||||
GPIO_BANK2_EXP = 7,
|
||||
#endif
|
||||
#ifdef GPIO3_EXP
|
||||
GPIO_BANK3_EXP = 8,
|
||||
#endif
|
||||
#ifdef GPIO4_EXP
|
||||
GPIO_BANK4_EXP = 9,
|
||||
#endif
|
||||
GPIO_BANK_NUM
|
||||
} eGPIO_bankId;
|
||||
|
||||
/** HAL function type definition */
|
||||
typedef void (*pFunc)(void);
|
||||
|
||||
/** @} */
|
||||
/***************************** Function Declare ******************************/
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,282 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef _HAL_DRIVER_H_
|
||||
#define _HAL_DRIVER_H_
|
||||
|
||||
#include "hal_pm.h"
|
||||
|
||||
#ifdef HAL_ACDCDIG_MODULE_ENABLED
|
||||
#include "hal_acdcdig.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_ACODEC_MODULE_ENABLED
|
||||
#include "hal_acodec.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_ARCHTIMER_MODULE_ENABLED
|
||||
#include "hal_archtimer.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_AUDIOPWM_MODULE_ENABLED
|
||||
#include "hal_audiopwm.h"
|
||||
#endif
|
||||
|
||||
// #include "hal_cache.h"
|
||||
|
||||
#ifdef HAL_BUFMGR_MODULE_ENABLED
|
||||
#include "hal_bufmgr.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_CANFD_MODULE_ENABLED
|
||||
#include "hal_canfd.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_CKCAL_MODULE_ENABLED
|
||||
#include "hal_ckcal.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_CACHE_ECC_MODULE_ENABLED
|
||||
#include "hal_cache_ecc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_CPU_TOPOLOGY_MODULE_ENABLED
|
||||
#include "hal_cpu_topology.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_CRU_MODULE_ENABLED
|
||||
#include "hal_cru.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_CRYPTO_MODULE_ENABLED
|
||||
#include "hal_crypto.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_DSI_MODULE_ENABLED
|
||||
#include "hal_display.h"
|
||||
#include "hal_dsi.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_DEMO_MODULE_ENABLED
|
||||
#include "hal_demo.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_DDR_ECC_MODULE_ENABLED
|
||||
#include "hal_ddr_ecc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_DSP_MODULE_ENABLED
|
||||
#include "hal_dsp.h"
|
||||
#endif
|
||||
|
||||
// #include "hal_dma.h"
|
||||
|
||||
#ifdef HAL_DWDMA_MODULE_ENABLED
|
||||
#include "hal_dwdma.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_EFUSE_MODULE_ENABLED
|
||||
#include "hal_efuse.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAL_GMAC_MODULE_ENABLED) || defined(HAL_GMAC1000_MODULE_ENABLED)
|
||||
#include "hal_gmac.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "hal_gpio.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
|
||||
#include "hal_gpio_irq_group.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PINCTRL_MODULE_ENABLED
|
||||
#include "hal_pinctrl.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAL_HCD_MODULE_ENABLED) || defined(HAL_PCD_MODULE_ENABLED)
|
||||
#include "hal_usb_core.h"
|
||||
#include "hal_usb_phy.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAL_EHCI_MODULE_ENABLED) || defined(HAL_OHCI_MODULE_ENABLED)
|
||||
#include "hal_usbh.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_HCD_MODULE_ENABLED
|
||||
#include "hal_hcd.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_HWSPINLOCK_MODULE_ENABLED
|
||||
#include "hal_hwspinlock.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_HYPERPSRAM_MODULE_ENABLED
|
||||
#include "hal_hyperpsram.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
#include "hal_i2c.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_I2S_MODULE_ENABLED
|
||||
#include "hal_i2s.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_I2STDM_MODULE_ENABLED
|
||||
#include "hal_i2stdm.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_INTC_MODULE_ENABLED
|
||||
#include "hal_intc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_INTMUX_MODULE_ENABLED
|
||||
#include "hal_intmux.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_IRQ_HANDLER_MODULE_ENABLED
|
||||
#include "hal_irq_handler.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GIC_MODULE_ENABLED
|
||||
#include "hal_gic.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_MBOX_MODULE_ENABLED
|
||||
#include "hal_mbox.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_NVIC_MODULE_ENABLED
|
||||
#include "hal_nvic.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
#include "hal_pcd.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PCIE_MODULE_ENABLED
|
||||
#include "hal_pci_core.h"
|
||||
#include "hal_pcie_dma.h"
|
||||
#include "hal_pcie.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PDM_MODULE_ENABLED
|
||||
#include "hal_pdm.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PL330_MODULE_ENABLED
|
||||
#include "hal_pl330.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PMU_MODULE_ENABLED
|
||||
#include "hal_pd.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PVTM_MODULE_ENABLED
|
||||
#include "hal_pvtm.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PWM_MODULE_ENABLED
|
||||
#include "hal_pwm.h"
|
||||
#endif
|
||||
|
||||
// #include "hal_pwr.h"
|
||||
|
||||
#ifdef HAL_RISCVIC_MODULE_ENABLED
|
||||
#include "hal_riscvic.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SDIO_MODULE_ENABLED
|
||||
#include "hal_sdio.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SNOR_MODULE_ENABLED
|
||||
#include "hal_spi_mem.h"
|
||||
#include "hal_snor.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SFC_MODULE_ENABLED
|
||||
#include "hal_sfc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SPINAND_MODULE_ENABLED
|
||||
#include "hal_spi_mem.h"
|
||||
#include "hal_spinand.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SPINLOCK_MODULE_ENABLED
|
||||
#include "hal_spinlock.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SYSTICK_MODULE_ENABLED
|
||||
#include "hal_systick.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_FSPI_MODULE_ENABLED
|
||||
#include "hal_spi_mem.h"
|
||||
#include "hal_fspi.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_QPIPSRAM_MODULE_ENABLED
|
||||
#include "hal_spi_mem.h"
|
||||
#include "hal_qpipsram.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_TOUCHKEY_MODULE_ENABLED
|
||||
#include "hal_touchkey.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_TSADC_MODULE_ENABLED
|
||||
#include "hal_tsadc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SARADC_MODULE_ENABLED
|
||||
#include "hal_saradc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SMCCC_MODULE_ENABLED
|
||||
#include "hal_smccc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_KEYCTRL_MODULE_ENABLED
|
||||
#include "hal_keyctrl.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "hal_spi.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_SPI2APB_MODULE_ENABLED
|
||||
#include "hal_spi2apb.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_TIMER_MODULE_ENABLED
|
||||
#include "hal_timer.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "hal_uart.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_VAD_MODULE_ENABLED
|
||||
#include "hal_vad.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_VICAP_MODULE_ENABLED
|
||||
#include "hal_vicap.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_VOP_MODULE_ENABLED
|
||||
#include "hal_display.h"
|
||||
#include "hal_vop.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_WDT_MODULE_ENABLED
|
||||
#include "hal_wdt.h"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,360 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_conf.h"
|
||||
|
||||
#if (defined(HAL_GMAC_MODULE_ENABLED) || defined(HAL_GMAC1000_MODULE_ENABLED))
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup GMAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __HAL_GMAC_H
|
||||
#define __HAL_GMAC_H
|
||||
|
||||
#include "hal_def.h"
|
||||
#include "hal_base.h"
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
/** @defgroup GMAC_Exported_Definition_Group1 Basic Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* GMAC PHY indicates what features are supported by the interface. */
|
||||
#define HAL_GMAC_PHY_SUPPORTED_10baseT_Half (1 << 0)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_10baseT_Full (1 << 1)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_100baseT_Half (1 << 2)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_100baseT_Full (1 << 3)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_1000baseT_Half (1 << 4)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_1000baseT_Full (1 << 5)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_Autoneg (1 << 6)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_TP (1 << 7)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_AUI (1 << 8)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_MII (1 << 9)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_FIBRE (1 << 10)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_BNC (1 << 11)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_10000baseT_Full (1 << 12)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_Pause (1 << 13)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_Asym_Pause (1 << 14)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_2500baseX_Full (1 << 15)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_Backplane (1 << 16)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_1000baseKX_Full (1 << 17)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_10000baseKX4_Full (1 << 18)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_10000baseKR_Full (1 << 19)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_10000baseR_FEC (1 << 20)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_1000baseX_Half (1 << 21)
|
||||
#define HAL_GMAC_PHY_SUPPORTED_1000baseX_Full (1 << 22)
|
||||
|
||||
#define HAL_GMAC_PHY_DEFAULT_FEATURES (HAL_GMAC_PHY_SUPPORTED_Autoneg | \
|
||||
HAL_GMAC_PHY_SUPPORTED_TP | \
|
||||
HAL_GMAC_PHY_SUPPORTED_MII)
|
||||
|
||||
#define HAL_GMAC_PHY_10BT_FEATURES (HAL_GMAC_PHY_SUPPORTED_10baseT_Half | \
|
||||
HAL_GMAC_PHY_SUPPORTED_10baseT_Full)
|
||||
|
||||
#define HAL_GMAC_PHY_100BT_FEATURES (HAL_GMAC_PHY_SUPPORTED_100baseT_Half | \
|
||||
HAL_GMAC_PHY_SUPPORTED_100baseT_Full)
|
||||
|
||||
#define HAL_GMAC_PHY_1000BT_FEATURES (HAL_GMAC_PHY_SUPPORTED_1000baseT_Half | \
|
||||
HAL_GMAC_PHY_SUPPORTED_1000baseT_Full)
|
||||
|
||||
#define HAL_GMAC_PHY_BASIC_FEATURES (HAL_GMAC_PHY_10BT_FEATURES | \
|
||||
HAL_GMAC_PHY_100BT_FEATURES | \
|
||||
HAL_GMAC_PHY_DEFAULT_FEATURES)
|
||||
|
||||
#define HAL_GMAC_PHY_GBIT_FEATURES (HAL_GMAC_PHY_BASIC_FEATURES | \
|
||||
HAL_GMAC_PHY_1000BT_FEATURES)
|
||||
|
||||
/* GMAC flow ctrl Definition */
|
||||
#define HAL_GMAC_FLOW_OFF 0
|
||||
#define HAL_GMAC_FLOW_RX 1
|
||||
#define HAL_GMAC_FLOW_TX 2
|
||||
#define HAL_GMAC_FLOW_AUTO (HAL_GMAC_FLOW_TX | HAL_GMAC_FLOW_RX)
|
||||
|
||||
/* GMAC descriptions and buffers Definition */
|
||||
#define HAL_GMAC_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
#define HAL_GMAC_DESCRIPTOR_WORDS 4
|
||||
#define HAL_GMAC_DESCRIPTOR_SIZE (HAL_GMAC_DESCRIPTOR_WORDS * 4)
|
||||
#define HAL_GMAC_BUFFER_ALIGN 64
|
||||
#define HAL_GMAC_MAX_FRAME_SIZE 1518
|
||||
#define HAL_GMAC_MAX_PACKET_SIZE HAL_GMAC_ALIGN(HAL_GMAC_MAX_FRAME_SIZE, HAL_GMAC_BUFFER_ALIGN)
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
struct GMAC_HANDLE;
|
||||
|
||||
/**
|
||||
* @brief GMAC PHY Speed
|
||||
*/
|
||||
typedef enum {
|
||||
PHY_SPEED_10M = 10,
|
||||
PHY_SPEED_100M = 100,
|
||||
PHY_SPEED_1000M = 1000,
|
||||
} eGMAC_PHY_SPEED;
|
||||
|
||||
/**
|
||||
* @brief GMAC PHY Duplex
|
||||
*/
|
||||
typedef enum {
|
||||
PHY_DUPLEX_HALF = 0,
|
||||
PHY_DUPLEX_FULL = 1,
|
||||
} eGMAC_PHY_DUPLEX;
|
||||
|
||||
/**
|
||||
* @brief GMAC PHY Auto Negrotetion
|
||||
*/
|
||||
typedef enum {
|
||||
PHY_AUTONEG_DISABLE = 0,
|
||||
PHY_AUTONEG_ENABLE = 1,
|
||||
} eGMAC_PHY_NEGROTETION;
|
||||
|
||||
/**
|
||||
* @brief GMAC PHY Interface Mode
|
||||
*/
|
||||
typedef enum {
|
||||
PHY_INTERFACE_MODE_MII,
|
||||
PHY_INTERFACE_MODE_RMII,
|
||||
PHY_INTERFACE_MODE_RGMII,
|
||||
PHY_INTERFACE_MODE_NONE,
|
||||
} eGMAC_PHY_Interface;
|
||||
|
||||
/**
|
||||
* @brief GMAC DMA IRQ Status
|
||||
*/
|
||||
typedef enum {
|
||||
DMA_UNKNOWN = 0x0,
|
||||
DMA_HANLE_RX = 0x1,
|
||||
DMA_HANLE_TX = 0x2,
|
||||
DMA_TX_ERROR = 0x10,
|
||||
DMA_RX_ERROR = 0x20,
|
||||
} eGMAC_IRQ_Status;
|
||||
|
||||
/**
|
||||
* @brief GMAC PHY OPS Structure Definition
|
||||
*/
|
||||
struct GMAC_PHY_OPS {
|
||||
HAL_Status (*init)(struct GMAC_HANDLE *pGMAC); /**< Will be called during HAL_GMAC_PHYInit(). */
|
||||
HAL_Status (*config)(struct GMAC_HANDLE *pGMAC); /**< Called to configure the PHY, and modify the PHY,
|
||||
based on the results. Should be called after HAL_GMAC_PHYInit(). */
|
||||
HAL_Status (*startup)(struct GMAC_HANDLE *pGMAC); /**< Called when starting up the PHY */
|
||||
HAL_Status (*shutdown)(struct GMAC_HANDLE *pGMAC); /**< Called when bringing down the PHY */
|
||||
HAL_Status (*reset)(struct GMAC_HANDLE *pGMAC); /**< Called when hardware reset */
|
||||
HAL_Status (*softreset)(struct GMAC_HANDLE *pGMAC);/**< Called when soft reset */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GMAC PHY Config Structure Definition
|
||||
*/
|
||||
struct GMAC_PHY_Config {
|
||||
eGMAC_PHY_Interface interface;/**< Ethernet interface mode. */
|
||||
int16_t phyAddress; /**< Ethernet PHY address,
|
||||
This parameter must be a number between Min = 0 and Max = 31 */
|
||||
eGMAC_PHY_NEGROTETION neg; /**< Selects or disable the AutoNegotiation mode for the external PHY,
|
||||
The AutoNegotiation allows an automatic setting of the Speed
|
||||
(10/100/1000 Mbps) and the mode (half/full-duplex). */
|
||||
eGMAC_PHY_SPEED speed; /**< Sets the Ethernet speed: 10/100/1000 Mbps
|
||||
while disable AutoNegotiation. */
|
||||
eGMAC_PHY_DUPLEX duplexMode; /**< Selects the Ethernet duplex mode: Half-Duplex or
|
||||
Full-Duplex mode while disable AutoNegotiation. */
|
||||
eGMAC_PHY_SPEED maxSpeed; /**< Sets the Ethernet max speed: 10/100/1000 Mbps. */
|
||||
uint32_t features; /**< Sets the Ethernet PHY features. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GMAC PHY Status Structure Definition
|
||||
*/
|
||||
struct GMAC_PHY_STATUS {
|
||||
eGMAC_PHY_Interface interface; /**< Ethernet interface mode. */
|
||||
|
||||
/* forced speed & duplex (no autoneg)
|
||||
* partner speed & duplex & pause (autoneg)
|
||||
*/
|
||||
eGMAC_PHY_SPEED speed; /**< Ethernet speed. */
|
||||
eGMAC_PHY_DUPLEX duplex; /**< Ethernet duplex. */
|
||||
eGMAC_PHY_SPEED maxSpeed; /**< Ethernet max speed. */
|
||||
eGMAC_PHY_NEGROTETION neg; /**< Ethernet AutoNegotiation or not. */
|
||||
|
||||
/* The most recently read link state */
|
||||
int link; /**< Ethernet current link. */
|
||||
int oldLink; /**< Store the Ethernet last link. */
|
||||
|
||||
uint32_t features; /**< Ethernet PHY actual features. */
|
||||
uint32_t advertising; /**< Ethernet PHY advertising features. */
|
||||
uint32_t supported; /**< Ethernet PHY supported features. */
|
||||
|
||||
int16_t addr; /**< Ethernet PHY address. */
|
||||
int16_t pause; /**< Ethernet PHY address. */
|
||||
uint32_t phyID; /**< Ethernet PHY ID. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GMAC Link Config Structure Definition
|
||||
*/
|
||||
struct GMAC_Link {
|
||||
uint32_t speedMask;
|
||||
uint32_t speed10;
|
||||
uint32_t speed100;
|
||||
uint32_t speed1000;
|
||||
uint32_t duplex;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GMAC DMA Descriptors Data Structure Definition
|
||||
*/
|
||||
struct GMAC_Desc {
|
||||
volatile uint32_t des0; /**< DMA Descriptors first word */
|
||||
volatile uint32_t des1; /**< DMA Descriptors second word */
|
||||
volatile uint32_t des2; /**< DMA Descriptors third word */
|
||||
volatile uint32_t des3; /**< DMA Descriptors four word */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GMAC DMA Transfer Status Structure Definition
|
||||
*/
|
||||
struct GMAC_DMAStats {
|
||||
uint32_t txUndeflowIRQ;
|
||||
uint32_t txProcessStoppedIRQ;
|
||||
uint32_t txJabberIRQ;
|
||||
uint32_t rxOverflowIRQ;
|
||||
uint32_t rxBufUnavIRQ;
|
||||
uint32_t rxProcessStoppedIRQ;
|
||||
uint32_t rxWatchdogIRQ;
|
||||
uint32_t txEarlyIRQ;
|
||||
uint32_t fatalBusErrorIRQ;
|
||||
uint32_t normalIRQN;
|
||||
uint32_t rxNormalIRQN;
|
||||
uint32_t txNormallIRQN;
|
||||
|
||||
uint32_t rxEarlyIRQ;
|
||||
uint32_t thresHold;
|
||||
uint32_t txPktN;
|
||||
uint32_t rxPktN;
|
||||
uint32_t txBytesN;
|
||||
uint32_t rxBytesN;
|
||||
uint32_t txErrors;
|
||||
uint32_t rxErrors;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GMAC device information Structure Definition
|
||||
*/
|
||||
struct GMAC_DEVICE_INFO {
|
||||
uint32_t miiAddrShift;
|
||||
uint32_t miiAddrMask;
|
||||
uint32_t miiRegShift;
|
||||
uint32_t miiRegMask;
|
||||
uint32_t clkCsrShift;
|
||||
uint32_t clkCsrMask;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GMAC Handle Structure Definition
|
||||
*/
|
||||
struct GMAC_HANDLE {
|
||||
struct GMAC_REG *pReg; /**< Register base address */
|
||||
uint32_t clkCSR; /**< clock csr value, div for MDC clock */
|
||||
|
||||
struct GMAC_DEVICE_INFO mac; /**< MAC information */
|
||||
|
||||
struct GMAC_PHY_OPS phyOps; /**< phy ops callback function */
|
||||
struct GMAC_PHY_Config phyConfig; /**< phy config provied by user */
|
||||
struct GMAC_PHY_STATUS phyStatus; /**< phy status */
|
||||
|
||||
struct GMAC_Link link; /**< GMAC link config */
|
||||
struct GMAC_DMAStats extraStatus; /**< GMAC DMA transfer status */
|
||||
|
||||
struct GMAC_Desc *rxDescs; /**< First Rx descriptor pointer */
|
||||
struct GMAC_Desc *rxDescs_dma;
|
||||
struct GMAC_Desc *txDescs; /**< First Tx descriptor pointer */
|
||||
struct GMAC_Desc *txDescs_dma;
|
||||
uint8_t *txBuf; /**< First Tx buffer pointer */
|
||||
uint8_t *txBuf_dma;
|
||||
uint8_t *rxBuf; /**< First Tx buffer pointer */
|
||||
uint8_t *rxBuf_dma;
|
||||
uint32_t txDescIdx; /**< Current Tx descriptor index */
|
||||
uint32_t rxDescIdx; /**< Current Rx descriptor pointer */
|
||||
uint32_t txSize; /**< Tx descriptor size*/
|
||||
uint32_t rxSize; /**< Rx descriptor size */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GMAC HW Information Definition
|
||||
*/
|
||||
struct HAL_GMAC_DEV {
|
||||
struct GMAC_REG *pReg;
|
||||
eCLOCK_Name clkID125M;
|
||||
eCLOCK_Name clkID50M;
|
||||
uint32_t clkGateID125M;
|
||||
uint32_t clkGateID50M;
|
||||
eCLOCK_Name pclkID;
|
||||
uint32_t pclkGateID;
|
||||
IRQn_Type irqNum;
|
||||
ePM_RUNTIME_ID runtimeID;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/***************************** Function Declare ******************************/
|
||||
/** @defgroup GMAC_Public_Function_Declare Public Function Declare
|
||||
* @{
|
||||
*/
|
||||
HAL_Status HAL_GMAC_Init(struct GMAC_HANDLE *pGMAC, struct GMAC_REG *pReg,
|
||||
uint32_t freq, eGMAC_PHY_Interface interface,
|
||||
bool extClk);
|
||||
HAL_Status HAL_GMAC_DeInit(struct GMAC_HANDLE *pGMAC);
|
||||
HAL_Status HAL_GMAC_Start(struct GMAC_HANDLE *pGMAC, uint8_t *addr);
|
||||
HAL_Status HAL_GMAC_Stop(struct GMAC_HANDLE *pGMAC);
|
||||
void HAL_GMAC_EnableDmaIRQ(struct GMAC_HANDLE *pGMAC);
|
||||
void HAL_GMAC_DisableDmaIRQ(struct GMAC_HANDLE *pGMAC);
|
||||
HAL_Status HAL_GMAC_DMATxDescInit(struct GMAC_HANDLE *pGMAC,
|
||||
struct GMAC_Desc *txDescs,
|
||||
struct GMAC_Desc *txDescs_dma,
|
||||
uint8_t *txBuff, uint8_t *txBuff_dma, uint32_t txBuffCount);
|
||||
HAL_Status HAL_GMAC_DMARxDescInit(struct GMAC_HANDLE *pGMAC,
|
||||
struct GMAC_Desc *rxDescs,
|
||||
struct GMAC_Desc *rxDescs_dma,
|
||||
uint8_t *rxBuff, uint8_t *rxBuff_dma, uint32_t rxBuffCount);
|
||||
eGMAC_IRQ_Status HAL_GMAC_IRQHandler(struct GMAC_HANDLE *pGMAC);
|
||||
HAL_Status HAL_GMAC_AdjustLink(struct GMAC_HANDLE *pGMAC, int32_t txDelay,
|
||||
int32_t rxDelay);
|
||||
uint32_t HAL_GMAC_GetTXIndex(struct GMAC_HANDLE *pGMAC);
|
||||
uint32_t HAL_GMAC_GetRXIndex(struct GMAC_HANDLE *pGMAC);
|
||||
uint8_t *HAL_GMAC_GetTXBuffer(struct GMAC_HANDLE *pGMAC);
|
||||
uint8_t *HAL_GMAC_GetTXBufferDMA(struct GMAC_HANDLE *pGMAC);
|
||||
uint8_t *HAL_GMAC_GetRXBuffer(struct GMAC_HANDLE *pGMAC);
|
||||
uint8_t *HAL_GMAC_GetRXBufferDMA(struct GMAC_HANDLE *pGMAC);
|
||||
HAL_Status HAL_GMAC_Send(struct GMAC_HANDLE *pGMAC,
|
||||
void *packet, uint32_t length);
|
||||
uint8_t *HAL_GMAC_Recv(struct GMAC_HANDLE *pGMAC, int32_t *length);
|
||||
void HAL_GMAC_CleanRX(struct GMAC_HANDLE *pGMAC);
|
||||
void HAL_GMAC_WriteHWAddr(struct GMAC_HANDLE *pGMAC, uint8_t *enetAddr);
|
||||
HAL_Status HAL_GMAC_PHYInit(struct GMAC_HANDLE *pGMAC,
|
||||
struct GMAC_PHY_Config *config);
|
||||
HAL_Status HAL_GMAC_PHYStartup(struct GMAC_HANDLE *pGMAC);
|
||||
HAL_Status HAL_GMAC_PHYUpdateLink(struct GMAC_HANDLE *pGMAC);
|
||||
HAL_Status HAL_GMAC_PHYParseLink(struct GMAC_HANDLE *pGMAC);
|
||||
int32_t HAL_GMAC_MDIORead(struct GMAC_HANDLE *pGMAC, int32_t mdioAddr,
|
||||
int32_t mdioReg);
|
||||
HAL_Status HAL_GMAC_MDIOWrite(struct GMAC_HANDLE *pGMAC, int32_t mdioAddr,
|
||||
int32_t mdioReg, uint16_t mdioVal);
|
||||
void HAL_GMAC_SetToRGMII(struct GMAC_HANDLE *pGMAC,
|
||||
int32_t txDelay, int32_t rxDelay);
|
||||
void HAL_GMAC_SetToRMII(struct GMAC_HANDLE *pGMAC);
|
||||
void HAL_GMAC_SetRGMIISpeed(struct GMAC_HANDLE *pGMAC, int32_t speed);
|
||||
void HAL_GMAC_SetRMIISpeed(struct GMAC_HANDLE *pGMAC, int32_t speed);
|
||||
void HAL_GMAC_SetExtclkSrc(struct GMAC_HANDLE *pGMAC, bool extClk);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* HAL_GMAC_MODULE_ENABLED */
|
|
@ -0,0 +1,170 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_conf.h"
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup GPIO
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __HAL_GPIO_H
|
||||
#define __HAL_GPIO_H
|
||||
|
||||
#include "hal_def.h"
|
||||
#include "hal_pinctrl.h"
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
/** @defgroup GPIO_Exported_Definition_Group1 Basic Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef GPIO_VER_ID
|
||||
#define GPIO_VER_ID (0U)
|
||||
#endif
|
||||
|
||||
#define PIN_NUMBER_PER_BANK (32)
|
||||
|
||||
#define GPIO_PIN_SHIFT (0) /**< Bits 0-4: GPIO Pin number: 0 - 31 */
|
||||
#define GPIO_PIN_MASK (0x1f << GPIO_PIN_SHIFT)
|
||||
#define GPIO_BANK_SHIFT (5) /**< Bits 5-7: GPIO Port number: 0 - 7 */
|
||||
#define GPIO_BANK_MASK (0x7 << GPIO_BANK_SHIFT)
|
||||
|
||||
#define BANK_PIN(BANK, PIN) ((((BANK) << GPIO_BANK_SHIFT) & GPIO_BANK_MASK) + (((PIN) << GPIO_PIN_SHIFT) & GPIO_PIN_MASK))
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
/** GPIO pin level definition */
|
||||
typedef enum {
|
||||
GPIO_LOW,
|
||||
GPIO_HIGH
|
||||
} eGPIO_pinLevel;
|
||||
|
||||
/** GPIO pin direction definition */
|
||||
typedef enum {
|
||||
GPIO_IN,
|
||||
GPIO_OUT
|
||||
} eGPIO_pinDirection;
|
||||
|
||||
/** GPIO pin debounce definition */
|
||||
typedef enum {
|
||||
GPIO_DEBOUNCE_DIS,
|
||||
GPIO_DEBOUNCE_EN
|
||||
} eGPIO_pinDebounce;
|
||||
|
||||
/** GPIO pin interrupt enable definition */
|
||||
typedef enum {
|
||||
GPIO_INT_DISABLE,
|
||||
GPIO_INT_ENABLE
|
||||
} eGPIO_intEnable;
|
||||
|
||||
/** GPIO pin interrupt type definition */
|
||||
typedef enum {
|
||||
GPIO_INT_TYPE_NONE = 0x00000000,
|
||||
GPIO_INT_TYPE_EDGE_RISING = 0x00000001,
|
||||
GPIO_INT_TYPE_EDGE_FALLING = 0x00000002,
|
||||
GPIO_INT_TYPE_EDGE_BOTH = (GPIO_INT_TYPE_EDGE_FALLING | GPIO_INT_TYPE_EDGE_RISING),
|
||||
GPIO_INT_TYPE_LEVEL_HIGH = 0x00000004,
|
||||
GPIO_INT_TYPE_LEVEL_LOW = 0x00000008,
|
||||
GPIO_INT_TYPE_LEVEL_MASK = (GPIO_INT_TYPE_LEVEL_LOW | GPIO_INT_TYPE_LEVEL_HIGH),
|
||||
GPIO_INT_TYPE_SENSE_MASK = 0x0000000f,
|
||||
GPIO_INT_TYPE_DEFAULT = GPIO_INT_TYPE_SENSE_MASK,
|
||||
} eGPIO_intType;
|
||||
|
||||
/** GPIO pin interrupt mode definition */
|
||||
typedef enum {
|
||||
GPIO_INT_MODE_EDGE_RISING,
|
||||
GPIO_INT_MODE_EDGE_FALLING,
|
||||
GPIO_INT_MODE_EDGE_RISING_FALLING,
|
||||
GPIO_INT_MODE_LEVEL_HIGH,
|
||||
GPIO_INT_MODE_LEVEL_LOW,
|
||||
GPIO_INT_MODE_INVALID
|
||||
} eGPIO_intMode;
|
||||
|
||||
/** GPIO pin virtual model definition */
|
||||
typedef enum {
|
||||
GPIO_VIRTUAL_MODEL_OS_A,
|
||||
GPIO_VIRTUAL_MODEL_OS_B,
|
||||
GPIO_VIRTUAL_MODEL_OS_C,
|
||||
GPIO_VIRTUAL_MODEL_OS_D,
|
||||
} eGPIO_VirtualModel;
|
||||
|
||||
#define IS_GPIO_PIN_DIR(ACTION) (((ACTION) == GPIO_IN) || ((ACTION) == GPIO_OUT))
|
||||
#define IS_GPIO_PIN_LEVEL(ACTION) (((ACTION) == GPIO_LOW) || ((ACTION) == GPIO_HIGH))
|
||||
|
||||
#define IS_GPIO_PIN(PIN) ((PIN) != 0x00000000U)
|
||||
#define IS_GPIO_HIGH_PIN(PIN) IS_GPIO_PIN(((PIN) & 0xFFFF0000U))
|
||||
|
||||
#define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_PIN_A0) || \
|
||||
((PIN) == GPIO_PIN_A1) || \
|
||||
((PIN) == GPIO_PIN_A2) || \
|
||||
((PIN) == GPIO_PIN_A3) || \
|
||||
((PIN) == GPIO_PIN_A4) || \
|
||||
((PIN) == GPIO_PIN_A5) || \
|
||||
((PIN) == GPIO_PIN_A6) || \
|
||||
((PIN) == GPIO_PIN_A7) || \
|
||||
((PIN) == GPIO_PIN_B0) || \
|
||||
((PIN) == GPIO_PIN_B1) || \
|
||||
((PIN) == GPIO_PIN_B2) || \
|
||||
((PIN) == GPIO_PIN_B3) || \
|
||||
((PIN) == GPIO_PIN_B4) || \
|
||||
((PIN) == GPIO_PIN_B5) || \
|
||||
((PIN) == GPIO_PIN_B6) || \
|
||||
((PIN) == GPIO_PIN_B7) || \
|
||||
((PIN) == GPIO_PIN_C0) || \
|
||||
((PIN) == GPIO_PIN_C1) || \
|
||||
((PIN) == GPIO_PIN_C2) || \
|
||||
((PIN) == GPIO_PIN_C3) || \
|
||||
((PIN) == GPIO_PIN_C4) || \
|
||||
((PIN) == GPIO_PIN_C5) || \
|
||||
((PIN) == GPIO_PIN_C6) || \
|
||||
((PIN) == GPIO_PIN_C7) || \
|
||||
((PIN) == GPIO_PIN_D0) || \
|
||||
((PIN) == GPIO_PIN_D1) || \
|
||||
((PIN) == GPIO_PIN_D2) || \
|
||||
((PIN) == GPIO_PIN_D3) || \
|
||||
((PIN) == GPIO_PIN_D4) || \
|
||||
((PIN) == GPIO_PIN_D5) || \
|
||||
((PIN) == GPIO_PIN_D6) || \
|
||||
((PIN) == GPIO_PIN_D7))
|
||||
|
||||
/** @} */
|
||||
/***************************** Function Declare ******************************/
|
||||
/** @defgroup GPIO_Exported_Definition_Group2 Public Functions Declare.
|
||||
* @{
|
||||
*/
|
||||
eGPIO_pinDirection HAL_GPIO_GetPinDirection(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin);
|
||||
eGPIO_pinLevel HAL_GPIO_GetPinLevel(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin);
|
||||
eGPIO_pinLevel HAL_GPIO_GetPinData(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin);
|
||||
uint32_t HAL_GPIO_GetBankLevel(struct GPIO_REG *pGPIO);
|
||||
|
||||
HAL_Status HAL_GPIO_SetPinLevel(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_pinLevel level);
|
||||
HAL_Status HAL_GPIO_SetPinDirection(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_pinDirection direction);
|
||||
HAL_Status HAL_GPIO_SetIntType(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_intType mode);
|
||||
|
||||
HAL_Status HAL_GPIO_SetPinsLevel(struct GPIO_REG *pGPIO, uint32_t mPins, eGPIO_pinLevel level);
|
||||
HAL_Status HAL_GPIO_SetPinsDirection(struct GPIO_REG *pGPIO, uint32_t mPins, eGPIO_pinDirection direction);
|
||||
|
||||
void HAL_GPIO_EnableIRQ(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin);
|
||||
void HAL_GPIO_DisableIRQ(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin);
|
||||
void HAL_GPIO_IRQHandler(struct GPIO_REG *pGPIO, eGPIO_bankId bank);
|
||||
|
||||
#ifdef HAL_GPIO_VIRTUAL_MODEL_FEATURE_ENABLED
|
||||
HAL_Status HAL_GPIO_EnableVirtualModel(struct GPIO_REG *pGPIO);
|
||||
HAL_Status HAL_GPIO_DisableVirtualModel(struct GPIO_REG *pGPIO);
|
||||
HAL_Status HAL_GPIO_SetVirtualModel(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_VirtualModel vmodel);
|
||||
#endif
|
||||
|
||||
/* The parameter pin for this function is special, it's 0~31. */
|
||||
void HAL_GPIO_IRQDispatch(eGPIO_bankId bank, uint32_t pin);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,181 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef _HAL_LIST_H_
|
||||
#define _HAL_LIST_H_
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
|
||||
/** double list struct */
|
||||
struct HAL_LIST_NODE {
|
||||
struct HAL_LIST_NODE *next;
|
||||
struct HAL_LIST_NODE *prev;
|
||||
};
|
||||
|
||||
typedef struct HAL_LIST_NODE HAL_LIST;
|
||||
|
||||
/***************************** Function Declare ******************************/
|
||||
/**
|
||||
* @brief cast a member of a structure out to the containing structure
|
||||
* @param ptr: the pointer to the member.
|
||||
* @param type: the type of the container struct this is embedded in.
|
||||
* @param member: the name of the member within the struct.
|
||||
*/
|
||||
#define HAL_CONTAINER_OF(ptr, type, member) \
|
||||
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* @brief initialize a list object
|
||||
* @param object: object itself.
|
||||
*/
|
||||
#define HAL_LIST_OBJECT_INIT(object) { &(object), &(object) }
|
||||
|
||||
#define HAL_LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
/**
|
||||
* @brief initialize a list head
|
||||
* @param name: list name..
|
||||
*/
|
||||
#define HAL_LIST_HEAD(name) \
|
||||
struct HAL_LIST_NODE name = HAL_LIST_HEAD_INIT(name)
|
||||
|
||||
/**
|
||||
* @brief initialize a list
|
||||
* @param l: list to be initialized
|
||||
*/
|
||||
static inline void HAL_LIST_Init(HAL_LIST *l)
|
||||
{
|
||||
l->next = l->prev = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief insert a node after a list
|
||||
* @param l: list to insert it
|
||||
* @param n: new node to be inserted
|
||||
*/
|
||||
static inline void HAL_LIST_InsertAfter(HAL_LIST *l, HAL_LIST *n)
|
||||
{
|
||||
l->next->prev = n;
|
||||
n->next = l->next;
|
||||
|
||||
l->next = n;
|
||||
n->prev = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief insert a node before a list
|
||||
* @param n: new node to be inserted
|
||||
* @param l: list to insert it
|
||||
*/
|
||||
static inline void HAL_LIST_InsertBefore(HAL_LIST *l, HAL_LIST *n)
|
||||
{
|
||||
l->prev->next = n;
|
||||
n->prev = l->prev;
|
||||
|
||||
l->prev = n;
|
||||
n->next = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief remove node from list.
|
||||
* @param n: the node to remove from the list.
|
||||
*/
|
||||
static inline void HAL_LIST_Remove(HAL_LIST *n)
|
||||
{
|
||||
n->next->prev = n->prev;
|
||||
n->prev->next = n->next;
|
||||
|
||||
n->next = n->prev = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief tests whether a list is empty
|
||||
* @param l: the list to test.
|
||||
*/
|
||||
static inline int HAL_LIST_IsEmpty(const HAL_LIST *l)
|
||||
{
|
||||
return l->next == l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the list length
|
||||
* @param l: the list to get.
|
||||
*/
|
||||
static inline uint32_t HAL_LIST_Len(const HAL_LIST *l)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
const HAL_LIST *p = l;
|
||||
|
||||
while (p->next != l) {
|
||||
p = p->next;
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the struct for this entry
|
||||
* @param node: the entry point
|
||||
* @param type: the type of structure
|
||||
* @param member: the name of list in structure
|
||||
*/
|
||||
#define HAL_LIST_ENTRY(node, type, member) \
|
||||
HAL_CONTAINER_OF(node, type, member)
|
||||
|
||||
/**
|
||||
* @brief iterate over a list
|
||||
* @param pos: the rt_list_t * to use as a loop cursor.
|
||||
* @param head: the head for your list.
|
||||
*/
|
||||
#define HAL_LIST_FOR_EACH(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* @brief iterate over a list safe against removal of list entry
|
||||
* @param pos: the rt_list_t * to use as a loop cursor.
|
||||
* @param n: another rt_list_t * to use as temporary storage
|
||||
* @param head: the head for your list.
|
||||
*/
|
||||
#define HAL_LIST_FOR_EACH_SAFE(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* @brief iterate over list of given type
|
||||
* @param pos: the type * to use as a loop cursor.
|
||||
* @param head: the head for your list.
|
||||
* @param member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define HAL_LIST_FOR_EACH_ENTRY(pos, head, member) \
|
||||
for (pos = HAL_LIST_ENTRY((head)->next, __typeof__(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = HAL_LIST_ENTRY(pos->member.next, __typeof__(*pos), member))
|
||||
|
||||
/**
|
||||
* @brief iterate over list of given type safe against removal of list entry
|
||||
* @param pos: the type * to use as a loop cursor.
|
||||
* @param n: another type * to use as temporary storage
|
||||
* @param head: the head for your list.
|
||||
* @param member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define HAL_LIST_FOR_EACH_ENTRY_SAFE(pos, n, head, member) \
|
||||
for (pos = HAL_LIST_ENTRY((head)->next, __typeof__(*pos), member), \
|
||||
n = HAL_LIST_ENTRY(pos->member.next, __typeof__(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = HAL_LIST_ENTRY(n->member.next, __typeof__(*n), member))
|
||||
|
||||
/**
|
||||
* @brief get the first element from a list
|
||||
* @param ptr: the list head to take the element from.
|
||||
* @param type: the type of the struct this is embedded in.
|
||||
* @param member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define HAL_LIST_FIRST_ENTRY(ptr, type, member) \
|
||||
HAL_LIST_ENTRY((ptr)->next, type, member)
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,200 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_conf.h"
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup PM
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HAL_PM_H_
|
||||
#define _HAL_PM_H_
|
||||
|
||||
#include "hal_def.h"
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
/** @defgroup DEMO_Exported_Definition_Group1 Basic Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define PM_RUNTIME_TYPE_MUTI_SFT (3)
|
||||
#define PM_RUNTIME_PER_TYPE_NUM (8)
|
||||
|
||||
#define PM_RUNTIME_TYPE_TO_FIRST_ID(type) ((type) << PM_RUNTIME_TYPE_MUTI_SFT)
|
||||
#define PM_RUNTIME_ID_TO_TYPE(id) ((id) >> PM_RUNTIME_TYPE_MUTI_SFT)
|
||||
#define PM_RUNTIME_ID_TO_TYPE_OFFSET(id) ((id) % PM_RUNTIME_PER_TYPE_NUM)
|
||||
#define PM_RUNTIME_ID_TYPE_BIT_MSK(id) HAL_BIT(((id) % PM_RUNTIME_PER_TYPE_NUM))
|
||||
|
||||
#define PM_DISPLAY_REQUESTED(pdata) ((pdata)->bits[PM_RUNTIME_TYPE_DISPLAY])
|
||||
#define PM_UART_REQUESTED(pdata) ((pdata)->bits[PM_RUNTIME_TYPE_UART])
|
||||
#define PM_I2C_REQUESTED(pdata) ((pdata)->bits[PM_RUNTIME_TYPE_I2C])
|
||||
#define PM_INTF_REQUESTED(pdata) ((pdata)->bits[PM_RUNTIME_TYPE_INTF])
|
||||
#define PM_HS_INTF_REQUESTED(pdata) ((pdata)->bits[PM_RUNTIME_TYPE_HS_INTF])
|
||||
#define PM_SPI_REQUESTED(pdata) ((pdata)->bits[PM_RUNTIME_TYPE_SPI])
|
||||
#define PM_CIF_REQUESTED(pdata) ((pdata)->bits[PM_RUNTIME_TYPE_CIF])
|
||||
|
||||
/* suspend config id */
|
||||
#define PM_SLEEP_MODE_CONFIG 0x01
|
||||
#define PM_SLEEP_WAKEUP_SOURCE 0x02
|
||||
|
||||
enum {
|
||||
PM_RUNTIME_TYPE_INTF = 0, /**< normal interface */
|
||||
PM_RUNTIME_TYPE_DISPLAY,
|
||||
PM_RUNTIME_TYPE_AUDIO,
|
||||
PM_RUNTIME_TYPE_HS_INTF, /**< high speed interface */
|
||||
PM_RUNTIME_TYPE_STORAGE,
|
||||
PM_RUNTIME_TYPE_UART,
|
||||
PM_RUNTIME_TYPE_I2C,
|
||||
PM_RUNTIME_TYPE_SPI,
|
||||
PM_RUNTIME_TYPE_CIF,
|
||||
PM_RUNTIME_TYPE_DEVICE,
|
||||
PM_RUNTIME_TYPE_END,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PM_RUNTIME_IDLE_ONLY = 0,
|
||||
PM_RUNTIME_IDLE_NORMAL,
|
||||
PM_RUNTIME_IDLE_DEEP,
|
||||
PM_RUNTIME_IDLE_DEEP1,
|
||||
PM_RUNTIME_IDLE_DEEP2,
|
||||
} ePM_RUNTIME_idleMode;
|
||||
|
||||
typedef enum {
|
||||
PM_RUNTIME_ID_INTF_INVLD = PM_RUNTIME_TYPE_TO_FIRST_ID(PM_RUNTIME_TYPE_INTF), /**< the id = 0, is means invalid */
|
||||
PM_RUNTIME_ID_SPI_APB,
|
||||
PM_RUNTIME_ID_VOP = PM_RUNTIME_TYPE_TO_FIRST_ID(PM_RUNTIME_TYPE_DISPLAY),
|
||||
PM_RUNTIME_ID_MIPI,
|
||||
|
||||
PM_RUNTIME_ID_I2S = PM_RUNTIME_TYPE_TO_FIRST_ID(PM_RUNTIME_TYPE_AUDIO),
|
||||
PM_RUNTIME_ID_I2S1,
|
||||
PM_RUNTIME_ID_I2S2,
|
||||
PM_RUNTIME_ID_ADC,
|
||||
PM_RUNTIME_ID_DMA,
|
||||
|
||||
PM_RUNTIME_ID_USB = PM_RUNTIME_TYPE_TO_FIRST_ID(PM_RUNTIME_TYPE_HS_INTF),
|
||||
PM_RUNTIME_ID_SDIO,
|
||||
|
||||
PM_RUNTIME_ID_UART0 = PM_RUNTIME_TYPE_TO_FIRST_ID(PM_RUNTIME_TYPE_UART),
|
||||
PM_RUNTIME_ID_UART1,
|
||||
PM_RUNTIME_ID_UART2,
|
||||
PM_RUNTIME_ID_UART3,
|
||||
PM_RUNTIME_ID_UART4,
|
||||
PM_RUNTIME_ID_UART5,
|
||||
PM_RUNTIME_ID_UART6,
|
||||
PM_RUNTIME_ID_UART7,
|
||||
PM_RUNTIME_ID_UART8,
|
||||
PM_RUNTIME_ID_UART9,
|
||||
|
||||
PM_RUNTIME_ID_I2C0 = PM_RUNTIME_TYPE_TO_FIRST_ID(PM_RUNTIME_TYPE_I2C),
|
||||
PM_RUNTIME_ID_I2C1,
|
||||
PM_RUNTIME_ID_I2C2,
|
||||
PM_RUNTIME_ID_I2C3,
|
||||
PM_RUNTIME_ID_I2C4,
|
||||
PM_RUNTIME_ID_I2C5,
|
||||
|
||||
PM_RUNTIME_ID_SPI = PM_RUNTIME_TYPE_TO_FIRST_ID(PM_RUNTIME_TYPE_SPI),
|
||||
PM_RUNTIME_ID_CIF = PM_RUNTIME_TYPE_TO_FIRST_ID(PM_RUNTIME_TYPE_CIF),
|
||||
|
||||
PM_RUNTIME_ID_END,
|
||||
} ePM_RUNTIME_ID;
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
struct PM_RUNTIME_INFO {
|
||||
uint8_t bits[PM_RUNTIME_TYPE_END];
|
||||
};
|
||||
|
||||
#ifdef HAL_PM_SLEEP_MODULE_ENABLED
|
||||
struct PM_SUSPEND_INFO {
|
||||
union {
|
||||
struct {
|
||||
uint32_t uartChannel : 4; /*!< bit: 0.. 3 uart debug channel num */
|
||||
uint32_t uartValid : 1; /*!< bit: 4 uart channel valid flag */
|
||||
uint32_t _reserved : 27; /*!< bit: 5..31 Reserved */
|
||||
} flag;
|
||||
uint32_t suspendFlag;
|
||||
};
|
||||
};
|
||||
|
||||
struct SLEEP_CONFIG_DATA {
|
||||
uint32_t suspendMode;
|
||||
uint32_t suspendWkupSrc;
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/***************************** Function Declare ******************************/
|
||||
/** @defgroup PM_Public_Function_Declare Public Function Declare
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_PM_SLEEP_MODULE_ENABLED
|
||||
/**
|
||||
* @brief it is the enterpoint for suspend invoked by a os's powermanager implement.
|
||||
* @param suspendInfo: suspend information for controlling
|
||||
* @return HAL_Status
|
||||
*/
|
||||
int HAL_SYS_Suspend(struct PM_SUSPEND_INFO *suspendInfo);
|
||||
struct SLEEP_CONFIG_DATA *HAL_SYS_GetSuspendConfig(void);
|
||||
HAL_Status HAL_SYS_SuspendConfig(uint32_t id, uint32_t data);
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PM_CPU_SLEEP_MODULE_ENABLED
|
||||
void HAL_CPU_ArchSuspend(uint32_t *ptr);
|
||||
void HAL_CPU_ArchResume(void);
|
||||
void HAL_CPU_DoResume(void);
|
||||
|
||||
void HAL_NVIC_SuspendSave(void);
|
||||
void HAL_NVIC_ResumeRestore(void);
|
||||
|
||||
void HAL_SCB_SuspendSave(void);
|
||||
void HAL_SCB_ResumeRestore(void);
|
||||
|
||||
int HAL_CPU_SuspendEnter(uint32_t flag, int (*suspend)(uint32_t));
|
||||
void HAL_CPU_SuspendSave(uint32_t *ptr, uint32_t ptrsz, uint32_t sp, uint32_t *ptrSave);
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PM_RUNTIME_MODULE_ENABLED
|
||||
HAL_Status HAL_PM_RuntimeRequest(ePM_RUNTIME_ID runtimeId);
|
||||
HAL_Status HAL_PM_RuntimeRelease(ePM_RUNTIME_ID runtimeId);
|
||||
const struct PM_RUNTIME_INFO *HAL_PM_RuntimeGetData(void);
|
||||
|
||||
/**
|
||||
* @brief it is for runtime power manager.
|
||||
* @param idleMode: the soc pm mode will be config
|
||||
* @return the mask bits indicate request source.
|
||||
*/
|
||||
uint32_t HAL_PM_RuntimeEnter(ePM_RUNTIME_idleMode idleMode);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief it is for statting a pm timer .
|
||||
* @param timeoutCount: the next timeout count
|
||||
* @param needTimeout: if ture, need to start a timer.
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_PM_TimerStart(uint64_t timeoutCount, bool needTimeout);
|
||||
|
||||
/**
|
||||
* @brief it is for stopping a pm timer .
|
||||
* @return HAL_Status.
|
||||
*/
|
||||
HAL_Status HAL_PM_TimerStop(void);
|
||||
|
||||
/**
|
||||
* @brief it is for getting the sleep time.
|
||||
* @return the sleep time.
|
||||
*/
|
||||
uint64_t HAL_PM_GetTimerCount(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,64 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "hal_conf.h"
|
||||
|
||||
#ifdef HAL_TIMER_MODULE_ENABLED
|
||||
|
||||
/** @addtogroup RK_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup TIMER
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HAL_TIMER_H_
|
||||
#define _HAL_TIMER_H_
|
||||
|
||||
#include "hal_def.h"
|
||||
|
||||
/***************************** MACRO Definition ******************************/
|
||||
|
||||
/** @defgroup TIMER_Exported_Definition_Group1 Basic Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
TIMER_FREE_RUNNING = 0,
|
||||
TIMER_USER_DEFINED,
|
||||
TIMER_MODE_MAX
|
||||
} eTIMER_MODE;
|
||||
|
||||
/***************************** Structure Definition **************************/
|
||||
|
||||
/** @} */
|
||||
/***************************** Function Declare ******************************/
|
||||
/** @defgroup TIMER_Public_Function_Declare Public Function Declare
|
||||
* @{
|
||||
*/
|
||||
|
||||
HAL_Status HAL_TIMER_Stop(struct TIMER_REG *pReg);
|
||||
HAL_Status HAL_TIMER_Start(struct TIMER_REG *pReg);
|
||||
HAL_Status HAL_TIMER_Stop_IT(struct TIMER_REG *pReg);
|
||||
HAL_Status HAL_TIMER_Start_IT(struct TIMER_REG *pReg);
|
||||
HAL_Status HAL_TIMER_SetCount(struct TIMER_REG *pReg, uint64_t usTick);
|
||||
uint64_t HAL_TIMER_GetCount(struct TIMER_REG *pReg);
|
||||
HAL_Status HAL_TIMER0_Handler(void);
|
||||
HAL_Status HAL_TIMER1_Handler(void);
|
||||
HAL_Status HAL_TIMER_Init(struct TIMER_REG *pReg, eTIMER_MODE mode);
|
||||
HAL_Status HAL_TIMER_SysTimerInit(struct TIMER_REG *pReg);
|
||||
HAL_Status HAL_TIMER_DeInit(struct TIMER_REG *pReg);
|
||||
HAL_Status HAL_TIMER_ClrInt(struct TIMER_REG *pReg);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* HAL_TIMER_MODULE_ENABLED */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,449 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_H
|
||||
#define __SOC_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hal_conf.h"
|
||||
|
||||
/* IO definitions (access restrictions to peripheral registers) */
|
||||
#ifdef __cplusplus
|
||||
#define __I volatile /*!< brief Defines 'read only' permissions */
|
||||
#else
|
||||
#define __I volatile const /*!< brief Defines 'read only' permissions */
|
||||
#endif
|
||||
#define __O volatile /*!< brief Defines 'write only' permissions */
|
||||
#define __IO volatile /*!< brief Defines 'read / write' permissions */
|
||||
|
||||
/* ================================================================================ */
|
||||
/* ================ DMA REQ =============== */
|
||||
/* ================================================================================ */
|
||||
typedef enum {
|
||||
DMA_REQ_UART0_TX = 0,
|
||||
DMA_REQ_UART0_RX = 1,
|
||||
DMA_REQ_UART1_TX = 2,
|
||||
DMA_REQ_UART1_RX = 3,
|
||||
DMA_REQ_UART2_TX = 4,
|
||||
DMA_REQ_UART2_RX = 5,
|
||||
DMA_REQ_UART3_TX = 6,
|
||||
DMA_REQ_UART3_RX = 7,
|
||||
DMA_REQ_UART4_TX = 8,
|
||||
DMA_REQ_UART4_RX = 9,
|
||||
DMA_REQ_UART5_TX = 10,
|
||||
DMA_REQ_UART5_RX = 11,
|
||||
DMA_REQ_UART6_TX = 12,
|
||||
DMA_REQ_UART6_RX = 13,
|
||||
DMA_REQ_UART7_TX = 14,
|
||||
DMA_REQ_UART7_RX = 15,
|
||||
DMA_REQ_UART8_TX = 16,
|
||||
DMA_REQ_UART8_RX = 17,
|
||||
DMA_REQ_UART9_TX = 18,
|
||||
DMA_REQ_UART9_RX = 19,
|
||||
DMA_REQ_SPI0_TX = 20,
|
||||
DMA_REQ_SPI0_RX = 21,
|
||||
DMA_REQ_SPI1_TX = 22,
|
||||
DMA_REQ_SPI1_RX = 23,
|
||||
DMA_REQ_SPI2_TX = 24,
|
||||
DMA_REQ_SPI2_RX = 25,
|
||||
DMA_REQ_SPI3_TX = 26,
|
||||
DMA_REQ_SPI3_RX = 27,
|
||||
} DMA_REQ_Type;
|
||||
|
||||
/* ================================================================================ */
|
||||
/* ================ IRQ ================ */
|
||||
/* ================================================================================ */
|
||||
#ifdef HAL_MCU_CORE
|
||||
#define INTMUX_IRQ_START_NUM 32
|
||||
#define INTMUX_OUT_IRQ_START_NUM 0
|
||||
#define INTMUX_NUM_INT_PER_OUT 64
|
||||
#define INTMUX_NUM_GROUP_PER_CON 8
|
||||
#define INTMUX_NUM_GROUP_PER_OUT 8
|
||||
#define INTMUX_NUM_INT_PER_GROUP 8
|
||||
#define NUM_EXT_INTERRUPTS 320
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/****** Platform Exceptions Numbers ***************************************************/
|
||||
NUM_INTERRUPTS = 0,
|
||||
DMAC0_ABORT_IRQn = 45, /*!< DMAC0 Abort Interrupt */
|
||||
DMAC0_IRQn = 46, /*!< DMAC0 Interrupt */
|
||||
DMAC1_ABORT_IRQn = 47, /*!< DMAC1 Abort Interrupt */
|
||||
DMAC1_IRQn = 48, /*!< DMAC1 Interrupt */
|
||||
GPIO0_IRQn = 65, /*!< GPIO0 Interrupt */
|
||||
GPIO1_IRQn = 66, /*!< GPIO1 Interrupt */
|
||||
GPIO2_IRQn = 67, /*!< GPIO2 Interrupt */
|
||||
GPIO3_IRQn = 68, /*!< GPIO3 Interrupt */
|
||||
GPIO4_IRQn = 69, /*!< GPIO4 Interrupt */
|
||||
I2C0_IRQn = 78, /*!< I2C0 Interrupt */
|
||||
I2C1_IRQn = 79, /*!< I2C1 Interrupt */
|
||||
I2C2_IRQn = 80, /*!< I2C2 Interrupt */
|
||||
I2C3_IRQn = 81, /*!< I2C3 Interrupt */
|
||||
I2C4_IRQn = 82, /*!< I2C4 Interrupt */
|
||||
I2C5_IRQn = 83, /*!< I2C5 Interrupt */
|
||||
PWM_PMU_IRQn = 114, /*!< PWM_PMU Interrupt */
|
||||
PWM1_IRQn = 115, /*!< PWM1 Interrupt */
|
||||
PWM2_IRQn = 116, /*!< PWM2 Interrupt */
|
||||
PWM3_IRQn = 117, /*!< PWM3 Interrupt */
|
||||
PWM_PMU_PWR_IRQn = 118, /*!< PWM_PMU PWR Interrupt */
|
||||
PWM1_PWR_IRQn = 119, /*!< PWM1 PWR Interrupt */
|
||||
PWM2_PWR_IRQn = 120, /*!< PWM2 PWR Interrupt */
|
||||
PWM3_PWR_IRQn = 121, /*!< PWM3 PWR Interrupt */
|
||||
SARADC_IRQn = 125, /*!< SARADC Interrupt */
|
||||
FSPI0_IRQn = 133, /*!< FSPI Interrupt */
|
||||
SPI0_IRQn = 135, /*!< SPI0 Interrupt */
|
||||
SPI1_IRQn = 136, /*!< SPI1 Interrupt */
|
||||
SPI2_IRQn = 137, /*!< SPI2 Interrupt */
|
||||
SPI3_IRQn = 138, /*!< SPI3 Interrupt */
|
||||
TIMER0_IRQn = 141, /*!< TIMER0 Interrupt */
|
||||
TIMER1_IRQn = 142, /*!< TIMER1 Interrupt */
|
||||
TIMER2_IRQn = 143, /*!< TIMER2 Interrupt */
|
||||
TIMER3_IRQn = 144, /*!< TIMER3 Interrupt */
|
||||
TIMER4_IRQn = 145, /*!< TIMER4 Interrupt */
|
||||
TIMER5_IRQn = 146, /*!< TIMER5 Interrupt */
|
||||
UART0_IRQn = 148, /*!< UART0 Interrupt */
|
||||
UART1_IRQn = 149, /*!< UART1 Interrupt */
|
||||
UART2_IRQn = 150, /*!< UART2 Interrupt */
|
||||
UART3_IRQn = 151, /*!< UART3 Interrupt */
|
||||
UART4_IRQn = 152, /*!< UART4 Interrupt */
|
||||
UART5_IRQn = 153, /*!< UART5 Interrupt */
|
||||
UART6_IRQn = 154, /*!< UART6 Interrupt */
|
||||
UART7_IRQn = 155, /*!< UART7 Interrupt */
|
||||
UART8_IRQn = 156, /*!< UART8 Interrupt */
|
||||
UART9_IRQn = 157, /*!< UART9 Interrupt */
|
||||
WDT0_IRQn = 181, /*!< WDT0 Interrupt */
|
||||
MBOX0_CH0_B2A_IRQn = 215, /*!< MBOX0 CH0 B2A Interrupt */
|
||||
MBOX0_CH1_B2A_IRQn = 216, /*!< MBOX0 CH1 B2A Interrupt */
|
||||
MBOX0_CH2_B2A_IRQn = 217, /*!< MBOX0 CH2 B2A Interrupt */
|
||||
MBOX0_CH3_B2A_IRQn = 218, /*!< MBOX0 CH3 B2A Interrupt */
|
||||
MBOX0_CH0_A2B_IRQn = 219, /*!< MBOX0 CH0 A2B Interrupt */
|
||||
MBOX0_CH1_A2B_IRQn = 220, /*!< MBOX0 CH1 A2B Interrupt */
|
||||
MBOX0_CH2_A2B_IRQn = 221, /*!< MBOX0 CH2 A2B Interrupt */
|
||||
MBOX0_CH3_A2B_IRQn = 222, /*!< MBOX0 CH3 A2B Interrupt */
|
||||
TOTAL_INTERRUPTS = (INTMUX_IRQ_START_NUM + NUM_INTERRUPTS + NUM_EXT_INTERRUPTS),
|
||||
} IRQn_Type;
|
||||
#else
|
||||
typedef enum
|
||||
{
|
||||
/* When IPI_SGIs are used in AMP mode, you need to pay attention to whether it conflicts
|
||||
* with SMP mode. Especially in the case of Linux OS as The Master Core.
|
||||
* IPI_SGI 0~7 for non-secure and IPI_SGI 8~15 for secure.
|
||||
*/
|
||||
IPI_SGI0 = 0,
|
||||
IPI_SGI1 = 1,
|
||||
IPI_SGI2 = 2,
|
||||
IPI_SGI3 = 3,
|
||||
IPI_SGI4 = 4,
|
||||
IPI_SGI5 = 5,
|
||||
IPI_SGI6 = 6,
|
||||
IPI_SGI7 = 7,
|
||||
IPI_SGI8 = 8,
|
||||
IPI_SGI9 = 9,
|
||||
IPI_SGI10 = 10,
|
||||
IPI_SGI11 = 11,
|
||||
IPI_SGI12 = 12,
|
||||
IPI_SGI13 = 13,
|
||||
IPI_SGI14 = 14,
|
||||
IPI_SGI15 = 15,
|
||||
|
||||
CNTHP_IRQn = 26,
|
||||
CNTV_IRQn = 27,
|
||||
CNTPS_IRQn = 29,
|
||||
CNTPNS_IRQn = 30,
|
||||
|
||||
/****** Platform Exceptions Numbers ***************************************************/
|
||||
CAN0_IRQn = 33, /*!< CAN0 Interrupt */
|
||||
CAN1_IRQn = 34, /*!< CAN1 Interrupt */
|
||||
CAN2_IRQn = 35, /*!< CAN2 Interrupt */
|
||||
DMAC0_ABORT_IRQn = 45, /*!< DMAC0 Abort Interrupt */
|
||||
DMAC0_IRQn = 46, /*!< DMAC0 Interrupt */
|
||||
DMAC1_ABORT_IRQn = 47, /*!< DMAC1 Abort Interrupt */
|
||||
DMAC1_IRQn = 48, /*!< DMAC1 Interrupt */
|
||||
GMAC0_IRQn = 59, /*!< GMAC0 Interrupt */
|
||||
GMAC1_IRQn = 64, /*!< GMAC1 Interrupt */
|
||||
GPIO0_IRQn = 65, /*!< GPIO0 Interrupt */
|
||||
GPIO1_IRQn = 66, /*!< GPIO1 Interrupt */
|
||||
GPIO2_IRQn = 67, /*!< GPIO2 Interrupt */
|
||||
GPIO3_IRQn = 68, /*!< GPIO3 Interrupt */
|
||||
GPIO4_IRQn = 69, /*!< GPIO4 Interrupt */
|
||||
I2C0_IRQn = 78, /*!< I2C0 Interrupt */
|
||||
I2C1_IRQn = 79, /*!< I2C1 Interrupt */
|
||||
I2C2_IRQn = 80, /*!< I2C2 Interrupt */
|
||||
I2C3_IRQn = 81, /*!< I2C3 Interrupt */
|
||||
I2C4_IRQn = 82, /*!< I2C4 Interrupt */
|
||||
I2C5_IRQn = 83, /*!< I2C5 Interrupt */
|
||||
PWM_PMU_IRQn = 114, /*!< PWM_PMU Interrupt */
|
||||
PWM1_IRQn = 115, /*!< PWM1 Interrupt */
|
||||
PWM2_IRQn = 116, /*!< PWM2 Interrupt */
|
||||
PWM3_IRQn = 117, /*!< PWM3 Interrupt */
|
||||
PWM_PMU_PWR_IRQn = 118, /*!< PWM_PMU PWR Interrupt */
|
||||
PWM1_PWR_IRQn = 119, /*!< PWM1 PWR Interrupt */
|
||||
PWM2_PWR_IRQn = 120, /*!< PWM2 PWR Interrupt */
|
||||
PWM3_PWR_IRQn = 121, /*!< PWM3 PWR Interrupt */
|
||||
SARADC_IRQn = 125, /*!< SARADC Interrupt */
|
||||
FSPI0_IRQn = 133, /*!< FSPI Interrupt */
|
||||
SPI0_IRQn = 135, /*!< SPI0 Interrupt */
|
||||
SPI1_IRQn = 136, /*!< SPI1 Interrupt */
|
||||
SPI2_IRQn = 137, /*!< SPI2 Interrupt */
|
||||
SPI3_IRQn = 138, /*!< SPI3 Interrupt */
|
||||
TIMER0_IRQn = 141, /*!< TIMER0 Interrupt */
|
||||
TIMER1_IRQn = 142, /*!< TIMER1 Interrupt */
|
||||
TIMER2_IRQn = 143, /*!< TIMER2 Interrupt */
|
||||
TIMER3_IRQn = 144, /*!< TIMER3 Interrupt */
|
||||
TIMER4_IRQn = 145, /*!< TIMER4 Interrupt */
|
||||
TIMER5_IRQn = 146, /*!< TIMER5 Interrupt */
|
||||
UART0_IRQn = 148, /*!< UART0 Interrupt */
|
||||
UART1_IRQn = 149, /*!< UART1 Interrupt */
|
||||
UART2_IRQn = 150, /*!< UART2 Interrupt */
|
||||
UART3_IRQn = 151, /*!< UART3 Interrupt */
|
||||
UART4_IRQn = 152, /*!< UART4 Interrupt */
|
||||
UART5_IRQn = 153, /*!< UART5 Interrupt */
|
||||
UART6_IRQn = 154, /*!< UART6 Interrupt */
|
||||
UART7_IRQn = 155, /*!< UART7 Interrupt */
|
||||
UART8_IRQn = 156, /*!< UART8 Interrupt */
|
||||
UART9_IRQn = 157, /*!< UART9 Interrupt */
|
||||
WDT0_IRQn = 181, /*!< WDT0 Interrupt */
|
||||
PCIE30x2_LEGACY_IRQn = 194, /*!< PCIe3x2_legacy Interrupt */
|
||||
DDR_ECC_CE_IRQn = 205, /*!< DDR ECC correctable fault Interrupt */
|
||||
DDR_ECC_UE_IRQn = 207, /*!< DDR ECC uncorrectable fault Interrupt */
|
||||
MBOX0_CH0_B2A_IRQn = 215, /*!< MBOX0 CH0 B2A Interrupt */
|
||||
MBOX0_CH1_B2A_IRQn = 216, /*!< MBOX0 CH1 B2A Interrupt */
|
||||
MBOX0_CH2_B2A_IRQn = 217, /*!< MBOX0 CH2 B2A Interrupt */
|
||||
MBOX0_CH3_B2A_IRQn = 218, /*!< MBOX0 CH3 B2A Interrupt */
|
||||
MBOX0_CH0_A2B_IRQn = 219, /*!< MBOX0 CH0 A2B Interrupt */
|
||||
MBOX0_CH1_A2B_IRQn = 220, /*!< MBOX0 CH1 A2B Interrupt */
|
||||
MBOX0_CH2_A2B_IRQn = 221, /*!< MBOX0 CH2 A2B Interrupt */
|
||||
MBOX0_CH3_A2B_IRQn = 222, /*!< MBOX0 CH3 A2B Interrupt */
|
||||
NFAULT0_IRQn = 272, /*!< DSU L3 CACHE ECC FAULT Interrupt */
|
||||
NFAULT1_IRQn = 273, /*!< CPU0 L1-L2 CACHE ECC FAULT Interrupt */
|
||||
NFAULT2_IRQn = 274, /*!< CPU1 L1-L2 CACHE ECC FAULT Interrupt */
|
||||
NFAULT3_IRQn = 275, /*!< CPU2 L1-L2 CACHE ECC FAULT Interrupt */
|
||||
NFAULT4_IRQn = 276, /*!< CPU3 L1-L2 CACHE ECC FAULT Interrupt */
|
||||
NERR0_IRQn = 277, /*!< DSU L3 CACHE ECC ERROR Interrupt */
|
||||
NERR1_IRQn = 278, /*!< CPU0 L1-L2 CACHE ECC ERROR Interrupt */
|
||||
NERR2_IRQn = 279, /*!< CPU1 L1-L2 CACHE ECC ERROR Interrupt */
|
||||
NERR3_IRQn = 280, /*!< CPU2 L1-L2 CACHE ECC ERROR Interrupt */
|
||||
NERR4_IRQn = 281, /*!< CPU3 L1-L2 CACHE ECC ERROR Interrupt */
|
||||
RSVD0_IRQn = 283, /*!< RSVD0 Interrupt */
|
||||
RPMSG_01_IRQn = 285, /*!< RPMSG 0->1 Interrupt */
|
||||
RPMSG_02_IRQn = 286, /*!< RPMSG 0->2 Interrupt */
|
||||
RPMSG_03_IRQn = 287, /*!< RPMSG 0->3 Interrupt */
|
||||
RPMSG_10_IRQn = 288, /*!< RPMSG 1->0 Interrupt */
|
||||
RPMSG_12_IRQn = 289, /*!< RPMSG 1->2 Interrupt */
|
||||
RPMSG_13_IRQn = 290, /*!< RPMSG 1->3 Interrupt */
|
||||
RPMSG_20_IRQn = 291, /*!< RPMSG 2->0 Interrupt */
|
||||
RPMSG_21_IRQn = 292, /*!< RPMSG 2->1 Interrupt */
|
||||
RPMSG_23_IRQn = 293, /*!< RPMSG 2->3 Interrupt */
|
||||
RPMSG_30_IRQn = 294, /*!< RPMSG 3->0 Interrupt */
|
||||
RPMSG_31_IRQn = 295, /*!< RPMSG 3->1 Interrupt */
|
||||
RPMSG_32_IRQn = 296, /*!< RPMSG 3->2 Interrupt */
|
||||
NUM_INTERRUPTS = 352,
|
||||
} IRQn_Type;
|
||||
#endif
|
||||
|
||||
#define RSVD_IRQn(_N) (RSVD0_IRQn + (_N))
|
||||
|
||||
#define AMP_CPUOFF_REQ_IRQ(cpu) RSVD_IRQn(11 + (cpu)) /* gic irq: 294 */
|
||||
#define GIC_TOUCH_REQ_IRQ(cpu) (AMP_CPUOFF_REQ_IRQ(4) + cpu) /* gic irq: 298 */
|
||||
|
||||
#define GPIO_IRQ_GROUP_DIRQ_BASE RSVD_IRQn(37) /* gic irq: 320 */
|
||||
#define GPIO_IRQ_GROUP_DIRQ_NUM (NUM_INTERRUPTS - GPIO_IRQ_GROUP_DIRQ_BASE)
|
||||
|
||||
#define GPIO_IRQ_GROUP_GPIO0_HWIRQ GPIO0_IRQn
|
||||
#define GPIO_IRQ_GROUP_GPION_HWIRQ GPIO4_IRQn
|
||||
|
||||
/* ================================================================================ */
|
||||
/* ================ Processor and Core Peripheral Section ================ */
|
||||
/* ================================================================================ */
|
||||
|
||||
#if defined(HAL_AP_CORE) && defined(HAL_MCU_CORE)
|
||||
#error "HAL_AP_CORE and HAL_MCU_CORE only one of them can be enabled"
|
||||
#endif
|
||||
|
||||
#if !defined(HAL_AP_CORE) && !defined(HAL_MCU_CORE)
|
||||
#error "Please define HAL_AP_CORE or HAL_MCU_CORE on hal_conf.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_AP_CORE
|
||||
#define __CORTEX_A 55U /* Cortex-A55 Core */
|
||||
#define __FPU_PRESENT 1U /* FPU present */
|
||||
#define __TIM_PRESENT 1U /* Generic Timer */
|
||||
|
||||
#define CACHE_LINE_SHIFT (6U)
|
||||
#define CACHE_LINE_SIZE (0x1U << CACHE_LINE_SHIFT)
|
||||
|
||||
#else
|
||||
#define __RISC_V
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
// #include "cmsis_compiler.h" /* CMSIS compiler specific defines */
|
||||
// #ifdef __CORTEX_A
|
||||
// #include "core_ca.h"
|
||||
// #endif
|
||||
#include "system_rk3568.h"
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#include "rk3568.h"
|
||||
|
||||
/****************************************************************************************/
|
||||
/* */
|
||||
/* Module Address Section */
|
||||
/* */
|
||||
/****************************************************************************************/
|
||||
/* Memory Base */
|
||||
#define PCIE3X2_DBI_BASE 0xF6000000 /* PCIe dbi base address */
|
||||
#define GIC_DISTRIBUTOR_BASE 0xFD400000 /* GICD base address */
|
||||
#define GIC_REDISTRIBUTOR_BASE 0xFD460000 /* GICR base address */
|
||||
#define PCIE3PHY_GRF_BASE 0xFDCB8000 /* S-PHY_GRF base address */
|
||||
#define PCIE3X2_APB_BASE 0xFE280000 /* PCIe apb base address */
|
||||
|
||||
/****************************************************************************************/
|
||||
/* */
|
||||
/* Register Bitmap Section */
|
||||
/* */
|
||||
/****************************************************************************************/
|
||||
/********************************** CPU Topology ****************************************/
|
||||
#define MPIDR_MT_MASK ((1U) << 24)
|
||||
#define MPIDR_AFFLVL_MASK (0xFFU)
|
||||
#define MPIDR_AFF0_SHIFT (0U)
|
||||
#define MPIDR_AFF1_SHIFT (8U)
|
||||
#define MPIDR_AFF2_SHIFT (16U)
|
||||
#define MPIDR_AFF3_SHIFT (32U)
|
||||
#define MPIDR_AFFINITY_MASK (0xFFFFFFU)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT (4)
|
||||
#define PLATFORM_CLUSTER1_CORE_COUNT (0)
|
||||
#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
|
||||
#define CPU_GET_AFFINITY(cpuId, clusterId) ((cpuId) << MPIDR_AFF1_SHIFT)
|
||||
|
||||
/********************************** CACHE ECC ****************************************/
|
||||
#ifndef __ASSEMBLY__
|
||||
/** @addtogroup CACHE_ECC_Exported_Definition_Group1
|
||||
* @{
|
||||
*/
|
||||
/** the fault value will be injected */
|
||||
typedef enum {
|
||||
CACHE_ECC_INJECT_UC = 0x80000002, /**< Uncontainable Error generation */
|
||||
CACHE_ECC_INJECT_DE_UER = 0x8000000a, /**< for l1~l2, generate a exception */
|
||||
} eCACHE_ECC_InjectFault;
|
||||
/** @} */
|
||||
#endif
|
||||
/******************************************CRU*******************************************/
|
||||
#define PLL_INPUT_OSC_RATE (24 * 1000 * 1000)
|
||||
|
||||
#define CRU_SRST_CON_CNT 29
|
||||
#define CRU_GATE_CON_CNT 35
|
||||
#define CRU_CLK_DIV_CON_CNT 84
|
||||
#define CRU_CLK_SEL_CON_CNT 84
|
||||
|
||||
#define CLK(mux, div) \
|
||||
(((mux) & 0x0F0F00FFU) | (((div) & 0xFFU) << 8) | (((div) & 0x0F0F0000U) << 4))
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
typedef enum CLOCK_Name {
|
||||
CLK_INVALID = 0U,
|
||||
PLL_APLL,
|
||||
PLL_CPLL,
|
||||
PLL_GPLL,
|
||||
PLL_NPLL,
|
||||
PLL_VPLL,
|
||||
PLL_PPLL,
|
||||
PLL_HPLL,
|
||||
CLK_WDT,
|
||||
CLK_UART0,
|
||||
CLK_I2C = CLK(CLK_I2C_SEL, 0U),
|
||||
CLK_PWM1 = CLK(CLK_PWM1_SEL, 0U),
|
||||
CLK_PWM2 = CLK(CLK_PWM2_SEL, 0U),
|
||||
CLK_PWM3 = CLK(CLK_PWM3_SEL, 0U),
|
||||
CLK_SPI0 = CLK(CLK_SPI0_SEL, 0U),
|
||||
CLK_SPI1 = CLK(CLK_SPI1_SEL, 0U),
|
||||
CLK_SPI2 = CLK(CLK_SPI2_SEL, 0U),
|
||||
CLK_SPI3 = CLK(CLK_SPI3_SEL, 0U),
|
||||
CLK_UART1_SRC = CLK(CLK_UART1_SRC_SEL, CLK_UART1_SRC_DIV),
|
||||
CLK_UART1_FRAC = CLK(0U, CLK_UART1_FRAC_DIV),
|
||||
CLK_UART1 = CLK(SCLK_UART1_SEL, 0U),
|
||||
CLK_UART2_SRC = CLK(CLK_UART2_SRC_SEL, CLK_UART2_SRC_DIV),
|
||||
CLK_UART2_FRAC = CLK(0U, CLK_UART2_FRAC_DIV),
|
||||
CLK_UART2 = CLK(SCLK_UART2_SEL, 0U),
|
||||
CLK_UART3_SRC = CLK(CLK_UART3_SRC_SEL, CLK_UART3_SRC_DIV),
|
||||
CLK_UART3_FRAC = CLK(0U, CLK_UART3_FRAC_DIV),
|
||||
CLK_UART3 = CLK(SCLK_UART3_SEL, 0U),
|
||||
CLK_UART4_SRC = CLK(CLK_UART4_SRC_SEL, CLK_UART4_SRC_DIV),
|
||||
CLK_UART4_FRAC = CLK(0U, CLK_UART4_FRAC_DIV),
|
||||
CLK_UART4 = CLK(SCLK_UART4_SEL, 0U),
|
||||
CLK_UART5_SRC = CLK(CLK_UART5_SRC_SEL, CLK_UART5_SRC_DIV),
|
||||
CLK_UART5_FRAC = CLK(0U, CLK_UART5_FRAC_DIV),
|
||||
CLK_UART5 = CLK(SCLK_UART5_SEL, 0U),
|
||||
CLK_UART6_SRC = CLK(CLK_UART6_SRC_SEL, CLK_UART6_SRC_DIV),
|
||||
CLK_UART6_FRAC = CLK(0U, CLK_UART6_FRAC_DIV),
|
||||
CLK_UART6 = CLK(SCLK_UART6_SEL, 0U),
|
||||
CLK_UART7_SRC = CLK(CLK_UART7_SRC_SEL, CLK_UART7_SRC_DIV),
|
||||
CLK_UART7_FRAC = CLK(0U, CLK_UART7_FRAC_DIV),
|
||||
CLK_UART7 = CLK(SCLK_UART7_SEL, 0U),
|
||||
CLK_UART8_SRC = CLK(CLK_UART8_SRC_SEL, CLK_UART8_SRC_DIV),
|
||||
CLK_UART8_FRAC = CLK(0U, CLK_UART8_FRAC_DIV),
|
||||
CLK_UART8 = CLK(SCLK_UART8_SEL, 0U),
|
||||
CLK_UART9_SRC = CLK(CLK_UART9_SRC_SEL, CLK_UART9_SRC_DIV),
|
||||
CLK_UART9_FRAC = CLK(0U, CLK_UART9_FRAC_DIV),
|
||||
CLK_UART9 = CLK(SCLK_UART9_SEL, 0U),
|
||||
CLK_CAN0 = CLK(CLK_CAN0_SEL, CLK_CAN0_DIV),
|
||||
CLK_CAN1 = CLK(CLK_CAN1_SEL, CLK_CAN1_DIV),
|
||||
CLK_CAN2 = CLK(CLK_CAN2_SEL, CLK_CAN2_DIV),
|
||||
CLK_TSADC_TSEN = CLK(CLK_TSADC_TSEN_SEL, CLK_TSADC_TSEN_DIV),
|
||||
CLK_TSADC = CLK(0, CLK_TSADC_DIV),
|
||||
SCLK_SFC = CLK(SCLK_SFC_SEL, 0U),
|
||||
CLK_MAC0_2TOP = CLK(CLK_MAC0_2TOP_SEL, 0U),
|
||||
CLK_MAC1_2TOP = CLK(CLK_MAC1_2TOP_SEL, 0U),
|
||||
CLK_MAC0_OUT = CLK(CLK_MAC0_OUT_SEL, 0U),
|
||||
CLK_MAC1_OUT = CLK(CLK_MAC1_OUT_SEL, 0U),
|
||||
CLK_GMAC0_PTP_REF = CLK(CLK_GMAC0_PTP_REF_SEL, 0U),
|
||||
CLK_GMAC1_PTP_REF = CLK(CLK_GMAC1_PTP_REF_SEL, 0U),
|
||||
SCLK_GMAC0 = CLK(RMII0_EXTCLK_SEL, 0U),
|
||||
SCLK_GMAC1 = CLK(RMII1_EXTCLK_SEL, 0U),
|
||||
SCLK_GMAC0_RGMII_SPEED = CLK(RGMII0_CLK_SEL, 0U),
|
||||
SCLK_GMAC1_RGMII_SPEED = CLK(RGMII1_CLK_SEL, 0U),
|
||||
SCLK_GMAC0_RMII_SPEED = CLK(RMII0_CLK_SEL, 0U),
|
||||
SCLK_GMAC1_RMII_SPEED = CLK(RMII1_CLK_SEL, 0U),
|
||||
SCLK_GMAC0_RX_TX = CLK(CLK_GMAC0_RX_TX_SEL, 0U),
|
||||
SCLK_GMAC1_RX_TX = CLK(CLK_GMAC1_RX_TX_SEL, 0U),
|
||||
ACLK_PHP = CLK(ACLK_PHP_SEL, 0U),
|
||||
HCLK_PHP = CLK(HCLK_PHP_SEL, 0U),
|
||||
PCLK_PHP = CLK(0U, PCLK_PHP_DIV),
|
||||
ACLK_USB = CLK(ACLK_USB_SEL, 0U),
|
||||
HCLK_USB = CLK(HCLK_USB_SEL, 0U),
|
||||
PCLK_USB = CLK(0U, PCLK_USB_DIV),
|
||||
CLK_SDMMC0 = CLK(CLK_SDMMC0_SEL, 0U),
|
||||
} eCLOCK_Name;
|
||||
#endif
|
||||
/****************************************MBOX********************************************/
|
||||
#define MBOX_CNT 2
|
||||
#define MBOX_CHAN_CNT 4
|
||||
/****************************************GRF*********************************************/
|
||||
#define GRF_IOMUX_BIT_PER_PIN (4)
|
||||
#define GRF_DS_BIT_PER_PIN (8)
|
||||
#define GRF_PULL_BIT_PER_PIN (2)
|
||||
/****************************************GPIO********************************************/
|
||||
// #ifdef GPIO_VER_ID
|
||||
// #undef GPIO_VER_ID
|
||||
// #define GPIO_VER_ID (0x01000C2BU)
|
||||
// #endif
|
||||
/****************************************PMU*********************************************/
|
||||
#ifndef __ASSEMBLY__
|
||||
typedef enum PD_Id {
|
||||
PD_INVALID = 0U,
|
||||
} ePD_Id;
|
||||
#endif
|
||||
/****************************************FSPI********************************************/
|
||||
#define FSPI_CHIP_CNT (2)
|
||||
|
||||
/****************************************WDT*********************************************/
|
||||
#define GLB_RST_SND_WDT GLB_RST_SND_WDT0
|
||||
#define GLB_RST_FST_WDT GLB_RST_FST_WDT0
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __SOC_H */
|
|
@ -0,0 +1,29 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __SYSTEM_RK3568_H_
|
||||
#define __SYSTEM_RK3568_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief Update SystemCoreClock variable.
|
||||
|
||||
Updates the SystemCoreClock with current core Clock retrieved from cpu registers.
|
||||
*/
|
||||
extern void SystemCoreClockUpdate (void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__SYSTEM_RK3568_H_ */
|
|
@ -312,12 +312,13 @@ __attribute__((weak)) HAL_Status HAL_DelayMs(uint32_t ms)
|
|||
*/
|
||||
HAL_Status HAL_DelayUs(uint32_t us)
|
||||
{
|
||||
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
|
||||
// #if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
|
||||
|
||||
// return TimerDelayUs(us);
|
||||
// #else
|
||||
|
||||
return TimerDelayUs(us);
|
||||
#else
|
||||
return HAL_CPUDelayUs(us);
|
||||
#endif
|
||||
// #endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1007,271 +1007,6 @@ HAL_Status HAL_CRU_SetPllPowerDown(struct PLL_SETUP *pSetup)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CRU_CLK_USE_CON_BANK
|
||||
static const struct HAL_CRU_DEV *CRU_GetInfo(void)
|
||||
{
|
||||
return &g_cruDev;
|
||||
}
|
||||
|
||||
HAL_Check HAL_CRU_ClkIsEnabled(uint32_t clk)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
||||
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
||||
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
||||
uint32_t reg;
|
||||
HAL_Check ret;
|
||||
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].gateOffset + index * 4;
|
||||
ret = (HAL_Check)(!((CRU_READ(reg) & (1 << shift)) >> shift));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HAL_SECTION_SRAM_CODE
|
||||
HAL_Status HAL_CRU_ClkEnable(uint32_t clk)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
||||
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
||||
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
||||
uint32_t reg;
|
||||
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].gateOffset + index * 4;
|
||||
CRU_WRITE(reg, shift, 1U << shift, 0U);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_Status HAL_CRU_ClkDisable(uint32_t clk)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
||||
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
||||
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
||||
uint32_t reg;
|
||||
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].gateOffset + index * 4;
|
||||
CRU_WRITE(reg, shift, 1U << shift, 1U);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_Status HAL_CRU_ClkDisableUnused(uint32_t bank, uint32_t index, uint32_t val)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t reg;
|
||||
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].gateOffset + index * 4;
|
||||
CRU_WRITE(reg, 0, 0, val);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_Check HAL_CRU_ClkIsReset(uint32_t clk)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
||||
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
||||
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
||||
uint32_t reg;
|
||||
HAL_Check ret;
|
||||
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
||||
ret = (HAL_Check)((CRU_READ(reg) & (1 << shift)) >> shift);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HAL_Status HAL_CRU_ClkResetAssert(uint32_t clk)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t index = CLK_RESET_GET_REG_OFFSET(clk);
|
||||
uint32_t shift = CLK_RESET_GET_BITS_SHIFT(clk);
|
||||
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
||||
uint32_t reg;
|
||||
|
||||
HAL_ASSERT(shift < 16);
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
||||
CRU_WRITE(reg, shift, 1U << shift, 1U);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_Status HAL_CRU_ClkResetDeassert(uint32_t clk)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t index = CLK_RESET_GET_REG_OFFSET(clk);
|
||||
uint32_t shift = CLK_RESET_GET_BITS_SHIFT(clk);
|
||||
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
||||
uint32_t reg;
|
||||
|
||||
HAL_ASSERT(shift < 16);
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
||||
CRU_WRITE(reg, shift, 1U << shift, 0U);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_Status HAL_CRU_ClkResetSyncAssert(int numClks, uint32_t *clks)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t index = CLK_RESET_GET_REG_OFFSET(clks[0]);
|
||||
uint32_t bank = CLK_GATE_GET_REG_BANK(clks[0]);
|
||||
uint32_t val = 0;
|
||||
uint32_t reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numClks; i++) {
|
||||
val |= HAL_BIT(CLK_RESET_GET_BITS_SHIFT(clks[i]));
|
||||
if (index != CLK_RESET_GET_REG_OFFSET(clks[i])) {
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
||||
CRU_WRITE(reg, 0, val, val);
|
||||
HAL_DBG("%s: index: 0x%lx, val: 0x%lx\n", __func__, index, val);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_Status HAL_CRU_ClkResetSyncDeassert(int numClks, uint32_t *clks)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t index = CLK_RESET_GET_REG_OFFSET(clks[0]);
|
||||
uint32_t bank = CLK_GATE_GET_REG_BANK(clks[0]);
|
||||
uint32_t val = 0;
|
||||
uint32_t reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numClks; i++) {
|
||||
val |= HAL_BIT(CLK_RESET_GET_BITS_SHIFT(clks[i]));
|
||||
if (index != CLK_RESET_GET_REG_OFFSET(clks[i])) {
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
||||
CRU_WRITE(reg, 0, val, 0);
|
||||
HAL_DBG("%s: index: 0x%lx, val: 0x%lx\n", __func__, index, val);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_SECTION_SRAM_CODE
|
||||
HAL_Status HAL_CRU_ClkSetDiv(uint32_t divName, uint32_t divValue)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t shift, mask, index;
|
||||
uint32_t reg, bank, maxDiv;
|
||||
|
||||
index = CLK_DIV_GET_REG_OFFSET(divName);
|
||||
shift = CLK_DIV_GET_BITS_SHIFT(divName);
|
||||
HAL_ASSERT(shift < 16);
|
||||
mask = CLK_DIV_GET_MASK(divName);
|
||||
maxDiv = CLK_DIV_GET_MAXDIV(divName) + 1;
|
||||
if (divValue > maxDiv) {
|
||||
divValue = maxDiv;
|
||||
}
|
||||
|
||||
bank = CLK_DIV_GET_BANK(divName);
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
||||
CRU_WRITE(reg, shift, mask, (divValue - 1U));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
uint32_t HAL_CRU_ClkGetDiv(uint32_t divName)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t shift, mask, index, divValue;
|
||||
uint32_t reg, bank;
|
||||
|
||||
index = CLK_DIV_GET_REG_OFFSET(divName);
|
||||
shift = CLK_DIV_GET_BITS_SHIFT(divName);
|
||||
HAL_ASSERT(shift < 16);
|
||||
mask = CLK_DIV_GET_MASK(divName);
|
||||
bank = CLK_DIV_GET_BANK(divName);
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
||||
divValue = ((CRU_READ(reg) & mask) >> shift) + 1;
|
||||
|
||||
return divValue;
|
||||
}
|
||||
|
||||
HAL_SECTION_SRAM_CODE
|
||||
HAL_Status HAL_CRU_ClkSetMux(uint32_t muxName, uint32_t muxValue)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t shift, mask, index;
|
||||
uint32_t reg, bank;
|
||||
|
||||
index = CLK_MUX_GET_REG_OFFSET(muxName);
|
||||
shift = CLK_MUX_GET_BITS_SHIFT(muxName);
|
||||
HAL_ASSERT(shift < 16);
|
||||
mask = CLK_MUX_GET_MASK(muxName);
|
||||
bank = CLK_MUX_GET_BANK(muxName);
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
||||
CRU_WRITE(reg, shift, mask, muxValue);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_SECTION_SRAM_CODE
|
||||
uint32_t HAL_CRU_ClkGetMux(uint32_t muxName)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t shift, mask, index, muxValue;
|
||||
uint32_t reg, bank;
|
||||
|
||||
index = CLK_MUX_GET_REG_OFFSET(muxName);
|
||||
shift = CLK_MUX_GET_BITS_SHIFT(muxName);
|
||||
HAL_ASSERT(shift < 16);
|
||||
mask = CLK_MUX_GET_MASK(muxName);
|
||||
bank = CLK_MUX_GET_BANK(muxName);
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
||||
muxValue = ((CRU_READ(reg) & mask) >> shift);
|
||||
|
||||
return muxValue;
|
||||
}
|
||||
|
||||
HAL_Status HAL_CRU_ClkSetFracDiv(uint32_t fracDivName,
|
||||
uint32_t numerator,
|
||||
uint32_t denominator)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t reg, bank;
|
||||
uint32_t index;
|
||||
|
||||
index = CLK_DIV_GET_REG_OFFSET(fracDivName);
|
||||
bank = CLK_DIV_GET_BANK(fracDivName);
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
||||
CRU_WRITE(reg, 0, 0, ((numerator << 16) | denominator));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_Status HAL_CRU_ClkGetFracDiv(uint32_t fracDivName,
|
||||
uint32_t *numerator,
|
||||
uint32_t *denominator)
|
||||
{
|
||||
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
||||
uint32_t reg, bank;
|
||||
uint32_t index;
|
||||
uint32_t val;
|
||||
|
||||
index = CLK_DIV_GET_REG_OFFSET(fracDivName);
|
||||
bank = CLK_DIV_GET_BANK(fracDivName);
|
||||
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
||||
val = CRU_READ(reg);
|
||||
|
||||
*numerator = (val & 0xffff0000) >> 16;
|
||||
*denominator = (val & 0x0000ffff);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#else /* CRU_CLK_USE_CON_BANK */
|
||||
|
||||
HAL_Check HAL_CRU_ClkIsEnabled(uint32_t clk)
|
||||
{
|
||||
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
||||
|
@ -1631,7 +1366,7 @@ HAL_Status HAL_CRU_ClkGetFracDiv(uint32_t fracDivName,
|
|||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* CRU_CLK_USE_CON_BANK */
|
||||
|
||||
|
||||
HAL_Status HAL_CRU_FracdivGetConfig(uint32_t rateOut, uint32_t rate,
|
||||
uint32_t *numerator,
|
||||
|
|
|
@ -285,7 +285,6 @@
|
|||
#define GMAC_DESC3_BUF1V (0x1 << 24)
|
||||
#define GMAC_DESC3_CIC (0x3 << 16)
|
||||
|
||||
#define DES3_ERROR_SUMMARY (1 << 15)
|
||||
#define DES3_ERROR_SUMMARY (1 << 15)
|
||||
|
||||
/* Generic MII registers. */
|
||||
|
@ -1794,8 +1793,8 @@ HAL_Status HAL_GMAC_Start(struct GMAC_HANDLE *pGMAC, uint8_t *addr)
|
|||
value |= (0x2 & DMA_AXI_OSR_MAX) << DMA_AXI_RD_OSR_LMT_SHIFT;
|
||||
|
||||
/* DMA init */
|
||||
WRITE_REG(pGMAC->pReg->DMA_SYSBUS_MODE, value | DMA_SYSBUS_MODE_BLEN16 |
|
||||
DMA_SYSBUS_MODE_BLEN8 | DMA_SYSBUS_MODE_BLEN4);
|
||||
WRITE_REG(pGMAC->pReg->DMA_SYSBUS_MODE, DMA_SYSBUS_MODE_BLEN16 |
|
||||
DMA_SYSBUS_MODE_BLEN8 | DMA_SYSBUS_MODE_BLEN4 | 1 << 12 | 1 << 14);
|
||||
|
||||
/* Mask interrupts by writing to CSR7 */
|
||||
WRITE_REG(pGMAC->pReg->DMA_CH0_INTERRUPT_ENABLE, DMA_CHAN_INTR_DEFAULT_MASK);
|
||||
|
@ -1816,10 +1815,6 @@ HAL_Status HAL_GMAC_Start(struct GMAC_HANDLE *pGMAC, uint8_t *addr)
|
|||
WRITE_REG(pGMAC->pReg->DMA_CH0_RXDESC_TAIL_POINTER,
|
||||
(uint32_t)(uint64_t)(pGMAC->rxDescs_dma + pGMAC->rxSize));
|
||||
|
||||
value = READ_REG(pGMAC->pReg->DMA_CH0_CONTROL);
|
||||
value = value | 1 << 16;
|
||||
WRITE_REG(pGMAC->pReg->DMA_CH0_CONTROL, value);
|
||||
|
||||
/* init tx chan */
|
||||
value = READ_REG(pGMAC->pReg->DMA_CH0_TX_CONTROL);
|
||||
value = value | (32 << DMA_CH0_TX_CONTROL_TXPBL_SHIFT);
|
||||
|
@ -2066,6 +2061,7 @@ uint8_t *HAL_GMAC_Recv(struct GMAC_HANDLE *pGMAC, int32_t *length)
|
|||
|
||||
*length = 0;
|
||||
desc = pGMAC->rxDescs + pGMAC->rxDescIdx;
|
||||
HAL_DBG("Rx at %p\n", desc->des0);
|
||||
des3 = desc->des3;
|
||||
if (des3 & GMAC_DESC3_OWN) {
|
||||
HAL_DBG("%p: RX packet not available\n", desc->des0);
|
||||
|
@ -2125,9 +2121,10 @@ void HAL_GMAC_CleanRX(struct GMAC_HANDLE *pGMAC)
|
|||
desc->des1 = 0;
|
||||
desc->des2 = 0;
|
||||
desc->des3 = GMAC_DESC3_OWN | GMAC_DESC3_BUF1V | GMAC_DESC3_IOC;
|
||||
|
||||
WRITE_REG(pGMAC->pReg->DMA_CH0_RXDESC_TAIL_POINTER,
|
||||
(uint32_t)(uint64_t)(pGMAC->rxDescs_dma + pGMAC->rxDescIdx));
|
||||
HAL_DBG("Clean buff %p\n", desc->des0);
|
||||
desc_dma = pGMAC->rxDescs_dma + pGMAC->rxDescIdx;
|
||||
HAL_DBG("Clean desc %p\n", desc_dma);
|
||||
WRITE_REG(pGMAC->pReg->DMA_CH0_RXDESC_TAIL_POINTER, (uint32_t)(uint64_t)desc_dma);
|
||||
|
||||
pGMAC->rxDescIdx++;
|
||||
pGMAC->rxDescIdx %= pGMAC->rxSize;
|
||||
|
|
|
@ -85,7 +85,7 @@ struct GMAC_ETH_CONFIG {
|
|||
/********************* Private Variable Definition ***************************/
|
||||
|
||||
|
||||
static uint8_t dstAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
static uint8_t dstAddr[6] = { 0x00, 0x0C, 0x29, 0xf8, 0x7a, 0x6b };
|
||||
|
||||
#if defined(HAL_GMAC_MODULE_ENABLED) && defined(SOC_RK3568)
|
||||
static struct GMAC_ETH_CONFIG ethConfigTable[] =
|
||||
|
@ -349,6 +349,7 @@ static void *malloc_align(size_t size, size_t align, uintptr_t va, uintptr_t *pa
|
|||
/* get total aligned size */
|
||||
align_size = ((size + 0x03) & ~0x03);
|
||||
/* allocate memory block from heap */
|
||||
HAL_DBG("size: %d, align:%d\n",align_size, align);
|
||||
// ptr = malloc(align_size);
|
||||
|
||||
if (naive_mmap(&va, pa, align_size, true) < 0){
|
||||
|
@ -416,7 +417,7 @@ static HAL_Status GMAC_Send_Test(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE
|
|||
}
|
||||
|
||||
/* dump packages */
|
||||
Dump_Hex("Tx", ptr, len);
|
||||
// Dump_Hex("Tx", ptr, len);
|
||||
|
||||
// HAL_DCACHE_CleanByRange((uint64_t)ptr, len);
|
||||
uint8_t * ptr_dma = (uint8_t *)HAL_GMAC_GetTXBufferDMA(pGMAC);
|
||||
|
@ -425,6 +426,7 @@ static HAL_Status GMAC_Send_Test(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE
|
|||
printf("GMAC send failed: %d\n", status);
|
||||
}
|
||||
|
||||
print_desc(pGMAC);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -442,6 +444,7 @@ static uint16_t GMAC_Recv_Test(struct GMAC_HANDLE *pGMAC)
|
|||
status = GMAC_ETH_IRQ(pGMAC);
|
||||
ptr = HAL_GMAC_Recv(pGMAC, &size);
|
||||
while (status && ptr) {
|
||||
print_desc(pGMAC);
|
||||
if (size > 0 && ptr) {
|
||||
/* dump packages */
|
||||
Dump_Hex("Rx", ptr, size);
|
||||
|
@ -459,21 +462,20 @@ static uint16_t GMAC_Recv_Test(struct GMAC_HANDLE *pGMAC)
|
|||
|
||||
static HAL_Status GMAC_Memory_Init(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC)
|
||||
{
|
||||
|
||||
uintptr_t tx_va = 0x1000000000, tx_pa = 0;
|
||||
if (naive_mmap(&tx_va, &tx_pa, GMAC_DESC_TX_SIZE, true) < 0){
|
||||
HAL_DBG("TX Desc alloc failed\n");
|
||||
}
|
||||
eth->txDescs = (struct GMAC_Desc *)0x1000000000;
|
||||
eth->txDescs_dma = (struct GMAC_Desc *)tx_pa;
|
||||
|
||||
uintptr_t rx_va = 0x1000400000, rx_pa = 0;
|
||||
uintptr_t rx_va = 0x1000000000, rx_pa = 0;
|
||||
if (naive_mmap(&rx_va, &rx_pa, GMAC_DESC_RX_SIZE, true) < 0){
|
||||
HAL_DBG("RX Desc alloc failed\n");
|
||||
}
|
||||
eth->rxDescs = (struct GMAC_Desc *)0x1000400000;
|
||||
eth->rxDescs = (struct GMAC_Desc *)0x1000000000;
|
||||
eth->rxDescs_dma = (struct GMAC_Desc *)rx_pa;
|
||||
|
||||
uintptr_t tx_va = 0x1000400000, tx_pa = 0;
|
||||
if (naive_mmap(&tx_va, &tx_pa, GMAC_DESC_TX_SIZE, true) < 0){
|
||||
HAL_DBG("TX Desc alloc failed\n");
|
||||
}
|
||||
eth->txDescs = (struct GMAC_Desc *)0x1000400000;
|
||||
eth->txDescs_dma = (struct GMAC_Desc *)tx_pa;
|
||||
|
||||
if (!eth->rxDescs || !eth->txDescs_dma ||
|
||||
!eth->txDescs || !eth->txDescs_dma){
|
||||
return -1;
|
||||
|
@ -482,16 +484,14 @@ static HAL_Status GMAC_Memory_Init(struct GMAC_ETH_CONFIG *eth, struct GMAC_HAND
|
|||
HAL_DBG("rx:%p, %p\n",eth->rxDescs, eth->rxDescs_dma);
|
||||
HAL_DBG("tx:%p, %p\n",eth->txDescs, eth->txDescs_dma);
|
||||
|
||||
|
||||
uintptr_t txbuf_va = 0x1000800000, txbuf_pa = 0;
|
||||
eth->txBuff = malloc_align(GMAC_TX_BUFFER_SIZE, ARCH_DMA_MINALIGN, txbuf_va, &txbuf_pa);
|
||||
eth->txBuff = (void *)0x1000800000;
|
||||
eth->txBuff_dma = (void *)txbuf_pa;
|
||||
|
||||
uintptr_t rxbuf_va = 0x1000c00000, rxbuf_pa = 0;
|
||||
uintptr_t rxbuf_va = 0x1000800000, rxbuf_pa = 0;
|
||||
uintptr_t txbuf_va = 0x1000C00000, txbuf_pa = 0;
|
||||
eth->rxBuff = malloc_align(GMAC_RX_BUFFER_SIZE, ARCH_DMA_MINALIGN, rxbuf_va, &rxbuf_pa);
|
||||
eth->rxBuff = (void *)0x1000c00000;
|
||||
eth->rxBuff = (void *)0x1000800000;
|
||||
eth->rxBuff_dma = (void *)rxbuf_pa;
|
||||
eth->txBuff = malloc_align(GMAC_TX_BUFFER_SIZE, ARCH_DMA_MINALIGN, txbuf_va, &txbuf_pa);
|
||||
eth->txBuff = (void *)0x1000C00000;
|
||||
eth->txBuff_dma = (void *)txbuf_pa;
|
||||
|
||||
if (!eth->rxBuff || !eth->txBuff ||
|
||||
!eth->rxBuff_dma || !eth->txBuff_dma){
|
||||
|
@ -499,6 +499,8 @@ static HAL_Status GMAC_Memory_Init(struct GMAC_ETH_CONFIG *eth, struct GMAC_HAND
|
|||
}
|
||||
HAL_DBG("rx_buff:%p,%p\n",eth->rxBuff, eth->rxBuff_dma);
|
||||
HAL_DBG("tx_buff:%p,%p,\n",eth->txBuff, eth->txBuff_dma);
|
||||
HAL_DBG("GMAC_DESC_RX_SIZE:%d\n", GMAC_DESC_RX_SIZE);
|
||||
HAL_DBG("GMAC_RX_BUFFER_SIZE:%d\n", GMAC_RX_BUFFER_SIZE);
|
||||
memset(eth->rxDescs, 0, GMAC_DESC_RX_SIZE);
|
||||
memset(eth->txDescs, 0, GMAC_DESC_TX_SIZE);
|
||||
memset(eth->rxBuff, 0, GMAC_RX_BUFFER_SIZE);
|
||||
|
@ -538,9 +540,9 @@ static HAL_Status GMAC_Init(uint8_t id)
|
|||
interface = eth->mode;
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_RGMII) {
|
||||
HAL_CRU_ClkSetFreq(gmacDev->clkID125M, 125000000);
|
||||
HAL_CRU_ClkSetFreq(gmacDev->clkID, 125000000);
|
||||
} else {
|
||||
HAL_CRU_ClkSetFreq(gmacDev->clkID50M, 50000000);
|
||||
HAL_CRU_ClkSetFreq(gmacDev->clkID, 50000000);
|
||||
}
|
||||
|
||||
freq = HAL_CRU_ClkGetFreq(gmacDev->pclkID);
|
||||
|
@ -581,6 +583,7 @@ static void GMAC0_Iomux_Config(void)
|
|||
GPIO_PIN_B6, /* gmac0_rxd0 */
|
||||
PIN_CONFIG_MUX_FUNC1);
|
||||
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
||||
GPIO_PIN_C0 | ///* eth0_refclko25m */
|
||||
GPIO_PIN_C3 | /* gmac0_mdc */
|
||||
GPIO_PIN_C4 | /* gmac0_mdio */
|
||||
GPIO_PIN_C0 | /* gmac0_rxdvcrs */
|
||||
|
@ -643,19 +646,19 @@ int main() {
|
|||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
HAL_DBG("map GMAC0\n");
|
||||
if (!mmap(0x2000000000ULL+ GMAC0_BASE, GMAC0_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap GMAC0(%8x) failed\n", GMAC0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
HAL_DBG("map GPIO2\n");
|
||||
if (!mmap(0x2000000000ULL + GPIO2_BASE, GPIO2_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap GPIO2(%8x) failed\n", GPIO2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
HAL_DBG("map GPIO3\n");
|
||||
if (!mmap(0x2000000000ULL + GPIO3_BASE, GPIO3_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap GPIO3(%8x) failed\n", GPIO3);
|
||||
printf("eth_hal: mmap GPIO2(%8x) failed\n", GPIO2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -665,69 +668,65 @@ int main() {
|
|||
}
|
||||
|
||||
if (!mmap(0x2000000000ULL + CRU_BASE, CRU_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap CRU(%8x) failed\n", CRU);
|
||||
printf("eth_hal: mmap GRF(%8x) failed\n", GRF);
|
||||
exit(1);
|
||||
}
|
||||
if (!mmap(0x2000000000ULL + TIMER5_BASE, TIMER5_BASE, 32, true)) {
|
||||
printf("eth_hal: mmap TIMER5(%8x) failed\n", TIMER5);
|
||||
if (!mmap(0x2000000000ULL + TIMER5_BASE, CRU_BASE, 32, true)) {
|
||||
printf("eth_hal: mmap GRF(%8x) failed\n", GRF);
|
||||
exit(1);
|
||||
}
|
||||
if (!mmap(0x2000000000ULL + PMUCRU_BASE, PMUCRU_BASE, 0x10000, true)) {
|
||||
printf("eth_hal: mmap PMUCRU(%8x) failed\n", PMUCRU);
|
||||
printf("eth_hal: mmap GRF(%8x) failed\n", GRF);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
HAL_TIMER_SysTimerInit(TIMER5);
|
||||
|
||||
HAL_DBG("config iomux\n");
|
||||
/* ionmux */
|
||||
GMAC_Iomux_Config(bus);
|
||||
HAL_DBG("config cru\n");
|
||||
HAL_CRU_ClkEnable(eth->halDev->pclkGateID);
|
||||
HAL_CRU_ClkEnable(eth->halDev->clkGateID125M);
|
||||
HAL_CRU_ClkEnable(eth->halDev->clkGateID50M);
|
||||
HAL_CRU_ClkEnable(eth->halDev->clkGateID);
|
||||
|
||||
/* Register irq */
|
||||
// register_irq(eth->halDev->irqNum, );
|
||||
/* PHY reset */
|
||||
HAL_DBG("reset phy\n");
|
||||
GMAC_PHY_Reset(eth);
|
||||
|
||||
/* GMAC Init */
|
||||
HAL_DBG("init gmac\n");
|
||||
GMAC_Init(bus);
|
||||
|
||||
HAL_DBG("init memory\n");
|
||||
GMAC_Memory_Init(eth, pGMAC);
|
||||
|
||||
/* Enable GMAC and DMA transmission and reception */
|
||||
HAL_DBG("start gmac\n");
|
||||
HAL_GMAC_Start(pGMAC, eth->macAddr);
|
||||
|
||||
// print_desc(pGMAC);
|
||||
/* Update links information */
|
||||
HAL_DBG("phy update link\n");
|
||||
PHY_Update_Links(eth, pGMAC, bus);
|
||||
|
||||
// print_desc(pGMAC);
|
||||
/* Dump MAC Regs */
|
||||
Dump_Regs(pGMAC);
|
||||
|
||||
/* Dump PHY Regs */
|
||||
// PHY_Dump(eth, pGMAC);
|
||||
HAL_DBG("Init Down\n");
|
||||
for (i = 0; i < GMAC_TEST_TIMES; i++) {
|
||||
HAL_DBG("TEST %d\n", i);
|
||||
|
||||
HAL_DBG("TEST Send %d\n", i);
|
||||
/* GMAC Send 64 bytes */
|
||||
HAL_DBG("--------------GMAC_Send_Test START!--------------\n");
|
||||
GMAC_Send_Test(eth, pGMAC, 64);
|
||||
HAL_DBG("--------------GMAC_Send_Test END!--------------\n");
|
||||
|
||||
// GMAC_Send_Test(eth, pGMAC, 64);
|
||||
/* GMAC Send 1500 bytes */
|
||||
GMAC_Send_Test(eth, pGMAC, 1500);
|
||||
HAL_DelayMs(1000);
|
||||
print_desc(pGMAC);
|
||||
|
||||
HAL_DBG("TEST Recv %d\n", i);
|
||||
/* GMAC Recv */
|
||||
HAL_DBG("--------------GMAC_Recv_Test START! -------------- \n");
|
||||
GMAC_Recv_Test(pGMAC);
|
||||
HAL_DBG("--------------GMAC_Recv_Test END!!-------------- \n");
|
||||
|
||||
HAL_DelayMs(1000);
|
||||
Dump_Regs(pGMAC);
|
||||
}
|
||||
Dump_Regs(pGMAC);
|
||||
HAL_CRU_ClkDisable(eth->halDev->pclkGateID);
|
||||
HAL_CRU_ClkDisable(eth->halDev->clkGateID125M);
|
||||
HAL_CRU_ClkDisable(eth->halDev->clkGateID50M);
|
||||
HAL_CRU_ClkDisable(eth->halDev->clkGateID);
|
||||
|
||||
// free_align(eth->txBuff);
|
||||
// free_align(eth->rxBuff);
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
|
||||
SRC_DIR := $(BOARD)
|
||||
|
||||
ifeq ($(BOARD), 3568)
|
||||
SRC_DIR += usb
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SRC_DIR := components
|
||||
SRC_DIR := components usb_service
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# libipc = $(KERNEL_ROOT)/services/app/libipc.o
|
||||
# libsem = $(KERNEL_ROOT)/services/app/libsemaphore.o
|
||||
|
||||
SRC_DIR := class core osal
|
||||
SRC_DIR := class core mem osal port dev usb_phy
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SRC_DIR := hub
|
||||
SRC_DIR := hub wireless
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -1,9 +1,585 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: usb_cdc.h
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: take CherryUSB v0.10.2/class/cdc/usb_cdc.h for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/class/cdc/usb_cdc.h
|
||||
|
||||
History:
|
||||
1. Date: 2024-07-09
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Replace __PACKED with __attribute__((packed)) because of a compilation error.
|
||||
*************************************************/
|
||||
|
||||
#ifndef USB_CDC_H_
|
||||
#define USB_CDC_H_
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Definitions based on usbcdc11.pdf (www.usb.org)
|
||||
*----------------------------------------------------------------------------*/
|
||||
/* Communication device class specification version 1.10 */
|
||||
#define CDC_V1_10 0x0110U
|
||||
// Communication device class specification version 1.2
|
||||
#define CDC_V1_2_0 0x0120U
|
||||
|
||||
/* Communication interface class code */
|
||||
/* (usbcdc11.pdf, 4.2, Table 15) */
|
||||
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02U
|
||||
|
||||
/* Communication interface class subclass codes */
|
||||
/* (usbcdc11.pdf, 4.3, Table 16) */
|
||||
#define CDC_SUBCLASS_NONE 0x00 /* Reserved */
|
||||
#define CDC_SUBCLASS_DLC 0x01 /* Direct Line Control Model */
|
||||
#define CDC_SUBCLASS_ACM 0x02 /* Abstract Control Model */
|
||||
#define CDC_SUBCLASS_TCM 0x03 /* Telephone Control Model */
|
||||
#define CDC_SUBCLASS_MCM 0x04 /* Multi-Channel Control Model */
|
||||
#define CDC_SUBCLASS_CAPI 0x05 /* CAPI Control Model */
|
||||
#define CDC_SUBCLASS_ECM 0x06 /* Ethernet Networking Control Model */
|
||||
#define CDC_SUBCLASS_ATM 0x07 /* ATM Networking Control Model */
|
||||
/* 0x08-0x0d Reserved (future use) */
|
||||
#define CDC_SUBCLASS_MBIM 0x0e /* MBIM Control Model */
|
||||
/* 0x0f-0x7f Reserved (future use) */
|
||||
/* 0x80-0xfe Reserved (vendor specific) */
|
||||
|
||||
#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01U
|
||||
#define CDC_ABSTRACT_CONTROL_MODEL 0x02U
|
||||
#define CDC_TELEPHONE_CONTROL_MODEL 0x03U
|
||||
#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04U
|
||||
#define CDC_CAPI_CONTROL_MODEL 0x05U
|
||||
#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06U
|
||||
#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07U
|
||||
#define CDC_WIRELESS_HANDSET_CONTROL_MODEL 0x08U
|
||||
#define CDC_DEVICE_MANAGEMENT 0x09U
|
||||
#define CDC_MOBILE_DIRECT_LINE_MODEL 0x0AU
|
||||
#define CDC_OBEX 0x0BU
|
||||
#define CDC_ETHERNET_EMULATION_MODEL 0x0CU
|
||||
#define CDC_NETWORK_CONTROL_MODEL 0x0DU
|
||||
|
||||
/* Communication interface class control protocol codes */
|
||||
/* (usbcdc11.pdf, 4.4, Table 17) */
|
||||
#define CDC_COMMON_PROTOCOL_NONE 0x00U
|
||||
#define CDC_COMMON_PROTOCOL_AT_COMMANDS 0x01U
|
||||
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101 0x02U
|
||||
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO 0x03U
|
||||
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_GSM_707 0x04U
|
||||
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_3GPP_27007 0x05U
|
||||
#define CDC_COMMON_PROTOCOL_AT_COMMANDS_CDMA 0x06U
|
||||
#define CDC_COMMON_PROTOCOL_ETHERNET_EMULATION_MODEL 0x07U
|
||||
// NCM Communication Interface Protocol Codes
|
||||
// (usbncm10.pdf, 4.2, Table 4-2)
|
||||
#define CDC_NCM_PROTOCOL_NONE 0x00U
|
||||
#define CDC_NCM_PROTOCOL_OEM 0xFEU
|
||||
|
||||
#endif
|
||||
/* Data interface class code */
|
||||
/* (usbcdc11.pdf, 4.5, Table 18) */
|
||||
#define CDC_DATA_INTERFACE_CLASS 0x0A
|
||||
|
||||
/* Data Interface Sub-Class Codes ********************************************/
|
||||
#define CDC_DATA_SUBCLASS_NONE 0x00
|
||||
|
||||
/* Data interface class protocol codes */
|
||||
/* (usbcdc11.pdf, 4.7, Table 19) */
|
||||
#define CDC_DATA_PROTOCOL_ISDN_BRI 0x30
|
||||
#define CDC_DATA_PROTOCOL_HDLC 0x31
|
||||
#define CDC_DATA_PROTOCOL_TRANSPARENT 0x32
|
||||
#define CDC_DATA_PROTOCOL_Q921_MANAGEMENT 0x50
|
||||
#define CDC_DATA_PROTOCOL_Q921_DATA_LINK 0x51
|
||||
#define CDC_DATA_PROTOCOL_Q921_MULTIPLEXOR 0x52
|
||||
#define CDC_DATA_PROTOCOL_V42 0x90
|
||||
#define CDC_DATA_PROTOCOL_EURO_ISDN 0x91
|
||||
#define CDC_DATA_PROTOCOL_V24_RATE_ADAPTATION 0x92
|
||||
#define CDC_DATA_PROTOCOL_CAPI 0x93
|
||||
#define CDC_DATA_PROTOCOL_HOST_BASED_DRIVER 0xFD
|
||||
#define CDC_DATA_PROTOCOL_DESCRIBED_IN_PUFD 0xFE
|
||||
|
||||
/* Type values for bDescriptorType field of functional descriptors */
|
||||
/* (usbcdc11.pdf, 5.2.3, Table 24) */
|
||||
#define CDC_CS_INTERFACE 0x24
|
||||
#define CDC_CS_ENDPOINT 0x25
|
||||
|
||||
/* Type values for bDescriptorSubtype field of functional descriptors */
|
||||
/* (usbcdc11.pdf, 5.2.3, Table 25) */
|
||||
#define CDC_FUNC_DESC_HEADER 0x00
|
||||
#define CDC_FUNC_DESC_CALL_MANAGEMENT 0x01
|
||||
#define CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT 0x02
|
||||
#define CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT 0x03
|
||||
#define CDC_FUNC_DESC_TELEPHONE_RINGER 0x04
|
||||
#define CDC_FUNC_DESC_REPORTING_CAPABILITIES 0x05
|
||||
#define CDC_FUNC_DESC_UNION 0x06
|
||||
#define CDC_FUNC_DESC_COUNTRY_SELECTION 0x07
|
||||
#define CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES 0x08
|
||||
#define CDC_FUNC_DESC_USB_TERMINAL 0x09
|
||||
#define CDC_FUNC_DESC_NETWORK_CHANNEL 0x0A
|
||||
#define CDC_FUNC_DESC_PROTOCOL_UNIT 0x0B
|
||||
#define CDC_FUNC_DESC_EXTENSION_UNIT 0x0C
|
||||
#define CDC_FUNC_DESC_MULTI_CHANNEL_MANAGEMENT 0x0D
|
||||
#define CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT 0x0E
|
||||
#define CDC_FUNC_DESC_ETHERNET_NETWORKING 0x0F
|
||||
#define CDC_FUNC_DESC_ATM_NETWORKING 0x10
|
||||
#define CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL 0x11
|
||||
#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL 0x12
|
||||
#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL 0x13
|
||||
#define CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL 0x14
|
||||
#define CDC_FUNC_DESC_OBEX 0x15
|
||||
#define CDC_FUNC_DESC_COMMAND_SET 0x16
|
||||
#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17
|
||||
#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18
|
||||
#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19
|
||||
|
||||
/* CDC class-specific request codes */
|
||||
/* (usbcdc11.pdf, 6.2, Table 46) */
|
||||
/* see Table 45 for info about the specific requests. */
|
||||
#define CDC_REQUEST_SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define CDC_REQUEST_GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define CDC_REQUEST_SET_COMM_FEATURE 0x02
|
||||
#define CDC_REQUEST_GET_COMM_FEATURE 0x03
|
||||
#define CDC_REQUEST_CLEAR_COMM_FEATURE 0x04
|
||||
#define CDC_REQUEST_SET_AUX_LINE_STATE 0x10
|
||||
#define CDC_REQUEST_SET_HOOK_STATE 0x11
|
||||
#define CDC_REQUEST_PULSE_SETUP 0x12
|
||||
#define CDC_REQUEST_SEND_PULSE 0x13
|
||||
#define CDC_REQUEST_SET_PULSE_TIME 0x14
|
||||
#define CDC_REQUEST_RING_AUX_JACK 0x15
|
||||
#define CDC_REQUEST_SET_LINE_CODING 0x20
|
||||
#define CDC_REQUEST_GET_LINE_CODING 0x21
|
||||
#define CDC_REQUEST_SET_CONTROL_LINE_STATE 0x22
|
||||
#define CDC_REQUEST_SEND_BREAK 0x23
|
||||
#define CDC_REQUEST_SET_RINGER_PARMS 0x30
|
||||
#define CDC_REQUEST_GET_RINGER_PARMS 0x31
|
||||
#define CDC_REQUEST_SET_OPERATION_PARMS 0x32
|
||||
#define CDC_REQUEST_GET_OPERATION_PARMS 0x33
|
||||
#define CDC_REQUEST_SET_LINE_PARMS 0x34
|
||||
#define CDC_REQUEST_GET_LINE_PARMS 0x35
|
||||
#define CDC_REQUEST_DIAL_DIGITS 0x36
|
||||
#define CDC_REQUEST_SET_UNIT_PARAMETER 0x37
|
||||
#define CDC_REQUEST_GET_UNIT_PARAMETER 0x38
|
||||
#define CDC_REQUEST_CLEAR_UNIT_PARAMETER 0x39
|
||||
#define CDC_REQUEST_GET_PROFILE 0x3A
|
||||
#define CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS 0x40
|
||||
#define CDC_REQUEST_SET_ETHERNET_PMP_FILTER 0x41
|
||||
#define CDC_REQUEST_GET_ETHERNET_PMP_FILTER 0x42
|
||||
#define CDC_REQUEST_SET_ETHERNET_PACKET_FILTER 0x43
|
||||
#define CDC_REQUEST_GET_ETHERNET_STATISTIC 0x44
|
||||
#define CDC_REQUEST_SET_ATM_DATA_FORMAT 0x50
|
||||
#define CDC_REQUEST_GET_ATM_DEVICE_STATISTICS 0x51
|
||||
#define CDC_REQUEST_SET_ATM_DEFAULT_VC 0x52
|
||||
#define CDC_REQUEST_GET_ATM_VC_STATISTICS 0x53
|
||||
|
||||
/* Communication feature selector codes */
|
||||
/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */
|
||||
#define CDC_ABSTRACT_STATE 0x01
|
||||
#define CDC_COUNTRY_SETTING 0x02
|
||||
|
||||
/** Control Signal Bitmap Values for SetControlLineState */
|
||||
#define SET_CONTROL_LINE_STATE_RTS 0x02
|
||||
#define SET_CONTROL_LINE_STATE_DTR 0x01
|
||||
|
||||
/* Feature Status returned for ABSTRACT_STATE Selector */
|
||||
/* (usbcdc11.pdf, 6.2.3, Table 48) */
|
||||
#define CDC_IDLE_SETTING (1 << 0)
|
||||
#define CDC_DATA_MULTPLEXED_STATE (1 << 1)
|
||||
|
||||
/* Control signal bitmap values for the SetControlLineState request */
|
||||
/* (usbcdc11.pdf, 6.2.14, Table 51) */
|
||||
#define CDC_DTE_PRESENT (1 << 0)
|
||||
#define CDC_ACTIVATE_CARRIER (1 << 1)
|
||||
|
||||
/* CDC class-specific notification codes */
|
||||
/* (usbcdc11.pdf, 6.3, Table 68) */
|
||||
/* see Table 67 for Info about class-specific notifications */
|
||||
#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00
|
||||
#define CDC_RESPONSE_AVAILABLE 0x01
|
||||
#define CDC_AUX_JACK_HOOK_STATE 0x08
|
||||
#define CDC_RING_DETECT 0x09
|
||||
#define CDC_NOTIFICATION_SERIAL_STATE 0x20
|
||||
#define CDC_CALL_STATE_CHANGE 0x28
|
||||
#define CDC_LINE_STATE_CHANGE 0x29
|
||||
#define CDC_CONNECTION_SPEED_CHANGE 0x2A
|
||||
|
||||
/* UART state bitmap values (Serial state notification). */
|
||||
/* (usbcdc11.pdf, 6.3.5, Table 69) */
|
||||
#define CDC_SERIAL_STATE_OVERRUN (1 << 6) /* receive data overrun error has occurred */
|
||||
#define CDC_SERIAL_STATE_OVERRUN_Pos (6)
|
||||
#define CDC_SERIAL_STATE_OVERRUN_Msk (1 << CDC_SERIAL_STATE_OVERRUN_Pos)
|
||||
#define CDC_SERIAL_STATE_PARITY (1 << 5) /* parity error has occurred */
|
||||
#define CDC_SERIAL_STATE_PARITY_Pos (5)
|
||||
#define CDC_SERIAL_STATE_PARITY_Msk (1 << CDC_SERIAL_STATE_PARITY_Pos)
|
||||
#define CDC_SERIAL_STATE_FRAMING (1 << 4) /* framing error has occurred */
|
||||
#define CDC_SERIAL_STATE_FRAMING_Pos (4)
|
||||
#define CDC_SERIAL_STATE_FRAMING_Msk (1 << CDC_SERIAL_STATE_FRAMING_Pos)
|
||||
#define CDC_SERIAL_STATE_RING (1 << 3) /* state of ring signal detection */
|
||||
#define CDC_SERIAL_STATE_RING_Pos (3)
|
||||
#define CDC_SERIAL_STATE_RING_Msk (1 << CDC_SERIAL_STATE_RING_Pos)
|
||||
#define CDC_SERIAL_STATE_BREAK (1 << 2) /* state of break detection */
|
||||
#define CDC_SERIAL_STATE_BREAK_Pos (2)
|
||||
#define CDC_SERIAL_STATE_BREAK_Msk (1 << CDC_SERIAL_STATE_BREAK_Pos)
|
||||
#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) /* state of transmission carrier */
|
||||
#define CDC_SERIAL_STATE_TX_CARRIER_Pos (1)
|
||||
#define CDC_SERIAL_STATE_TX_CARRIER_Msk (1 << CDC_SERIAL_STATE_TX_CARRIER_Pos)
|
||||
#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) /* state of receiver carrier */
|
||||
#define CDC_SERIAL_STATE_RX_CARRIER_Pos (0)
|
||||
#define CDC_SERIAL_STATE_RX_CARRIER_Msk (1 << CDC_SERIAL_STATE_RX_CARRIER_Pos)
|
||||
|
||||
#define CDC_ECM_XMIT_OK (1 << 0)
|
||||
#define CDC_ECM_RVC_OK (1 << 1)
|
||||
#define CDC_ECM_XMIT_ERROR (1 << 2)
|
||||
#define CDC_ECM_RCV_ERROR (1 << 3)
|
||||
#define CDC_ECM_RCV_NO_BUFFER (1 << 4)
|
||||
#define CDC_ECM_DIRECTED_BYTES_XMIT (1 << 5)
|
||||
#define CDC_ECM_DIRECTED_FRAMES_XMIT (1 << 6)
|
||||
#define CDC_ECM_MULTICAST_BYTES_XMIT (1 << 7)
|
||||
#define CDC_ECM_MULTICAST_FRAMES_XMIT (1 << 8)
|
||||
#define CDC_ECM_BROADCAST_BYTES_XMIT (1 << 9)
|
||||
#define CDC_ECM_BROADCAST_FRAMES_XMIT (1 << 10)
|
||||
#define CDC_ECM_DIRECTED_BYTES_RCV (1 << 11)
|
||||
#define CDC_ECM_DIRECTED_FRAMES_RCV (1 << 12)
|
||||
#define CDC_ECM_MULTICAST_BYTES_RCV (1 << 13)
|
||||
#define CDC_ECM_MULTICAST_FRAMES_RCV (1 << 14)
|
||||
#define CDC_ECM_BROADCAST_BYTES_RCV (1 << 15)
|
||||
#define CDC_ECM_BROADCAST_FRAMES_RCV (1 << 16)
|
||||
#define CDC_ECM_RCV_CRC_ERROR (1 << 17)
|
||||
#define CDC_ECM_TRANSMIT_QUEUE_LENGTH (1 << 18)
|
||||
#define CDC_ECM_RCV_ERROR_ALIGNMENT (1 << 19)
|
||||
#define CDC_ECM_XMIT_ONE_COLLISION (1 << 20)
|
||||
#define CDC_ECM_XMIT_MORE_COLLISIONS (1 << 21)
|
||||
#define CDC_ECM_XMIT_DEFERRED (1 << 22)
|
||||
#define CDC_ECM_XMIT_MAX_COLLISIONS (1 << 23)
|
||||
#define CDC_ECM_RCV_OVERRUN (1 << 24)
|
||||
#define CDC_ECM_XMIT_UNDERRUN (1 << 25)
|
||||
#define CDC_ECM_XMIT_HEARTBEAT_FAILURE (1 << 26)
|
||||
#define CDC_ECM_XMIT_TIMES_CRS_LOST (1 << 27)
|
||||
#define CDC_ECM_XMIT_LATE_COLLISIONS (1 << 28)
|
||||
|
||||
#define CDC_ECM_MAC_STR_DESC (uint8_t *)"010202030000"
|
||||
#define CDC_ECM_MAC_ADDR0 0x00U /* 01 */
|
||||
#define CDC_ECM_MAC_ADDR1 0x02U /* 02 */
|
||||
#define CDC_ECM_MAC_ADDR2 0x02U /* 03 */
|
||||
#define CDC_ECM_MAC_ADDR3 0x03U /* 00 */
|
||||
#define CDC_ECM_MAC_ADDR4 0x00U /* 00 */
|
||||
#define CDC_ECM_MAC_ADDR5 0x00U /* 00 */
|
||||
|
||||
#define CDC_ECM_NET_DISCONNECTED 0x00U
|
||||
#define CDC_ECM_NET_CONNECTED 0x01U
|
||||
|
||||
#define CDC_ECM_ETH_STATS_RESERVED 0xE0U
|
||||
#define CDC_ECM_BMREQUEST_TYPE_ECM 0xA1U
|
||||
|
||||
#define CDC_ECM_CONNECT_SPEED_UPSTREAM 0x004C4B40U /* 5Mbps */
|
||||
#define CDC_ECM_CONNECT_SPEED_DOWNSTREAM 0x004C4B40U /* 5Mbps */
|
||||
|
||||
#define CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION 0x00
|
||||
#define CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE 0x01
|
||||
#define CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE 0x2A
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Structures based on usbcdc11.pdf (www.usb.org)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/* Header functional descriptor */
|
||||
/* (usbcdc11.pdf, 5.2.3.1) */
|
||||
/* This header must precede any list of class-specific descriptors. */
|
||||
struct cdc_header_descriptor {
|
||||
uint8_t bFunctionLength; /* size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
uint8_t bDescriptorSubtype; /* Header functional descriptor subtype */
|
||||
uint16_t bcdCDC; /* USB CDC specification release version */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Call management functional descriptor */
|
||||
/* (usbcdc11.pdf, 5.2.3.2) */
|
||||
/* Describes the processing of calls for the communication class interface. */
|
||||
struct cdc_call_management_descriptor {
|
||||
uint8_t bFunctionLength; /* size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
uint8_t bDescriptorSubtype; /* call management functional descriptor subtype */
|
||||
uint8_t bmCapabilities; /* capabilities that this configuration supports */
|
||||
uint8_t bDataInterface; /* interface number of the data class interface used for call management (optional) */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Abstract control management functional descriptor */
|
||||
/* (usbcdc11.pdf, 5.2.3.3) */
|
||||
/* Describes the command supported by the communication interface class with the Abstract Control Model subclass code. */
|
||||
struct cdc_abstract_control_management_descriptor {
|
||||
uint8_t bFunctionLength; /* size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
uint8_t bDescriptorSubtype; /* abstract control management functional descriptor subtype */
|
||||
uint8_t bmCapabilities; /* capabilities supported by this configuration */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Union functional descriptors */
|
||||
/* (usbcdc11.pdf, 5.2.3.8) */
|
||||
/* Describes the relationship between a group of interfaces that can be considered to form a functional unit. */
|
||||
struct cdc_union_descriptor {
|
||||
uint8_t bFunctionLength; /* size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
uint8_t bDescriptorSubtype; /* union functional descriptor subtype */
|
||||
uint8_t bMasterInterface; /* interface number designated as master */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Union functional descriptors with one slave interface */
|
||||
/* (usbcdc11.pdf, 5.2.3.8) */
|
||||
struct cdc_union_1slave_descriptor {
|
||||
uint8_t bFunctionLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bControlInterface;
|
||||
uint8_t bSubordinateInterface0;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Line coding structure for GET_LINE_CODING / SET_LINE_CODING class requests*/
|
||||
/* Format of the data returned when a GetLineCoding request is received */
|
||||
/* (usbcdc11.pdf, 6.2.13) */
|
||||
struct cdc_line_coding {
|
||||
uint32_t dwDTERate; /* Data terminal rate in bits per second */
|
||||
uint8_t bCharFormat; /* Number of stop bits */
|
||||
uint8_t bParityType; /* Parity bit type */
|
||||
uint8_t bDataBits; /* Number of data bits */
|
||||
} __attribute__((packed));
|
||||
|
||||
/** Data structure for the notification about SerialState */
|
||||
struct cdc_acm_notification {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bNotificationType;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
uint16_t data;
|
||||
} __attribute__((packed));
|
||||
|
||||
/** Ethernet Networking Functional Descriptor */
|
||||
struct cdc_ecm_descriptor {
|
||||
uint8_t bFunctionLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t iMACAddress;
|
||||
uint32_t bmEthernetStatistics;
|
||||
uint16_t wMaxSegmentSize;
|
||||
uint16_t wNumberMCFilters;
|
||||
uint8_t bNumberPowerFilters;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cdc_ecm_notification {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bNotificationType;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
uint8_t data[8];
|
||||
} __attribute__((packed));
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
|
||||
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
|
||||
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
|
||||
WBVAL(CDC_V1_10), /* bcdCDC */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
|
||||
0x04, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x02, /* bmCapabilities */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
|
||||
bFirstInterface, /* bMasterInterface */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x08, 0x00, /* wMaxPacketSize */ \
|
||||
0x0a, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
|
||||
0x00, /* bInterfaceSubClass */ \
|
||||
0x00, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
// clang-format on
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
#define CDC_RNDIS_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
|
||||
WBVAL(CDC_V1_10), /* bcdCDC */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
|
||||
0x04, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
|
||||
0x00, /* bmCapabilities */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
|
||||
bFirstInterface, /* bMasterInterface */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x08, 0x00, /* wMaxPacketSize */ \
|
||||
0x10, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
|
||||
0x00, /* bInterfaceSubClass */ \
|
||||
0x00, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
// clang-format on
|
||||
|
||||
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
|
||||
eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
|
||||
CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
|
||||
CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
|
||||
WBVAL(CDC_V1_10), /* bcdCDC */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
|
||||
bFirstInterface, /* bMasterInterface */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||
/* CDC_ECM Functional Descriptor */ \
|
||||
0x0D, /* bFunctionLength */\
|
||||
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */\
|
||||
CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
|
||||
str_idx, /* Device's MAC string index */\
|
||||
DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
|
||||
WBVAL(wMaxPacketSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
|
||||
WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
|
||||
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x10, 0x00, /* wMaxPacketSize */ \
|
||||
0x10, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
|
||||
0x00, /* bInterfaceSubClass */ \
|
||||
0x00, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
// clang-format on
|
||||
|
||||
#endif /* USB_CDC_H_ */
|
||||
|
|
|
@ -1,6 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_HUB_H_
|
||||
#define USB_HUB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* HUB Class Descriptor Types */
|
||||
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
|
||||
#define HUB_DESCRIPTOR_TYPE_HUB3 0x2a
|
||||
|
||||
/* Hub class requests */
|
||||
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
|
||||
#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
|
||||
#define HUB_REQUEST_SET_FEATURE USB_REQUEST_SET_FEATURE
|
||||
#define HUB_REQUEST_GET_DESCRIPTOR USB_REQUEST_GET_DESCRIPTOR
|
||||
#define HUB_REQUEST_SET_DESCRIPTOR USB_REQUEST_SET_DESCRIPTOR
|
||||
#define HUB_REQUEST_CLEAR_TT_BUFFER (0x08)
|
||||
#define HUB_REQUEST_RESET_TT (0x09)
|
||||
#define HUB_REQUEST_GET_TT_STATE (0x0a)
|
||||
#define HUB_REQUEST_STOP_TT (0x0b)
|
||||
#define HUB_REQUEST_SET_HUB_DEPTH (0x0C)
|
||||
|
||||
/* Hub class features */
|
||||
#define HUB_FEATURE_HUB_C_LOCALPOWER (0x0)
|
||||
#define HUB_FEATURE_HUB_C_OVERCURRENT (0x1)
|
||||
|
||||
/* Port features */
|
||||
#define HUB_PORT_FEATURE_CONNECTION (0x00)
|
||||
#define HUB_PORT_FEATURE_ENABLE (0x01)
|
||||
#define HUB_PORT_FEATURE_SUSPEND (0x02)
|
||||
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
|
||||
#define HUB_PORT_FEATURE_RESET (0x04)
|
||||
#define HUB_PORT_FEATURE_L1 (0x05)
|
||||
#define HUB_PORT_FEATURE_POWER (0x08)
|
||||
#define HUB_PORT_FEATURE_LOWSPEED (0x09)
|
||||
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a)
|
||||
#define HUB_PORT_FEATURE_C_CONNECTION (0x10)
|
||||
#define HUB_PORT_FEATURE_C_ENABLE (0x11)
|
||||
#define HUB_PORT_FEATURE_C_SUSPEND (0x12)
|
||||
#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
|
||||
#define HUB_PORT_FEATURE_C_RESET (0x14)
|
||||
#define HUB_PORT_FEATURE_TEST (0x15)
|
||||
#define HUB_PORT_FEATURE_INDICATOR (0x16)
|
||||
#define HUB_PORT_FEATURE_C_PORTL1 (0x17)
|
||||
|
||||
/* Hub status */
|
||||
#define HUB_STATUS_LOCALPOWER (1 << 0)
|
||||
#define HUB_STATUS_OVERCURRENT (1 << 1)
|
||||
|
||||
/* Hub status change */
|
||||
#define HUB_STATUS_C_LOCALPOWER (1 << 0)
|
||||
#define HUB_STATUS_C_OVERCURRENT (1 << 1)
|
||||
|
||||
/* Hub port status */
|
||||
#define HUB_PORT_STATUS_CONNECTION (1 << 0)
|
||||
#define HUB_PORT_STATUS_ENABLE (1 << 1)
|
||||
#define HUB_PORT_STATUS_SUSPEND (1 << 2)
|
||||
#define HUB_PORT_STATUS_OVERCURRENT (1 << 3)
|
||||
#define HUB_PORT_STATUS_RESET (1 << 4)
|
||||
#define HUB_PORT_STATUS_L1 (1 << 5)
|
||||
#define HUB_PORT_STATUS_POWER (1 << 8)
|
||||
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9)
|
||||
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10)
|
||||
#define HUB_PORT_STATUS_TEST (1 << 11)
|
||||
#define HUB_PORT_STATUS_INDICATOR (1 << 12)
|
||||
|
||||
/* Hub port status change */
|
||||
#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
|
||||
#define HUB_PORT_STATUS_C_ENABLE (1 << 1)
|
||||
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2)
|
||||
#define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3)
|
||||
#define HUB_PORT_STATUS_C_RESET (1 << 4)
|
||||
#define HUB_PORT_STATUS_C_L1 (1 << 5)
|
||||
|
||||
/* Hub characteristics */
|
||||
#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */
|
||||
#define HUB_CHAR_LPSM_MASK (3 << HUB_CHAR_LPSM_SHIFT)
|
||||
#define HUB_CHAR_LPSM_GANGED (0 << HUB_CHAR_LPSM_SHIFT)
|
||||
#define HUB_CHAR_LPSM_INDIVIDUAL (1 << HUB_CHAR_LPSM_SHIFT)
|
||||
#define HUB_CHAR_COMPOUND (1 << 2) /* Bit 2: Compound device */
|
||||
#define HUB_CHAR_OCPM_SHIFT (3) /* Bits 3-4: Over-current Protection Mode */
|
||||
#define HUB_CHAR_OCPM_MASK (3 << HUB_CHAR_OCPM_SHIFT)
|
||||
#define HUB_CHAR_OCPM_GLOBAL (0 << HUB_CHAR_OCPM_SHIFT)
|
||||
#define HUB_CHAR_OCPM_INDIVIDUAL (1 << HUB_CHAR_OCPM_SHIFT)
|
||||
#define HUB_CHAR_TTTT_SHIFT (5) /* Bits 5-6: TT Think Time */
|
||||
#define HUB_CHAR_TTTT_MASK (3 << HUB_CHAR_TTTT_SHIFT)
|
||||
#define HUB_CHAR_TTTT_8_BITS (0 << HUB_CHAR_TTTT_SHIFT)
|
||||
#define HUB_CHAR_TTTT_16_BITS (1 << HUB_CHAR_TTTT_SHIFT)
|
||||
#define HUB_CHAR_TTTT_24_BITS (2 << HUB_CHAR_TTTT_SHIFT)
|
||||
#define HUB_CHAR_TTTT_32_BITS (3 << HUB_CHAR_TTTT_SHIFT)
|
||||
#define HUB_CHAR_PORTIND (1 << 7) /* Bit 7: Port Indicators Supported */
|
||||
|
||||
/* Hub descriptor */
|
||||
struct usb_hub_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bNbrPorts;
|
||||
uint16_t wHubCharacteristics;
|
||||
uint8_t bPwrOn2PwrGood;
|
||||
uint8_t bHubContrCurrent;
|
||||
uint8_t DeviceRemovable;
|
||||
uint8_t PortPwrCtrlMask;
|
||||
} __PACKED;
|
||||
|
||||
#define USB_SIZEOF_HUB_DESC 9
|
||||
|
||||
/* Hub status */
|
||||
struct hub_status {
|
||||
uint16_t wPortStatus;
|
||||
uint16_t wPortChange;
|
||||
};
|
||||
|
||||
/* Hub port status */
|
||||
struct hub_port_status {
|
||||
uint16_t wPortStatus;
|
||||
uint16_t wPortChange;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1 +1,784 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*************************************************
|
||||
File name: usbh_hub.c
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: CherryUSB third-party/cherryusb/class/hub/usbh_hub.c for references
|
||||
https://gitee.com/phytium_embedded/phytium-free-rtos-sdk/blob/master/third-party/cherryusb/class/hub/usbh_hub.c
|
||||
|
||||
History:
|
||||
1. Date: 2024-06-24
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Modify the hub to decouple from xhci.
|
||||
|
||||
2. Date: 2024-07-16
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: rndis uses naive_mmap to assign virtual and physical addresses and match the relevant codes.
|
||||
*************************************************/
|
||||
|
||||
#include "usbh_hub.h"
|
||||
#include "usb_def.h"
|
||||
#include "usyscall.h"
|
||||
|
||||
extern void xhci_dump_port_status_debug(int id); //Debugging function
|
||||
|
||||
#define DEV_FORMAT "/usb%d/hub%d"
|
||||
|
||||
#define HUB_DEBOUNCE_TIMEOUT 1500
|
||||
#define HUB_DEBOUNCE_STEP 25
|
||||
#define HUB_DEBOUNCE_STABLE 100
|
||||
#define DELAY_TIME_AFTER_RESET 200
|
||||
|
||||
#define EXTHUB_FIRST_INDEX 2
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static uint32_t g_devinuse = 0;
|
||||
#endif
|
||||
|
||||
extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
|
||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub);
|
||||
|
||||
static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
|
||||
struct usbh_bus *g_usb_debug;
|
||||
|
||||
struct usbh_hubport *usbh_get_roothub_port (struct usbh_bus *bus, unsigned int address)
|
||||
{
|
||||
return &(bus->roothub.child[ address - 1 ]);
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int usbh_hub_devno_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
|
||||
for (devno = EXTHUB_FIRST_INDEX; devno < 32; devno++) {
|
||||
uint32_t bitno = 1 << devno;
|
||||
if ((g_devinuse & bitno) == 0) {
|
||||
g_devinuse |= bitno;
|
||||
return devno;
|
||||
}
|
||||
}
|
||||
|
||||
return -EMFILE;
|
||||
}
|
||||
|
||||
static void usbh_hub_devno_free(uint8_t devno)
|
||||
{
|
||||
if (devno >= EXTHUB_FIRST_INDEX && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usbh_hub_register(struct usbh_hub *hub)
|
||||
{
|
||||
struct usbh_bus *usb = hub->usb;
|
||||
usb_slist_add_tail(&usb->hub_class_head, &hub->list);
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static void usbh_hub_unregister(struct usbh_hub *hub)
|
||||
{
|
||||
struct usbh_bus *usb = hub->usb;
|
||||
usb_slist_remove(&usb->hub_class_head, &hub->list);
|
||||
}
|
||||
|
||||
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
setup = hub->parent->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
|
||||
/* TODO: hub descriptor has some difference between USB 2.0 and USB 3.x,
|
||||
and we havn't handle the difference here */
|
||||
if ((hub->parent->speed == USB_SPEED_SUPER) ||
|
||||
(hub->parent->speed == USB_SPEED_SUPER_PLUS)) {
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
|
||||
} else {
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
|
||||
}
|
||||
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_HUB_DESC;
|
||||
|
||||
ret = usbh_control_transfer_xiuos(hub->parent, hub->parent->ep0, setup, hub->g_hub_buf_phy);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, hub->g_hub_buf, USB_SIZEOF_HUB_DESC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
setup = hub->parent->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = HUB_REQUEST_GET_STATUS;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 2;
|
||||
|
||||
ret = usbh_control_transfer_xiuos(hub->parent, hub->parent->ep0, setup, hub->g_hub_buf_phy);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, hub->g_hub_buf, 2);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
setup = hub->parent->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
|
||||
setup->bRequest = HUB_REQUEST_GET_STATUS;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 4;
|
||||
|
||||
ret = usbh_control_transfer_xiuos(hub->parent, hub->parent->ep0, setup, hub->g_hub_buf_phy);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(port_status, hub->g_hub_buf, 4);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
setup = hub->parent->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
|
||||
setup->bRequest = HUB_REQUEST_SET_FEATURE;
|
||||
setup->wValue = feature;
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer_xiuos(hub->parent, hub->parent->ep0, setup, NULL);
|
||||
}
|
||||
|
||||
static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
setup = hub->parent->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
|
||||
setup->bRequest = HUB_REQUEST_CLEAR_FEATURE;
|
||||
setup->wValue = feature;
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer_xiuos(hub->parent, hub->parent->ep0, setup, NULL);
|
||||
}
|
||||
|
||||
static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
setup = hub->parent->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = HUB_REQUEST_SET_HUB_DEPTH;
|
||||
setup->wValue = depth;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer_xiuos(hub->parent, hub->parent->ep0, setup, NULL);
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
|
||||
{
|
||||
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
|
||||
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
||||
return -1;
|
||||
} else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB) {
|
||||
USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
|
||||
return -2;
|
||||
} else {
|
||||
USB_LOG_RAW("Hub Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
|
||||
USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
|
||||
USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
|
||||
USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
|
||||
USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
|
||||
USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
|
||||
USB_LOG_RAW("PortPwrCtrlMask: 0x%02x \r\n", desc->PortPwrCtrlMask);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (hub->is_roothub) {
|
||||
setup = &roothub_setup;
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
|
||||
setup->bRequest = HUB_REQUEST_GET_STATUS;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 4;
|
||||
return usbh_roothub_control(hub->usb, &roothub_setup, (uint8_t *)port_status);
|
||||
} else {
|
||||
return _usbh_hub_get_portstatus(hub, port, port_status);
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (hub->is_roothub) {
|
||||
setup = &roothub_setup;
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
|
||||
setup->bRequest = HUB_REQUEST_SET_FEATURE;
|
||||
setup->wValue = feature;
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 0;
|
||||
return usbh_roothub_control(hub->usb, setup, NULL);
|
||||
} else {
|
||||
return _usbh_hub_set_feature(hub, port, feature);
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (hub->is_roothub) {
|
||||
setup = &roothub_setup;
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
|
||||
setup->bRequest = HUB_REQUEST_CLEAR_FEATURE;
|
||||
setup->wValue = feature;
|
||||
setup->wIndex = port;
|
||||
setup->wLength = 0;
|
||||
return usbh_roothub_control(hub->usb, setup, NULL);
|
||||
} else {
|
||||
return _usbh_hub_clear_feature(hub, port, feature);
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (hub->is_roothub) {
|
||||
setup = &roothub_setup;
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = HUB_REQUEST_SET_HUB_DEPTH;
|
||||
setup->wValue = depth;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
return usbh_roothub_control(hub->usb, setup, NULL);
|
||||
} else {
|
||||
return _usbh_hub_set_depth(hub, depth);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static void hub_int_complete_callback(void *arg, int nbytes)
|
||||
{
|
||||
struct usbh_hub *hub = (struct usbh_hub *)arg;
|
||||
|
||||
if (nbytes > 0) {
|
||||
usbh_hub_thread_wakeup(hub);
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
struct hub_port_status port_status;
|
||||
struct usbh_bus *usb = usbh_get_bus_of_port(hport);
|
||||
int ret;
|
||||
int index;
|
||||
uintptr_t vaddr, paddr;
|
||||
int rc;
|
||||
|
||||
index = usbh_hub_devno_alloc();
|
||||
if (index > (CONFIG_USBHOST_MAX_EXTHUBS + EXTHUB_FIRST_INDEX - 1)) {
|
||||
USB_LOG_ERR("No memory to alloc hub class\r\n");
|
||||
usbh_hub_devno_free(index);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
struct usbh_hub *hub = &(usb->exthub[index - EXTHUB_FIRST_INDEX]);
|
||||
|
||||
memset(hub, 0, sizeof(struct usbh_hub));
|
||||
hub->hub_addr = hport->dev_addr;
|
||||
hub->parent = hport;
|
||||
hub->index = index;
|
||||
|
||||
/* g_hub_buf allocate virtual address and physical address*/
|
||||
vaddr = USB_MEM_VIRADDR_ALLOC;
|
||||
paddr = 0;
|
||||
hub->g_hub_buf = (uint8_t *)vaddr;
|
||||
rc = naive_mmap(&vaddr, &paddr, 32, true);
|
||||
if(rc != 0){
|
||||
USB_LOG_ERR("g_hub_buf allocate error, ret: %d\n", rc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hub->g_hub_buf_phy = (uint8_t *)paddr;
|
||||
USB_LOG_DBG("usbh_hub_connect hub->g_hub_buf=%lx hub->g_hub_buf_phy=%08lx\n", hub->g_hub_buf, hub->g_hub_buf_phy);
|
||||
|
||||
hport->config.intf[intf].priv = hub;
|
||||
|
||||
ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
hub->child[port].port = port + 1;
|
||||
hub->child[port].parent = hub;
|
||||
}
|
||||
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&hub->intin, hport, ep_desc);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hport->speed == USB_SPEED_SUPER) {
|
||||
uint16_t depth = 0;
|
||||
struct usbh_hubport *parent = hport->parent->parent;
|
||||
while (parent) {
|
||||
depth++;
|
||||
parent = parent->parent->parent;
|
||||
}
|
||||
|
||||
ret = usbh_hub_set_depth(hub, depth);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
|
||||
USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
hub->ports = hub->hub_desc.bNbrPorts;
|
||||
hub->connected = true;
|
||||
hub->usb = usb;
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, usb->id, hub->index);
|
||||
usbh_hub_register(hub);
|
||||
USB_LOG_RAW("Register HUB Class:%s for USB-%d\r\n", hport->config.intf[intf].devname, usb->id);
|
||||
|
||||
hub->int_buffer = hub->g_hub_intbuf[hub->index - 1];
|
||||
usbh_int_urb_fill_xiuos(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usbh_hubport *child;
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_hub *hub = (struct usbh_hub *)hport->config.intf[intf].priv;
|
||||
|
||||
if (hub) {
|
||||
usbh_hub_devno_free(hub->index);
|
||||
|
||||
if (hub->intin) {
|
||||
usbh_pipe_free_xiuos(hport, hub->intin);
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
child = &hub->child[port];
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
child->parent = NULL;
|
||||
}
|
||||
|
||||
usbh_hub_unregister(hub);
|
||||
memset(hub, 0, sizeof(struct usbh_hub));
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0')
|
||||
USB_LOG_RAW("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usbh_hubport_release(struct usbh_hubport *child)
|
||||
{
|
||||
if (child->connected) {
|
||||
child->connected = false;
|
||||
usbh_hport_deactivate_ep0(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hub_dump_status(struct usbh_hub *hub, uint8_t port, uint16_t portstatus, uint16_t portchange)
|
||||
{
|
||||
USB_LOG_DBG("===================== \r\n");
|
||||
USB_LOG_DBG("hub-%d port-%d status 0x%x\r\n", hub->hub_addr, port, portstatus);
|
||||
USB_LOG_DBG(" connection: %d\r\n", !!(portstatus & HUB_PORT_STATUS_CONNECTION));
|
||||
USB_LOG_DBG(" enable: %d\r\n", !!(portstatus & HUB_PORT_STATUS_ENABLE));
|
||||
USB_LOG_DBG(" suspend: %d\r\n", !!(portstatus & HUB_PORT_STATUS_SUSPEND));
|
||||
USB_LOG_DBG(" overcurrent: %d\r\n", !!(portstatus & HUB_PORT_STATUS_OVERCURRENT));
|
||||
USB_LOG_DBG(" reseting: %d\r\n", !!(portstatus & HUB_PORT_STATUS_RESET));
|
||||
USB_LOG_DBG(" power: %d\r\n", !!(portstatus & HUB_PORT_STATUS_POWER));
|
||||
if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
|
||||
USB_LOG_DBG(" low-speed\r\n");
|
||||
} else if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
|
||||
USB_LOG_DBG(" high-speed\r\n");
|
||||
} else {
|
||||
USB_LOG_DBG(" full-speed\r\n");
|
||||
}
|
||||
USB_LOG_DBG(" test: %d\r\n", !!(portstatus & HUB_PORT_STATUS_TEST));
|
||||
USB_LOG_DBG(" indicator: %d\r\n", !!(portstatus & HUB_PORT_STATUS_INDICATOR));
|
||||
USB_LOG_DBG("hub-%d port-%d change 0x%x\r\n", hub->hub_addr, port, portchange);
|
||||
USB_LOG_DBG(" connection change: %d\r\n", !!(portchange & HUB_PORT_STATUS_C_CONNECTION));
|
||||
USB_LOG_DBG(" enable change: %d\r\n", !!(portchange & HUB_PORT_STATUS_C_ENABLE));
|
||||
USB_LOG_DBG(" suspend change: %d\r\n", !!(portchange & HUB_PORT_STATUS_C_SUSPEND));
|
||||
USB_LOG_DBG(" overcurrent change: %d\r\n", !!(portchange & HUB_PORT_STATUS_C_OVERCURRENT));
|
||||
USB_LOG_DBG(" reset change: %d\r\n", !!(portchange & HUB_PORT_STATUS_C_RESET));
|
||||
USB_LOG_DBG("=====================\r\n");
|
||||
}
|
||||
|
||||
static void usbh_hub_events(struct usbh_hub *hub)
|
||||
{
|
||||
struct usbh_hubport *child;
|
||||
struct hub_port_status port_status;
|
||||
uint8_t portchange_index;
|
||||
uint16_t portstatus;
|
||||
uint16_t portchange;
|
||||
uint16_t mask;
|
||||
uint16_t feat;
|
||||
uint8_t speed;
|
||||
int ret;
|
||||
|
||||
if (!hub->connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
portchange_index = hub->int_buffer[0];
|
||||
|
||||
USB_LOG_DBG("Port change:0x%02x, Port:%u\r\n", portchange_index, port + 1);
|
||||
|
||||
if (!(portchange_index & (1 << (port + 1)))) {
|
||||
continue;
|
||||
}
|
||||
portchange_index &= ~(1 << (port + 1));
|
||||
USB_LOG_DBG("Port %d change\r\n", port + 1);
|
||||
|
||||
/* Read hub port status */
|
||||
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
portstatus = port_status.wPortStatus;
|
||||
portchange = port_status.wPortChange;
|
||||
|
||||
usbh_hub_dump_status(hub, port + 1, portstatus, portchange);
|
||||
|
||||
/* First, clear all change bits */
|
||||
mask = 1;
|
||||
feat = HUB_PORT_FEATURE_C_CONNECTION;
|
||||
while (portchange) {
|
||||
if (portchange & mask) {
|
||||
ret = usbh_hub_clear_feature(hub, port + 1, feat);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to clear port %u, change mask:%04x, errorcode:%d\r\n", port + 1, mask, ret);
|
||||
continue;
|
||||
}
|
||||
portchange &= (~mask);
|
||||
}
|
||||
mask <<= 1;
|
||||
feat++;
|
||||
}
|
||||
|
||||
portchange = port_status.wPortChange;
|
||||
|
||||
/* Second, if port changes, debounces first */
|
||||
if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
|
||||
uint16_t connection = 0;
|
||||
uint16_t debouncestable = 0;
|
||||
for (uint32_t debouncetime = 0; debouncetime < HUB_DEBOUNCE_TIMEOUT; debouncetime += HUB_DEBOUNCE_STEP) {
|
||||
/* Read hub port status */
|
||||
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
portstatus = port_status.wPortStatus;
|
||||
portchange = port_status.wPortChange;
|
||||
|
||||
USB_LOG_DBG("Port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange);
|
||||
|
||||
if (!(portchange & HUB_PORT_STATUS_C_CONNECTION) &&
|
||||
((portstatus & HUB_PORT_STATUS_CONNECTION) == connection)) {
|
||||
debouncestable += HUB_DEBOUNCE_STEP;
|
||||
if (debouncestable >= HUB_DEBOUNCE_STABLE) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
debouncestable = 0;
|
||||
connection = portstatus & HUB_PORT_STATUS_CONNECTION;
|
||||
}
|
||||
|
||||
if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
|
||||
usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION);
|
||||
}
|
||||
|
||||
usb_osal_msleep(HUB_DEBOUNCE_STEP);
|
||||
}
|
||||
|
||||
/** check if debounce ok */
|
||||
if (debouncestable < HUB_DEBOUNCE_STABLE) {
|
||||
USB_LOG_ERR("Failed to debounce port %u\r\n", port + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Last, check connect status */
|
||||
if (portstatus & HUB_PORT_STATUS_CONNECTION) {
|
||||
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_RESET);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to reset port %u,errorcode:%d\r\n", port + 1, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
usb_osal_msleep(DELAY_TIME_AFTER_RESET);
|
||||
/* Read hub port status */
|
||||
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
portstatus = port_status.wPortStatus;
|
||||
portchange = port_status.wPortChange;
|
||||
USB_LOG_DBG("Reset: %d, Enable: %d \r\n",
|
||||
!!(portstatus & HUB_PORT_STATUS_RESET),
|
||||
!!(portstatus & HUB_PORT_STATUS_ENABLE));
|
||||
if (!(portstatus & HUB_PORT_STATUS_RESET) && (portstatus & HUB_PORT_STATUS_ENABLE)) {
|
||||
if (portchange & HUB_PORT_STATUS_C_RESET) {
|
||||
ret = usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_RESET);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to clear port %u reset change, errorcode: %d\r\n", port + 1, ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
|
||||
speed = USB_SPEED_HIGH;
|
||||
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
|
||||
speed = USB_SPEED_LOW;
|
||||
}
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
/* USB3.0 speed cannot get from portstatus, checkout port speed instead */
|
||||
else {
|
||||
uint8_t port_speed = usbh_get_port_speed(hub, port + 1);
|
||||
if (port_speed >= USB_SPEED_SUPER) {
|
||||
/* assert that when using USB 3.0 ports, attached device must also be USB 3.0 speed */
|
||||
speed = port_speed;
|
||||
} else {
|
||||
speed = USB_SPEED_FULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
else {
|
||||
speed = USB_SPEED_FULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
child = &hub->child[port];
|
||||
/** release child sources first */
|
||||
usbh_hubport_release(child);
|
||||
|
||||
memset(child, 0, sizeof(struct usbh_hubport));
|
||||
child->parent = hub;
|
||||
child->connected = true;
|
||||
child->port = port + 1;
|
||||
child->speed = speed;
|
||||
|
||||
USB_LOG_RAW("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1);
|
||||
|
||||
/* Configure EP0 with the default maximum packet size */
|
||||
usbh_hport_activate_ep0(child);
|
||||
|
||||
if (usbh_enumerate(child) < 0) {
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
USB_LOG_ERR("Port %u enumerate fail\r\n", port + 1);
|
||||
}
|
||||
} else {
|
||||
child = &hub->child[port];
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
|
||||
/** some USB 3.0 ip may failed to enable USB 2.0 port for USB 3.0 device */
|
||||
USB_LOG_WRN("Failed to enable port %u\r\n", port + 1);
|
||||
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
child = &hub->child[port];
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
USB_LOG_INFO("Device on Hub %u, Port %u disconnected\r\n", hub->index, port + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hub->int_buffer[0] = 0;
|
||||
/* Start next hub int transfer */
|
||||
if (!hub->is_roothub && hub->connected) {
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hub_thread(void *argument)
|
||||
{
|
||||
struct usbh_hub *hub;
|
||||
int ret = 0;
|
||||
struct usbh_bus *usb = (struct usbh_bus *)argument;
|
||||
|
||||
USB_LOG_DBG("usbh_hub_thread usb pointer=%08x\r\n", usb);
|
||||
usb = g_usb_debug;
|
||||
USB_LOG_DBG("usbh_hub_thread usb pointer=%08x\r\n", usb);
|
||||
usb_hc_init(usb->id);
|
||||
while (1) {
|
||||
USB_LOG_DBG("wait event of mq@%p \r\n", usb->hub_mq);
|
||||
ret = usb_osal_mq_recv(usb->hub_mq, (void *)&hub, 10000);
|
||||
if (ret <= 0) {
|
||||
xhci_dump_port_status_debug(usb->id);
|
||||
continue;
|
||||
}
|
||||
USB_LOG_DBG("handle event of hub@%p \r\n", hub);
|
||||
usbh_hub_events(hub);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_roothub_register(struct usbh_bus *usb)
|
||||
{
|
||||
struct usbh_hub* roothub = &(usb->roothub);
|
||||
memset(roothub, 0, sizeof(struct usbh_hub));
|
||||
|
||||
roothub->connected = true;
|
||||
roothub->index = 1;
|
||||
roothub->is_roothub = true;
|
||||
roothub->parent = NULL;
|
||||
roothub->hub_addr = 1;
|
||||
roothub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
|
||||
roothub->usb = usb;
|
||||
usbh_hub_register(roothub);
|
||||
}
|
||||
|
||||
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||
{
|
||||
USB_LOG_DBG("try to wakeup hub0x%x \r\n", hub);
|
||||
struct usbh_bus *usb = hub->usb;
|
||||
usb_osal_mq_send(usb->hub_mq, (uintptr_t)hub);
|
||||
}
|
||||
|
||||
void usbh_roothub_thread_wakeup(uint32_t usb_id, uint8_t port)
|
||||
{
|
||||
struct usbh_bus* usb = usbh_get_bus_of_index(usb_id);
|
||||
struct usbh_hub* roothub = &(usb->roothub);
|
||||
|
||||
roothub->int_buffer = roothub->g_hub_intbuf[roothub->index - 1];
|
||||
roothub->int_buffer[0] |= (1 << port);
|
||||
USB_LOG_DBG("port-%u wakeup roothub@%p \r\n", port, roothub);
|
||||
usbh_hub_thread_wakeup(roothub);
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
const struct usbh_class_driver hub_class_driver = {
|
||||
.driver_name = "hub",
|
||||
.connect = usbh_hub_connect,
|
||||
.disconnect = usbh_hub_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE struct usbh_class_info hub_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = USB_DEVICE_CLASS_HUB,
|
||||
.subclass = 0,
|
||||
.protocol = 0,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &hub_class_driver
|
||||
};
|
||||
#endif
|
||||
|
||||
int usbh_hub_initialize(struct usbh_bus *usb)
|
||||
{
|
||||
usbh_class_info_set(USBH_CLASS_INFO_HUB, &hub_class_info);
|
||||
|
||||
usbh_roothub_register(usb);
|
||||
|
||||
usb->hub_mq = usb_osal_mq_create(7);
|
||||
if (usb->hub_mq == NULL) {
|
||||
return -1;
|
||||
}
|
||||
g_usb_debug = usb;
|
||||
USB_LOG_DBG("usbh_hub_initialize usb pointer=%08x\r\n", usb);
|
||||
char thread_name[12];
|
||||
snprintf(thread_name, 12, "usb%d_hub", usb->id);
|
||||
usb->hub_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, usb);
|
||||
if (usb->hub_thread == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#if 1
|
||||
usb_osal_msleep(10); //Avoid log character confusion after usb_osal_thread_create
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_HUB_H_
|
||||
#define USBH_HUB_H_
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usb_hub.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbh_roothub_thread_wakeup(uint32_t usb_id, uint8_t port);
|
||||
int usbh_hub_initialize(struct usbh_bus *usb);
|
||||
struct usbh_hubport *usbh_get_roothub_port (struct usbh_bus *bus, unsigned int port);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
include $(KERNEL_ROOT)/services/drivers/usb/components/usb.mk
|
||||
|
||||
objs = usbh_rndis.o rndis_host.o
|
||||
|
||||
all: ${objs}
|
||||
@echo "generate $^"
|
||||
@mv $^ $(KERNEL_ROOT)/services/drivers/usb/components
|
||||
|
||||
%.o: %.c
|
||||
@echo "cc $^"
|
||||
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^
|
|
@ -0,0 +1,277 @@
|
|||
/* This file has been prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file ndis.h ***************************************************************
|
||||
*
|
||||
* \brief
|
||||
* This file contains the possible external configuration of the USB.
|
||||
*
|
||||
* \addtogroup usbstick
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
\ingroup usbstick
|
||||
\defgroup RNDIS RNDIS Support
|
||||
@{
|
||||
*/
|
||||
|
||||
/*
|
||||
* ndis.h
|
||||
*
|
||||
* Modified by Colin O'Flynn <coflynn@newae.com>
|
||||
* ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
|
||||
*
|
||||
* Thanks to the cygwin development team,
|
||||
* espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
|
||||
*
|
||||
* THIS SOFTWARE IS NOT COPYRIGHTED
|
||||
*
|
||||
* This source code is offered for use in the public domain. You may
|
||||
* use, modify or distribute it freely.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful but
|
||||
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
|
||||
* DISCLAIMED. This includes but is not limited to warranties of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: ndis.h
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: take CherryUSB v0.10.2/class/wireless/ndis.h for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/class/wireless/ndis.h
|
||||
*************************************************/
|
||||
|
||||
#ifndef _NDIS_H_
|
||||
#define _NDIS_H_
|
||||
|
||||
#define NDIS_STATUS_MULTICAST_FULL 0xC0010009
|
||||
#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
|
||||
#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B
|
||||
|
||||
/* from drivers/net/sk98lin/h/skgepnmi.h */
|
||||
#define OID_PNP_CAPABILITIES 0xFD010100
|
||||
#define OID_PNP_SET_POWER 0xFD010101
|
||||
#define OID_PNP_QUERY_POWER 0xFD010102
|
||||
#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
|
||||
#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
|
||||
#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
|
||||
|
||||
enum NDIS_DEVICE_POWER_STATE {
|
||||
NdisDeviceStateUnspecified = 0,
|
||||
NdisDeviceStateD0,
|
||||
NdisDeviceStateD1,
|
||||
NdisDeviceStateD2,
|
||||
NdisDeviceStateD3,
|
||||
NdisDeviceStateMaximum
|
||||
};
|
||||
|
||||
struct NDIS_PM_WAKE_UP_CAPABILITIES {
|
||||
enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
|
||||
enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp;
|
||||
enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp;
|
||||
};
|
||||
|
||||
/* NDIS_PNP_CAPABILITIES.Flags constants */
|
||||
#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001
|
||||
#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002
|
||||
#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004
|
||||
|
||||
/*
|
||||
struct NDIS_PNP_CAPABILITIES {
|
||||
__le32 Flags;
|
||||
struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities;
|
||||
};
|
||||
|
||||
struct NDIS_PM_PACKET_PATTERN {
|
||||
__le32 Priority;
|
||||
__le32 Reserved;
|
||||
__le32 MaskSize;
|
||||
__le32 PatternOffset;
|
||||
__le32 PatternSize;
|
||||
__le32 PatternFlags;
|
||||
};
|
||||
*/
|
||||
|
||||
/* Required Object IDs (OIDs) */
|
||||
#define OID_GEN_SUPPORTED_LIST 0x00010101
|
||||
#define OID_GEN_HARDWARE_STATUS 0x00010102
|
||||
#define OID_GEN_MEDIA_SUPPORTED 0x00010103
|
||||
#define OID_GEN_MEDIA_IN_USE 0x00010104
|
||||
#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
|
||||
#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
|
||||
#define OID_GEN_LINK_SPEED 0x00010107
|
||||
#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
|
||||
#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
|
||||
#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
|
||||
#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
|
||||
#define OID_GEN_VENDOR_ID 0x0001010C
|
||||
#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
|
||||
#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
|
||||
#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
|
||||
#define OID_GEN_DRIVER_VERSION 0x00010110
|
||||
#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
|
||||
#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
|
||||
#define OID_GEN_MAC_OPTIONS 0x00010113
|
||||
#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
|
||||
#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
|
||||
#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
|
||||
#define OID_GEN_SUPPORTED_GUIDS 0x00010117
|
||||
#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118
|
||||
#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119
|
||||
#define OID_GEN_MACHINE_NAME 0x0001021A
|
||||
#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B
|
||||
#define OID_GEN_VLAN_ID 0x0001021C
|
||||
|
||||
/* Optional OIDs */
|
||||
#define OID_GEN_MEDIA_CAPABILITIES 0x00010201
|
||||
#define OID_GEN_PHYSICAL_MEDIUM 0x00010202
|
||||
|
||||
/* Required statistics OIDs */
|
||||
#define OID_GEN_XMIT_OK 0x00020101
|
||||
#define OID_GEN_RCV_OK 0x00020102
|
||||
#define OID_GEN_XMIT_ERROR 0x00020103
|
||||
#define OID_GEN_RCV_ERROR 0x00020104
|
||||
#define OID_GEN_RCV_NO_BUFFER 0x00020105
|
||||
|
||||
/* Optional statistics OIDs */
|
||||
#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
|
||||
#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
|
||||
#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
|
||||
#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
|
||||
#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
|
||||
#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
|
||||
#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
|
||||
#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
|
||||
#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
|
||||
#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
|
||||
#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
|
||||
#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
|
||||
#define OID_GEN_RCV_CRC_ERROR 0x0002020D
|
||||
#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
|
||||
#define OID_GEN_GET_TIME_CAPS 0x0002020F
|
||||
#define OID_GEN_GET_NETCARD_TIME 0x00020210
|
||||
#define OID_GEN_NETCARD_LOAD 0x00020211
|
||||
#define OID_GEN_DEVICE_PROFILE 0x00020212
|
||||
#define OID_GEN_INIT_TIME_MS 0x00020213
|
||||
#define OID_GEN_RESET_COUNTS 0x00020214
|
||||
#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215
|
||||
#define OID_GEN_FRIENDLY_NAME 0x00020216
|
||||
#define OID_GEN_MINIPORT_INFO 0x00020217
|
||||
#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218
|
||||
|
||||
/* IEEE 802.3 (Ethernet) OIDs */
|
||||
#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
|
||||
|
||||
#define OID_802_3_PERMANENT_ADDRESS 0x01010101
|
||||
#define OID_802_3_CURRENT_ADDRESS 0x01010102
|
||||
#define OID_802_3_MULTICAST_LIST 0x01010103
|
||||
#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
|
||||
#define OID_802_3_MAC_OPTIONS 0x01010105
|
||||
#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
|
||||
#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
|
||||
#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
|
||||
#define OID_802_3_XMIT_DEFERRED 0x01020201
|
||||
#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
|
||||
#define OID_802_3_RCV_OVERRUN 0x01020203
|
||||
#define OID_802_3_XMIT_UNDERRUN 0x01020204
|
||||
#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
|
||||
#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
|
||||
#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
|
||||
|
||||
/* Wireless LAN OIDs */
|
||||
/* Mandatory */
|
||||
#define OID_802_11_BSSID 0x0D010101 /* Q S */
|
||||
#define OID_802_11_SSID 0x0D010102 /* Q S */
|
||||
#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */
|
||||
#define OID_802_11_RSSI 0x0D010206 /* Q I */
|
||||
#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */
|
||||
#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */
|
||||
#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */
|
||||
#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */
|
||||
#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */
|
||||
#define OID_802_11_ADD_WEP 0x0D010113 /* S */
|
||||
#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */
|
||||
#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */
|
||||
#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */
|
||||
#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */
|
||||
#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */
|
||||
|
||||
/* OID_GEN_MINIPORT_INFO constants */
|
||||
#define NDIS_MINIPORT_BUS_MASTER 0x00000001
|
||||
#define NDIS_MINIPORT_WDM_DRIVER 0x00000002
|
||||
#define NDIS_MINIPORT_SG_LIST 0x00000004
|
||||
#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008
|
||||
#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010
|
||||
#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020
|
||||
#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040
|
||||
#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080
|
||||
#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100
|
||||
#define NDIS_MINIPORT_IS_NDIS_5 0x00000200
|
||||
#define NDIS_MINIPORT_IS_CO 0x00000400
|
||||
#define NDIS_MINIPORT_DESERIALIZE 0x00000800
|
||||
#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000
|
||||
#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000
|
||||
#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000
|
||||
#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000
|
||||
#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000
|
||||
#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000
|
||||
#define NDIS_MINIPORT_HIDDEN 0x00040000
|
||||
#define NDIS_MINIPORT_SWENUM 0x00080000
|
||||
#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000
|
||||
#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000
|
||||
#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000
|
||||
#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000
|
||||
#define NDIS_MINIPORT_64BITS_DMA 0x01000000
|
||||
|
||||
#define NDIS_MEDIUM_802_3 0x00000000
|
||||
#define NDIS_MEDIUM_802_5 0x00000001
|
||||
#define NDIS_MEDIUM_FDDI 0x00000002
|
||||
#define NDIS_MEDIUM_WAN 0x00000003
|
||||
#define NDIS_MEDIUM_LOCAL_TALK 0x00000004
|
||||
#define NDIS_MEDIUM_DIX 0x00000005
|
||||
#define NDIS_MEDIUM_ARCENT_RAW 0x00000006
|
||||
#define NDIS_MEDIUM_ARCENT_878_2 0x00000007
|
||||
#define NDIS_MEDIUM_ATM 0x00000008
|
||||
#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009
|
||||
#define NDIS_MEDIUM_IRDA 0x0000000A
|
||||
#define NDIS_MEDIUM_BPC 0x0000000B
|
||||
#define NDIS_MEDIUM_CO_WAN 0x0000000C
|
||||
#define NDIS_MEDIUM_1394 0x0000000D
|
||||
|
||||
#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
|
||||
#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
|
||||
#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
|
||||
#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
|
||||
#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
|
||||
#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
|
||||
#define NDIS_PACKET_TYPE_SMT 0x00000040
|
||||
#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
|
||||
#define NDIS_PACKET_TYPE_GROUP 0x00000100
|
||||
#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200
|
||||
#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
|
||||
#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
|
||||
|
||||
#define NDIS_MEDIA_STATE_CONNECTED 0x00000000
|
||||
#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001
|
||||
|
||||
#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
|
||||
#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
|
||||
#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
|
||||
#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
|
||||
#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
|
||||
#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
|
||||
#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040
|
||||
#define NDIS_MAC_OPTION_RESERVED 0x80000000
|
||||
|
||||
/** Hardware status of the underlying NIC */
|
||||
#define NDIS_HW_STS_READY 0x00000000UL
|
||||
#define NDIS_HW_STS_INITIALIZING 0x00000001UL
|
||||
#define NDIS_HW_STS_RESET 0x00000002UL
|
||||
#define NDIS_HW_STS_CLOSING 0x00000003UL
|
||||
#define NDIS_HW_STS_NOT_READY 0x00000004UL
|
||||
|
||||
#endif /* _NDIS_H_ */
|
||||
|
||||
/** @} */
|
|
@ -1 +1,287 @@
|
|||
/* FreeRTOS kernel includes. */
|
||||
|
||||
/*************************************************
|
||||
File name: rndis_host.c
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: CherryUSB v0.10.2/CherryUSB/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c
|
||||
|
||||
History:
|
||||
1. Date: 2024-07-22
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Modify rndis_host.c according to
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/third_party/rt-thread-4.1.1/rndis_host/rndis_host_lwip2.1.2.c
|
||||
and https://github.com/longtengmcu/USB-HOST-driver-4G-rndis-device/components/drivers/usb/usbhost/class/rndis_dev.c (Zhaoshimin).
|
||||
|
||||
2. Date: 2024-07-23
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: rndis bulk transfer buffer uses physical addresses.
|
||||
|
||||
3. Date: 2024-07-23
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Modify MessageLength in usbh_rndis_eth_tx, see https://github.com/cherry-embedded/CherryUSB.
|
||||
|
||||
4. Date: 2024-07-24
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Modify IPC-related functions in rndis.
|
||||
*************************************************/
|
||||
#include <usb_osal.h>
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_rndis.h"
|
||||
#include "rndis_protocol.h"
|
||||
#include "usyscall.h"
|
||||
|
||||
/* define the rdnis device state*/
|
||||
#define RNDIS_BUS_UNINITIALIZED 0
|
||||
#define RNDIS_BUS_INITIALIZED 1
|
||||
#define RNDIS_INITIALIZED 2
|
||||
#define RNDIS_DATA_INITIALIZED 3
|
||||
|
||||
#define USB_ETH_MTU (1500 + 14)
|
||||
#define RNDIS_THREAD_STACK_SIZE (4096)
|
||||
|
||||
#define NIOCTL_GADDR 0x01
|
||||
#define MAX_ADDR_LEN 6
|
||||
/* rndis device keepalive time 5000ms*/
|
||||
#define RNDIS_DEV_KEEPALIVE_TIMEOUT 5000
|
||||
/*should be the usb Integer multiple of maximum packet length N*64*/
|
||||
#define RNDIS_ETH_BUFFER_LEN (sizeof(rndis_data_packet_t) + USB_ETH_MTU + 42)
|
||||
/* The maximum number of concatenated REMOTE_NDIS_PACKET_MSG messages in a single bus transfer to it, see MaxPacketsPerTransfer in REMOTE_NDIS_INITIALIZE_CMPLT. */
|
||||
#define RNDIS_RXETH_BUFFER_LEN (RNDIS_ETH_BUFFER_LEN * 1)
|
||||
|
||||
/* Static Variable Definition*/
|
||||
static struct usbh_rndis *s_rndis_class_ptr;
|
||||
|
||||
//USB_NOCACHE_RAM_SECTION uint8_t tx_buffer[RNDIS_ETH_BUFFER_LEN];
|
||||
//USB_NOCACHE_RAM_SECTION uint8_t rx_buffer[RNDIS_RXETH_BUFFER_LEN];
|
||||
//static uint8_t *rx_buf_ptr;
|
||||
static uint8_t *tx_buffer;
|
||||
static uint8_t *tx_buffer_phy;
|
||||
static uint8_t *rx_buffer;
|
||||
static uint8_t *rx_buffer_phy;
|
||||
|
||||
usb_osal_sem_t mutex_sem_handle;
|
||||
usb_osal_thread_t timer_handle;
|
||||
usb_osal_thread_t data_recv_task_handle;
|
||||
|
||||
|
||||
__WEAK int lwip_rndis_device_linkchange(bool up)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK int lwip_rndis_data_recv(void *dataptr, size_t len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rndis_dev_keepalive_timeout(void *pdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
usb_osal_msleep(RNDIS_DEV_KEEPALIVE_TIMEOUT);
|
||||
|
||||
usb_osal_sem_take(mutex_sem_handle, USB_OSAL_WAITING_FOREVER);
|
||||
ret = usbh_rndis_keepalive(s_rndis_class_ptr);
|
||||
usb_osal_sem_give(mutex_sem_handle);
|
||||
if (ret < 0) {
|
||||
printf("rndis dev keepalive timeout!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_rndis_data_recv_entry(void *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
rndis_data_packet_t *pmsg;
|
||||
int pmg_offset;
|
||||
int recount = 5;
|
||||
uint8_t data[4];
|
||||
uint32_t info_len = 0;
|
||||
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)pdata;
|
||||
|
||||
if (!rndis_class->link_status) {
|
||||
printf("linkdown, drop pkg\r\n");
|
||||
while(recount--) {
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, sizeof(data), data, &info_len);
|
||||
if (ret < 0) {
|
||||
continue;;
|
||||
}
|
||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||
s_rndis_class_ptr->link_status = true;
|
||||
lwip_rndis_device_linkchange(true);
|
||||
printf("linkup, drop pkg\r\n");
|
||||
break;
|
||||
} else {
|
||||
s_rndis_class_ptr->link_status = false;
|
||||
lwip_rndis_device_linkchange(false);
|
||||
}
|
||||
usb_osal_msleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
pmg_offset = 0;
|
||||
ret = usbh_rndis_bulk_in_transfer(rndis_class, rx_buffer_phy, RNDIS_RXETH_BUFFER_LEN, USB_OSAL_WAITING_FOREVER);
|
||||
if (ret <= 0) {
|
||||
usb_osal_msleep(1);
|
||||
continue;
|
||||
}
|
||||
while (ret > 0) {
|
||||
pmsg = (rndis_data_packet_t *)(rx_buffer + pmg_offset);
|
||||
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
|
||||
lwip_rndis_data_recv((uint8_t *)(&pmsg->DataOffset) + pmsg->DataOffset, pmsg->DataLength);
|
||||
pmg_offset += pmsg->MessageLength;
|
||||
ret -= pmsg->MessageLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
uintptr_t vaddr, paddr;
|
||||
int ret;
|
||||
|
||||
s_rndis_class_ptr = rndis_class;
|
||||
|
||||
vaddr = USB_MEM_VIRADDR_ALLOC;
|
||||
paddr = 0;
|
||||
tx_buffer = (uint8_t *)vaddr;
|
||||
ret = naive_mmap(&vaddr, &paddr, RNDIS_ETH_BUFFER_LEN, true);
|
||||
if(ret != 0){
|
||||
USB_LOG_ERR("tx_buf_ptr allocate error, ret: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
tx_buffer_phy = (uint8_t *)paddr;
|
||||
USB_LOG_DBG("usbh_rndis_run tx_buffer=%lx tx_buffer_phy=%08lx\n", tx_buffer, tx_buffer_phy);
|
||||
|
||||
vaddr = USB_MEM_VIRADDR_ALLOC;
|
||||
paddr = 0;
|
||||
rx_buffer = (uint8_t *)vaddr;
|
||||
ret = naive_mmap(&vaddr, &paddr, RNDIS_RXETH_BUFFER_LEN, true);
|
||||
if(ret != 0){
|
||||
USB_LOG_ERR("rx_buf_ptr allocate error, ret: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
rx_buffer_phy = (uint8_t *)paddr;
|
||||
USB_LOG_DBG("usbh_rndis_run rx_buffer=%lx rx_buffer_phy=%08lx\n", rx_buffer, rx_buffer_phy);
|
||||
|
||||
mutex_sem_handle = usb_osal_sem_create(0);
|
||||
if (NULL == mutex_sem_handle) {
|
||||
printf("mutex semaphore creat faile!\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
timer_handle = usb_osal_thread_create("keepalive", RNDIS_THREAD_STACK_SIZE, 5, rndis_dev_keepalive_timeout, rndis_class);
|
||||
if (NULL == timer_handle) {
|
||||
printf("timer creation failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
data_recv_task_handle = usb_osal_thread_create("rndis_recv", RNDIS_THREAD_STACK_SIZE, 5, usbh_rndis_data_recv_entry, rndis_class);
|
||||
if (NULL == data_recv_task_handle) {
|
||||
printf("rndis_lwip_rx Task creation failed!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
usb_osal_thread_delete(data_recv_task_handle);
|
||||
usb_osal_thread_delete(timer_handle);
|
||||
usb_osal_sem_delete(mutex_sem_handle);
|
||||
printf("rndis dev stop!\n");
|
||||
}
|
||||
|
||||
static int rndis_msg_data_send(struct usbh_rndis *rndis_class, uint8_t *buffer,
|
||||
int nbytes)
|
||||
{
|
||||
int ret = 0;
|
||||
int len = 0;
|
||||
usb_osal_sem_take(mutex_sem_handle, USB_OSAL_WAITING_FOREVER);
|
||||
len = usbh_rndis_bulk_out_transfer(rndis_class, buffer, nbytes, 5000);
|
||||
usb_osal_sem_give(mutex_sem_handle);
|
||||
if (len != nbytes) {
|
||||
printf("rndis msg send fail\r\n");
|
||||
ret = -EBUSY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_eth_tx(void *dataptr, size_t tot_len)
|
||||
{
|
||||
uint8_t *buffer;
|
||||
rndis_data_packet_t *hdr;
|
||||
int ret;
|
||||
int recount = 5;
|
||||
uint8_t data[4];
|
||||
uint32_t info_len = 0;
|
||||
|
||||
if (!s_rndis_class_ptr->link_status) {
|
||||
printf("linkdown, drop pkg\r\n");
|
||||
while (recount--) {
|
||||
ret = usbh_rndis_query_msg_transfer(s_rndis_class_ptr, OID_GEN_MEDIA_CONNECT_STATUS, sizeof(data), data, &info_len);
|
||||
if (ret < 0) {
|
||||
return -EBUSY;
|
||||
}
|
||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||
s_rndis_class_ptr->link_status = true;
|
||||
lwip_rndis_device_linkchange(true);
|
||||
printf("linkup, drop pkg\r\n");
|
||||
break;
|
||||
} else {
|
||||
s_rndis_class_ptr->link_status = false;
|
||||
lwip_rndis_device_linkchange(false);
|
||||
}
|
||||
usb_osal_msleep(100);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
USB_ASSERT((tot_len + sizeof(rndis_data_packet_t)) < RNDIS_ETH_BUFFER_LEN);
|
||||
if (tot_len > RNDIS_ETH_BUFFER_LEN) {
|
||||
printf("RNDIS MTU is:%d, but the send packet size is %d\r\n", RNDIS_ETH_BUFFER_LEN, tot_len);
|
||||
tot_len = RNDIS_ETH_BUFFER_LEN;
|
||||
}
|
||||
|
||||
hdr = (rndis_data_packet_t *)tx_buffer;
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = sizeof(rndis_data_packet_t) + tot_len;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
|
||||
hdr->DataLength = tot_len;
|
||||
|
||||
buffer = (uint8_t *)(tx_buffer + sizeof(rndis_data_packet_t));
|
||||
memcpy(buffer, dataptr, tot_len);
|
||||
|
||||
/* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
|
||||
if (!(hdr->MessageLength % s_rndis_class_ptr->ep_mps)) {
|
||||
hdr->MessageLength += 1;
|
||||
}
|
||||
|
||||
return rndis_msg_data_send(s_rndis_class_ptr, (uint8_t *)tx_buffer_phy, hdr->MessageLength);
|
||||
}
|
||||
|
||||
int usbh_rndis_eth_control(int cmd, void *args, size_t len)
|
||||
{
|
||||
switch (cmd) {
|
||||
case NIOCTL_GADDR:
|
||||
/* get mac address */
|
||||
if (args) {
|
||||
memcpy(args, s_rndis_class_ptr->mac, MAX_ADDR_LEN);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,307 @@
|
|||
/**
|
||||
* \file rndis_protocol.h
|
||||
* RNDIS Defines
|
||||
*
|
||||
* \author
|
||||
* Colin O'Flynn <coflynn@newae.com>
|
||||
*
|
||||
* \addtogroup usbstick
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2008 Colin O'Flynn
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: rndis_protocol.h
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: take CherryUSB v0.10.2/class/wireless/rndis_protocol.h for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/class/wireless/rndis_protocol.h
|
||||
*************************************************/
|
||||
|
||||
#ifndef RNDIS_PROTOCOL_H_
|
||||
#define RNDIS_PROTOCOL_H_
|
||||
|
||||
/**
|
||||
\addtogroup RNDIS
|
||||
@{
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define RNDIS_MAJOR_VERSION 1
|
||||
#define RNDIS_MINOR_VERSION 0
|
||||
|
||||
#define RNDIS_STATUS_SUCCESS 0X00000000
|
||||
#define RNDIS_STATUS_FAILURE 0XC0000001
|
||||
#define RNDIS_STATUS_INVALID_DATA 0XC0010015
|
||||
#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB
|
||||
#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B
|
||||
#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C
|
||||
|
||||
/* Message set for Connectionless (802.3) Devices */
|
||||
#define REMOTE_NDIS_PACKET_MSG 0x00000001
|
||||
#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002
|
||||
#define REMOTE_NDIS_HALT_MSG 0X00000003
|
||||
#define REMOTE_NDIS_QUERY_MSG 0X00000004
|
||||
#define REMOTE_NDIS_SET_MSG 0X00000005
|
||||
#define REMOTE_NDIS_RESET_MSG 0X00000006
|
||||
#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007
|
||||
#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008
|
||||
#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002
|
||||
#define REMOTE_NDIS_QUERY_CMPLT 0X80000004
|
||||
#define REMOTE_NDIS_SET_CMPLT 0X80000005
|
||||
#define REMOTE_NDIS_RESET_CMPLT 0X80000006
|
||||
#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008
|
||||
|
||||
typedef uint32_t rndis_MessageType_t;
|
||||
typedef uint32_t rndis_MessageLength_t;
|
||||
typedef uint32_t rndis_RequestId_t;
|
||||
typedef uint32_t rndis_MajorVersion_t;
|
||||
typedef uint32_t rndis_MinorVersion_t;
|
||||
typedef uint32_t rndis_MaxTransferSize_t;
|
||||
typedef uint32_t rndis_Status_t;
|
||||
|
||||
/* Device Flags */
|
||||
#define RNDIS_DF_CONNECTIONLESS 0x00000001
|
||||
#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002
|
||||
typedef uint32_t rndis_DeviceFlags_t;
|
||||
|
||||
/* Mediums */
|
||||
#define RNDIS_MEDIUM_802_3 0x00000000
|
||||
typedef uint32_t rndis_Medium_t;
|
||||
|
||||
typedef uint32_t rndis_MaxPacketsPerTransfer_t;
|
||||
typedef uint32_t rndis_PacketAlignmentFactor_t;
|
||||
typedef uint32_t rndis_AfListOffset_t;
|
||||
typedef uint32_t rndis_AfListSize_t;
|
||||
|
||||
/*** Remote NDIS Generic Message type ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
} rndis_generic_msg_t;
|
||||
|
||||
/*** Remote NDIS Initialize Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_MajorVersion_t MajorVersion;
|
||||
rndis_MinorVersion_t MinorVersion;
|
||||
rndis_MaxTransferSize_t MaxTransferSize;
|
||||
} rndis_initialize_msg_t;
|
||||
|
||||
/* Response: */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Status_t Status;
|
||||
rndis_MajorVersion_t MajorVersion;
|
||||
rndis_MinorVersion_t MinorVersion;
|
||||
rndis_DeviceFlags_t DeviceFlags;
|
||||
rndis_Medium_t Medium;
|
||||
rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer;
|
||||
rndis_MaxTransferSize_t MaxTransferSize;
|
||||
rndis_PacketAlignmentFactor_t PacketAlignmentFactor;
|
||||
rndis_AfListOffset_t AfListOffset;
|
||||
rndis_AfListSize_t AfListSize;
|
||||
} rndis_initialize_cmplt_t;
|
||||
|
||||
/*** Remote NDIS Halt Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
} rndis_halt_msg_t;
|
||||
|
||||
typedef uint32_t rndis_Oid_t;
|
||||
typedef uint32_t rndis_InformationBufferLength_t;
|
||||
typedef uint32_t rndis_InformationBufferOffset_t;
|
||||
typedef uint32_t rndis_DeviceVcHandle_t;
|
||||
|
||||
/*** Remote NDIS Query Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Oid_t Oid;
|
||||
rndis_InformationBufferLength_t InformationBufferLength;
|
||||
rndis_InformationBufferOffset_t InformationBufferOffset;
|
||||
rndis_DeviceVcHandle_t DeviceVcHandle;
|
||||
} rndis_query_msg_t;
|
||||
|
||||
/* Response: */
|
||||
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Status_t Status;
|
||||
rndis_InformationBufferLength_t InformationBufferLength;
|
||||
rndis_InformationBufferOffset_t InformationBufferOffset;
|
||||
} rndis_query_cmplt_t;
|
||||
|
||||
/*** Remote NDIS Set Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Oid_t Oid;
|
||||
rndis_InformationBufferLength_t InformationBufferLength;
|
||||
rndis_InformationBufferOffset_t InformationBufferOffset;
|
||||
rndis_DeviceVcHandle_t DeviceVcHandle;
|
||||
} rndis_set_msg_t;
|
||||
|
||||
/* Response */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Status_t Status;
|
||||
} rndis_set_cmplt_t;
|
||||
|
||||
/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */
|
||||
typedef uint32_t rndis_ParameterNameOffset_t;
|
||||
typedef uint32_t rndis_ParameterNameLength_t;
|
||||
typedef uint32_t rndis_ParameterType_t;
|
||||
typedef uint32_t rndis_ParameterValueOffset_t;
|
||||
typedef uint32_t rndis_ParameterValueLength_t;
|
||||
|
||||
#define PARAMETER_TYPE_STRING 2
|
||||
#define PARAMETER_TYPE_NUMERICAL 0
|
||||
|
||||
typedef struct {
|
||||
rndis_ParameterNameOffset_t ParameterNameOffset;
|
||||
rndis_ParameterNameLength_t ParameterNameLength;
|
||||
rndis_ParameterType_t ParameterType;
|
||||
rndis_ParameterValueOffset_t ParameterValueOffset;
|
||||
rndis_ParameterValueLength_t ParameterValueLength;
|
||||
} rndis_config_parameter_t;
|
||||
|
||||
typedef uint32_t rndis_Reserved_t;
|
||||
|
||||
/*** Remote NDIS Soft Reset Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_Reserved_t Reserved;
|
||||
} rndis_reset_msg_t;
|
||||
|
||||
typedef uint32_t rndis_AddressingReset_t;
|
||||
|
||||
/* Response: */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_Status_t Status;
|
||||
rndis_AddressingReset_t AddressingReset;
|
||||
} rndis_reset_cmplt_t;
|
||||
|
||||
/*** Remote NDIS Indicate Status Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_Status_t Status;
|
||||
rndis_Status_t StatusBufferLength;
|
||||
rndis_Status_t StatusBufferOffset;
|
||||
} rndis_indicate_status_t;
|
||||
|
||||
typedef uint32_t rndis_DiagStatus_t;
|
||||
typedef uint32_t rndis_ErrorOffset_t;
|
||||
|
||||
typedef struct {
|
||||
rndis_DiagStatus_t DiagStatus;
|
||||
rndis_ErrorOffset_t ErrorOffset;
|
||||
} rndis_diagnostic_info_t;
|
||||
|
||||
/*** Remote NDIS Keepalive Message */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
} rndis_keepalive_msg_t;
|
||||
|
||||
/* Response: */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Status_t Status;
|
||||
} rndis_keepalive_cmplt_t;
|
||||
|
||||
/*** Remote NDIS Data Packet ***/
|
||||
|
||||
typedef uint32_t rndis_DataOffset_t;
|
||||
typedef uint32_t rndis_DataLength_t;
|
||||
typedef uint32_t rndis_OOBDataOffset_t;
|
||||
typedef uint32_t rndis_OOBDataLength_t;
|
||||
typedef uint32_t rndis_NumOOBDataElements_t;
|
||||
typedef uint32_t rndis_PerPacketInfoOffset_t;
|
||||
typedef uint32_t rndis_PerPacketInfoLength_t;
|
||||
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_DataOffset_t DataOffset;
|
||||
rndis_DataLength_t DataLength;
|
||||
rndis_OOBDataOffset_t OOBDataOffset;
|
||||
rndis_OOBDataLength_t OOBDataLength;
|
||||
rndis_NumOOBDataElements_t NumOOBDataElements;
|
||||
rndis_PerPacketInfoOffset_t PerPacketInfoOffset;
|
||||
rndis_PerPacketInfoLength_t PerPacketInfoLength;
|
||||
rndis_DeviceVcHandle_t DeviceVcHandle;
|
||||
rndis_Reserved_t Reserved;
|
||||
} rndis_data_packet_t;
|
||||
|
||||
typedef uint32_t rndis_ClassInformationOffset_t;
|
||||
typedef uint32_t rndis_Size_t;
|
||||
typedef uint32_t rndis_Type_t;
|
||||
|
||||
typedef struct {
|
||||
rndis_Size_t Size;
|
||||
rndis_Type_t Type;
|
||||
rndis_ClassInformationOffset_t ClassInformationType;
|
||||
} rndis_OOB_packet_t;
|
||||
|
||||
#include "ndis.h"
|
||||
|
||||
typedef enum rnids_state_e {
|
||||
rndis_uninitialized,
|
||||
rndis_initialized,
|
||||
rndis_data_initialized
|
||||
} rndis_state_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t txok;
|
||||
uint32_t rxok;
|
||||
uint32_t txbad;
|
||||
uint32_t rxbad;
|
||||
} usb_eth_stat_t;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1 +1,490 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: usbh_rndis.c
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: take CherryUSB v0.10.2/class/wireless/usbh_rndis.c for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/class/wireless/usbh_rndis.c
|
||||
|
||||
History:
|
||||
1. Date: 2024-07-10
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: rndis ADAPTS to usb core to decouple xhci.
|
||||
|
||||
2. Date: 2024-07-16
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: rndis uses naive_mmap to assign virtual and physical addresses and match the relevant codes.
|
||||
*************************************************/
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_rndis.h"
|
||||
#include "rndis_protocol.h"
|
||||
#include "usyscall.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/rndis"
|
||||
|
||||
//USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
|
||||
uint8_t *g_rndis_buf;
|
||||
uint8_t *g_rndis_buf_phy;
|
||||
uint8_t *g_rndis_keepalive_buf;
|
||||
uint8_t *g_rndis_keepalive_buf_phy;
|
||||
|
||||
static struct usbh_rndis g_rndis_class;
|
||||
|
||||
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
int ret = 0;
|
||||
rndis_initialize_msg_t *cmd;
|
||||
rndis_initialize_cmplt_t *resp;
|
||||
rndis_initialize_msg_t *cmd_phy;
|
||||
rndis_initialize_cmplt_t *resp_phy;
|
||||
|
||||
cmd = (rndis_initialize_msg_t *)g_rndis_buf;
|
||||
cmd_phy = (rndis_initialize_msg_t *)g_rndis_buf_phy;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_INITIALIZE_MSG;
|
||||
cmd->MessageLength = sizeof(rndis_initialize_msg_t);
|
||||
cmd->RequestId = rndis_class->request_id++;
|
||||
cmd->MajorVersion = 1;
|
||||
cmd->MinorVersion = 0;
|
||||
cmd->MaxTransferSize = 0x4000;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_initialize_msg_t);
|
||||
|
||||
ret = usbh_control_transfer_xiuos(rndis_class->hport, rndis_class->hport->ep0, setup, (uint8_t *)cmd_phy);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("rndis_initialize_msg_t send error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer()
|
||||
|
||||
resp = (rndis_initialize_cmplt_t *)g_rndis_buf;
|
||||
resp_phy = (rndis_initialize_cmplt_t *)g_rndis_buf_phy;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer_xiuos(rndis_class->hport, rndis_class->hport->ep0, setup, (uint8_t *)resp_phy);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("rndis_initialize_cmplt_t recv error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
int ret = 0;
|
||||
rndis_query_msg_t *cmd;
|
||||
rndis_query_cmplt_t *resp;
|
||||
rndis_query_msg_t *cmd_phy;
|
||||
rndis_query_cmplt_t *resp_phy;
|
||||
|
||||
cmd = (rndis_query_msg_t *)g_rndis_buf;
|
||||
cmd_phy = (rndis_query_msg_t *)g_rndis_buf_phy;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_QUERY_MSG;
|
||||
cmd->MessageLength = query_len + sizeof(rndis_query_msg_t);
|
||||
cmd->RequestId = rndis_class->request_id++;
|
||||
cmd->Oid = oid;
|
||||
cmd->InformationBufferLength = query_len;
|
||||
cmd->InformationBufferOffset = 20;
|
||||
cmd->DeviceVcHandle = 0;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = query_len + sizeof(rndis_query_msg_t);
|
||||
|
||||
ret = usbh_control_transfer_xiuos(rndis_class->hport, rndis_class->hport->ep0, setup, (uint8_t *)cmd_phy);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer()
|
||||
|
||||
resp = (rndis_query_cmplt_t *)g_rndis_buf;
|
||||
resp_phy = (rndis_query_cmplt_t *)g_rndis_buf_phy;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer_xiuos(rndis_class->hport, rndis_class->hport->ep0, setup, (uint8_t *)resp_phy);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(info, ((uint8_t *)resp + sizeof(rndis_query_cmplt_t)), resp->InformationBufferLength);
|
||||
*info_len = resp->InformationBufferLength;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint8_t *info, uint32_t info_len)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
int ret = 0;
|
||||
rndis_set_msg_t *cmd;
|
||||
rndis_set_cmplt_t *resp;
|
||||
rndis_set_msg_t *cmd_phy;
|
||||
rndis_set_cmplt_t *resp_phy;
|
||||
|
||||
cmd = (rndis_set_msg_t *)g_rndis_buf;
|
||||
cmd_phy = (rndis_set_msg_t *)g_rndis_buf_phy;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_SET_MSG;
|
||||
cmd->MessageLength = info_len + sizeof(rndis_set_msg_t);
|
||||
cmd->RequestId = rndis_class->request_id++;
|
||||
cmd->Oid = oid;
|
||||
cmd->InformationBufferLength = info_len;
|
||||
cmd->InformationBufferOffset = 20;
|
||||
cmd->DeviceVcHandle = 0;
|
||||
|
||||
memcpy(((uint8_t *)cmd + sizeof(rndis_set_msg_t)), info, info_len);
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = info_len + sizeof(rndis_set_msg_t);
|
||||
|
||||
ret = usbh_control_transfer_xiuos(rndis_class->hport, rndis_class->hport->ep0, setup, (uint8_t *)cmd_phy);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
|
||||
|
||||
resp = (rndis_set_cmplt_t *)g_rndis_buf;
|
||||
resp_phy = (rndis_set_cmplt_t *)g_rndis_buf_phy;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer_xiuos(rndis_class->hport, rndis_class->hport->ep0, setup, (uint8_t *)resp_phy);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &rndis_class->bulkout_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill_xiuos(urb, rndis_class->hport, rndis_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &rndis_class->bulkin_urb;
|
||||
memset(urb, 0, sizeof(struct usbh_urb));
|
||||
|
||||
usbh_bulk_urb_fill_xiuos(urb, rndis_class->hport, rndis_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
int ret = 0;
|
||||
rndis_keepalive_msg_t *cmd;
|
||||
rndis_keepalive_cmplt_t *resp;
|
||||
rndis_keepalive_msg_t *cmd_phy;
|
||||
rndis_keepalive_cmplt_t *resp_phy;
|
||||
|
||||
cmd = (rndis_keepalive_msg_t *)g_rndis_keepalive_buf;
|
||||
cmd_phy = (rndis_keepalive_msg_t *)g_rndis_keepalive_buf_phy;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
|
||||
cmd->MessageLength = sizeof(rndis_keepalive_msg_t);
|
||||
cmd->RequestId = rndis_class->request_id++;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_keepalive_msg_t);
|
||||
|
||||
ret = usbh_control_transfer_xiuos(rndis_class->hport, rndis_class->hport->ep0, setup, (uint8_t *)cmd_phy);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("keepalive send error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
|
||||
|
||||
resp = (rndis_keepalive_cmplt_t *)g_rndis_keepalive_buf;
|
||||
resp_phy = (rndis_keepalive_cmplt_t *)g_rndis_keepalive_buf_phy;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer_xiuos(rndis_class->hport, rndis_class->hport->ep0, setup, (uint8_t *)resp_phy);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint32_t *oid_support_list;
|
||||
unsigned int oid = 0;
|
||||
unsigned int oid_num = 0;
|
||||
uint32_t data_len;
|
||||
uint8_t tmp_buffer[512];
|
||||
uint8_t data[32];
|
||||
uintptr_t vaddr, paddr;
|
||||
|
||||
struct usbh_rndis *rndis_class = &g_rndis_class;
|
||||
|
||||
memset(rndis_class, 0, sizeof(struct usbh_rndis));
|
||||
|
||||
rndis_class->hport = hport;
|
||||
rndis_class->ctrl_intf = intf;
|
||||
rndis_class->data_intf = intf + 1;
|
||||
|
||||
/* allocate virtual address and physical address*/
|
||||
vaddr = USB_MEM_VIRADDR_ALLOC;
|
||||
paddr = 0;
|
||||
g_rndis_buf = (uint8_t *)vaddr;
|
||||
ret = naive_mmap(&vaddr, &paddr, 4096, true);
|
||||
if(ret != 0){
|
||||
USB_LOG_ERR("g_rndis_buf allocate error, ret: %d\n", ret);
|
||||
return -ENOMEM;
|
||||
}
|
||||
g_rndis_buf_phy = (uint8_t *)paddr;
|
||||
USB_LOG_DBG("usbh_rndis_connect g_rndis_buf=%lx g_rndis_buf_phy=%08lx\n", g_rndis_buf, g_rndis_buf_phy);
|
||||
|
||||
vaddr = USB_MEM_VIRADDR_ALLOC;
|
||||
paddr = 0;
|
||||
g_rndis_keepalive_buf = (uint8_t *)vaddr;
|
||||
ret = naive_mmap(&vaddr, &paddr, 4096, true);
|
||||
if(ret != 0){
|
||||
USB_LOG_ERR("g_rndis_keepalive_buf allocate error, ret: %d\n", ret);
|
||||
return -ENOMEM;
|
||||
}
|
||||
g_rndis_keepalive_buf_phy = (uint8_t *)paddr;
|
||||
USB_LOG_DBG("usbh_rndis_connect g_rndis_keepalive_buf=%lx g_rndis_keepalive_buf_phy=%08lx\n", g_rndis_keepalive_buf, g_rndis_keepalive_buf_phy);
|
||||
|
||||
hport->config.intf[intf].priv = rndis_class;
|
||||
hport->config.intf[intf + 1].priv = NULL;
|
||||
|
||||
#ifdef CONFIG_USBHOST_RNDIS_NOTIFY
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
usbh_hport_activate_epx(&rndis_class->intin, hport, ep_desc);
|
||||
#endif
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
usbh_hport_activate_epx(&rndis_class->bulkin, hport, ep_desc);
|
||||
} else {
|
||||
usbh_hport_activate_epx(&rndis_class->bulkout, hport, ep_desc);
|
||||
rndis_class->ep_mps = ep_desc->wMaxPacketSize;
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_rndis_init_msg_transfer(rndis_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("rndis init success\r\n");
|
||||
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_SUPPORTED_LIST, 0, tmp_buffer, &data_len);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
oid_num = (data_len / 4);
|
||||
USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%d\r\n", oid_num);
|
||||
|
||||
oid_support_list = (uint32_t *)tmp_buffer;
|
||||
|
||||
for (uint8_t i = 0; i < oid_num; i++) {
|
||||
oid = oid_support_list[i];
|
||||
switch (oid) {
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_PHYSICAL_MEDIUM, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
break;
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MAXIMUM_FRAME_SIZE, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
break;
|
||||
case OID_GEN_LINK_SPEED:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_LINK_SPEED, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
|
||||
memcpy(&rndis_class->link_speed, data, 4);
|
||||
break;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||
rndis_class->link_status = true;
|
||||
} else {
|
||||
rndis_class->link_status = false;
|
||||
}
|
||||
break;
|
||||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_MAXIMUM_LIST_SIZE, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
break;
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_CURRENT_ADDRESS, 6, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
|
||||
for (uint8_t j = 0; j < 6; j++) {
|
||||
rndis_class->mac[j] = data[j];
|
||||
}
|
||||
break;
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_PERMANENT_ADDRESS, 6, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Ignore rndis query iod:%08x\r\n", oid);
|
||||
continue;
|
||||
}
|
||||
USB_LOG_INFO("rndis query iod:%08x success\r\n", oid);
|
||||
}
|
||||
|
||||
uint32_t packet_filter = 0x0f;
|
||||
usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("rndis set OID_GEN_CURRENT_PACKET_FILTER success\r\n");
|
||||
|
||||
uint8_t multicast_list[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x01 };
|
||||
usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("rndis set OID_802_3_MULTICAST_LIST success\r\n");
|
||||
|
||||
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_rndis_run(rndis_class);
|
||||
return ret;
|
||||
query_errorout:
|
||||
USB_LOG_ERR("rndis query iod:%08x error\r\n", oid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)hport->config.intf[intf].priv;
|
||||
|
||||
if (rndis_class) {
|
||||
if (rndis_class->bulkin) {
|
||||
usbh_pipe_free_xiuos(rndis_class->hport, rndis_class->bulkin);
|
||||
}
|
||||
|
||||
if (rndis_class->bulkout) {
|
||||
usbh_pipe_free_xiuos(rndis_class->hport, rndis_class->bulkout);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_rndis_stop(rndis_class);
|
||||
}
|
||||
|
||||
memset(rndis_class, 0, sizeof(struct usbh_rndis));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver rndis_class_driver = {
|
||||
.driver_name = "rndis",
|
||||
.connect = usbh_rndis_connect,
|
||||
.disconnect = usbh_rndis_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE struct usbh_class_info rndis_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_WIRELESS,
|
||||
.subclass = 0x01,
|
||||
.protocol = 0x03,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.class_driver = &rndis_class_driver
|
||||
};
|
||||
|
||||
int usbh_rndis_initialize(struct usbh_bus *usb)
|
||||
{
|
||||
usbh_class_info_set(USBH_CLASS_INFO_RNDIS, &rndis_class_info);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
/*************************************************
|
||||
File name: usbh_rndis.h
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: take CherryUSB v0.10.2/class/wireless/usbh_rndis.h for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/class/wireless/usbh_rndis.h
|
||||
|
||||
History:
|
||||
1. Date: 2024-07-09
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Add usb_def.h stdbool.h and usb_hc.h because of a compilation error.
|
||||
*************************************************/
|
||||
#ifndef USBH_RNDIS_H_
|
||||
#define USBH_RNDIS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "usb_def.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "usb_hc.h"
|
||||
|
||||
struct usbh_rndis {
|
||||
struct usbh_hubport *hport;
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
uint8_t minor;
|
||||
usbh_pipe_t bulkin; /* Bulk IN endpoint */
|
||||
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
|
||||
usbh_pipe_t intin; /* Notify endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
uint32_t request_id;
|
||||
|
||||
uint32_t ep_mps;
|
||||
uint32_t link_speed;
|
||||
bool link_status;
|
||||
uint8_t mac[6];
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int usbh_rndis_initialize(struct usbh_bus *usb);
|
||||
|
||||
int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
|
||||
int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len);
|
||||
|
||||
void usbh_rndis_run(struct usbh_rndis *rndis_class);
|
||||
void usbh_rndis_stop(struct usbh_rndis *rndis_class);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_RNDIS_H_ */
|
||||
|
|
|
@ -1,8 +1,708 @@
|
|||
#ifndef USB_DEF_H_
|
||||
#define USB_DEF_H_
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/* Useful define */
|
||||
#define USB_1_1 0x0110
|
||||
#define USB_2_0 0x0200
|
||||
/* Set USB version to 2.1 so that the host will request the BOS descriptor */
|
||||
#define USB_2_1 0x0210
|
||||
#define USB_3_0 0x0300
|
||||
#define USB_3_1 0x0310
|
||||
|
||||
/* Device speeds */
|
||||
#define USB_SPEED_UNKNOWN 0 /* Transfer rate not yet set */
|
||||
#define USB_SPEED_LOW 1 /* USB 1.1 */
|
||||
#define USB_SPEED_FULL 2 /* USB 1.1 */
|
||||
#define USB_SPEED_HIGH 3 /* USB 2.0 */
|
||||
#define USB_SPEED_WIRELESS 4 /* Wireless USB 2.5 */
|
||||
#define USB_SPEED_SUPER 5 /* USB 3.0 */
|
||||
#define USB_SPEED_SUPER_PLUS 6 /* USB 3.1 */
|
||||
|
||||
/* Maximum number of devices per controller */
|
||||
#define USB_MAX_DEVICES (127)
|
||||
|
||||
/* Default USB control EP, always 0 and 0x80 */
|
||||
#define USB_CONTROL_OUT_EP0 0
|
||||
#define USB_CONTROL_IN_EP0 0x80
|
||||
|
||||
/**< maximum packet size (MPS) for EP 0 */
|
||||
#define USB_CTRL_EP_MPS 64
|
||||
|
||||
/* USB PID Types */
|
||||
#define USB_PID_OUT (0x01) /* Tokens */
|
||||
#define USB_PID_IN (0x09)
|
||||
#define USB_PID_SOF (0x05)
|
||||
#define USB_PID_SETUP (0x0d)
|
||||
|
||||
#define USB_PID_DATA0 (0x03) /* Data */
|
||||
#define USB_PID_DATA1 (0x0b)
|
||||
#define USB_PID_DATA2 (0x07)
|
||||
#define USB_PID_MDATA (0x0f)
|
||||
|
||||
#define USB_PID_ACK (0x02) /* Handshake */
|
||||
#define USB_PID_NAK (0x0a)
|
||||
#define USB_PID_STALL (0x0e)
|
||||
#define USB_PID_NYET (0x06)
|
||||
|
||||
#define USB_PID_PRE (0x0c) /* Special */
|
||||
#define USB_PID_ERR (0x0c)
|
||||
#define USB_PID_SPLIT (0x08)
|
||||
#define USB_PID_PING (0x04)
|
||||
#define USB_PID_RESERVED (0x00)
|
||||
|
||||
#define USB_REQUEST_DIR_SHIFT 7U /* Bits 7: Request dir */
|
||||
#define USB_REQUEST_DIR_OUT (0U << USB_REQUEST_DIR_SHIFT) /* Bit 7=0: Host-to-device */
|
||||
#define USB_REQUEST_DIR_IN (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Device-to-host */
|
||||
#define USB_REQUEST_DIR_MASK (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Direction bit */
|
||||
|
||||
#define USB_REQUEST_TYPE_SHIFT 5U /* Bits 5:6: Request type */
|
||||
#define USB_REQUEST_STANDARD (0U << USB_REQUEST_TYPE_SHIFT)
|
||||
#define USB_REQUEST_CLASS (1U << USB_REQUEST_TYPE_SHIFT)
|
||||
#define USB_REQUEST_VENDOR (2U << USB_REQUEST_TYPE_SHIFT)
|
||||
#define USB_REQUEST_RESERVED (3U << USB_REQUEST_TYPE_SHIFT)
|
||||
#define USB_REQUEST_TYPE_MASK (3U << USB_REQUEST_TYPE_SHIFT)
|
||||
|
||||
#define USB_REQUEST_RECIPIENT_SHIFT 0U /* Bits 0:4: Recipient */
|
||||
#define USB_REQUEST_RECIPIENT_DEVICE (0U << USB_REQUEST_RECIPIENT_SHIFT)
|
||||
#define USB_REQUEST_RECIPIENT_INTERFACE (1U << USB_REQUEST_RECIPIENT_SHIFT)
|
||||
#define USB_REQUEST_RECIPIENT_ENDPOINT (2U << USB_REQUEST_RECIPIENT_SHIFT)
|
||||
#define USB_REQUEST_RECIPIENT_OTHER (3U << USB_REQUEST_RECIPIENT_SHIFT)
|
||||
#define USB_REQUEST_RECIPIENT_MASK (3U << USB_REQUEST_RECIPIENT_SHIFT)
|
||||
|
||||
/* USB Standard Request Codes */
|
||||
#define USB_REQUEST_GET_STATUS 0x00
|
||||
#define USB_REQUEST_CLEAR_FEATURE 0x01
|
||||
#define USB_REQUEST_SET_FEATURE 0x03
|
||||
#define USB_REQUEST_SET_ADDRESS 0x05
|
||||
#define USB_REQUEST_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQUEST_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQUEST_GET_CONFIGURATION 0x08
|
||||
#define USB_REQUEST_SET_CONFIGURATION 0x09
|
||||
#define USB_REQUEST_GET_INTERFACE 0x0A
|
||||
#define USB_REQUEST_SET_INTERFACE 0x0B
|
||||
#define USB_REQUEST_SYNCH_FRAME 0x0C
|
||||
#define USB_REQUEST_SET_ENCRYPTION 0x0D
|
||||
#define USB_REQUEST_GET_ENCRYPTION 0x0E
|
||||
#define USB_REQUEST_RPIPE_ABORT 0x0E
|
||||
#define USB_REQUEST_SET_HANDSHAKE 0x0F
|
||||
#define USB_REQUEST_RPIPE_RESET 0x0F
|
||||
#define USB_REQUEST_GET_HANDSHAKE 0x10
|
||||
#define USB_REQUEST_SET_CONNECTION 0x11
|
||||
#define USB_REQUEST_SET_SECURITY_DATA 0x12
|
||||
#define USB_REQUEST_GET_SECURITY_DATA 0x13
|
||||
#define USB_REQUEST_SET_WUSB_DATA 0x14
|
||||
#define USB_REQUEST_LOOPBACK_DATA_WRITE 0x15
|
||||
#define USB_REQUEST_LOOPBACK_DATA_READ 0x16
|
||||
#define USB_REQUEST_SET_INTERFACE_DS 0x17
|
||||
|
||||
/* USB Standard Feature selectors */
|
||||
#define USB_FEATURE_ENDPOINT_HALT 0
|
||||
#define USB_FEATURE_SELF_POWERED 0
|
||||
#define USB_FEATURE_REMOTE_WAKEUP 1
|
||||
#define USB_FEATURE_TEST_MODE 2
|
||||
#define USB_FEATURE_BATTERY 2
|
||||
#define USB_FEATURE_BHNPENABLE 3
|
||||
#define USB_FEATURE_WUSBDEVICE 3
|
||||
#define USB_FEATURE_AHNPSUPPORT 4
|
||||
#define USB_FEATURE_AALTHNPSUPPORT 5
|
||||
#define USB_FEATURE_DEBUGMODE 6
|
||||
|
||||
/* USB GET_STATUS Bit Values */
|
||||
#define USB_GETSTATUS_ENDPOINT_HALT 0x01
|
||||
#define USB_GETSTATUS_SELF_POWERED 0x01
|
||||
#define USB_GETSTATUS_REMOTE_WAKEUP 0x02
|
||||
|
||||
/* USB Descriptor Types */
|
||||
#define USB_DESCRIPTOR_TYPE_DEVICE 0x01U
|
||||
#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02U
|
||||
#define USB_DESCRIPTOR_TYPE_STRING 0x03U
|
||||
#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04U
|
||||
#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05U
|
||||
#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06U
|
||||
#define USB_DESCRIPTOR_TYPE_OTHER_SPEED 0x07U
|
||||
#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08U
|
||||
#define USB_DESCRIPTOR_TYPE_OTG 0x09U
|
||||
#define USB_DESCRIPTOR_TYPE_DEBUG 0x0AU
|
||||
#define USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0BU
|
||||
#define USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE 0x0FU
|
||||
#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10U
|
||||
#define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINTCOMP 0x11U
|
||||
|
||||
/* Class Specific Descriptor */
|
||||
#define USB_CS_DESCRIPTOR_TYPE_DEVICE 0x21U
|
||||
#define USB_CS_DESCRIPTOR_TYPE_CONFIGURATION 0x22U
|
||||
#define USB_CS_DESCRIPTOR_TYPE_STRING 0x23U
|
||||
#define USB_CS_DESCRIPTOR_TYPE_INTERFACE 0x24U
|
||||
#define USB_CS_DESCRIPTOR_TYPE_ENDPOINT 0x25U
|
||||
|
||||
#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ENDPOINT_COMPANION 0x30U
|
||||
#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ISO_ENDPOINT_COMPANION 0x31U
|
||||
|
||||
/* USB Device Classes */
|
||||
#define USB_DEVICE_CLASS_RESERVED 0x00
|
||||
#define USB_DEVICE_CLASS_AUDIO 0x01
|
||||
#define USB_DEVICE_CLASS_CDC 0x02
|
||||
#define USB_DEVICE_CLASS_HID 0x03
|
||||
#define USB_DEVICE_CLASS_MONITOR 0x04
|
||||
#define USB_DEVICE_CLASS_PHYSICAL 0x05
|
||||
#define USB_DEVICE_CLASS_IMAGE 0x06
|
||||
#define USB_DEVICE_CLASS_PRINTER 0x07
|
||||
#define USB_DEVICE_CLASS_MASS_STORAGE 0x08
|
||||
#define USB_DEVICE_CLASS_HUB 0x09
|
||||
#define USB_DEVICE_CLASS_CDC_DATA 0x0a
|
||||
#define USB_DEVICE_CLASS_SMART_CARD 0x0b
|
||||
#define USB_DEVICE_CLASS_SECURITY 0x0d
|
||||
#define USB_DEVICE_CLASS_VIDEO 0x0e
|
||||
#define USB_DEVICE_CLASS_HEALTHCARE 0x0f
|
||||
#define USB_DEVICE_CLASS_DIAG_DEVICE 0xdc
|
||||
#define USB_DEVICE_CLASS_WIRELESS 0xe0
|
||||
#define USB_DEVICE_CLASS_MISC 0xef
|
||||
#define USB_DEVICE_CLASS_APP_SPECIFIC 0xfe
|
||||
#define USB_DEVICE_CLASS_VEND_SPECIFIC 0xff
|
||||
|
||||
/* usb string index define */
|
||||
#define USB_STRING_LANGID_INDEX 0x00
|
||||
#define USB_STRING_MFC_INDEX 0x01
|
||||
#define USB_STRING_PRODUCT_INDEX 0x02
|
||||
#define USB_STRING_SERIAL_INDEX 0x03
|
||||
#define USB_STRING_CONFIG_INDEX 0x04
|
||||
#define USB_STRING_INTERFACE_INDEX 0x05
|
||||
#define USB_STRING_OS_INDEX 0x06
|
||||
#define USB_STRING_MAX USB_STRING_OS_INDEX
|
||||
/*
|
||||
* Devices supporting Microsoft OS Descriptors store special string
|
||||
* descriptor at fixed index (0xEE). It is read when a new device is
|
||||
* attached to a computer for the first time.
|
||||
*/
|
||||
#define USB_OSDESC_STRING_DESC_INDEX 0xEE
|
||||
|
||||
/* bmAttributes in Configuration Descriptor */
|
||||
#define USB_CONFIG_REMOTE_WAKEUP 0x20
|
||||
#define USB_CONFIG_POWERED_MASK 0x40
|
||||
#define USB_CONFIG_BUS_POWERED 0x80
|
||||
#define USB_CONFIG_SELF_POWERED 0xC0
|
||||
|
||||
/* bMaxPower in Configuration Descriptor */
|
||||
#define USB_CONFIG_POWER_MA(mA) ((mA) / 2)
|
||||
|
||||
/* bEndpointAddress in Endpoint Descriptor */
|
||||
#define USB_ENDPOINT_DIRECTION_MASK 0x80
|
||||
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
|
||||
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
|
||||
|
||||
/**
|
||||
* USB endpoint direction and number.
|
||||
*/
|
||||
#define USB_EP_DIR_MASK 0x80U
|
||||
#define USB_EP_DIR_IN 0x80U
|
||||
#define USB_EP_DIR_OUT 0x00U
|
||||
|
||||
/** Get endpoint index (number) from endpoint address */
|
||||
#define USB_EP_GET_IDX(ep) ((ep) & ~USB_EP_DIR_MASK)
|
||||
/** Get direction from endpoint address */
|
||||
#define USB_EP_GET_DIR(ep) ((ep)&USB_EP_DIR_MASK)
|
||||
/** Get endpoint address from endpoint index and direction */
|
||||
#define USB_EP_GET_ADDR(idx, dir) ((idx) | ((dir)&USB_EP_DIR_MASK))
|
||||
/** True if the endpoint is an IN endpoint */
|
||||
#define USB_EP_DIR_IS_IN(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_IN)
|
||||
/** True if the endpoint is an OUT endpoint */
|
||||
#define USB_EP_DIR_IS_OUT(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_OUT)
|
||||
|
||||
/* bmAttributes in Endpoint Descriptor */
|
||||
#define USB_ENDPOINT_TYPE_SHIFT 0
|
||||
#define USB_ENDPOINT_TYPE_CONTROL (0 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_ENDPOINT_TYPE_ISOCHRONOUS (1 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_ENDPOINT_TYPE_BULK (2 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_ENDPOINT_TYPE_INTERRUPT (3 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
#define USB_ENDPOINT_TYPE_MASK (3 << USB_ENDPOINT_TYPE_SHIFT)
|
||||
|
||||
#define USB_ENDPOINT_SYNC_SHIFT 2
|
||||
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT)
|
||||
#define USB_ENDPOINT_SYNC_ASYNCHRONOUS (1 << USB_ENDPOINT_SYNC_SHIFT)
|
||||
#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << USB_ENDPOINT_SYNC_SHIFT)
|
||||
#define USB_ENDPOINT_SYNC_SYNCHRONOUS (3 << USB_ENDPOINT_SYNC_SHIFT)
|
||||
#define USB_ENDPOINT_SYNC_MASK (3 << USB_ENDPOINT_SYNC_SHIFT)
|
||||
|
||||
#define USB_ENDPOINT_USAGE_SHIFT 4
|
||||
#define USB_ENDPOINT_USAGE_DATA (0 << USB_ENDPOINT_USAGE_SHIFT)
|
||||
#define USB_ENDPOINT_USAGE_FEEDBACK (1 << USB_ENDPOINT_USAGE_SHIFT)
|
||||
#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << USB_ENDPOINT_USAGE_SHIFT)
|
||||
#define USB_ENDPOINT_USAGE_MASK (3 << USB_ENDPOINT_USAGE_SHIFT)
|
||||
|
||||
#define USB_ENDPOINT_MAX_ADJUSTABLE (1 << 7)
|
||||
|
||||
/* wMaxPacketSize in Endpoint Descriptor */
|
||||
#define USB_MAXPACKETSIZE_SHIFT 0
|
||||
#define USB_MAXPACKETSIZE_MASK (0x7ff << USB_MAXPACKETSIZE_SHIFT)
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT 11
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_NONE (0 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_ONE (1 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_TWO (2 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK (3 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
|
||||
|
||||
/* bDevCapabilityType in Device Capability Descriptor */
|
||||
#define USB_DEVICE_CAPABILITY_WIRELESS_USB 1
|
||||
#define USB_DEVICE_CAPABILITY_USB_2_0_EXTENSION 2
|
||||
#define USB_DEVICE_CAPABILITY_SUPERSPEED_USB 3
|
||||
#define USB_DEVICE_CAPABILITY_CONTAINER_ID 4
|
||||
#define USB_DEVICE_CAPABILITY_PLATFORM 5
|
||||
#define USB_DEVICE_CAPABILITY_POWER_DELIVERY_CAPABILITY 6
|
||||
#define USB_DEVICE_CAPABILITY_BATTERY_INFO_CAPABILITY 7
|
||||
#define USB_DEVICE_CAPABILITY_PD_CONSUMER_PORT_CAPABILITY 8
|
||||
#define USB_DEVICE_CAPABILITY_PD_PROVIDER_PORT_CAPABILITY 9
|
||||
#define USB_DEVICE_CAPABILITY_SUPERSPEED_PLUS 10
|
||||
#define USB_DEVICE_CAPABILITY_PRECISION_TIME_MEASUREMENT 11
|
||||
#define USB_DEVICE_CAPABILITY_WIRELESS_USB_EXT 12
|
||||
|
||||
#define USB_BOS_CAPABILITY_EXTENSION 0x02
|
||||
#define USB_BOS_CAPABILITY_PLATFORM 0x05
|
||||
|
||||
/* OTG SET FEATURE Constants */
|
||||
#define USB_OTG_FEATURE_B_HNP_ENABLE 3 /* Enable B device to perform HNP */
|
||||
#define USB_OTG_FEATURE_A_HNP_SUPPORT 4 /* A device supports HNP */
|
||||
#define USB_OTG_FEATURE_A_ALT_HNP_SUPPORT 5 /* Another port on the A device supports HNP */
|
||||
|
||||
/* WinUSB Microsoft OS 2.0 descriptor request codes */
|
||||
#define WINUSB_REQUEST_GET_DESCRIPTOR_SET 0x07
|
||||
#define WINUSB_REQUEST_SET_ALT_ENUM 0x08
|
||||
|
||||
/* WinUSB Microsoft OS 2.0 descriptor sizes */
|
||||
#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10
|
||||
#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
|
||||
#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20
|
||||
|
||||
/* WinUSB Microsoft OS 2.0 Descriptor Types */
|
||||
#define WINUSB_SET_HEADER_DESCRIPTOR_TYPE 0x00
|
||||
#define WINUSB_SUBSET_HEADER_CONFIGURATION_TYPE 0x01
|
||||
#define WINUSB_SUBSET_HEADER_FUNCTION_TYPE 0x02
|
||||
#define WINUSB_FEATURE_COMPATIBLE_ID_TYPE 0x03
|
||||
#define WINUSB_FEATURE_REG_PROPERTY_TYPE 0x04
|
||||
#define WINUSB_FEATURE_MIN_RESUME_TIME_TYPE 0x05
|
||||
#define WINUSB_FEATURE_MODEL_ID_TYPE 0x06
|
||||
#define WINUSB_FEATURE_CCGP_DEVICE_TYPE 0x07
|
||||
|
||||
#define WINUSB_PROP_DATA_TYPE_REG_SZ 0x01
|
||||
#define WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ 0x07
|
||||
|
||||
/* WebUSB Descriptor Types */
|
||||
#define WEBUSB_DESCRIPTOR_SET_HEADER_TYPE 0x00
|
||||
#define WEBUSB_CONFIGURATION_SUBSET_HEADER_TYPE 0x01
|
||||
#define WEBUSB_FUNCTION_SUBSET_HEADER_TYPE 0x02
|
||||
#define WEBUSB_URL_TYPE 0x03
|
||||
|
||||
/* WebUSB Request Codes */
|
||||
#define WEBUSB_REQUEST_GET_URL 0x02
|
||||
|
||||
/* bScheme in URL descriptor */
|
||||
#define WEBUSB_URL_SCHEME_HTTP 0x00
|
||||
#define WEBUSB_URL_SCHEME_HTTPS 0x01
|
||||
|
||||
/* WebUSB Descriptor sizes */
|
||||
#define WEBUSB_DESCRIPTOR_SET_HEADER_SIZE 5
|
||||
#define WEBUSB_CONFIGURATION_SUBSET_HEADER_SIZE 4
|
||||
#define WEBUSB_FUNCTION_SUBSET_HEADER_SIZE 3
|
||||
|
||||
/* Setup packet definition used to read raw data from USB line */
|
||||
struct usb_setup_packet {
|
||||
/** Request type. Bits 0:4 determine recipient, see
|
||||
* \ref usb_request_recipient. Bits 5:6 determine type, see
|
||||
* \ref usb_request_type. Bit 7 determines data transfer direction, see
|
||||
* \ref usb_endpoint_direction.
|
||||
*/
|
||||
uint8_t bmRequestType;
|
||||
|
||||
/** Request. If the type bits of bmRequestType are equal to
|
||||
* \ref usb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
|
||||
* "USB_REQUEST_TYPE_STANDARD" then this field refers to
|
||||
* \ref usb_standard_request. For other cases, use of this field is
|
||||
* application-specific. */
|
||||
uint8_t bRequest;
|
||||
|
||||
/** Value. Varies according to request */
|
||||
uint16_t wValue;
|
||||
|
||||
/** Index. Varies according to request, typically used to pass an index
|
||||
* or offset */
|
||||
uint16_t wIndex;
|
||||
|
||||
/** Number of bytes to transfer */
|
||||
uint16_t wLength;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_SIZEOF_SETUP_PACKET 8
|
||||
|
||||
struct usb_device_descriptor {
|
||||
uint8_t bLength; /* Descriptor size in bytes = 18 */
|
||||
uint8_t bDescriptorType; /* DEVICE descriptor type = 1 */
|
||||
uint16_t bcdUSB; /* USB spec in BCD, e.g. 0x0200 */
|
||||
uint8_t bDeviceClass; /* Class code, if 0 see interface */
|
||||
uint8_t bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */
|
||||
uint8_t bDeviceProtocol; /* Protocol, if 0 see interface */
|
||||
uint8_t bMaxPacketSize0; /* Endpoint 0 max. size */
|
||||
uint16_t idVendor; /* Vendor ID per USB-IF */
|
||||
uint16_t idProduct; /* Product ID per manufacturer */
|
||||
uint16_t bcdDevice; /* Device release # in BCD */
|
||||
uint8_t iManufacturer; /* Index to manufacturer string */
|
||||
uint8_t iProduct; /* Index to product string */
|
||||
uint8_t iSerialNumber; /* Index to serial number string */
|
||||
uint8_t bNumConfigurations; /* Number of possible configurations */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_SIZEOF_DEVICE_DESC 18
|
||||
|
||||
/** Standard Configuration Descriptor */
|
||||
struct usb_configuration_descriptor {
|
||||
uint8_t bLength; /* Descriptor size in bytes = 9 */
|
||||
uint8_t bDescriptorType; /* CONFIGURATION type = 2 or 7 */
|
||||
uint16_t wTotalLength; /* Length of concatenated descriptors */
|
||||
uint8_t bNumInterfaces; /* Number of interfaces, this config. */
|
||||
uint8_t bConfigurationValue; /* Value to set this config. */
|
||||
uint8_t iConfiguration; /* Index to configuration string */
|
||||
uint8_t bmAttributes; /* Config. characteristics */
|
||||
uint8_t bMaxPower; /* Max.power from bus, 2mA units */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_SIZEOF_CONFIG_DESC 9
|
||||
|
||||
|
||||
|
||||
/** Standard Interface Descriptor */
|
||||
struct usb_interface_descriptor {
|
||||
uint8_t bLength; /* Descriptor size in bytes = 9 */
|
||||
uint8_t bDescriptorType; /* INTERFACE descriptor type = 4 */
|
||||
uint8_t bInterfaceNumber; /* Interface no.*/
|
||||
uint8_t bAlternateSetting; /* Value to select this IF */
|
||||
uint8_t bNumEndpoints; /* Number of endpoints excluding 0 */
|
||||
uint8_t bInterfaceClass; /* Class code, 0xFF = vendor */
|
||||
uint8_t bInterfaceSubClass; /* Sub-Class code, 0 if class = 0 */
|
||||
uint8_t bInterfaceProtocol; /* Protocol, 0xFF = vendor */
|
||||
uint8_t iInterface; /* Index to interface string */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_SIZEOF_INTERFACE_DESC 9
|
||||
|
||||
/** Standard Endpoint Descriptor */
|
||||
struct usb_endpoint_descriptor {
|
||||
uint8_t bLength; /* Descriptor size in bytes = 7 */
|
||||
uint8_t bDescriptorType; /* ENDPOINT descriptor type = 5 */
|
||||
uint8_t bEndpointAddress; /* Endpoint # 0 - 15 | IN/OUT */
|
||||
uint8_t bmAttributes; /* Transfer type */
|
||||
uint16_t wMaxPacketSize; /* Bits 10:0 = max. packet size */
|
||||
uint8_t bInterval; /* Polling interval in (micro) frames */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_SIZEOF_ENDPOINT_DESC 7
|
||||
|
||||
/** Unicode (UTF16LE) String Descriptor */
|
||||
struct usb_string_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bString;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_SIZEOF_STRING_LANGID_DESC 4
|
||||
|
||||
/* USB Interface Association Descriptor */
|
||||
struct usb_interface_association_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bFirstInterface;
|
||||
uint8_t bInterfaceCount;
|
||||
uint8_t bFunctionClass;
|
||||
uint8_t bFunctionSubClass;
|
||||
uint8_t bFunctionProtocol;
|
||||
uint8_t iFunction;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_SIZEOF_IAD_DESC 8
|
||||
|
||||
/** USB device_qualifier descriptor */
|
||||
struct usb_device_qualifier_descriptor {
|
||||
uint8_t bLength; /* Descriptor size in bytes = 10 */
|
||||
uint8_t bDescriptorType; /* DEVICE QUALIFIER type = 6 */
|
||||
uint16_t bcdUSB; /* USB spec in BCD, e.g. 0x0200 */
|
||||
uint8_t bDeviceClass; /* Class code, if 0 see interface */
|
||||
uint8_t bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */
|
||||
uint8_t bDeviceProtocol; /* Protocol, if 0 see interface */
|
||||
uint8_t bMaxPacketSize; /* Endpoint 0 max. size */
|
||||
uint8_t bNumConfigurations; /* Number of possible configurations */
|
||||
uint8_t bReserved; /* Reserved = 0 */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define USB_SIZEOF_DEVICE_QUALIFIER_DESC 10
|
||||
|
||||
/* Microsoft OS function descriptor.
|
||||
* This can be used to request a specific driver (such as WINUSB) to be
|
||||
* loaded on Windows. Unlike other descriptors, it is requested by a special
|
||||
* request USB_REQ_GETMSFTOSDESCRIPTOR.
|
||||
* More details:
|
||||
* https://msdn.microsoft.com/en-us/windows/hardware/gg463179
|
||||
* And excellent explanation:
|
||||
* https://github.com/pbatard/libwdi/wiki/WCID-Devices
|
||||
*
|
||||
* The device will have exactly one "Extended Compat ID Feature Descriptor",
|
||||
* which may contain multiple "Function Descriptors" associated with
|
||||
* different interfaces.
|
||||
*/
|
||||
|
||||
/* MS OS 1.0 string descriptor */
|
||||
struct usb_msosv1_string_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bString[14];
|
||||
uint8_t bMS_VendorCode; /* Vendor Code, used for a control request */
|
||||
uint8_t bPad; /* Padding byte for VendorCode look as UTF16 */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* MS OS 1.0 Header descriptor */
|
||||
struct usb_msosv1_compat_id_header_descriptor {
|
||||
uint32_t dwLength;
|
||||
uint16_t bcdVersion;
|
||||
uint16_t wIndex;
|
||||
uint8_t bCount;
|
||||
uint8_t reserved[7];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* MS OS 1.0 Function descriptor */
|
||||
struct usb_msosv1_comp_id_function_descriptor {
|
||||
uint8_t bFirstInterfaceNumber;
|
||||
uint8_t reserved1;
|
||||
uint8_t compatibleID[8];
|
||||
uint8_t subCompatibleID[8];
|
||||
uint8_t reserved2[6];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define usb_msosv1_comp_id_create(x) \
|
||||
struct usb_msosv1_comp_id { \
|
||||
struct usb_msosv1_compat_id_header_descriptor compat_id_header; \
|
||||
struct usb_msosv1_comp_id_function_descriptor compat_id_function[x]; \
|
||||
};
|
||||
|
||||
struct usb_msosv1_descriptor {
|
||||
uint8_t *string;
|
||||
uint8_t string_len;
|
||||
uint8_t vendor_code;
|
||||
uint8_t *compat_id;
|
||||
uint16_t compat_id_len;
|
||||
uint8_t *comp_id_property;
|
||||
uint16_t comp_id_property_len;
|
||||
};
|
||||
|
||||
|
||||
/* MS OS 2.0 Header descriptor */
|
||||
struct usb_msosv2_header_descriptor {
|
||||
uint32_t dwLength;
|
||||
uint16_t bcdVersion;
|
||||
uint16_t wIndex;
|
||||
uint8_t bCount;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*Microsoft OS 2.0 set header descriptor*/
|
||||
struct usb_msosv2_set_header_descriptor {
|
||||
uint16_t wLength;
|
||||
uint16_t wDescriptorType;
|
||||
uint32_t dwWindowsVersion;
|
||||
uint16_t wDescriptorSetTotalLength;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Microsoft OS 2.0 compatibleID descriptor*/
|
||||
struct usb_msosv2_comp_id_descriptor {
|
||||
uint16_t wLength;
|
||||
uint16_t wDescriptorType;
|
||||
uint8_t compatibleID[8];
|
||||
uint8_t subCompatibleID[8];
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/* MS OS 2.0 property descriptor */
|
||||
struct usb_msosv2_property_descriptor {
|
||||
uint16_t wLength;
|
||||
uint16_t wDescriptorType;
|
||||
uint32_t dwPropertyDataType;
|
||||
uint16_t wPropertyNameLength;
|
||||
const char *bPropertyName;
|
||||
uint32_t dwPropertyDataLength;
|
||||
const char *bPropertyData;
|
||||
};
|
||||
|
||||
/* Microsoft OS 2.0 subset function descriptor */
|
||||
struct usb_msosv2_subset_function_descriptor {
|
||||
uint16_t wLength;
|
||||
uint16_t wDescriptorType;
|
||||
uint8_t bFirstInterface;
|
||||
uint8_t bReserved;
|
||||
uint16_t wSubsetLength;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_msosv2_descriptor {
|
||||
uint8_t *compat_id;
|
||||
uint16_t compat_id_len;
|
||||
uint8_t vendor_code;
|
||||
};
|
||||
|
||||
/* BOS header Descriptor */
|
||||
struct usb_bos_header_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wTotalLength;
|
||||
uint8_t bNumDeviceCaps;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* BOS Capability platform Descriptor */
|
||||
struct usb_bos_capability_platform_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDevCapabilityType;
|
||||
uint8_t bReserved;
|
||||
uint8_t PlatformCapabilityUUID[16];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* BOS Capability MS OS Descriptors version 2 */
|
||||
struct usb_bos_capability_msosv2_descriptor {
|
||||
uint32_t dwWindowsVersion;
|
||||
uint16_t wMSOSDescriptorSetTotalLength;
|
||||
uint8_t bVendorCode;
|
||||
uint8_t bAltEnumCode;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* BOS Capability webusb */
|
||||
struct usb_bos_capability_webusb_descriptor {
|
||||
uint16_t bcdVersion;
|
||||
uint8_t bVendorCode;
|
||||
uint8_t iLandingPage;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* BOS Capability extension Descriptor*/
|
||||
struct usb_bos_capability_extension_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDevCapabilityType;
|
||||
uint32_t bmAttributes;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Microsoft OS 2.0 Platform Capability Descriptor
|
||||
* See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/
|
||||
* microsoft-defined-usb-descriptors
|
||||
* Adapted from the source:
|
||||
* https://github.com/sowbug/weblight/blob/master/firmware/webusb.c
|
||||
* (BSD-2) Thanks http://janaxelson.com/files/ms_os_20_descriptors.c
|
||||
*/
|
||||
struct usb_bos_capability_platform_msosv2_descriptor {
|
||||
struct usb_bos_capability_platform_descriptor platform_msos;
|
||||
struct usb_bos_capability_msosv2_descriptor data_msosv2;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* WebUSB Platform Capability Descriptor:
|
||||
* https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
|
||||
*/
|
||||
struct usb_bos_capability_platform_webusb_descriptor {
|
||||
struct usb_bos_capability_platform_descriptor platform_webusb;
|
||||
struct usb_bos_capability_webusb_descriptor data_webusb;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_webusb_url_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bScheme;
|
||||
char URL[];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_webusb_url_ex_descriptor {
|
||||
uint8_t vendor_code;
|
||||
uint8_t *string;
|
||||
uint32_t string_len;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_bos_descriptor {
|
||||
uint8_t *string;
|
||||
uint32_t string_len;
|
||||
};
|
||||
|
||||
/* USB Device Capability Descriptor */
|
||||
struct usb_device_capability_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDevCapabilityType;
|
||||
} __attribute__((packed));
|
||||
|
||||
/** USB descriptor header */
|
||||
struct usb_desc_header {
|
||||
uint8_t bLength; /**< descriptor length */
|
||||
uint8_t bDescriptorType; /**< descriptor type */
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
#define USB_DEVICE_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct, bcdDevice, bNumConfigurations) \
|
||||
0x12, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_DEVICE, /* bDescriptorType */ \
|
||||
WBVAL(bcdUSB), /* bcdUSB */ \
|
||||
bDeviceClass, /* bDeviceClass */ \
|
||||
bDeviceSubClass, /* bDeviceSubClass */ \
|
||||
bDeviceProtocol, /* bDeviceProtocol */ \
|
||||
0x40, /* bMaxPacketSize */ \
|
||||
WBVAL(idVendor), /* idVendor */ \
|
||||
WBVAL(idProduct), /* idProduct */ \
|
||||
WBVAL(bcdDevice), /* bcdDevice */ \
|
||||
USB_STRING_MFC_INDEX, /* iManufacturer */ \
|
||||
USB_STRING_PRODUCT_INDEX, /* iProduct */ \
|
||||
USB_STRING_SERIAL_INDEX, /* iSerial */ \
|
||||
bNumConfigurations /* bNumConfigurations */
|
||||
|
||||
#define USB_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, /* bDescriptorType */ \
|
||||
WBVAL(wTotalLength), /* wTotalLength */ \
|
||||
bNumInterfaces, /* bNumInterfaces */ \
|
||||
bConfigurationValue, /* bConfigurationValue */ \
|
||||
0x00, /* iConfiguration */ \
|
||||
bmAttributes, /* bmAttributes */ \
|
||||
USB_CONFIG_POWER_MA(bMaxPower) /* bMaxPower */
|
||||
|
||||
#define USB_INTERFACE_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints, \
|
||||
bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber */ \
|
||||
bAlternateSetting, /* bAlternateSetting */ \
|
||||
bNumEndpoints, /* bNumEndpoints */ \
|
||||
bInterfaceClass, /* bInterfaceClass */ \
|
||||
bInterfaceSubClass, /* bInterfaceSubClass */ \
|
||||
bInterfaceProtocol, /* bInterfaceProtocol */ \
|
||||
iInterface /* iInterface */
|
||||
|
||||
#define USB_ENDPOINT_DESCRIPTOR_INIT(bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
bEndpointAddress, /* bEndpointAddress */ \
|
||||
bmAttributes, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
bInterval /* bInterval */
|
||||
|
||||
#define USB_IAD_INIT(bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol) \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
bInterfaceCount, /* bInterfaceCount */ \
|
||||
bFunctionClass, /* bFunctionClass */ \
|
||||
bFunctionSubClass, /* bFunctionSubClass */ \
|
||||
bFunctionProtocol, /* bFunctionProtocol */ \
|
||||
0x00 /* iFunction */
|
||||
|
||||
#define USB_LANGID_INIT(id) \
|
||||
0x04, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ \
|
||||
WBVAL(id) /* wLangID0 */
|
||||
// clang-format on
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,303 @@
|
|||
#ifndef USB_ERROR_H_
|
||||
#define USB_ERROR_H_
|
||||
/*
|
||||
* Apache NuttX
|
||||
* Copyright 2020 The Apache Software Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_ERRNO_H_
|
||||
#define USB_ERRNO_H_
|
||||
|
||||
#ifndef CONFIG_USB_ERROR_USE_SYSTEM
|
||||
|
||||
#define EPERM 1
|
||||
#define EPERM_STR "Operation not permitted"
|
||||
#define ENOENT 2
|
||||
#define ENOENT_STR "No such file or directory"
|
||||
#define ESRCH 3
|
||||
#define ESRCH_STR "No such process"
|
||||
#define EINTR 4
|
||||
#define EINTR_STR "Interrupted system call"
|
||||
#define EIO 5
|
||||
#define EIO_STR "I/O error"
|
||||
#define ENXIO 6
|
||||
#define ENXIO_STR "No such device or address"
|
||||
#define E2BIG 7
|
||||
#define E2BIG_STR "Arg list too long"
|
||||
#define ENOEXEC 8
|
||||
#define ENOEXEC_STR "Exec format error"
|
||||
#define EBADF 9
|
||||
#define EBADF_STR "Bad file number"
|
||||
#define ECHILD 10
|
||||
#define ECHILD_STR "No child processes"
|
||||
#define EAGAIN 11
|
||||
#define EWOULDBLOCK EAGAIN
|
||||
#define EAGAIN_STR "Try again"
|
||||
#define ENOMEM 12
|
||||
#define ENOMEM_STR "Out of memory"
|
||||
#define EACCES 13
|
||||
#define EACCES_STR "Permission denied"
|
||||
#define EFAULT 14 /* Linux errno extension */
|
||||
#define EFAULT_STR "Bad address"
|
||||
#define ENOTBLK 15
|
||||
#define ENOTBLK_STR "Block device required"
|
||||
#define EBUSY 16
|
||||
#define EBUSY_STR "Device or resource busy"
|
||||
#define EEXIST 17
|
||||
#define EEXIST_STR "File exists"
|
||||
#define EXDEV 18
|
||||
#define EXDEV_STR "Cross-device link"
|
||||
#define ENODEV 19
|
||||
#define ENODEV_STR "No such device"
|
||||
#define ENOTDIR 20
|
||||
#define ENOTDIR_STR "Not a directory"
|
||||
#define EISDIR 21
|
||||
#define EISDIR_STR "Is a directory"
|
||||
#define EINVAL 22
|
||||
#define EINVAL_STR "Invalid argument"
|
||||
#define ENFILE 23
|
||||
#define ENFILE_STR "File table overflow"
|
||||
#define EMFILE 24
|
||||
#define EMFILE_STR "Too many open files"
|
||||
#define ENOTTY 25
|
||||
#define ENOTTY_STR "Not a typewriter"
|
||||
#define ETXTBSY 26
|
||||
#define ETXTBSY_STR "Text file busy"
|
||||
#define EFBIG 27
|
||||
#define EFBIG_STR "File too large"
|
||||
#define ENOSPC 28
|
||||
#define ENOSPC_STR "No space left on device"
|
||||
#define ESPIPE 29
|
||||
#define ESPIPE_STR "Illegal seek"
|
||||
#define EROFS 30
|
||||
#define EROFS_STR "Read-only file system"
|
||||
#define EMLINK 31
|
||||
#define EMLINK_STR "Too many links"
|
||||
#define EPIPE 32
|
||||
#define EPIPE_STR "Broken pipe"
|
||||
#define EDOM 33
|
||||
#define EDOM_STR "Math argument out of domain of func"
|
||||
#define ERANGE 34
|
||||
#define ERANGE_STR "Math result not representable"
|
||||
#define ENOMSG 35
|
||||
#define ENOMSG_STR "No message of desired type"
|
||||
#define EIDRM 36
|
||||
#define EIDRM_STR "Identifier removed"
|
||||
#define ECHRNG 37 /* Linux errno extension */
|
||||
#define ECHRNG_STR "Channel number out of range"
|
||||
#define EL2NSYNC 38 /* Linux errno extension */
|
||||
#define EL2NSYNC_STR "Level 2 not synchronized"
|
||||
#define EL3HLT 39 /* Linux errno extension */
|
||||
#define EL3HLT_STR "Level 3 halted"
|
||||
#define EL3RST 40 /* Linux errno extension */
|
||||
#define EL3RST_STR "Level 3 reset"
|
||||
#define ELNRNG 41 /* Linux errno extension */
|
||||
#define ELNRNG_STR "Link number out of range"
|
||||
#define EUNATCH 42 /* Linux errno extension */
|
||||
#define EUNATCH_STR "Protocol driver not attached"
|
||||
#define ENOCSI 43 /* Linux errno extension */
|
||||
#define ENOCSI_STR "No CSI structure available"
|
||||
#define EL2HLT 44 /* Linux errno extension */
|
||||
#define EL2HLT_STR "Level 2 halted"
|
||||
#define EDEADLK 45
|
||||
#define EDEADLK_STR "Resource deadlock would occur"
|
||||
#define ENOLCK 46
|
||||
#define ENOLCK_STR "No record locks available"
|
||||
|
||||
#define EBADE 50 /* Linux errno extension */
|
||||
#define EBADE_STR "Invalid exchange"
|
||||
#define EBADR 51 /* Linux errno extension */
|
||||
#define EBADR_STR "Invalid request descriptor"
|
||||
#define EXFULL 52 /* Linux errno extension */
|
||||
#define EXFULL_STR "Exchange full"
|
||||
#define ENOANO 53 /* Linux errno extension */
|
||||
#define ENOANO_STR "No anode"
|
||||
#define EBADRQC 54 /* Linux errno extension */
|
||||
#define EBADRQC_STR "Invalid request code"
|
||||
#define EBADSLT 55 /* Linux errno extension */
|
||||
#define EBADSLT_STR "Invalid slot"
|
||||
#define EDEADLOCK 56 /* Linux errno extension */
|
||||
#define EDEADLOCK_STR "File locking deadlock error"
|
||||
#define EBFONT 57 /* Linux errno extension */
|
||||
#define EBFONT_STR "Bad font file format"
|
||||
|
||||
#define ENOSTR 60
|
||||
#define ENOSTR_STR "Device not a stream"
|
||||
#define ENODATA 61
|
||||
#define ENODATA_STR "No data available"
|
||||
#define ETIME 62
|
||||
#define ETIME_STR "Timer expired"
|
||||
#define ENOSR 63
|
||||
#define ENOSR_STR "Out of streams resources"
|
||||
#define ENONET 64 /* Linux errno extension */
|
||||
#define ENONET_STR "Machine is not on the network"
|
||||
#define ENOPKG 65 /* Linux errno extension */
|
||||
#define ENOPKG_STR "Package not installed"
|
||||
#define EREMOTE 66 /* Linux errno extension */
|
||||
#define EREMOTE_STR "Object is remote"
|
||||
#define ENOLINK 67
|
||||
#define ENOLINK_STR "Link has been severed"
|
||||
#define EADV 68 /* Linux errno extension */
|
||||
#define EADV_STR "Advertise error"
|
||||
#define ESRMNT 69 /* Linux errno extension */
|
||||
#define ESRMNT_STR "Srmount error"
|
||||
#define ECOMM 70 /* Linux errno extension */
|
||||
#define ECOMM_STR "Communication error on send"
|
||||
#define EPROTO 71
|
||||
#define EPROTO_STR "Protocol error"
|
||||
|
||||
#define EMULTIHOP 74
|
||||
#define EMULTIHOP_STR "Multihop attempted"
|
||||
#define ELBIN 75 /* Linux errno extension */
|
||||
#define ELBIN_STR "Inode is remote"
|
||||
#define EDOTDOT 76 /* Linux errno extension */
|
||||
#define EDOTDOT_STR "RFS specific error"
|
||||
#define EBADMSG 77
|
||||
#define EBADMSG_STR "Not a data message"
|
||||
|
||||
#define EFTYPE 79
|
||||
#define EFTYPE_STR "Inappropriate file type or format"
|
||||
#define ENOTUNIQ 80 /* Linux errno extension */
|
||||
#define ENOTUNIQ_STR "Name not unique on network"
|
||||
#define EBADFD 81 /* Linux errno extension */
|
||||
#define EBADFD_STR "File descriptor in bad state"
|
||||
#define EREMCHG 82 /* Linux errno extension */
|
||||
#define EREMCHG_STR "Remote address changed"
|
||||
#define ELIBACC 83 /* Linux errno extension */
|
||||
#define ELIBACC_STR "Can not access a needed shared library"
|
||||
#define ELIBBAD 84 /* Linux errno extension */
|
||||
#define ELIBBAD_STR "Accessing a corrupted shared library"
|
||||
#define ELIBSCN 85 /* Linux errno extension */
|
||||
#define ELIBSCN_STR ".lib section in a.out corrupted"
|
||||
#define ELIBMAX 86 /* Linux errno extension */
|
||||
#define ELIBMAX_STR "Attempting to link in too many shared libraries"
|
||||
#define ELIBEXEC 87 /* Linux errno extension */
|
||||
#define ELIBEXEC_STR "Cannot exec a shared library directly"
|
||||
#define ENOSYS 88
|
||||
#define ENOSYS_STR "Function not implemented"
|
||||
#define ENMFILE 89 /* Cygwin */
|
||||
#define ENMFILE_STR "No more files"
|
||||
#define ENOTEMPTY 90
|
||||
#define ENOTEMPTY_STR "Directory not empty"
|
||||
#define ENAMETOOLONG 91
|
||||
#define ENAMETOOLONG_STR "File name too long"
|
||||
#define ELOOP 92
|
||||
#define ELOOP_STR "Too many symbolic links encountered"
|
||||
|
||||
#define EOPNOTSUPP 95
|
||||
#define EOPNOTSUPP_STR "Operation not supported on transport endpoint"
|
||||
#define EPFNOSUPPORT 96
|
||||
#define EPFNOSUPPORT_STR "Protocol family not supported"
|
||||
|
||||
#define ECONNRESET 104
|
||||
#define ECONNRESET_STR "Connection reset by peer"
|
||||
#define ENOBUFS 105
|
||||
#define ENOBUFS_STR "No buffer space available"
|
||||
#define EAFNOSUPPORT 106
|
||||
#define EAFNOSUPPORT_STR "Address family not supported by protocol"
|
||||
#define EPROTOTYPE 107
|
||||
#define EPROTOTYPE_STR "Protocol wrong type for socket"
|
||||
#define ENOTSOCK 108
|
||||
#define ENOTSOCK_STR "Socket operation on non-socket"
|
||||
#define ENOPROTOOPT 109
|
||||
#define ENOPROTOOPT_STR "Protocol not available"
|
||||
#define ESHUTDOWN 110 /* Linux errno extension */
|
||||
#define ESHUTDOWN_STR "Cannot send after transport endpoint shutdown"
|
||||
#define ECONNREFUSED 111
|
||||
#define ECONNREFUSED_STR "Connection refused"
|
||||
#define EADDRINUSE 112
|
||||
#define EADDRINUSE_STR "Address already in use"
|
||||
#define ECONNABORTED 113
|
||||
#define ECONNABORTED_STR "Software caused connection abort"
|
||||
#define ENETUNREACH 114
|
||||
#define ENETUNREACH_STR "Network is unreachable"
|
||||
#define ENETDOWN 115
|
||||
#define ENETDOWN_STR "Network is down"
|
||||
#define ETIMEDOUT 116
|
||||
#define ETIMEDOUT_STR "Connection timed out"
|
||||
#define EHOSTDOWN 117
|
||||
#define EHOSTDOWN_STR "Host is down"
|
||||
#define EHOSTUNREACH 118
|
||||
#define EHOSTUNREACH_STR "No route to host"
|
||||
#define EINPROGRESS 119
|
||||
#define EINPROGRESS_STR "Operation now in progress"
|
||||
#define EALREADY 120
|
||||
#define EALREADY_STR "Socket already connected"
|
||||
#define EDESTADDRREQ 121
|
||||
#define EDESTADDRREQ_STR "Destination address required"
|
||||
#define EMSGSIZE 122
|
||||
#define EMSGSIZE_STR "Message too long"
|
||||
#define EPROTONOSUPPORT 123
|
||||
#define EPROTONOSUPPORT_STR "Protocol not supported"
|
||||
#define ESOCKTNOSUPPORT 124 /* Linux errno extension */
|
||||
#define ESOCKTNOSUPPORT_STR "Socket type not supported"
|
||||
#define EADDRNOTAVAIL 125
|
||||
#define EADDRNOTAVAIL_STR "Cannot assign requested address"
|
||||
#define ENETRESET 126
|
||||
#define ENETRESET_STR "Network dropped connection because of reset"
|
||||
#define EISCONN 127
|
||||
#define EISCONN_STR "Transport endpoint is already connected"
|
||||
#define ENOTCONN 128
|
||||
#define ENOTCONN_STR "Transport endpoint is not connected"
|
||||
#define ETOOMANYREFS 129
|
||||
#define ETOOMANYREFS_STR "Too many references: cannot splice"
|
||||
#define EPROCLIM 130
|
||||
#define EPROCLIM_STR "Limit would be exceeded by attempted fork"
|
||||
#define EUSERS 131
|
||||
#define EUSERS_STR "Too many users"
|
||||
#define EDQUOT 132
|
||||
#define EDQUOT_STR "Quota exceeded"
|
||||
#define ESTALE 133
|
||||
#define ESTALE_STR "Stale NFS file handle"
|
||||
#define ENOTSUP 134
|
||||
#define ENOTSUP_STR "Not supported"
|
||||
#define ENOMEDIUM 135 /* Linux errno extension */
|
||||
#define ENOMEDIUM_STR "No medium found"
|
||||
#define ENOSHARE 136 /* Cygwin */
|
||||
#define ENOSHARE_STR "No such host or network path"
|
||||
#define ECASECLASH 137 /* Cygwin */
|
||||
#define ECASECLASH_STR "Filename exists with different case"
|
||||
#define EILSEQ 138
|
||||
#define EILSEQ_STR "Illegal byte sequence"
|
||||
#define EOVERFLOW 139
|
||||
#define EOVERFLOW_STR "Value too large for defined data type"
|
||||
#define ECANCELED 140
|
||||
#define ECANCELED_STR "Operation cancelled"
|
||||
#define ENOTRECOVERABLE 141
|
||||
#define ENOTRECOVERABLE_STR "State not recoverable"
|
||||
#define EOWNERDEAD 142
|
||||
#define EOWNERDEAD_STR "Previous owner died"
|
||||
#define ESTRPIPE 143 /* Linux errno extension */
|
||||
#define ESTRPIPE_STR "Streams pipe error"
|
||||
|
||||
#define __ELASTERROR 2000 /* Users can add values starting here */
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* Return a pointer to the thread specific errno. */
|
||||
|
||||
int *__errno(void);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,175 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*************************************************
|
||||
File name: usb_hc.h
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: take CherryUSB v0.1.2/common/usb_hc.h for references
|
||||
https://gitee.com/phytium_embedded/phytium-free-rtos-sdk/blob/master/third-party/cherryusb/common/usb_hc.h
|
||||
History:
|
||||
1. Date: 2024-06-19
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: New field usb_hc_type in data structure usbh_urb.
|
||||
*************************************************/
|
||||
|
||||
#ifndef USB_HC_H_
|
||||
#define USB_HC_H_
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
|
||||
typedef void *usbh_pipe_t;
|
||||
|
||||
struct usbh_bus;
|
||||
struct usbh_hub;
|
||||
|
||||
/**
|
||||
* @brief USB Endpoint Configuration.
|
||||
*
|
||||
* Structure containing the USB endpoint configuration.
|
||||
*/
|
||||
struct usbh_endpoint_cfg {
|
||||
struct usbh_hubport *hport;
|
||||
uint8_t ep_addr; /* Endpoint addr with direction */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_interval; /* Endpoint interval */
|
||||
uint8_t mult; /* Endpoint additional transcation */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief USB Iso Configuration.
|
||||
*
|
||||
* Structure containing the USB Iso configuration.
|
||||
*/
|
||||
struct usbh_iso_frame_packet {
|
||||
uint8_t *transfer_buffer;
|
||||
uint32_t transfer_buffer_length;
|
||||
uint32_t actual_length;
|
||||
int errorcode;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief USB Urb Configuration.
|
||||
*
|
||||
* Structure containing the USB Urb configuration.
|
||||
*/
|
||||
struct usbh_urb {
|
||||
usbh_pipe_t pipe;
|
||||
struct usb_setup_packet *setup;
|
||||
uint8_t *transfer_buffer;
|
||||
uint32_t transfer_buffer_length;
|
||||
int transfer_flags;
|
||||
uint32_t actual_length;
|
||||
uint32_t timeout;
|
||||
int errorcode;
|
||||
uint8_t usb_hc_type;
|
||||
uint32_t num_of_iso_packets;
|
||||
uint32_t start_frame;
|
||||
usbh_complete_callback_t complete;
|
||||
void *arg;
|
||||
struct usbh_iso_frame_packet iso_packet[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief usb host controller hardware init.
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usb_hc_init(uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Get frame number.
|
||||
*
|
||||
* @return frame number.
|
||||
*/
|
||||
uint16_t usbh_get_frame_number(void);
|
||||
/**
|
||||
* @brief control roothub.
|
||||
*
|
||||
* @param usb usb bus instance
|
||||
* @param setup setup request buffer.
|
||||
* @param buf buf for reading response or write data.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_roothub_control(struct usbh_bus *usb, struct usb_setup_packet *setup, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief get device address.
|
||||
*
|
||||
* @param hport Hub port of USB device
|
||||
* @return On success will return device address, and others indicate fail.
|
||||
*/
|
||||
int usbh_get_devaddr(struct usbh_hubport *hport);
|
||||
|
||||
/**
|
||||
* @brief get port speed.
|
||||
*
|
||||
* @param hport Hub of USB device
|
||||
* @param port Port index
|
||||
* @return On success will return speed, and others indicate fail.
|
||||
*/
|
||||
uint8_t usbh_get_port_speed(struct usbh_hub *hub, const uint8_t port);
|
||||
|
||||
/**
|
||||
* @brief reconfig endpoint pipe.
|
||||
*
|
||||
* @param pipe A memory allocated for pipe.
|
||||
* @param dev_addr device address.
|
||||
* @param ep_mps endpoint max packet size.
|
||||
* @param mult endpoint additional transcation
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_ep_pipe_reconfigure(struct usbh_bus *usb, usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
|
||||
|
||||
/**
|
||||
* @brief Allocate pipe for endpoint
|
||||
*
|
||||
* @param pipe A memory location provided by the caller in which to save the allocated pipe.
|
||||
* @param ep_cfg Describes the endpoint info to be allocated.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg);
|
||||
|
||||
/**
|
||||
* @brief Free a pipe in which saves endpoint info.
|
||||
*
|
||||
* @param pipe A memory location provided by the caller in which to free the allocated endpoint info.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_pipe_free(usbh_pipe_t pipe);
|
||||
int usbh_pipe_free_xiuos(struct usbh_hubport *hport, usbh_pipe_t pipe);
|
||||
|
||||
/**
|
||||
* @brief Submit a usb transfer request to an endpoint.
|
||||
*
|
||||
* If timeout is not zero, this function will be in poll transfer mode,
|
||||
* otherwise will be in async transfer mode.
|
||||
*
|
||||
* @param urb Usb request block.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_submit_urb(struct usbh_urb *urb);
|
||||
|
||||
/**
|
||||
* @brief Cancel a transfer request.
|
||||
*
|
||||
* This function will call When calls usbh_submit_urb and return -ETIMEOUT or -ESHUTDOWN.
|
||||
*
|
||||
* @param urb Usb request block.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_kill_urb(struct usbh_urb *urb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USB_HC_H_ */
|
||||
|
|
|
@ -1,7 +1,460 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_LIST_H_
|
||||
#define USB_LIST_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* usb_container_of - return the member address of ptr, if the type of ptr is the
|
||||
* struct type.
|
||||
*/
|
||||
#define usb_container_of(ptr, type, member) \
|
||||
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* Single List structure
|
||||
*/
|
||||
struct usb_slist_node {
|
||||
struct usb_slist_node *next; /**< point to next node. */
|
||||
};
|
||||
typedef struct usb_slist_node usb_slist_t; /**< Type for single list. */
|
||||
|
||||
/**
|
||||
* @brief initialize a single list
|
||||
*
|
||||
* @param l the single list to be initialized
|
||||
*/
|
||||
static inline void usb_slist_init(usb_slist_t *l)
|
||||
{
|
||||
l->next = NULL;
|
||||
}
|
||||
|
||||
static inline void usb_slist_add_head(usb_slist_t *l, usb_slist_t *n)
|
||||
{
|
||||
n->next = l->next;
|
||||
l->next = n;
|
||||
}
|
||||
|
||||
static inline void usb_slist_add_tail(usb_slist_t *l, usb_slist_t *n)
|
||||
{
|
||||
usb_slist_t *tmp = l;
|
||||
|
||||
while (tmp->next) {
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
/* append the node to the tail */
|
||||
tmp->next = n;
|
||||
n->next = NULL;
|
||||
}
|
||||
|
||||
static inline void usb_slist_insert(usb_slist_t *l, usb_slist_t *next, usb_slist_t *n)
|
||||
{
|
||||
if (!next) {
|
||||
usb_slist_add_tail(next, l);
|
||||
return;
|
||||
}
|
||||
|
||||
while (l->next) {
|
||||
if (l->next == next) {
|
||||
l->next = n;
|
||||
n->next = next;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
static inline usb_slist_t *usb_slist_remove(usb_slist_t *l, usb_slist_t *n)
|
||||
{
|
||||
usb_slist_t *tmp = l;
|
||||
/* remove slist head */
|
||||
while (tmp->next && tmp->next != n) {
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
/* remove node */
|
||||
if (tmp->next != (usb_slist_t *)0) {
|
||||
tmp->next = tmp->next->next;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static inline unsigned int usb_slist_len(const usb_slist_t *l)
|
||||
{
|
||||
unsigned int len = 0;
|
||||
const usb_slist_t *list = l->next;
|
||||
|
||||
while (list != NULL) {
|
||||
list = list->next;
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline unsigned int usb_slist_contains(usb_slist_t *l, usb_slist_t *n)
|
||||
{
|
||||
while (l->next) {
|
||||
if (l->next == n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline usb_slist_t *usb_slist_head(usb_slist_t *l)
|
||||
{
|
||||
return l->next;
|
||||
}
|
||||
|
||||
static inline usb_slist_t *usb_slist_tail(usb_slist_t *l)
|
||||
{
|
||||
while (l->next) {
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static inline usb_slist_t *usb_slist_next(usb_slist_t *n)
|
||||
{
|
||||
return n->next;
|
||||
}
|
||||
|
||||
static inline int usb_slist_isempty(usb_slist_t *l)
|
||||
{
|
||||
return l->next == NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize a slist object
|
||||
*/
|
||||
#define USB_SLIST_OBJECT_INIT(object) \
|
||||
{ \
|
||||
NULL \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize a slist object
|
||||
*/
|
||||
#define USB_SLIST_DEFINE(slist) \
|
||||
usb_slist_t slist = { NULL }
|
||||
|
||||
/**
|
||||
* @brief get the struct for this single list node
|
||||
* @param node the entry point
|
||||
* @param type the type of structure
|
||||
* @param member the name of list in structure
|
||||
*/
|
||||
#define usb_slist_entry(node, type, member) \
|
||||
usb_container_of(node, type, member)
|
||||
|
||||
/**
|
||||
* usb_slist_first_entry - get the first element from a slist
|
||||
* @ptr: the slist head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the slist_struct within the struct.
|
||||
*
|
||||
* Note, that slist is expected to be not empty.
|
||||
*/
|
||||
#define usb_slist_first_entry(ptr, type, member) \
|
||||
usb_slist_entry((ptr)->next, type, member)
|
||||
|
||||
/**
|
||||
* usb_slist_tail_entry - get the tail element from a slist
|
||||
* @ptr: the slist head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the slist_struct within the struct.
|
||||
*
|
||||
* Note, that slist is expected to be not empty.
|
||||
*/
|
||||
#define usb_slist_tail_entry(ptr, type, member) \
|
||||
usb_slist_entry(usb_slist_tail(ptr), type, member)
|
||||
|
||||
/**
|
||||
* usb_slist_first_entry_or_null - get the first element from a slist
|
||||
* @ptr: the slist head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the slist_struct within the struct.
|
||||
*
|
||||
* Note, that slist is expected to be not empty.
|
||||
*/
|
||||
#define usb_slist_first_entry_or_null(ptr, type, member) \
|
||||
(usb_slist_isempty(ptr) ? NULL : usb_slist_first_entry(ptr, type, member))
|
||||
|
||||
/**
|
||||
* usb_slist_for_each - iterate over a single list
|
||||
* @pos: the usb_slist_t * to use as a loop cursor.
|
||||
* @head: the head for your single list.
|
||||
*/
|
||||
#define usb_slist_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != NULL; pos = pos->next)
|
||||
|
||||
#define usb_slist_for_each_safe(pos, next, head) \
|
||||
for (pos = (head)->next, next = pos->next; pos; \
|
||||
pos = next, next = pos->next)
|
||||
|
||||
/**
|
||||
* usb_slist_for_each_entry - iterate over single list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your single list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define usb_slist_for_each_entry(pos, head, member) \
|
||||
for (pos = usb_slist_entry((head)->next, typeof(*pos), member); \
|
||||
&pos->member != (NULL); \
|
||||
pos = usb_slist_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
#define usb_slist_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = usb_slist_entry((head)->next, typeof(*pos), member), \
|
||||
n = usb_slist_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (NULL); \
|
||||
pos = n, n = usb_slist_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* Double List structure
|
||||
*/
|
||||
struct usb_dlist_node {
|
||||
struct usb_dlist_node *next; /**< point to next node. */
|
||||
struct usb_dlist_node *prev; /**< point to prev node. */
|
||||
};
|
||||
typedef struct usb_dlist_node usb_dlist_t; /**< Type for lists. */
|
||||
|
||||
/**
|
||||
* @brief initialize a list
|
||||
*
|
||||
* @param l list to be initialized
|
||||
*/
|
||||
static inline void usb_dlist_init(usb_dlist_t *l)
|
||||
{
|
||||
l->next = l->prev = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief insert a node after a list
|
||||
*
|
||||
* @param l list to insert it
|
||||
* @param n new node to be inserted
|
||||
*/
|
||||
static inline void usb_dlist_insert_after(usb_dlist_t *l, usb_dlist_t *n)
|
||||
{
|
||||
l->next->prev = n;
|
||||
n->next = l->next;
|
||||
|
||||
l->next = n;
|
||||
n->prev = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief insert a node before a list
|
||||
*
|
||||
* @param n new node to be inserted
|
||||
* @param l list to insert it
|
||||
*/
|
||||
static inline void usb_dlist_insert_before(usb_dlist_t *l, usb_dlist_t *n)
|
||||
{
|
||||
l->prev->next = n;
|
||||
n->prev = l->prev;
|
||||
|
||||
l->prev = n;
|
||||
n->next = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief remove node from list.
|
||||
* @param n the node to remove from the list.
|
||||
*/
|
||||
static inline void usb_dlist_remove(usb_dlist_t *n)
|
||||
{
|
||||
n->next->prev = n->prev;
|
||||
n->prev->next = n->next;
|
||||
|
||||
n->next = n->prev = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief move node from list.
|
||||
* @param n the node to remove from the list.
|
||||
*/
|
||||
static inline void usb_dlist_move_head(usb_dlist_t *l, usb_dlist_t *n)
|
||||
{
|
||||
usb_dlist_remove(n);
|
||||
usb_dlist_insert_after(l, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief move node from list.
|
||||
* @param n the node to remove from the list.
|
||||
*/
|
||||
static inline void usb_dlist_move_tail(usb_dlist_t *l, usb_dlist_t *n)
|
||||
{
|
||||
usb_dlist_remove(n);
|
||||
usb_dlist_insert_before(l, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief tests whether a list is empty
|
||||
* @param l the list to test.
|
||||
*/
|
||||
static inline int usb_dlist_isempty(const usb_dlist_t *l)
|
||||
{
|
||||
return l->next == l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the list length
|
||||
* @param l the list to get.
|
||||
*/
|
||||
static inline unsigned int usb_dlist_len(const usb_dlist_t *l)
|
||||
{
|
||||
unsigned int len = 0;
|
||||
const usb_dlist_t *p = l;
|
||||
|
||||
while (p->next != l) {
|
||||
p = p->next;
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize a dlist object
|
||||
*/
|
||||
#define USB_DLIST_OBJECT_INIT(object) \
|
||||
{ \
|
||||
&(object), &(object) \
|
||||
}
|
||||
/**
|
||||
* @brief initialize a dlist object
|
||||
*/
|
||||
#define USB_DLIST_DEFINE(list) \
|
||||
usb_dlist_t list = { &(list), &(list) }
|
||||
|
||||
/**
|
||||
* @brief get the struct for this entry
|
||||
* @param node the entry point
|
||||
* @param type the type of structure
|
||||
* @param member the name of list in structure
|
||||
*/
|
||||
#define usb_dlist_entry(node, type, member) \
|
||||
usb_container_of(node, type, member)
|
||||
|
||||
/**
|
||||
* dlist_first_entry - get the first element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define usb_dlist_first_entry(ptr, type, member) \
|
||||
usb_dlist_entry((ptr)->next, type, member)
|
||||
/**
|
||||
* dlist_first_entry_or_null - get the first element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define usb_dlist_first_entry_or_null(ptr, type, member) \
|
||||
(usb_dlist_isempty(ptr) ? NULL : usb_dlist_first_entry(ptr, type, member))
|
||||
|
||||
/**
|
||||
* usb_dlist_for_each - iterate over a list
|
||||
* @pos: the usb_dlist_t * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define usb_dlist_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* usb_dlist_for_each_prev - iterate over a list
|
||||
* @pos: the dlist_t * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define usb_dlist_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||
|
||||
/**
|
||||
* usb_dlist_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the dlist_t * to use as a loop cursor.
|
||||
* @n: another dlist_t * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define usb_dlist_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
#define usb_dlist_for_each_prev_safe(pos, n, head) \
|
||||
for (pos = (head)->prev, n = pos->prev; pos != (head); \
|
||||
pos = n, n = pos->prev)
|
||||
/**
|
||||
* usb_dlist_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define usb_dlist_for_each_entry(pos, head, member) \
|
||||
for (pos = usb_dlist_entry((head)->next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = usb_dlist_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* usb_usb_dlist_for_each_entry_reverse - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define usb_dlist_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = usb_dlist_entry((head)->prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = usb_dlist_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* usb_usb_dlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define usb_dlist_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = usb_dlist_entry((head)->next, typeof(*pos), member), \
|
||||
n = usb_dlist_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = usb_dlist_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* usb_usb_dlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define usb_dlist_for_each_entry_safe_reverse(pos, n, head, member) \
|
||||
for (pos = usb_dlist_entry((head)->prev, typeof(*pos), field), \
|
||||
n = usb_dlist_entry(pos->member.prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = usb_dlist_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_LOG_H_
|
||||
#define USB_LOG_H_
|
||||
|
||||
#include "libserial.h"
|
||||
|
||||
/* DEBUG level */
|
||||
#define USB_DBG_ERROR 0
|
||||
#define USB_DBG_WARNING 1
|
||||
#define USB_DBG_INFO 2
|
||||
#define USB_DBG_LOG 3
|
||||
|
||||
#ifndef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "USB"
|
||||
#endif
|
||||
/*
|
||||
* The color for terminal (foreground)
|
||||
* BLACK 30
|
||||
* RED 31
|
||||
* GREEN 32
|
||||
* YELLOW 33
|
||||
* BLUE 34
|
||||
* PURPLE 35
|
||||
* CYAN 36
|
||||
* WHITE 37
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_USB_PRINTF_COLOR_ENABLE
|
||||
#define _USB_DBG_COLOR(n) CONFIG_USB_PRINTF("\033[" #n "m")
|
||||
#define _USB_DBG_LOG_HDR(lvl_name, color_n) \
|
||||
CONFIG_USB_PRINTF("\033[" #color_n "m[" lvl_name "/" USB_DBG_TAG "] ")
|
||||
#define _USB_DBG_LOG_X_END \
|
||||
CONFIG_USB_PRINTF("\033[0m")
|
||||
#else
|
||||
#define _USB_DBG_COLOR(n)
|
||||
#define _USB_DBG_LOG_HDR(lvl_name, color_n) \
|
||||
CONFIG_USB_PRINTF("[" lvl_name "/" USB_DBG_TAG "] ")
|
||||
#define _USB_DBG_LOG_X_END
|
||||
#endif
|
||||
|
||||
#define usb_dbg_log_line(lvl, color_n, fmt, ...) \
|
||||
do { \
|
||||
_USB_DBG_LOG_HDR(lvl, color_n); \
|
||||
CONFIG_USB_PRINTF(fmt, ##__VA_ARGS__); \
|
||||
_USB_DBG_LOG_X_END; \
|
||||
} while (0)
|
||||
|
||||
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_LOG)
|
||||
#define USB_LOG_DBG(fmt, ...) usb_dbg_log_line("D", 0, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define USB_LOG_DBG(...) {}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_INFO)
|
||||
#define USB_LOG_INFO(fmt, ...) usb_dbg_log_line("I", 32, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define USB_LOG_INFO(...) {}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_WARNING)
|
||||
#define USB_LOG_WRN(fmt, ...) usb_dbg_log_line("W", 33, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define USB_LOG_WRN(...) {}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_ERROR)
|
||||
#define USB_LOG_ERR(fmt, ...) usb_dbg_log_line("E", 31, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define USB_LOG_ERR(...) {}
|
||||
#endif
|
||||
|
||||
#define USB_LOG_RAW(...) CONFIG_USB_PRINTF(__VA_ARGS__)
|
||||
|
||||
void usb_assert(const char *filename, int linenum);
|
||||
#define USB_ASSERT(f) \
|
||||
do { \
|
||||
if (!(f)) \
|
||||
usb_assert(__FILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef USB_MEM_H_
|
||||
#define USB_MEM_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -1,7 +1,210 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_UTIL_H_
|
||||
#define USB_TIIL_H_
|
||||
#define USB_UTIL_H_
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT __packed struct
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION __packed union
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __attribute__((packed, aligned(1)))
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
||||
#ifndef __USED
|
||||
#if __ICCARM_V8
|
||||
#define __USED __attribute__((used))
|
||||
#else
|
||||
#define __USED __root
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __WEAK
|
||||
#if __ICCARM_V8
|
||||
#define __WEAK __attribute__((weak))
|
||||
#else
|
||||
#define __WEAK _Pragma("__weak")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED
|
||||
#if __ICCARM_V8
|
||||
#define __PACKED __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
#define __PACKED __packed
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED_STRUCT
|
||||
#if __ICCARM_V8
|
||||
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
#define __PACKED_STRUCT __packed struct
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED_UNION
|
||||
#if __ICCARM_V8
|
||||
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
#define __PACKED_UNION __packed union
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __ALIGNED
|
||||
#if __ICCARM_V8
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#elif (__VER__ >= 7080000)
|
||||
/* Needs IAR language extensions */
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#else
|
||||
#warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
|
||||
#define __ALIGNED(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __ALIGN_BEGIN
|
||||
#define __ALIGN_BEGIN
|
||||
#endif
|
||||
#ifndef __ALIGN_END
|
||||
#define __ALIGN_END __attribute__((aligned(4)))
|
||||
#endif
|
||||
|
||||
#ifndef ARG_UNUSED
|
||||
#define ARG_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
#ifndef LO_BYTE
|
||||
#define LO_BYTE(x) ((uint8_t)(x & 0x00FF))
|
||||
#endif
|
||||
|
||||
#ifndef HI_BYTE
|
||||
#define HI_BYTE(x) ((uint8_t)((x & 0xFF00) >> 8))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef BCD
|
||||
#define BCD(x) ((((x) / 10) << 4) | ((x) % 10))
|
||||
#endif
|
||||
|
||||
#ifdef BIT
|
||||
#undef BIT
|
||||
#define BIT(n) (1UL << (n))
|
||||
#else
|
||||
#define BIT(n) (1UL << (n))
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) \
|
||||
((int)((sizeof(array) / sizeof((array)[0]))))
|
||||
#endif
|
||||
|
||||
#ifndef BSWAP16
|
||||
#define BSWAP16(u16) (__builtin_bswap16(u16))
|
||||
#endif
|
||||
#ifndef BSWAP32
|
||||
#define BSWAP32(u32) (__builtin_bswap32(u32))
|
||||
#endif
|
||||
|
||||
#define GET_BE16(field) \
|
||||
(((uint16_t)(field)[0] << 8) | ((uint16_t)(field)[1]))
|
||||
|
||||
#define GET_BE32(field) \
|
||||
(((uint32_t)(field)[0] << 24) | ((uint32_t)(field)[1] << 16) | ((uint32_t)(field)[2] << 8) | ((uint32_t)(field)[3] << 0))
|
||||
|
||||
#define SET_BE16(field, value) \
|
||||
do { \
|
||||
(field)[0] = (uint8_t)((value) >> 8); \
|
||||
(field)[1] = (uint8_t)((value) >> 0); \
|
||||
} while (0)
|
||||
|
||||
#define SET_BE24(field, value) \
|
||||
do { \
|
||||
(field)[0] = (uint8_t)((value) >> 16); \
|
||||
(field)[1] = (uint8_t)((value) >> 8); \
|
||||
(field)[2] = (uint8_t)((value) >> 0); \
|
||||
} while (0)
|
||||
|
||||
#define SET_BE32(field, value) \
|
||||
do { \
|
||||
(field)[0] = (uint8_t)((value) >> 24); \
|
||||
(field)[1] = (uint8_t)((value) >> 16); \
|
||||
(field)[2] = (uint8_t)((value) >> 8); \
|
||||
(field)[3] = (uint8_t)((value) >> 0); \
|
||||
} while (0)
|
||||
|
||||
#define WBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF)
|
||||
#define DBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF), ((x >> 16) & 0xFF), ((x >> 24) & 0xFF)
|
||||
|
||||
#define PP_NARG(...) \
|
||||
PP_NARG_(__VA_ARGS__, PP_RSEQ_N())
|
||||
#define PP_NARG_(...) \
|
||||
PP_ARG_N(__VA_ARGS__)
|
||||
#define PP_ARG_N( \
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
|
||||
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
|
||||
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
|
||||
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
|
||||
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
|
||||
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
|
||||
_61, _62, _63, N, ...) N
|
||||
#define PP_RSEQ_N() \
|
||||
63, 62, 61, 60, \
|
||||
59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
|
||||
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
|
||||
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
|
||||
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
|
||||
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
||||
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
|
||||
#define upper_32_bits(n) ((uint32_t)(((n) >> 16) >> 16))
|
||||
#define lower_32_bits(n) ((uint32_t)(n))
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,388 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: usbh_core.c
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: CherryUSB third-party/cherryusb/core/usbh_core.h for references
|
||||
https://gitee.com/phytium_embedded/phytium-free-rtos-sdk/blob/master/third-party/cherryusb/core/usbh_core.h
|
||||
|
||||
History:
|
||||
1. Date: 2024-06-18
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: New parameter usb_hc_type for host controller type.
|
||||
|
||||
2. Date: 2024-06-24
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Refactor the function that fills urb with usb_hc_type.
|
||||
|
||||
2. Date: 2024-07-16
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Add physical addresses to data structures usbh_bus and usbh_bus.
|
||||
*************************************************/
|
||||
|
||||
|
||||
#ifndef USBH_CORE_H_
|
||||
#define USBH_CORE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "usb_config.h"
|
||||
#include "usb_util.h"
|
||||
#include "usb_errno.h"
|
||||
#include "usb_def.h"
|
||||
#include "usb_list.h"
|
||||
#include "usb_mem.h"
|
||||
#include "usb_log.h"
|
||||
#include "usb_hc.h"
|
||||
#include "usb_osal.h"
|
||||
#include "usb_hub.h"
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB host controller type.
|
||||
* USB 1.1 OHCI UHCI
|
||||
* USB 2.0 EHCI DWC2
|
||||
* USB 3.0 XHCI DWC3
|
||||
*/
|
||||
#define USB_HC_XHCI 5
|
||||
#define USB_HC_DWC3 6
|
||||
|
||||
/** Supported usb class types */
|
||||
enum usbh_class_info_type {
|
||||
USBH_CLASS_INFO_HUB = 0,
|
||||
USBH_CLASS_INFO_RNDIS = 1,
|
||||
USBH_CLASS_INFO_MAX = 2
|
||||
};
|
||||
|
||||
#define USB_CLASS_MATCH_VENDOR 0x0001
|
||||
#define USB_CLASS_MATCH_PRODUCT 0x0002
|
||||
#define USB_CLASS_MATCH_INTF_CLASS 0x0004
|
||||
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
|
||||
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
|
||||
|
||||
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
||||
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
|
||||
|
||||
#ifdef __ARMCC_VERSION /* ARM C Compiler */
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#elif defined(__GNUC__)
|
||||
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__)
|
||||
#pragma section = "usbh_class_info"
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#endif
|
||||
|
||||
/* TODO: This function will be replaced by usbh_control_urb_fill_xiuos.*/
|
||||
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
struct usb_setup_packet *setup,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = setup;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
/* TODO: This function will be replaced by usbh_bulk_urb_fill_xiuos.*/
|
||||
static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
/* TODO: This function will be replaced by usbh_int_urb_fill_xiuos.*/
|
||||
static inline void usbh_int_urb_fill(struct usbh_urb *urb,
|
||||
usbh_pipe_t pipe,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
urb->pipe = pipe;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
struct usbh_class_info {
|
||||
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
|
||||
uint8_t class; /* Base device class code */
|
||||
uint8_t subclass; /* Sub-class, depends on base class. Eg. */
|
||||
uint8_t protocol; /* Protocol, depends on base class. Eg. */
|
||||
uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
|
||||
uint16_t pid; /* Product ID (for vendor/product specific devices) */
|
||||
const struct usbh_class_driver *class_driver;
|
||||
};
|
||||
|
||||
struct usbh_hubport;
|
||||
struct usbh_class_driver {
|
||||
const char *driver_name;
|
||||
int (*connect)(struct usbh_hubport *hport, uint8_t intf);
|
||||
int (*disconnect)(struct usbh_hubport *hport, uint8_t intf);
|
||||
};
|
||||
|
||||
struct usbh_endpoint {
|
||||
struct usb_endpoint_descriptor ep_desc;
|
||||
};
|
||||
|
||||
struct usbh_interface_altsetting {
|
||||
struct usb_interface_descriptor intf_desc;
|
||||
struct usbh_endpoint ep[CONFIG_USBHOST_MAX_ENDPOINTS];
|
||||
};
|
||||
|
||||
struct usbh_interface {
|
||||
char devname[CONFIG_USBHOST_DEV_NAMELEN];
|
||||
struct usbh_class_driver *class_driver;
|
||||
void *priv;
|
||||
struct usbh_interface_altsetting altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
|
||||
uint8_t altsetting_num;
|
||||
};
|
||||
|
||||
struct usbh_configuration {
|
||||
struct usb_configuration_descriptor config_desc;
|
||||
struct usbh_interface intf[CONFIG_USBHOST_MAX_INTERFACES];
|
||||
};
|
||||
|
||||
struct usbh_hub;
|
||||
struct usbh_hubport {
|
||||
/** Name */
|
||||
char name[32];
|
||||
bool connected; /* True: device connected; false: disconnected */
|
||||
uint8_t port; /* Hub port index */
|
||||
uint8_t dev_addr; /* device address */
|
||||
uint8_t speed; /* device speed */
|
||||
usbh_pipe_t ep0; /* control ep pipe info */
|
||||
struct usb_device_descriptor device_desc;
|
||||
struct usbh_configuration config;
|
||||
const char *iManufacturer;
|
||||
const char *iProduct;
|
||||
const char *iSerialNumber;
|
||||
uint8_t *raw_config_desc;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usbh_hub *parent;
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct usbh_bus;
|
||||
struct usbh_hub {
|
||||
usb_slist_t list;
|
||||
bool connected;
|
||||
bool is_roothub;
|
||||
uint8_t index;
|
||||
uint8_t hub_addr;
|
||||
usbh_pipe_t intin;
|
||||
uint8_t *int_buffer;
|
||||
struct usbh_urb intin_urb;
|
||||
struct usb_hub_descriptor hub_desc;
|
||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||
struct usbh_hubport *parent;
|
||||
usb_slist_t hub_event_list;
|
||||
struct usbh_bus *usb;
|
||||
uint32_t ports; /* num of ports */
|
||||
//USB_MEM_ALIGNX uint8_t g_hub_buf[32];
|
||||
uint8_t* g_hub_buf; //virtual address
|
||||
uint8_t* g_hub_buf_phy; //physical address
|
||||
USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][1];
|
||||
};
|
||||
|
||||
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
|
||||
|
||||
/**
|
||||
* @brief Submit an control transfer to an endpoint.
|
||||
* This is a blocking method; this method will not return until the transfer has completed.
|
||||
* Default timeout is 500ms.
|
||||
*
|
||||
* @param pipe The control endpoint to send/receive the control request.
|
||||
* @param setup Setup packet to be sent.
|
||||
* @param buffer buffer used for sending the request and for returning any responses.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer);
|
||||
|
||||
int usbh_control_transfer_xiuos(struct usbh_hubport *hport, usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer);
|
||||
|
||||
struct usbh_devaddr_map {
|
||||
/**
|
||||
* alloctab[0]:addr from 0~31
|
||||
* alloctab[1]:addr from 32~63
|
||||
* alloctab[2]:addr from 64~95
|
||||
* alloctab[3]:addr from 96~127
|
||||
*
|
||||
*/
|
||||
uint8_t next; /* Next device address */
|
||||
uint32_t alloctab[4]; /* Bit allocation table */
|
||||
};
|
||||
|
||||
struct usbh_bus {
|
||||
usb_slist_t list;
|
||||
uint8_t id;
|
||||
uint8_t usb_hc_type;
|
||||
/** Largest transfer allowed on the bus */
|
||||
size_t mtu;
|
||||
struct usbh_devaddr_map devgen;
|
||||
struct usbh_hub roothub;
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
struct usbh_hub exthub[CONFIG_USBHOST_MAX_EXTHUBS];
|
||||
#endif
|
||||
struct usbh_hubport roothub_parent_port;
|
||||
usb_slist_t hub_event_head;
|
||||
usb_slist_t hub_class_head;
|
||||
usb_osal_sem_t hub_event_wait;
|
||||
usb_osal_thread_t hub_thread;
|
||||
usb_osal_mq_t hub_mq;
|
||||
void *priv; /* private data, usb host */
|
||||
int (*hub_open)(struct usbh_hub *hub);
|
||||
void (*hub_close)(struct usbh_hub *hub);
|
||||
int (*root_open)(struct usbh_hub *hub);
|
||||
//USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_REQUEST_BUFFER_LEN];
|
||||
uint8_t* ep0_request_buffer; //virtual address
|
||||
uint8_t* ep0_request_buffer_phy; //physical address
|
||||
USB_MEM_ALIGNX struct usb_setup_packet g_setup[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get USB transaction translator
|
||||
*
|
||||
* @v hport Hub port of USB device
|
||||
* @ret port Transaction translator port, or NULL
|
||||
*/
|
||||
struct usbh_hubport *usbh_transaction_translator ( struct usbh_hubport *hport );
|
||||
|
||||
/**
|
||||
* Get USB route string
|
||||
*
|
||||
* @v hport Hub Port of USB device
|
||||
* @ret route USB route string
|
||||
*/
|
||||
unsigned int usbh_route_string ( struct usbh_hubport *hport );
|
||||
|
||||
static inline struct usbh_bus* usbh_get_bus_of_port(struct usbh_hubport *hport)
|
||||
{
|
||||
USB_ASSERT(hport && hport->parent);
|
||||
return hport->parent->usb;
|
||||
}
|
||||
|
||||
static inline struct usbh_hub *usbh_get_roothub_of_port(struct usbh_hubport *hport)
|
||||
{
|
||||
return &(usbh_get_bus_of_port(hport)->roothub);
|
||||
}
|
||||
|
||||
struct usbh_bus* usbh_get_bus_of_index(uint8_t usb);
|
||||
|
||||
/**
|
||||
* Get USB root hub port
|
||||
*
|
||||
* @v hport Hub port of USB device
|
||||
* @ret port Root hub port
|
||||
*/
|
||||
struct usbh_hubport * usbh_root_hub_port ( struct usbh_hubport *hport );
|
||||
|
||||
static inline void usbh_control_urb_fill_xiuos(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
usbh_pipe_t pipe,
|
||||
struct usb_setup_packet *setup,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
struct usbh_bus *usb = usbh_get_bus_of_port(hport);
|
||||
urb->usb_hc_type = usb->usb_hc_type;
|
||||
urb->pipe = pipe;
|
||||
urb->setup = setup;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_bulk_urb_fill_xiuos(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
usbh_pipe_t pipe,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
struct usbh_bus *usb = usbh_get_bus_of_port(hport);
|
||||
urb->usb_hc_type = usb->usb_hc_type;
|
||||
urb->pipe = pipe;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
static inline void usbh_int_urb_fill_xiuos(struct usbh_urb *urb,
|
||||
struct usbh_hubport *hport,
|
||||
usbh_pipe_t pipe,
|
||||
uint8_t *transfer_buffer,
|
||||
uint32_t transfer_buffer_length,
|
||||
uint32_t timeout,
|
||||
usbh_complete_callback_t complete,
|
||||
void *arg)
|
||||
{
|
||||
struct usbh_bus *usb = usbh_get_bus_of_port(hport);
|
||||
urb->usb_hc_type = usb->usb_hc_type;
|
||||
urb->pipe = pipe;
|
||||
urb->setup = NULL;
|
||||
urb->transfer_buffer = transfer_buffer;
|
||||
urb->transfer_buffer_length = transfer_buffer_length;
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
}
|
||||
|
||||
int usbh_initialize(uint32_t id, struct usbh_bus *usb);
|
||||
struct usbh_hubport *usbh_find_hubport(uint32_t id, uint8_t dev_addr);
|
||||
void *usbh_find_class_instance(const char *devname);
|
||||
int lsusb(int argc, char **argv);
|
||||
|
||||
int usbh_class_info_set(enum usbh_class_info_type class_type, struct usbh_class_info *class_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_CORE_H */
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
SRC_DIR := rk3568
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,11 @@
|
|||
include $(KERNEL_ROOT)/services/drivers/usb/components/usb.mk
|
||||
|
||||
objs += rk3568_usb.o
|
||||
|
||||
all: ${objs}
|
||||
@echo "generate $^"
|
||||
@mv $^ $(KERNEL_ROOT)/services/drivers/usb/components
|
||||
|
||||
%.o: %.c
|
||||
@echo "cc $^"
|
||||
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^
|
|
@ -0,0 +1,73 @@
|
|||
/*************************************************
|
||||
File name: rk3568_usb.c
|
||||
Description: the dwc3 host probe function adapted to xiuos.
|
||||
Others: take RK3568 codes uboot\drivers\usb\dwc3\dwc3-generic.c
|
||||
*************************************************/
|
||||
#include "rk3568_usb.h"
|
||||
#include "usb_hc_xhci.h"
|
||||
|
||||
|
||||
struct dwc3 dwc3_rk3568[CONFIG_USBHOST_XHCI_NUM];
|
||||
|
||||
|
||||
static uint32_t usb_get_maximum_speed(uint32_t id)
|
||||
{
|
||||
return USB_SPEED_SUPER;
|
||||
}
|
||||
|
||||
static enum usb_dr_mode usb_get_dr_mode(uint32_t id)
|
||||
{
|
||||
return USB_DR_MODE_HOST;
|
||||
}
|
||||
|
||||
|
||||
int dwc3_generic_host_probe(uint32_t id)
|
||||
{
|
||||
struct dwc3 *dwc3;
|
||||
|
||||
USB_LOG_DBG("%s usb3.0 id=%d\r\n", __func__, id);
|
||||
USB_ASSERT(id < CONFIG_USBHOST_XHCI_NUM);
|
||||
dwc3 = &(dwc3_rk3568[id]);
|
||||
memset(dwc3, 0, sizeof(*dwc3));
|
||||
dwc3->id = id;
|
||||
|
||||
return dwc3_generic_probe(dwc3);
|
||||
}
|
||||
|
||||
|
||||
int dwc3_generic_probe(struct dwc3 *dwc3)
|
||||
{
|
||||
int rc;
|
||||
uintptr_t base;
|
||||
uintptr_t base_vir;
|
||||
int len;
|
||||
|
||||
dwc3->maximum_speed = usb_get_maximum_speed(dwc3->id);
|
||||
dwc3->dr_mode = usb_get_dr_mode(dwc3->id);
|
||||
|
||||
dwc3_of_parse(dwc3);
|
||||
|
||||
/* TODO: */
|
||||
rc = dwc3_setup_phy(NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
base = usb_hc_get_register_base(dwc3->id);
|
||||
base_vir = usb_hc_get_register_vir_base(dwc3->id);
|
||||
|
||||
dwc3->regs = (void *)base + DWC3_GLOBALS_REGS_START;
|
||||
dwc3->regs_vir = (void *)base_vir + DWC3_GLOBALS_REGS_START;
|
||||
len = DWC3_OTG_REGS_END - DWC3_GLOBALS_REGS_START + 1;
|
||||
|
||||
if(!mmap((uintptr_t)dwc3->regs_vir, (uintptr_t)dwc3->regs, len, true)){
|
||||
USB_LOG_ERR("%s mmap fail\r\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = dwc3_init(dwc3);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef RK3568_USB_H_
|
||||
#define RK3568_USB_H_
|
||||
|
||||
#include "dwc3.h"
|
||||
|
||||
int dwc3_generic_host_probe(uint32_t id);
|
||||
int dwc3_generic_probe(struct dwc3 *dwc3);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
include $(KERNEL_ROOT)/services/drivers/usb/components/usb.mk
|
||||
|
||||
objs = usb_mem.o
|
||||
|
||||
all: ${objs}
|
||||
@echo "generate $^"
|
||||
@mv $^ $(KERNEL_ROOT)/services/drivers/usb/components
|
||||
|
||||
%.o: %.c
|
||||
@echo "cc $^"
|
||||
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^
|
|
@ -0,0 +1,194 @@
|
|||
#include <libmem.h>
|
||||
#include "usb_mem.h"
|
||||
|
||||
/*************************************************
|
||||
File name: usb_mem.c
|
||||
Description: support usb memory management
|
||||
Others: take CherryUSB v0.1.2/CherryUSB/port/xhci/usb_hc_xhci.c for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/port/xhci/usb_hc_xhci.c
|
||||
History:
|
||||
1. Date: 2024-06-12
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: re-develop usb_hc_malloc, usb_hc_malloc_align and usb_hc_free functions
|
||||
2. Date: 2024-08-21
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: The usb memory virtual address base address uses 0x1000000000, refer to XiZi virtual memory distribution.
|
||||
*************************************************/
|
||||
|
||||
/* The usb memory virtual address base address uses 0x1000000000, refer to XiZi virtual memory distribution.*/
|
||||
uintptr_t usb_mem_base_viraddr = 0x1000000000;
|
||||
|
||||
struct usb_mem_pool usb_mem_data_pool;
|
||||
|
||||
|
||||
void *usb_hc_malloc(size_t size){
|
||||
void *result = malloc(size);
|
||||
|
||||
if (result)
|
||||
{
|
||||
memset(result, 0U, size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void *usb_hc_malloc_align(size_t align, size_t size)
|
||||
{
|
||||
size_t flag, adj_size;
|
||||
|
||||
flag = align & (align - 1);
|
||||
|
||||
/*
|
||||
* align should be a power of 2.
|
||||
*/
|
||||
if(flag != 0)
|
||||
return NULL;
|
||||
|
||||
adj_size = (size + (align - 1)) &~ (align);
|
||||
|
||||
void *result = malloc(size);
|
||||
|
||||
if (result)
|
||||
{
|
||||
memset(result, 0U, size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void usb_hc_free(void* ptr){
|
||||
if(ptr != NULL)
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
int usb_mem_data_pool_init(){
|
||||
int rc, count;
|
||||
uintptr_t phy_addr, vir_addr;
|
||||
|
||||
memset(&usb_mem_data_pool, 0, sizeof(usb_mem_data_pool));
|
||||
|
||||
count = 0;
|
||||
while(count < MEM_POOL_SIZE){
|
||||
vir_addr = USB_MEM_VIRADDR_ALLOC;
|
||||
usb_mem_data_pool.pages[count].vir_addr = vir_addr;
|
||||
|
||||
rc = naive_mmap(&vir_addr, &phy_addr, 4096, true);
|
||||
|
||||
if(rc != 0)
|
||||
goto mmap_error;
|
||||
|
||||
usb_mem_data_pool.pages[count].phy_addr = phy_addr;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
mmap_error:
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void usb_mem_data_pool_destory(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
int usb_alloc_mem_data_page(usb_mem_page_t page){
|
||||
usb_mem_page_t selected_page;
|
||||
int header, tail;
|
||||
|
||||
header = usb_mem_data_pool.header;
|
||||
tail = usb_mem_data_pool.tail;
|
||||
|
||||
|
||||
/*
|
||||
* Check whether the memory pool is full or not.
|
||||
*/
|
||||
|
||||
if((tail + 1) % MEM_POOL_SIZE == header)
|
||||
return -1;
|
||||
|
||||
selected_page = &usb_mem_data_pool.pages[tail];
|
||||
tail++;
|
||||
|
||||
memcpy(page, selected_page, sizeof(struct usb_mem_page));
|
||||
|
||||
if(tail == MEM_POOL_SIZE)
|
||||
tail = 0;
|
||||
|
||||
usb_mem_data_pool.tail = tail;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usb_free_mem_data_page(usb_mem_page_t page){
|
||||
usb_mem_page_t selected_page;
|
||||
int header, tail;
|
||||
|
||||
header = usb_mem_data_pool.header;
|
||||
tail = usb_mem_data_pool.tail;
|
||||
|
||||
/*
|
||||
* Check whether the memory pool is full or not.
|
||||
*/
|
||||
if((header + 1) % MEM_POOL_SIZE == tail)
|
||||
return;
|
||||
|
||||
selected_page = &usb_mem_data_pool.pages[header];
|
||||
selected_page->vir_addr = page->vir_addr;
|
||||
selected_page->phy_addr = page->phy_addr;
|
||||
|
||||
header++;
|
||||
|
||||
if(header == MEM_POOL_SIZE)
|
||||
header = 0;
|
||||
|
||||
usb_mem_data_pool.header = header;
|
||||
}
|
||||
|
||||
|
||||
int usb_used_page_num_mem_pool(usb_mem_pool_t mem_pool){
|
||||
int header, tail, used_num;
|
||||
header = mem_pool->header;
|
||||
tail = mem_pool->tail;
|
||||
|
||||
used_num = tail - header;
|
||||
|
||||
if(used_num < 0)
|
||||
used_num += MEM_POOL_SIZE;
|
||||
|
||||
return used_num;
|
||||
}
|
||||
|
||||
|
||||
uintptr_t usb_mem_data_page_phy2vir(uintptr_t phy_addr){
|
||||
int header, used_num, cnt;
|
||||
uintptr_t vir_addr = 0;
|
||||
|
||||
header = usb_mem_data_pool.header;
|
||||
used_num = usb_used_page_num_mem_pool(&usb_mem_data_pool);
|
||||
|
||||
cnt = 0;
|
||||
while(cnt < used_num){
|
||||
if(usb_mem_data_pool.pages[header].phy_addr == phy_addr){
|
||||
vir_addr = usb_mem_data_pool.pages[header].vir_addr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
header++;
|
||||
|
||||
if(header == MEM_POOL_SIZE - 1)
|
||||
header = 0;
|
||||
|
||||
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return vir_addr;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*************************************************
|
||||
File name: usb_mem.h
|
||||
Description: support usb memory management
|
||||
Others: take CherryUSB v0.10.2/CherryUSB/cherryusb_config_template.h for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/cherryusb_config_template.h
|
||||
History:
|
||||
1. Date: 2024-06-12
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: Use usb_malloc, usb_free and usb_align functions
|
||||
*************************************************/
|
||||
|
||||
|
||||
#ifndef USB_MEM_H_
|
||||
#define USB_MEM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "usb_config.h"
|
||||
#include "usyscall.h"
|
||||
|
||||
|
||||
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
|
||||
|
||||
/*The usb virtual address offset 0x1000 corresponds to the function naive_mmap. */
|
||||
extern uintptr_t usb_mem_base_viraddr;
|
||||
#define USB_MEM_VIRADDR_ALLOC (usb_mem_base_viraddr += 0x1000)
|
||||
|
||||
#define MEM_POOL_SIZE 128
|
||||
|
||||
void *usb_hc_malloc(size_t size);
|
||||
void usb_hc_free();
|
||||
void *usb_hc_malloc_align(size_t align, size_t size);
|
||||
|
||||
#define usb_malloc(size) usb_hc_malloc(size)
|
||||
#define usb_free(ptr) usb_hc_free(ptr)
|
||||
#define usb_align(align, size) usb_hc_malloc_align(align, size)
|
||||
|
||||
struct usb_mem_page{
|
||||
uintptr_t vir_addr;
|
||||
uintptr_t phy_addr;
|
||||
|
||||
};
|
||||
|
||||
struct usb_mem_pool{
|
||||
int header;
|
||||
int tail;
|
||||
struct usb_mem_page pages[MEM_POOL_SIZE];
|
||||
};
|
||||
|
||||
typedef struct usb_mem_page *usb_mem_page_t;
|
||||
typedef struct usb_mem_pool *usb_mem_pool_t;
|
||||
|
||||
int usb_mem_data_pool_init();
|
||||
void usb_mem_data_pool_destory();
|
||||
int usb_alloc_mem_data_page(usb_mem_page_t page);
|
||||
void usb_free_mem_data_page(usb_mem_page_t page);
|
||||
int usb_used_page_num_mem_pool(usb_mem_pool_t mem_pool);
|
||||
uintptr_t usb_mem_data_page_phy2vir(uintptr_t phy_addr);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,6 +1,384 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: usb_osal.c
|
||||
Description: adopt cherry USB to XiZi AIOT.
|
||||
Others: CherryUSB v0.1.2/CherryUSB/osal/usb_osal_freertos.c for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/osal/usb_osal_freertos.c
|
||||
|
||||
History:
|
||||
1. Date: 2024-06-17
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: rename the file name, and re-develop all OS abstract layer functions.
|
||||
*************************************************/
|
||||
|
||||
#include "usb_osal.h"
|
||||
#include "usb_mem.h"
|
||||
#include "libserial.h"
|
||||
// #include "syscall.h"
|
||||
#include "usyscall.h"
|
||||
|
||||
|
||||
int usb_wait_until(int msec){
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args){
|
||||
long ret;
|
||||
char *task_param[] = { args, NULL };
|
||||
ret = thread(entry, name, task_param);
|
||||
|
||||
return (usb_osal_thread_t)ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usb_osal_thread_delete(usb_osal_thread_t thread){
|
||||
long thread_id;
|
||||
thread_id = (long)thread;
|
||||
|
||||
kill(thread_id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count){
|
||||
long sem_id;
|
||||
|
||||
sem_id = semaphore_new(initial_count);
|
||||
|
||||
return (usb_osal_sem_t)sem_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usb_osal_sem_delete(usb_osal_sem_t sem){
|
||||
long sem_id;
|
||||
sem_id = (long)sem;
|
||||
semaphore_free(sem_id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout){
|
||||
long sem_id;
|
||||
sem_id = (long)sem;
|
||||
|
||||
if(sem_id < 0)
|
||||
return -1;
|
||||
|
||||
semaphore_wait(sem_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int usb_osal_sem_give(usb_osal_sem_t sem){
|
||||
long sem_id;
|
||||
sem_id = (long)sem;
|
||||
|
||||
if(sem_id < 0)
|
||||
return -1;
|
||||
|
||||
semaphore_signal(sem_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void){
|
||||
long mutex_id;
|
||||
|
||||
mutex_id = semaphore_new(1);
|
||||
|
||||
printf("In %s, mutex_id = %d\n", __func__, mutex_id);
|
||||
|
||||
return (usb_osal_mutex_t)mutex_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usb_osal_mutex_delete(usb_osal_mutex_t mutex){
|
||||
long mutex_id;
|
||||
mutex_id = (long)mutex;
|
||||
semaphore_free(mutex_id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int usb_osal_mutex_take(usb_osal_mutex_t mutex){
|
||||
long mutex_id;
|
||||
mutex_id = (long)mutex;
|
||||
|
||||
if(mutex_id < 0)
|
||||
return -1;
|
||||
|
||||
semaphore_wait(mutex_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex){
|
||||
long mutex_id;
|
||||
mutex_id = (long)mutex;
|
||||
|
||||
if(mutex_id < 0)
|
||||
return -1;
|
||||
|
||||
semaphore_signal(mutex_id);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
osal_msg_queue_t osal_mq_create(const char *name,
|
||||
size_t msg_size,
|
||||
size_t max_msgs,
|
||||
uint8_t flag){
|
||||
osal_msg_queue_t mq;
|
||||
size_t buf_size;
|
||||
|
||||
/* Unused now */
|
||||
// (void *)name;
|
||||
// (void *)flag;
|
||||
|
||||
|
||||
if(msg_size <= 0 || max_msgs <=0)
|
||||
return NULL;
|
||||
|
||||
mq = usb_malloc(sizeof(struct osal_msg_queue));
|
||||
|
||||
if(mq == NULL)
|
||||
return NULL;
|
||||
|
||||
buf_size = (sizeof(struct osal_mq_msg_header) + msg_size) * max_msgs;
|
||||
|
||||
if(buf_size > MAX_MSG_QUEUE_BUF_SIZE){
|
||||
usb_free(mq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(mq, 0, sizeof(struct osal_msg_queue));
|
||||
|
||||
mq->data = usb_malloc(buf_size);
|
||||
|
||||
if(mq->data == NULL){
|
||||
usb_free(mq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mq->mutex = usb_osal_mutex_create();
|
||||
|
||||
if(mq->mutex == NULL){
|
||||
usb_free(mq->data);
|
||||
usb_free(mq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mq->msg_size = msg_size;
|
||||
mq->max_msgs = max_msgs;
|
||||
|
||||
printf("In %s, msg_size = %d, max_msgs = %d\n", __func__, msg_size, max_msgs);
|
||||
|
||||
return mq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void osal_mq_delete(osal_msg_queue_t mq){
|
||||
long mutex_id;
|
||||
if(mq == NULL)
|
||||
return;
|
||||
|
||||
if(mq->data)
|
||||
usb_free(mq->data);
|
||||
|
||||
mutex_id = (long)(mq->mutex);
|
||||
if(mutex_id > 0)
|
||||
usb_osal_mutex_delete(mq->mutex);
|
||||
|
||||
usb_free(mq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int osal_mq_send(osal_msg_queue_t mq,
|
||||
void *msg,
|
||||
size_t msg_len,
|
||||
uint32_t timeout){
|
||||
uint16_t header, tail, tail_nxt;
|
||||
long mutex_id;
|
||||
osal_mq_msg_header_t msg_tail;
|
||||
uint8_t *msg_buf;
|
||||
|
||||
if(mq == NULL || msg == NULL || msg_len == 0)
|
||||
return -1;
|
||||
|
||||
if(msg_len > mq->msg_size)
|
||||
return -1;
|
||||
|
||||
mutex_id = (long)(mq->mutex);
|
||||
if(mutex_id <= 0)
|
||||
return -1;
|
||||
|
||||
usb_osal_sem_take(mq->mutex, timeout);
|
||||
|
||||
|
||||
tail = mq->tail;
|
||||
header = mq->header;
|
||||
|
||||
printf("In %s, tail = %d, header = %d\n", __func__, tail, header);
|
||||
/* message queue is full. */
|
||||
tail_nxt = (tail + 1) > mq->max_msgs ? (tail + 1 - mq->max_msgs):(tail + 1);
|
||||
if(tail_nxt == header){
|
||||
usb_osal_sem_give(mq->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_tail = (osal_mq_msg_header_t)(mq->data + (sizeof(struct osal_mq_msg_header) + mq->msg_size) * header);
|
||||
msg_buf = (uint8_t *)(msg_tail + 1);
|
||||
|
||||
msg_tail->len = msg_len;
|
||||
memcpy(msg_buf, msg, msg_len);
|
||||
usb_osal_sem_give(mq->mutex);
|
||||
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int __osal_mq_recv(osal_msg_queue_t mq,
|
||||
void *msg,
|
||||
size_t msg_len,
|
||||
uint32_t timeout){
|
||||
uint16_t header, tail;
|
||||
long mutex_id;
|
||||
osal_mq_msg_header_t msg_header;
|
||||
uint8_t *msg_buf;
|
||||
size_t copy_len;
|
||||
|
||||
if(mq == NULL || msg == NULL || msg_len == 0)
|
||||
return -1;
|
||||
|
||||
if(msg_len > mq->msg_size)
|
||||
return -1;
|
||||
|
||||
mutex_id = (long)(mq->mutex);
|
||||
if(mutex_id <= 0)
|
||||
return -1;
|
||||
|
||||
usb_osal_sem_take(mq->mutex, timeout);
|
||||
|
||||
header = mq->header;
|
||||
tail = mq->tail;
|
||||
|
||||
/* message queue is empty. */
|
||||
if(header == tail){
|
||||
usb_osal_sem_give(mq->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("In %s, tail = %d, header = %d\n", __func__, tail, header);
|
||||
|
||||
msg_header = (osal_mq_msg_header_t)(mq->data + (sizeof(struct osal_mq_msg_header) + mq->msg_size) * header);
|
||||
msg_buf = (uint8_t *)(msg_header + 1);
|
||||
copy_len = (msg_header->len > msg_len ? msg_len : msg_header->len);
|
||||
|
||||
memcpy(msg, msg_buf, copy_len);
|
||||
|
||||
header++;
|
||||
mq->header = (header > mq->max_msgs) ? (header - mq->max_msgs) : (header);
|
||||
usb_osal_sem_give(mq->mutex);
|
||||
|
||||
return copy_len;
|
||||
}
|
||||
|
||||
int osal_mq_recv(osal_msg_queue_t mq,
|
||||
void *msg,
|
||||
size_t msg_len,
|
||||
uint32_t timeout){
|
||||
int ret = 0;
|
||||
int sleep_time = timeout;
|
||||
int for_ever = 0;
|
||||
|
||||
if(sleep_time == 0)
|
||||
for_ever = 1;
|
||||
|
||||
do{
|
||||
ret = __osal_mq_recv(mq, msg, msg_len, timeout);
|
||||
|
||||
if(ret == 0){
|
||||
if(sleep_time > 0 || for_ever == 1){
|
||||
usb_osal_msleep(10);
|
||||
|
||||
if(for_ever == 0)
|
||||
sleep_time -= 10;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}while(ret == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs){
|
||||
osal_msg_queue_t mq;
|
||||
mq = osal_mq_create("usb_mq", sizeof(uintptr_t *), max_msgs, 0);
|
||||
return (usb_osal_mq_t)mq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq){
|
||||
osal_msg_queue_t osal_mq;
|
||||
osal_mq = (osal_msg_queue_t)mq;
|
||||
|
||||
if(osal_mq != NULL)
|
||||
osal_mq_delete(osal_mq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout){
|
||||
return osal_mq_recv((osal_msg_queue_t)mq, addr, sizeof(uintptr_t *), timeout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr){
|
||||
return osal_mq_send((osal_msg_queue_t)mq, &addr, sizeof(uintptr_t *), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t usb_osal_enter_critical_section(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usb_osal_leave_critical_section(size_t flag){
|
||||
|
||||
}
|
||||
|
||||
|
||||
void usb_osal_msleep(uint32_t delay){
|
||||
if(delay > 0){
|
||||
sleep(delay);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void usb_assert(const char *filename, int linenum){
|
||||
printf("%s, %d\n", filename, linenum);
|
||||
exit(-1);
|
||||
}
|
|
@ -1,9 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
/*************************************************
|
||||
File name: usb_osal.h
|
||||
Description: support OS abstract layer
|
||||
Others: take CherryUSB v0.1.2/CherryUSB/osal/usb_osal.h for references
|
||||
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/osal/usb_osal.h
|
||||
History:
|
||||
1. Date: 2024-06-13
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: introduce message queue mechanism.
|
||||
*************************************************/
|
||||
#ifndef USB_OSAL_H_
|
||||
#define USB_OSAL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "usb_config.h"
|
||||
|
||||
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
|
||||
|
||||
typedef void *usb_osal_thread_t;
|
||||
typedef void *usb_osal_sem_t;
|
||||
typedef void *usb_osal_mutex_t;
|
||||
typedef void *usb_osal_mq_t;
|
||||
typedef void (*usb_thread_entry_t)(void *argument);
|
||||
|
||||
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
|
||||
void usb_osal_thread_delete(usb_osal_thread_t thread);
|
||||
|
||||
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
|
||||
void usb_osal_sem_delete(usb_osal_sem_t sem);
|
||||
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
|
||||
int usb_osal_sem_give(usb_osal_sem_t sem);
|
||||
|
||||
usb_osal_mutex_t usb_osal_mutex_create(void);
|
||||
void usb_osal_mutex_delete(usb_osal_mutex_t mutex);
|
||||
int usb_osal_mutex_take(usb_osal_mutex_t mutex);
|
||||
int usb_osal_mutex_give(usb_osal_mutex_t mutex);
|
||||
|
||||
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs);
|
||||
void usb_osal_mq_delete(usb_osal_mq_t mq);
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr);
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout);
|
||||
|
||||
size_t usb_osal_enter_critical_section(void);
|
||||
void usb_osal_leave_critical_section(size_t flag);
|
||||
|
||||
void usb_osal_msleep(uint32_t delay);
|
||||
|
||||
|
||||
int usb_wait_until(int msec);
|
||||
/*
|
||||
* Defination of the Message queue.
|
||||
*/
|
||||
|
||||
#define MAX_MSG_QUEUE_BUF_SIZE 65535
|
||||
|
||||
struct osal_msg_queue{
|
||||
uint16_t msg_size;
|
||||
uint16_t max_msgs;
|
||||
uint16_t cur;
|
||||
uint16_t header;
|
||||
uint16_t tail;
|
||||
void *msg_queue_head;
|
||||
void *msg_queue_tail;
|
||||
usb_osal_mutex_t *mutex;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
typedef struct osal_msg_queue *osal_msg_queue_t;
|
||||
|
||||
struct osal_mq_msg_header{
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
typedef struct osal_mq_msg_header *osal_mq_msg_header_t;
|
||||
|
||||
osal_msg_queue_t osal_mq_create(const char *name,
|
||||
size_t msg_size,
|
||||
size_t max_msgs,
|
||||
uint8_t flag);
|
||||
|
||||
void osal_mq_delete(osal_msg_queue_t mq);
|
||||
|
||||
int osal_mq_send(osal_msg_queue_t mq,
|
||||
void *msg,
|
||||
size_t msg_len,
|
||||
uint32_t timeout);
|
||||
|
||||
int osal_mq_recv(osal_msg_queue_t mq,
|
||||
void *msg,
|
||||
size_t msg_len,
|
||||
uint32_t timeout);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "usb_osal.h"
|
|
@ -0,0 +1,4 @@
|
|||
SRC_DIR := xhci dwc3
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,3 @@
|
|||
USB3.0: xhci dwc3
|
||||
USB2.0: ehci dwc2
|
||||
USB1.1: ohci uhci
|
|
@ -0,0 +1,11 @@
|
|||
include $(KERNEL_ROOT)/services/drivers/usb/components/usb.mk
|
||||
|
||||
objs += dwc3.o
|
||||
|
||||
all: ${objs}
|
||||
@echo "generate $^"
|
||||
@mv $^ $(KERNEL_ROOT)/services/drivers/usb/components
|
||||
|
||||
%.o: %.c
|
||||
@echo "cc $^"
|
||||
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^
|
|
@ -0,0 +1,721 @@
|
|||
#include "dwc3.h"
|
||||
#include "usb_config.h"
|
||||
#include "usyscall.h"
|
||||
|
||||
|
||||
void dwc3_of_parse(struct dwc3 *dwc)
|
||||
{
|
||||
uint8_t lpm_nyet_threshold;
|
||||
uint8_t tx_de_emphasis;
|
||||
uint8_t hird_threshold;
|
||||
|
||||
/* default to highest possible threshold */
|
||||
lpm_nyet_threshold = 0xff;
|
||||
|
||||
/* default to -3.5dB de-emphasis */
|
||||
tx_de_emphasis = 1;
|
||||
|
||||
/*
|
||||
* default to assert utmi_sleep_n and use maximum allowed HIRD
|
||||
* threshold value of 0b1100
|
||||
*/
|
||||
hird_threshold = 12;
|
||||
|
||||
dwc->hsphy_mode = usb_get_phy_mode(dwc->id);
|
||||
|
||||
/* xiuos: The parameters are updated according to the dts of RK3568 */
|
||||
dwc->has_lpm_erratum = 0;
|
||||
lpm_nyet_threshold = lpm_nyet_threshold;
|
||||
dwc->is_utmi_l1_suspend = 0;
|
||||
hird_threshold = hird_threshold;
|
||||
dwc->disable_scramble_quirk = 0;
|
||||
dwc->u2exit_lfps_quirk = 0;
|
||||
dwc->u2ss_inp3_quirk = 0;
|
||||
dwc->req_p1p2p3_quirk = 0;
|
||||
dwc->del_p1p2p3_quirk = 0;
|
||||
dwc->del_phy_power_chg_quirk = 0;
|
||||
dwc->lfps_filter_quirk = 0;
|
||||
dwc->rx_detect_poll_quirk = 0;
|
||||
dwc->dis_u3_susphy_quirk = 0;
|
||||
dwc->dis_u2_susphy_quirk = 0;
|
||||
dwc->dis_enblslpm_quirk = 1;
|
||||
dwc->dis_u2_freeclk_exists_quirk = 1;
|
||||
dwc->tx_de_emphasis_quirk = 0;
|
||||
tx_de_emphasis = tx_de_emphasis;
|
||||
|
||||
dwc->lpm_nyet_threshold = lpm_nyet_threshold;
|
||||
dwc->tx_de_emphasis = tx_de_emphasis;
|
||||
|
||||
dwc->hird_threshold = hird_threshold
|
||||
| (dwc->is_utmi_l1_suspend << 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dwc3_host_init(struct dwc3 *dwc){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum usb_phy_interface usb_get_phy_mode(uint32_t id){
|
||||
return USBPHY_INTERFACE_MODE_UTMIW;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dwc3_setup_phy(void *dev, struct phy **array, int *num_phys){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dwc3_cache_hwparams(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_hwparams *parms = &dwc->hwparams;
|
||||
|
||||
parms->hwparams0 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS0);
|
||||
parms->hwparams1 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS1);
|
||||
parms->hwparams2 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS2);
|
||||
parms->hwparams3 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS3);
|
||||
parms->hwparams4 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS4);
|
||||
parms->hwparams5 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS5);
|
||||
parms->hwparams6 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS6);
|
||||
parms->hwparams7 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS7);
|
||||
parms->hwparams8 = dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dwc3_core_init - Low-level initialization of DWC3 Core
|
||||
* @dwc: Pointer to our controller context structure
|
||||
*
|
||||
* Returns 0 on success otherwise negative errno.
|
||||
*/
|
||||
int dwc3_core_init(struct dwc3 *dwc)
|
||||
{
|
||||
unsigned long timeout;
|
||||
uint32_t hwparams4 = dwc->hwparams.hwparams4;
|
||||
uint32_t reg;
|
||||
int ret;
|
||||
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GSNPSID);
|
||||
/* This should read as U3 followed by revision number */
|
||||
if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
|
||||
USB_LOG_ERR("this is not a DesignWare USB3 DRD Core\n");
|
||||
ret = -ENODEV;
|
||||
goto err0;
|
||||
}
|
||||
dwc->revision = reg;
|
||||
USB_LOG_DBG("%s dwc revision=%08x\n", __func__, dwc->revision);
|
||||
|
||||
/* Handle USB2.0-only core configuration */
|
||||
if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
|
||||
DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
|
||||
if (dwc->maximum_speed == USB_SPEED_SUPER)
|
||||
dwc->maximum_speed = USB_SPEED_HIGH;
|
||||
}
|
||||
|
||||
/* issue device SoftReset too */
|
||||
timeout = 5000;
|
||||
dwc3_writel(dwc->regs_vir, DWC3_DCTL, DWC3_DCTL_CSFTRST);
|
||||
while (timeout--) {
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_DCTL);
|
||||
if (!(reg & DWC3_DCTL_CSFTRST))
|
||||
break;
|
||||
};
|
||||
|
||||
if (!timeout) {
|
||||
USB_LOG_ERR("Reset Timed Out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
ret = dwc3_core_soft_reset(dwc);
|
||||
if (ret)
|
||||
goto err0;
|
||||
|
||||
if (dwc->revision >= DWC3_REVISION_250A) {
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GUCTL1);
|
||||
|
||||
if (dwc->maximum_speed == USB_SPEED_HIGH ||
|
||||
dwc->maximum_speed == USB_SPEED_FULL)
|
||||
reg |= DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK;
|
||||
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GUCTL1, reg);
|
||||
}
|
||||
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GCTL);
|
||||
reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
|
||||
|
||||
switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
|
||||
case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
|
||||
/**
|
||||
* WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
|
||||
* issue which would cause xHCI compliance tests to fail.
|
||||
*
|
||||
* Because of that we cannot enable clock gating on such
|
||||
* configurations.
|
||||
*
|
||||
* Refers to:
|
||||
*
|
||||
* STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
|
||||
* SOF/ITP Mode Used
|
||||
*/
|
||||
if ((dwc->dr_mode == USB_DR_MODE_HOST ||
|
||||
dwc->dr_mode == USB_DR_MODE_OTG) &&
|
||||
(dwc->revision >= DWC3_REVISION_210A &&
|
||||
dwc->revision <= DWC3_REVISION_250A))
|
||||
reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
|
||||
else
|
||||
reg &= ~DWC3_GCTL_DSBLCLKGTNG;
|
||||
break;
|
||||
case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
|
||||
/* enable hibernation here */
|
||||
dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
|
||||
|
||||
/*
|
||||
* REVISIT Enabling this bit so that host-mode hibernation
|
||||
* will work. Device-mode hibernation is not yet implemented.
|
||||
*/
|
||||
reg |= DWC3_GCTL_GBLHIBERNATIONEN;
|
||||
break;
|
||||
default:
|
||||
USB_LOG_DBG("No power optimization available\n");
|
||||
}
|
||||
|
||||
/* check if current dwc3 is on simulation board */
|
||||
if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
|
||||
USB_LOG_DBG("it is on FPGA board\n");
|
||||
dwc->is_fpga = true;
|
||||
}
|
||||
|
||||
if(dwc->disable_scramble_quirk && !dwc->is_fpga)
|
||||
USB_LOG_WRN("disable_scramble cannot be used on non-FPGA builds\n");
|
||||
|
||||
if (dwc->disable_scramble_quirk && dwc->is_fpga)
|
||||
reg |= DWC3_GCTL_DISSCRAMBLE;
|
||||
else
|
||||
reg &= ~DWC3_GCTL_DISSCRAMBLE;
|
||||
|
||||
if (dwc->u2exit_lfps_quirk)
|
||||
reg |= DWC3_GCTL_U2EXIT_LFPS;
|
||||
|
||||
/*
|
||||
* WORKAROUND: DWC3 revisions <1.90a have a bug
|
||||
* where the device can fail to connect at SuperSpeed
|
||||
* and falls back to high-speed mode which causes
|
||||
* the device to enter a Connect/Disconnect loop
|
||||
*/
|
||||
if (dwc->revision < DWC3_REVISION_190A)
|
||||
reg |= DWC3_GCTL_U2RSTECN;
|
||||
|
||||
dwc3_core_num_eps(dwc);
|
||||
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GCTL, reg);
|
||||
|
||||
dwc3_phy_setup(dwc);
|
||||
|
||||
ret = dwc3_alloc_scratch_buffers(dwc);
|
||||
if (ret)
|
||||
goto err0;
|
||||
|
||||
ret = dwc3_setup_scratch_buffers(dwc);
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
return 0;
|
||||
|
||||
err1:
|
||||
dwc3_free_scratch_buffers(dwc);
|
||||
|
||||
err0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void dwc3_core_exit(struct dwc3 *dwc){
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dwc3_core_soft_reset - Issues core soft reset and PHY reset
|
||||
* @dwc: pointer to our context structure
|
||||
*/
|
||||
int dwc3_core_soft_reset(struct dwc3 *dwc)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Before Resetting PHY, put Core in Reset */
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GCTL);
|
||||
reg |= DWC3_GCTL_CORESOFTRESET;
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GCTL, reg);
|
||||
|
||||
/* Assert USB3 PHY reset */
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GUSB3PIPECTL(0));
|
||||
reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GUSB3PIPECTL(0), reg);
|
||||
|
||||
/* Assert USB2 PHY reset */
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GUSB2PHYCFG(0));
|
||||
reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GUSB2PHYCFG(0), reg);
|
||||
|
||||
usb_osal_msleep(100);
|
||||
|
||||
/* Clear USB3 PHY reset */
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GUSB3PIPECTL(0));
|
||||
reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GUSB3PIPECTL(0), reg);
|
||||
|
||||
/* Clear USB2 PHY reset */
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GUSB2PHYCFG(0));
|
||||
reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GUSB2PHYCFG(0), reg);
|
||||
|
||||
usb_osal_msleep(100);
|
||||
|
||||
/* After PHYs are stable we can take Core out of reset state */
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GCTL);
|
||||
reg &= ~DWC3_GCTL_CORESOFTRESET;
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GCTL, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void dwc3_core_num_eps(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_hwparams *parms = &dwc->hwparams;
|
||||
|
||||
dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
|
||||
dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
|
||||
|
||||
USB_LOG_DBG("found %d IN and %d OUT endpoints\n",
|
||||
dwc->num_in_eps, dwc->num_out_eps);
|
||||
}
|
||||
|
||||
|
||||
void dwc3_phy_setup(struct dwc3 *dwc)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GUSB3PIPECTL(0));
|
||||
|
||||
/*
|
||||
* Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
|
||||
* to '0' during coreConsultant configuration. So default value
|
||||
* will be '0' when the core is reset. Application needs to set it
|
||||
* to '1' after the core initialization is completed.
|
||||
*/
|
||||
if (dwc->revision > DWC3_REVISION_194A)
|
||||
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
|
||||
|
||||
if (dwc->u2ss_inp3_quirk)
|
||||
reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
|
||||
|
||||
if (dwc->req_p1p2p3_quirk)
|
||||
reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
|
||||
|
||||
if (dwc->del_p1p2p3_quirk)
|
||||
reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
|
||||
|
||||
if (dwc->del_phy_power_chg_quirk)
|
||||
reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
|
||||
|
||||
if (dwc->lfps_filter_quirk)
|
||||
reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
|
||||
|
||||
if (dwc->rx_detect_poll_quirk)
|
||||
reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
|
||||
|
||||
if (dwc->tx_de_emphasis_quirk)
|
||||
reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
|
||||
|
||||
/*
|
||||
* RK3568 uboot: For some Rokchip SoCs like RK3588, if the USB3 PHY is suspended
|
||||
* in U-Boot would cause the PHY initialize abortively in Linux Kernel,
|
||||
* so disable the DWC3_GUSB3PIPECTL_SUSPHY feature here to fix it.
|
||||
*/
|
||||
/*if (dwc->dis_u3_susphy_quirk || CONFIG_IS_ENABLED(ARCH_ROCKCHIP))
|
||||
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;*/
|
||||
/*
|
||||
* Linux: Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be
|
||||
* cleared after power-on reset, and it can be set after core
|
||||
* initialization.
|
||||
*/
|
||||
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
|
||||
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GUSB3PIPECTL(0), reg);
|
||||
|
||||
dwc3_hsphy_mode_setup(dwc);
|
||||
|
||||
usb_osal_msleep(100);
|
||||
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GUSB2PHYCFG(0));
|
||||
|
||||
/*
|
||||
* Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
|
||||
* '0' during coreConsultant configuration. So default value will
|
||||
* be '0' when the core is reset. Application needs to set it to
|
||||
* '1' after the core initialization is completed.
|
||||
*/
|
||||
if (dwc->revision > DWC3_REVISION_194A)
|
||||
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
|
||||
if (dwc->dis_u2_susphy_quirk)
|
||||
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
|
||||
if (dwc->dis_enblslpm_quirk)
|
||||
reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
|
||||
|
||||
if (dwc->dis_u2_freeclk_exists_quirk)
|
||||
reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
|
||||
|
||||
if (dwc->usb2_phyif_utmi_width == 16) {
|
||||
reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
|
||||
DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
|
||||
reg |= DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
|
||||
reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT);
|
||||
}
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GUSB2PHYCFG(0), reg);
|
||||
|
||||
usb_osal_msleep(100);
|
||||
}
|
||||
|
||||
|
||||
void dwc3_hsphy_mode_setup(struct dwc3 *dwc)
|
||||
{
|
||||
enum usb_phy_interface hsphy_mode = dwc->hsphy_mode;
|
||||
uint32_t reg;
|
||||
|
||||
/* Set dwc3 usb2 phy config */
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GUSB2PHYCFG(0));
|
||||
|
||||
switch (hsphy_mode) {
|
||||
case USBPHY_INTERFACE_MODE_UTMI:
|
||||
reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
|
||||
DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
|
||||
reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
|
||||
DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
|
||||
break;
|
||||
case USBPHY_INTERFACE_MODE_UTMIW:
|
||||
reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
|
||||
DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
|
||||
reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
|
||||
DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GUSB2PHYCFG(0), reg);
|
||||
}
|
||||
|
||||
|
||||
int dwc3_alloc_scratch_buffers(struct dwc3 *dwc){
|
||||
uint32_t len;
|
||||
uintptr_t phy_addr, vir_addr;
|
||||
int ret;
|
||||
|
||||
if (!dwc->has_hibernation)
|
||||
return 0;
|
||||
|
||||
if (!dwc->nr_scratch)
|
||||
return 0;
|
||||
|
||||
len = dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE;
|
||||
|
||||
vir_addr = USB_MEM_VIRADDR_ALLOC;
|
||||
phy_addr = 0;
|
||||
dwc->scratchbuf = (void *)vir_addr;
|
||||
|
||||
ret = naive_mmap(&vir_addr, &phy_addr, len, true);
|
||||
|
||||
if(ret != 0){
|
||||
USB_LOG_ERR("could not allocate DWC3 scratch buffers!\n");
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
dwc->scratch_addr = phy_addr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dwc3_setup_scratch_buffers(struct dwc3 *dwc){
|
||||
uint32_t param;
|
||||
int ret;
|
||||
|
||||
if (!dwc->has_hibernation)
|
||||
return 0;
|
||||
|
||||
if (!dwc->nr_scratch)
|
||||
return 0;
|
||||
|
||||
param = lower_32_bits(dwc->scratch_addr);
|
||||
|
||||
ret = dwc3_send_gadget_generic_command(dwc,
|
||||
DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
|
||||
|
||||
if(ret != 0)
|
||||
goto err_cmd;
|
||||
|
||||
param = upper_32_bits(dwc->scratch_addr);
|
||||
|
||||
ret = dwc3_send_gadget_generic_command(dwc,
|
||||
DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
|
||||
|
||||
if(ret != 0)
|
||||
goto err_cmd;
|
||||
|
||||
return ret;
|
||||
|
||||
err_cmd:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void dwc3_free_scratch_buffers(struct dwc3 *dwc){
|
||||
}
|
||||
|
||||
|
||||
int dwc3_alloc_event_buffers(struct dwc3 *dwc, uint32_t length){
|
||||
int num;
|
||||
int i;
|
||||
|
||||
num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
|
||||
dwc->num_event_buffers = num;
|
||||
|
||||
dwc->ev_buffs = usb_malloc(num * sizeof(*dwc->ev_buffs));
|
||||
|
||||
if (!dwc->ev_buffs)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
struct dwc3_event_buffer *evt;
|
||||
evt = dwc3_alloc_one_event_buffer(dwc, length);
|
||||
|
||||
if(evt == NULL){
|
||||
goto err_alloc_evt;
|
||||
}
|
||||
dwc->ev_buffs[i] = evt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_alloc_evt:
|
||||
i = i - 1;
|
||||
for(; i >= 0; i--){
|
||||
usb_free(dwc->ev_buffs[i]);
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length){
|
||||
struct dwc3_event_buffer *evt;
|
||||
uintptr_t phy_addr, vir_addr;
|
||||
int ret;
|
||||
|
||||
evt = usb_malloc(sizeof(*evt));
|
||||
|
||||
if(evt == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evt->dwc = dwc;
|
||||
evt->length = length;
|
||||
|
||||
vir_addr = USB_MEM_VIRADDR_ALLOC;
|
||||
phy_addr = 0;
|
||||
evt->buf = (void *)vir_addr;
|
||||
|
||||
ret = naive_mmap(&vir_addr, &phy_addr, length, true);
|
||||
|
||||
if(ret != 0){
|
||||
USB_LOG_ERR("could not allocate DWC3 event buffers!\n");
|
||||
goto err_evt;
|
||||
}
|
||||
|
||||
evt->dma = phy_addr;
|
||||
|
||||
return evt;
|
||||
|
||||
err_evt:
|
||||
usb_free(evt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void dwc3_free_event_buffers(struct dwc3 *dwc){
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dwc3_event_buffers_setup(struct dwc3 *dwc){
|
||||
struct dwc3_event_buffer *evt;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < dwc->num_event_buffers; n++) {
|
||||
evt = dwc->ev_buffs[n];
|
||||
|
||||
evt->lpos = 0;
|
||||
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GEVNTADRLO(n),
|
||||
lower_32_bits(evt->dma));
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GEVNTADRHI(n),
|
||||
upper_32_bits(evt->dma));
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GEVNTSIZ(n),
|
||||
DWC3_GEVNTSIZ_SIZE(evt->length));
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GEVNTCOUNT(n), 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void dwc3_event_buffers_cleanup(struct dwc3 *dwc){
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dwc3_core_init_mode(struct dwc3 *dwc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (dwc->dr_mode) {
|
||||
case USB_DR_MODE_HOST:
|
||||
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
|
||||
ret = dwc3_host_init(dwc);
|
||||
if (ret) {
|
||||
USB_LOG_ERR("failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_ERR("Unsupported mode of operation %d\n", dwc->dr_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void dwc3_set_mode(struct dwc3 *dwc, uint32_t mode)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_GCTL);
|
||||
reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
|
||||
reg |= DWC3_GCTL_PRTCAPDIR(mode);
|
||||
dwc3_writel(dwc->regs_vir, DWC3_GCTL, reg);
|
||||
}
|
||||
|
||||
|
||||
int dwc3_init(struct dwc3 *dwc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dwc3_cache_hwparams(dwc);
|
||||
|
||||
ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
|
||||
if (ret) {
|
||||
USB_LOG_ERR("failed to allocate event buffers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = dwc3_core_init(dwc);
|
||||
if (ret) {
|
||||
USB_LOG_ERR("failed to initialize core\n");
|
||||
goto core_fail;
|
||||
}
|
||||
|
||||
ret = dwc3_event_buffers_setup(dwc);
|
||||
if (ret) {
|
||||
USB_LOG_ERR("failed to setup event buffers\n");
|
||||
goto event_fail;
|
||||
}
|
||||
|
||||
ret = dwc3_core_init_mode(dwc);
|
||||
if (ret)
|
||||
goto mode_fail;
|
||||
|
||||
dwc3_dump(dwc);
|
||||
|
||||
return 0;
|
||||
|
||||
mode_fail:
|
||||
dwc3_event_buffers_cleanup(dwc);
|
||||
|
||||
event_fail:
|
||||
dwc3_core_exit(dwc);
|
||||
|
||||
core_fail:
|
||||
dwc3_free_event_buffers(dwc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, uint32_t param){
|
||||
uint32_t timeout = 500;
|
||||
uint32_t reg;
|
||||
|
||||
dwc3_writel(dwc->regs_vir, DWC3_DGCMDPAR, param);
|
||||
dwc3_writel(dwc->regs_vir, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
|
||||
|
||||
do {
|
||||
reg = dwc3_readl(dwc->regs_vir, DWC3_DGCMD);
|
||||
|
||||
if(!(reg & DWC3_DGCMD_CMDACT)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
timeout--;
|
||||
usb_osal_msleep(1);
|
||||
|
||||
if(!timeout)
|
||||
return -1;
|
||||
}while(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dwc3_dump(struct dwc3 *dwc)
|
||||
{
|
||||
USB_LOG_DBG("%s regs=%08lx regs_vir=%08lx\n", __func__, dwc->regs, dwc->regs_vir );
|
||||
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GSBUSCFG0, dwc3_readl(dwc->regs_vir, DWC3_GSBUSCFG0) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GCTL, dwc3_readl(dwc->regs_vir, DWC3_GCTL) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GUCTL1, dwc3_readl(dwc->regs_vir, DWC3_GUCTL1) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GSNPSID, dwc3_readl(dwc->regs_vir, DWC3_GSNPSID) );
|
||||
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS0, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS0) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS1, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS1) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS2, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS2) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS3, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS3) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS4, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS4) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS5, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS5) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS6, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS6) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS7, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS7) );
|
||||
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GUSB2PHYCFG(0), dwc3_readl(dwc->regs_vir, DWC3_GUSB2PHYCFG(0)) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GUSB3PIPECTL(0), dwc3_readl(dwc->regs_vir, DWC3_GUSB3PIPECTL(0)) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GEVNTADRLO(0), dwc3_readl(dwc->regs_vir, DWC3_GEVNTADRLO(0)) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GEVNTADRHI(0), dwc3_readl(dwc->regs_vir, DWC3_GEVNTADRHI(0)) );
|
||||
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_GHWPARAMS8, dwc3_readl(dwc->regs_vir, DWC3_GHWPARAMS8) );
|
||||
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_DCTL, dwc3_readl(dwc->regs_vir, DWC3_DCTL) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_DGCMDPAR, dwc3_readl(dwc->regs_vir, DWC3_DGCMDPAR) );
|
||||
USB_LOG_DBG("%04x: %08x\n", DWC3_DGCMD, dwc3_readl(dwc->regs_vir, DWC3_DGCMD) );
|
||||
}
|
||||
|
|
@ -0,0 +1,940 @@
|
|||
#ifndef DWC3_H_
|
||||
#define DWC3_H_
|
||||
|
||||
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_hub.h"
|
||||
#include "usb_util.h"
|
||||
#include "xhci_reg.h"
|
||||
#include "xhci.h"
|
||||
#include "gadget.h"
|
||||
#include "usb_phy.h"
|
||||
|
||||
#define CONFIG_SYS_CACHELINE_SIZE 64
|
||||
#define CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE
|
||||
|
||||
|
||||
|
||||
#define DWC3_MSG_MAX 500
|
||||
|
||||
/* Global constants */
|
||||
#define DWC3_EP0_BOUNCE_SIZE 512
|
||||
#define DWC3_ENDPOINTS_NUM 32
|
||||
#define DWC3_XHCI_RESOURCES_NUM 2
|
||||
|
||||
#define DWC3_SCRATCHBUF_SIZE 4096 /* each buffer is assumed to be 4KiB */
|
||||
#define DWC3_EVENT_SIZE 4 /* bytes */
|
||||
#define DWC3_EVENT_MAX_NUM 64 /* 2 events/endpoint */
|
||||
#define DWC3_EVENT_BUFFERS_SIZE (DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM)
|
||||
#define DWC3_EVENT_TYPE_MASK 0xfe
|
||||
|
||||
#define DWC3_EVENT_TYPE_DEV 0
|
||||
#define DWC3_EVENT_TYPE_CARKIT 3
|
||||
#define DWC3_EVENT_TYPE_I2C 4
|
||||
|
||||
#define DWC3_DEVICE_EVENT_DISCONNECT 0
|
||||
#define DWC3_DEVICE_EVENT_RESET 1
|
||||
#define DWC3_DEVICE_EVENT_CONNECT_DONE 2
|
||||
#define DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE 3
|
||||
#define DWC3_DEVICE_EVENT_WAKEUP 4
|
||||
#define DWC3_DEVICE_EVENT_HIBER_REQ 5
|
||||
#define DWC3_DEVICE_EVENT_EOPF 6
|
||||
#define DWC3_DEVICE_EVENT_SOF 7
|
||||
#define DWC3_DEVICE_EVENT_ERRATIC_ERROR 9
|
||||
#define DWC3_DEVICE_EVENT_CMD_CMPL 10
|
||||
#define DWC3_DEVICE_EVENT_OVERFLOW 11
|
||||
|
||||
#define DWC3_GEVNTCOUNT_MASK 0xfffc
|
||||
#define DWC3_GSNPSID_MASK 0xffff0000
|
||||
#define DWC3_GSNPSREV_MASK 0xffff
|
||||
|
||||
/* DWC3 registers memory space boundries */
|
||||
#define DWC3_XHCI_REGS_START 0x0
|
||||
#define DWC3_XHCI_REGS_END 0x7fff
|
||||
#define DWC3_GLOBALS_REGS_START 0xc100
|
||||
#define DWC3_GLOBALS_REGS_END 0xc6ff
|
||||
#define DWC3_DEVICE_REGS_START 0xc700
|
||||
#define DWC3_DEVICE_REGS_END 0xcbff
|
||||
#define DWC3_OTG_REGS_START 0xcc00
|
||||
#define DWC3_OTG_REGS_END 0xccff
|
||||
|
||||
/* Global Registers */
|
||||
#define DWC3_GSBUSCFG0 0xc100
|
||||
#define DWC3_GSBUSCFG1 0xc104
|
||||
#define DWC3_GTXTHRCFG 0xc108
|
||||
#define DWC3_GRXTHRCFG 0xc10c
|
||||
#define DWC3_GCTL 0xc110
|
||||
#define DWC3_GEVTEN 0xc114
|
||||
#define DWC3_GSTS 0xc118
|
||||
#define DWC3_GUCTL1 0xc11c
|
||||
#define DWC3_GSNPSID 0xc120
|
||||
#define DWC3_GGPIO 0xc124
|
||||
#define DWC3_GUID 0xc128
|
||||
#define DWC3_GUCTL 0xc12c
|
||||
#define DWC3_GBUSERRADDR0 0xc130
|
||||
#define DWC3_GBUSERRADDR1 0xc134
|
||||
#define DWC3_GPRTBIMAP0 0xc138
|
||||
#define DWC3_GPRTBIMAP1 0xc13c
|
||||
#define DWC3_GHWPARAMS0 0xc140
|
||||
#define DWC3_GHWPARAMS1 0xc144
|
||||
#define DWC3_GHWPARAMS2 0xc148
|
||||
#define DWC3_GHWPARAMS3 0xc14c
|
||||
#define DWC3_GHWPARAMS4 0xc150
|
||||
#define DWC3_GHWPARAMS5 0xc154
|
||||
#define DWC3_GHWPARAMS6 0xc158
|
||||
#define DWC3_GHWPARAMS7 0xc15c
|
||||
#define DWC3_GDBGFIFOSPACE 0xc160
|
||||
#define DWC3_GDBGLTSSM 0xc164
|
||||
#define DWC3_GPRTBIMAP_HS0 0xc180
|
||||
#define DWC3_GPRTBIMAP_HS1 0xc184
|
||||
#define DWC3_GPRTBIMAP_FS0 0xc188
|
||||
#define DWC3_GPRTBIMAP_FS1 0xc18c
|
||||
|
||||
#define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04))
|
||||
#define DWC3_GUSB2I2CCTL(n) (0xc240 + (n * 0x04))
|
||||
|
||||
#define DWC3_GUSB2PHYACC(n) (0xc280 + (n * 0x04))
|
||||
|
||||
#define DWC3_GUSB3PIPECTL(n) (0xc2c0 + (n * 0x04))
|
||||
|
||||
#define DWC3_GTXFIFOSIZ(n) (0xc300 + (n * 0x04))
|
||||
#define DWC3_GRXFIFOSIZ(n) (0xc380 + (n * 0x04))
|
||||
|
||||
#define DWC3_GEVNTADRLO(n) (0xc400 + (n * 0x10))
|
||||
#define DWC3_GEVNTADRHI(n) (0xc404 + (n * 0x10))
|
||||
#define DWC3_GEVNTSIZ(n) (0xc408 + (n * 0x10))
|
||||
#define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10))
|
||||
|
||||
#define DWC3_GHWPARAMS8 0xc600
|
||||
|
||||
/* Device Registers */
|
||||
#define DWC3_DCFG 0xc700
|
||||
#define DWC3_DCTL 0xc704
|
||||
#define DWC3_DEVTEN 0xc708
|
||||
#define DWC3_DSTS 0xc70c
|
||||
#define DWC3_DGCMDPAR 0xc710
|
||||
#define DWC3_DGCMD 0xc714
|
||||
#define DWC3_DALEPENA 0xc720
|
||||
#define DWC3_DEPCMDPAR2(n) (0xc800 + (n * 0x10))
|
||||
#define DWC3_DEPCMDPAR1(n) (0xc804 + (n * 0x10))
|
||||
#define DWC3_DEPCMDPAR0(n) (0xc808 + (n * 0x10))
|
||||
#define DWC3_DEPCMD(n) (0xc80c + (n * 0x10))
|
||||
|
||||
/* OTG Registers */
|
||||
#define DWC3_OCFG 0xcc00
|
||||
#define DWC3_OCTL 0xcc04
|
||||
#define DWC3_OEVT 0xcc08
|
||||
#define DWC3_OEVTEN 0xcc0C
|
||||
#define DWC3_OSTS 0xcc10
|
||||
|
||||
/* Bit fields */
|
||||
|
||||
/* Global Configuration Register */
|
||||
#define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19)
|
||||
#define DWC3_GCTL_U2RSTECN (1 << 16)
|
||||
#define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6)
|
||||
#define DWC3_GCTL_CLK_BUS (0)
|
||||
#define DWC3_GCTL_CLK_PIPE (1)
|
||||
#define DWC3_GCTL_CLK_PIPEHALF (2)
|
||||
#define DWC3_GCTL_CLK_MASK (3)
|
||||
|
||||
#define DWC3_GCTL_PRTCAP(n) (((n) & (3 << 12)) >> 12)
|
||||
#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12)
|
||||
#define DWC3_GCTL_PRTCAP_HOST 1
|
||||
#define DWC3_GCTL_PRTCAP_DEVICE 2
|
||||
#define DWC3_GCTL_PRTCAP_OTG 3
|
||||
|
||||
#define DWC3_GCTL_CORESOFTRESET (1 << 11)
|
||||
#define DWC3_GCTL_SOFITPSYNC (1 << 10)
|
||||
#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4)
|
||||
#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3)
|
||||
#define DWC3_GCTL_DISSCRAMBLE (1 << 3)
|
||||
#define DWC3_GCTL_U2EXIT_LFPS (1 << 2)
|
||||
#define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1)
|
||||
#define DWC3_GCTL_DSBLCLKGTNG (1 << 0)
|
||||
|
||||
/* Global User Control 1 Register */
|
||||
#define DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK BIT(26)
|
||||
|
||||
/* Global USB2 PHY Configuration Register */
|
||||
#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31)
|
||||
#define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS (1 << 30)
|
||||
#define DWC3_GUSB2PHYCFG_ENBLSLPM (1 << 8)
|
||||
#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6)
|
||||
#define DWC3_GUSB2PHYCFG_PHYIF_8BIT (0 << 3)
|
||||
#define DWC3_GUSB2PHYCFG_PHYIF_16BIT (1 << 3)
|
||||
#define DWC3_GUSB2PHYCFG_PHYIF(n) ((n) << 3)
|
||||
#define DWC3_GUSB2PHYCFG_PHYIF_MASK DWC3_GUSB2PHYCFG_PHYIF(1)
|
||||
#define DWC3_GUSB2PHYCFG_USBTRDTIM(n) ((n) << 10)
|
||||
#define DWC3_GUSB2PHYCFG_USBTRDTIM_MASK DWC3_GUSB2PHYCFG_USBTRDTIM(0xf)
|
||||
#define USBTRDTIM_UTMI_8_BIT 9
|
||||
#define USBTRDTIM_UTMI_16_BIT 5
|
||||
#define UTMI_PHYIF_16_BIT 1
|
||||
#define UTMI_PHYIF_8_BIT 0
|
||||
|
||||
/* Global USB3 PIPE Control Register */
|
||||
#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31)
|
||||
#define DWC3_GUSB3PIPECTL_U2SSINP3OK (1 << 29)
|
||||
#define DWC3_GUSB3PIPECTL_REQP1P2P3 (1 << 24)
|
||||
#define DWC3_GUSB3PIPECTL_DEP1P2P3(n) ((n) << 19)
|
||||
#define DWC3_GUSB3PIPECTL_DEP1P2P3_MASK DWC3_GUSB3PIPECTL_DEP1P2P3(7)
|
||||
#define DWC3_GUSB3PIPECTL_DEP1P2P3_EN DWC3_GUSB3PIPECTL_DEP1P2P3(1)
|
||||
#define DWC3_GUSB3PIPECTL_DEPOCHANGE (1 << 18)
|
||||
#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17)
|
||||
#define DWC3_GUSB3PIPECTL_LFPSFILT (1 << 9)
|
||||
#define DWC3_GUSB3PIPECTL_RX_DETOPOLL (1 << 8)
|
||||
#define DWC3_GUSB3PIPECTL_TX_DEEPH_MASK DWC3_GUSB3PIPECTL_TX_DEEPH(3)
|
||||
#define DWC3_GUSB3PIPECTL_TX_DEEPH(n) ((n) << 1)
|
||||
|
||||
/* Global TX Fifo Size Register */
|
||||
#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
|
||||
#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
|
||||
|
||||
/* Global Event Size Registers */
|
||||
#define DWC3_GEVNTSIZ_INTMASK (1 << 31)
|
||||
#define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff)
|
||||
|
||||
/* Global HWPARAMS1 Register */
|
||||
#define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24)
|
||||
#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0
|
||||
#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1
|
||||
#define DWC3_GHWPARAMS1_EN_PWROPT_HIB 2
|
||||
#define DWC3_GHWPARAMS1_PWROPT(n) ((n) << 24)
|
||||
#define DWC3_GHWPARAMS1_PWROPT_MASK DWC3_GHWPARAMS1_PWROPT(3)
|
||||
|
||||
/* Global HWPARAMS3 Register */
|
||||
#define DWC3_GHWPARAMS3_SSPHY_IFC(n) ((n) & 3)
|
||||
#define DWC3_GHWPARAMS3_SSPHY_IFC_DIS 0
|
||||
#define DWC3_GHWPARAMS3_SSPHY_IFC_ENA 1
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC(n) (((n) & (3 << 2)) >> 2)
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC_DIS 0
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI 1
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC_ULPI 2
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI 3
|
||||
#define DWC3_GHWPARAMS3_FSPHY_IFC(n) (((n) & (3 << 4)) >> 4)
|
||||
#define DWC3_GHWPARAMS3_FSPHY_IFC_DIS 0
|
||||
#define DWC3_GHWPARAMS3_FSPHY_IFC_ENA 1
|
||||
|
||||
/* Global HWPARAMS4 Register */
|
||||
#define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) & (0x0f << 13)) >> 13)
|
||||
#define DWC3_MAX_HIBER_SCRATCHBUFS 15
|
||||
|
||||
/* Global HWPARAMS6 Register */
|
||||
#define DWC3_GHWPARAMS6_EN_FPGA (1 << 7)
|
||||
|
||||
/* Device Configuration Register */
|
||||
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
|
||||
#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
|
||||
|
||||
#define DWC3_DCFG_SPEED_MASK (7 << 0)
|
||||
#define DWC3_DCFG_SUPERSPEED (4 << 0)
|
||||
#define DWC3_DCFG_HIGHSPEED (0 << 0)
|
||||
#define DWC3_DCFG_FULLSPEED2 (1 << 0)
|
||||
#define DWC3_DCFG_LOWSPEED (2 << 0)
|
||||
#define DWC3_DCFG_FULLSPEED1 (3 << 0)
|
||||
|
||||
#define DWC3_DCFG_LPM_CAP (1 << 22)
|
||||
|
||||
/* Device Control Register */
|
||||
#define DWC3_DCTL_RUN_STOP (1 << 31)
|
||||
#define DWC3_DCTL_CSFTRST (1 << 30)
|
||||
#define DWC3_DCTL_LSFTRST (1 << 29)
|
||||
|
||||
#define DWC3_DCTL_HIRD_THRES_MASK (0x1f << 24)
|
||||
#define DWC3_DCTL_HIRD_THRES(n) ((n) << 24)
|
||||
|
||||
#define DWC3_DCTL_APPL1RES (1 << 23)
|
||||
|
||||
/* These apply for core versions 1.87a and earlier */
|
||||
#define DWC3_DCTL_TRGTULST_MASK (0x0f << 17)
|
||||
#define DWC3_DCTL_TRGTULST(n) ((n) << 17)
|
||||
#define DWC3_DCTL_TRGTULST_U2 (DWC3_DCTL_TRGTULST(2))
|
||||
#define DWC3_DCTL_TRGTULST_U3 (DWC3_DCTL_TRGTULST(3))
|
||||
#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4))
|
||||
#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5))
|
||||
#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6))
|
||||
|
||||
/* These apply for core versions 1.94a and later */
|
||||
#define DWC3_DCTL_LPM_ERRATA_MASK DWC3_DCTL_LPM_ERRATA(0xf)
|
||||
#define DWC3_DCTL_LPM_ERRATA(n) ((n) << 20)
|
||||
|
||||
#define DWC3_DCTL_KEEP_CONNECT (1 << 19)
|
||||
#define DWC3_DCTL_L1_HIBER_EN (1 << 18)
|
||||
#define DWC3_DCTL_CRS (1 << 17)
|
||||
#define DWC3_DCTL_CSS (1 << 16)
|
||||
|
||||
#define DWC3_DCTL_INITU2ENA (1 << 12)
|
||||
#define DWC3_DCTL_ACCEPTU2ENA (1 << 11)
|
||||
#define DWC3_DCTL_INITU1ENA (1 << 10)
|
||||
#define DWC3_DCTL_ACCEPTU1ENA (1 << 9)
|
||||
#define DWC3_DCTL_TSTCTRL_MASK (0xf << 1)
|
||||
|
||||
#define DWC3_DCTL_ULSTCHNGREQ_MASK (0x0f << 5)
|
||||
#define DWC3_DCTL_ULSTCHNGREQ(n) (((n) << 5) & DWC3_DCTL_ULSTCHNGREQ_MASK)
|
||||
|
||||
#define DWC3_DCTL_ULSTCHNG_NO_ACTION (DWC3_DCTL_ULSTCHNGREQ(0))
|
||||
#define DWC3_DCTL_ULSTCHNG_SS_DISABLED (DWC3_DCTL_ULSTCHNGREQ(4))
|
||||
#define DWC3_DCTL_ULSTCHNG_RX_DETECT (DWC3_DCTL_ULSTCHNGREQ(5))
|
||||
#define DWC3_DCTL_ULSTCHNG_SS_INACTIVE (DWC3_DCTL_ULSTCHNGREQ(6))
|
||||
#define DWC3_DCTL_ULSTCHNG_RECOVERY (DWC3_DCTL_ULSTCHNGREQ(8))
|
||||
#define DWC3_DCTL_ULSTCHNG_COMPLIANCE (DWC3_DCTL_ULSTCHNGREQ(10))
|
||||
#define DWC3_DCTL_ULSTCHNG_LOOPBACK (DWC3_DCTL_ULSTCHNGREQ(11))
|
||||
|
||||
/* Device Event Enable Register */
|
||||
#define DWC3_DEVTEN_VNDRDEVTSTRCVEDEN (1 << 12)
|
||||
#define DWC3_DEVTEN_EVNTOVERFLOWEN (1 << 11)
|
||||
#define DWC3_DEVTEN_CMDCMPLTEN (1 << 10)
|
||||
#define DWC3_DEVTEN_ERRTICERREN (1 << 9)
|
||||
#define DWC3_DEVTEN_SOFEN (1 << 7)
|
||||
#define DWC3_DEVTEN_EOPFEN (1 << 6)
|
||||
#define DWC3_DEVTEN_HIBERNATIONREQEVTEN (1 << 5)
|
||||
#define DWC3_DEVTEN_WKUPEVTEN (1 << 4)
|
||||
#define DWC3_DEVTEN_ULSTCNGEN (1 << 3)
|
||||
#define DWC3_DEVTEN_CONNECTDONEEN (1 << 2)
|
||||
#define DWC3_DEVTEN_USBRSTEN (1 << 1)
|
||||
#define DWC3_DEVTEN_DISCONNEVTEN (1 << 0)
|
||||
|
||||
/* Device Status Register */
|
||||
#define DWC3_DSTS_DCNRD (1 << 29)
|
||||
|
||||
/* This applies for core versions 1.87a and earlier */
|
||||
#define DWC3_DSTS_PWRUPREQ (1 << 24)
|
||||
|
||||
/* These apply for core versions 1.94a and later */
|
||||
#define DWC3_DSTS_RSS (1 << 25)
|
||||
#define DWC3_DSTS_SSS (1 << 24)
|
||||
|
||||
#define DWC3_DSTS_COREIDLE (1 << 23)
|
||||
#define DWC3_DSTS_DEVCTRLHLT (1 << 22)
|
||||
|
||||
#define DWC3_DSTS_USBLNKST_MASK (0x0f << 18)
|
||||
#define DWC3_DSTS_USBLNKST(n) (((n) & DWC3_DSTS_USBLNKST_MASK) >> 18)
|
||||
|
||||
#define DWC3_DSTS_RXFIFOEMPTY (1 << 17)
|
||||
|
||||
#define DWC3_DSTS_SOFFN_MASK (0x3fff << 3)
|
||||
#define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3)
|
||||
|
||||
#define DWC3_DSTS_CONNECTSPD (7 << 0)
|
||||
|
||||
#define DWC3_DSTS_SUPERSPEED (4 << 0)
|
||||
#define DWC3_DSTS_HIGHSPEED (0 << 0)
|
||||
#define DWC3_DSTS_FULLSPEED2 (1 << 0)
|
||||
#define DWC3_DSTS_LOWSPEED (2 << 0)
|
||||
#define DWC3_DSTS_FULLSPEED1 (3 << 0)
|
||||
|
||||
/* Device Generic Command Register */
|
||||
#define DWC3_DGCMD_SET_LMP 0x01
|
||||
#define DWC3_DGCMD_SET_PERIODIC_PAR 0x02
|
||||
#define DWC3_DGCMD_XMIT_FUNCTION 0x03
|
||||
|
||||
/* These apply for core versions 1.94a and later */
|
||||
#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO 0x04
|
||||
#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI 0x05
|
||||
|
||||
#define DWC3_DGCMD_SELECTED_FIFO_FLUSH 0x09
|
||||
#define DWC3_DGCMD_ALL_FIFO_FLUSH 0x0a
|
||||
#define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c
|
||||
#define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10
|
||||
|
||||
#define DWC3_DGCMD_STATUS(n) (((n) >> 15) & 1)
|
||||
#define DWC3_DGCMD_CMDACT (1 << 10)
|
||||
#define DWC3_DGCMD_CMDIOC (1 << 8)
|
||||
|
||||
/* Device Generic Command Parameter Register */
|
||||
#define DWC3_DGCMDPAR_FORCE_LINKPM_ACCEPT (1 << 0)
|
||||
#define DWC3_DGCMDPAR_FIFO_NUM(n) ((n) << 0)
|
||||
#define DWC3_DGCMDPAR_RX_FIFO (0 << 5)
|
||||
#define DWC3_DGCMDPAR_TX_FIFO (1 << 5)
|
||||
#define DWC3_DGCMDPAR_LOOPBACK_DIS (0 << 0)
|
||||
#define DWC3_DGCMDPAR_LOOPBACK_ENA (1 << 0)
|
||||
|
||||
/* Device Endpoint Command Register */
|
||||
#define DWC3_DEPCMD_PARAM_SHIFT 16
|
||||
#define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT)
|
||||
#define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
|
||||
#define DWC3_DEPCMD_STATUS(x) (((x) >> 15) & 1)
|
||||
#define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11)
|
||||
#define DWC3_DEPCMD_CMDACT (1 << 10)
|
||||
#define DWC3_DEPCMD_CMDIOC (1 << 8)
|
||||
|
||||
#define DWC3_DEPCMD_DEPSTARTCFG (0x09 << 0)
|
||||
#define DWC3_DEPCMD_ENDTRANSFER (0x08 << 0)
|
||||
#define DWC3_DEPCMD_UPDATETRANSFER (0x07 << 0)
|
||||
#define DWC3_DEPCMD_STARTTRANSFER (0x06 << 0)
|
||||
#define DWC3_DEPCMD_CLEARSTALL (0x05 << 0)
|
||||
#define DWC3_DEPCMD_SETSTALL (0x04 << 0)
|
||||
/* This applies for core versions 1.90a and earlier */
|
||||
#define DWC3_DEPCMD_GETSEQNUMBER (0x03 << 0)
|
||||
/* This applies for core versions 1.94a and later */
|
||||
#define DWC3_DEPCMD_GETEPSTATE (0x03 << 0)
|
||||
#define DWC3_DEPCMD_SETTRANSFRESOURCE (0x02 << 0)
|
||||
#define DWC3_DEPCMD_SETEPCONFIG (0x01 << 0)
|
||||
|
||||
/* The EP number goes 0..31 so ep0 is always out and ep1 is always in */
|
||||
#define DWC3_DALEPENA_EP(n) (1 << n)
|
||||
|
||||
#define DWC3_DEPCMD_TYPE_CONTROL 0
|
||||
#define DWC3_DEPCMD_TYPE_ISOC 1
|
||||
#define DWC3_DEPCMD_TYPE_BULK 2
|
||||
#define DWC3_DEPCMD_TYPE_INTR 3
|
||||
|
||||
struct dwc3_trb;
|
||||
struct dwc3;
|
||||
|
||||
|
||||
/**
|
||||
* struct dwc3_event_buffer - Software event buffer representation
|
||||
* @buf: _THE_ buffer
|
||||
* @length: size of this buffer
|
||||
* @lpos: event offset
|
||||
* @count: cache of last read event count register
|
||||
* @flags: flags related to this event buffer
|
||||
* @dma: dma_addr_t
|
||||
* @dwc: pointer to DWC controller
|
||||
*/
|
||||
struct dwc3_event_buffer {
|
||||
void *buf;
|
||||
uint16_t length;
|
||||
unsigned int lpos;
|
||||
unsigned int count;
|
||||
unsigned int flags;
|
||||
|
||||
#define DWC3_EVENT_PENDING (1UL << 0)
|
||||
uintptr_t dma;
|
||||
struct dwc3 *dwc;
|
||||
};
|
||||
|
||||
#define DWC3_EP_FLAG_STALLED (1 << 0)
|
||||
#define DWC3_EP_FLAG_WEDGED (1 << 1)
|
||||
|
||||
#define DWC3_EP_DIRECTION_TX true
|
||||
#define DWC3_EP_DIRECTION_RX false
|
||||
|
||||
#define DWC3_TRB_NUM 32
|
||||
#define DWC3_TRB_MASK (DWC3_TRB_NUM - 1)
|
||||
|
||||
struct dwc3_ep {
|
||||
struct usb_ep endpoint;
|
||||
usb_slist_t request_list;
|
||||
usb_slist_t req_queued;
|
||||
|
||||
struct dwc3_trb *trb_pool;
|
||||
uintptr_t trb_pool_dma;
|
||||
uint32_t free_slot;
|
||||
uint32_t busy_slot;
|
||||
const struct usb_ss_ep_comp_descriptor *comp_desc;
|
||||
struct dwc3 *dwc;
|
||||
|
||||
uint32_t saved_state;
|
||||
unsigned flags;
|
||||
#define DWC3_EP_ENABLED (1 << 0)
|
||||
#define DWC3_EP_STALL (1 << 1)
|
||||
#define DWC3_EP_WEDGE (1 << 2)
|
||||
#define DWC3_EP_BUSY (1 << 4)
|
||||
#define DWC3_EP_PENDING_REQUEST (1 << 5)
|
||||
#define DWC3_EP_MISSED_ISOC (1 << 6)
|
||||
|
||||
/* This last one is specific to EP0 */
|
||||
#define DWC3_EP0_DIR_IN (1 << 31)
|
||||
|
||||
unsigned current_trb;
|
||||
|
||||
uint8_t number;
|
||||
uint8_t type;
|
||||
uint8_t resource_index;
|
||||
uint32_t interval;
|
||||
|
||||
char name[20];
|
||||
|
||||
unsigned direction:1;
|
||||
unsigned stream_capable:1;
|
||||
};
|
||||
|
||||
|
||||
enum usb_dr_mode {
|
||||
USB_DR_MODE_UNKNOWN,
|
||||
USB_DR_MODE_HOST,
|
||||
USB_DR_MODE_PERIPHERAL,
|
||||
USB_DR_MODE_OTG,
|
||||
};
|
||||
|
||||
enum dwc3_phy {
|
||||
DWC3_PHY_UNKNOWN = 0,
|
||||
DWC3_PHY_USB3,
|
||||
DWC3_PHY_USB2,
|
||||
};
|
||||
|
||||
|
||||
enum usb_phy_interface {
|
||||
USBPHY_INTERFACE_MODE_UNKNOWN,
|
||||
USBPHY_INTERFACE_MODE_UTMI,
|
||||
USBPHY_INTERFACE_MODE_UTMIW,
|
||||
};
|
||||
|
||||
enum dwc3_ep0_next {
|
||||
DWC3_EP0_UNKNOWN = 0,
|
||||
DWC3_EP0_COMPLETE,
|
||||
DWC3_EP0_NRDY_DATA,
|
||||
DWC3_EP0_NRDY_STATUS,
|
||||
};
|
||||
|
||||
enum dwc3_ep0_state {
|
||||
EP0_UNCONNECTED = 0,
|
||||
EP0_SETUP_PHASE,
|
||||
EP0_DATA_PHASE,
|
||||
EP0_STATUS_PHASE,
|
||||
};
|
||||
|
||||
enum dwc3_link_state {
|
||||
/* In SuperSpeed */
|
||||
DWC3_LINK_STATE_U0 = 0x00, /* in HS, means ON */
|
||||
DWC3_LINK_STATE_U1 = 0x01,
|
||||
DWC3_LINK_STATE_U2 = 0x02, /* in HS, means SLEEP */
|
||||
DWC3_LINK_STATE_U3 = 0x03, /* in HS, means SUSPEND */
|
||||
DWC3_LINK_STATE_SS_DIS = 0x04,
|
||||
DWC3_LINK_STATE_RX_DET = 0x05, /* in HS, means Early Suspend */
|
||||
DWC3_LINK_STATE_SS_INACT = 0x06,
|
||||
DWC3_LINK_STATE_POLL = 0x07,
|
||||
DWC3_LINK_STATE_RECOV = 0x08,
|
||||
DWC3_LINK_STATE_HRESET = 0x09,
|
||||
DWC3_LINK_STATE_CMPLY = 0x0a,
|
||||
DWC3_LINK_STATE_LPBK = 0x0b,
|
||||
DWC3_LINK_STATE_RESET = 0x0e,
|
||||
DWC3_LINK_STATE_RESUME = 0x0f,
|
||||
DWC3_LINK_STATE_MASK = 0x0f,
|
||||
};
|
||||
|
||||
|
||||
/* TRB Length, PCM and Status */
|
||||
#define DWC3_TRB_SIZE_MASK (0x00ffffff)
|
||||
#define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK)
|
||||
#define DWC3_TRB_SIZE_PCM1(n) (((n) & 0x03) << 24)
|
||||
#define DWC3_TRB_SIZE_TRBSTS(n) (((n) & (0x0f << 28)) >> 28)
|
||||
|
||||
#define DWC3_TRBSTS_OK 0
|
||||
#define DWC3_TRBSTS_MISSED_ISOC 1
|
||||
#define DWC3_TRBSTS_SETUP_PENDING 2
|
||||
#define DWC3_TRB_STS_XFER_IN_PROG 4
|
||||
|
||||
/* TRB Control */
|
||||
#define DWC3_TRB_CTRL_HWO (1 << 0)
|
||||
#define DWC3_TRB_CTRL_LST (1 << 1)
|
||||
#define DWC3_TRB_CTRL_CHN (1 << 2)
|
||||
#define DWC3_TRB_CTRL_CSP (1 << 3)
|
||||
#define DWC3_TRB_CTRL_TRBCTL(n) (((n) & 0x3f) << 4)
|
||||
#define DWC3_TRB_CTRL_ISP_IMI (1 << 10)
|
||||
#define DWC3_TRB_CTRL_IOC (1 << 11)
|
||||
#define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14)
|
||||
|
||||
#define DWC3_TRBCTL_NORMAL DWC3_TRB_CTRL_TRBCTL(1)
|
||||
#define DWC3_TRBCTL_CONTROL_SETUP DWC3_TRB_CTRL_TRBCTL(2)
|
||||
#define DWC3_TRBCTL_CONTROL_STATUS2 DWC3_TRB_CTRL_TRBCTL(3)
|
||||
#define DWC3_TRBCTL_CONTROL_STATUS3 DWC3_TRB_CTRL_TRBCTL(4)
|
||||
#define DWC3_TRBCTL_CONTROL_DATA DWC3_TRB_CTRL_TRBCTL(5)
|
||||
#define DWC3_TRBCTL_ISOCHRONOUS_FIRST DWC3_TRB_CTRL_TRBCTL(6)
|
||||
#define DWC3_TRBCTL_ISOCHRONOUS DWC3_TRB_CTRL_TRBCTL(7)
|
||||
#define DWC3_TRBCTL_LINK_TRB DWC3_TRB_CTRL_TRBCTL(8)
|
||||
|
||||
|
||||
struct dwc3_trb {
|
||||
uint32_t bpl;
|
||||
uint32_t bph;
|
||||
uint32_t size;
|
||||
uint32_t ctrl;
|
||||
} __packed;
|
||||
|
||||
|
||||
/**
|
||||
* dwc3_hwparams - copy of HWPARAMS registers
|
||||
* @hwparams0 - GHWPARAMS0
|
||||
* @hwparams1 - GHWPARAMS1
|
||||
* @hwparams2 - GHWPARAMS2
|
||||
* @hwparams3 - GHWPARAMS3
|
||||
* @hwparams4 - GHWPARAMS4
|
||||
* @hwparams5 - GHWPARAMS5
|
||||
* @hwparams6 - GHWPARAMS6
|
||||
* @hwparams7 - GHWPARAMS7
|
||||
* @hwparams8 - GHWPARAMS8
|
||||
*/
|
||||
struct dwc3_hwparams {
|
||||
uint32_t hwparams0;
|
||||
uint32_t hwparams1;
|
||||
uint32_t hwparams2;
|
||||
uint32_t hwparams3;
|
||||
uint32_t hwparams4;
|
||||
uint32_t hwparams5;
|
||||
uint32_t hwparams6;
|
||||
uint32_t hwparams7;
|
||||
uint32_t hwparams8;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* HWPARAMS0 */
|
||||
#define DWC3_MODE(n) ((n) & 0x7)
|
||||
|
||||
#define DWC3_MDWIDTH(n) (((n) & 0xff00) >> 8)
|
||||
|
||||
/* HWPARAMS1 */
|
||||
#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15)
|
||||
|
||||
/* HWPARAMS3 */
|
||||
#define DWC3_NUM_IN_EPS_MASK (0x1f << 18)
|
||||
#define DWC3_NUM_EPS_MASK (0x3f << 12)
|
||||
#define DWC3_NUM_EPS(p) (((p)->hwparams3 & \
|
||||
(DWC3_NUM_EPS_MASK)) >> 12)
|
||||
#define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \
|
||||
(DWC3_NUM_IN_EPS_MASK)) >> 18)
|
||||
|
||||
/* HWPARAMS7 */
|
||||
#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
|
||||
|
||||
struct dwc3_request {
|
||||
struct usb_request request;
|
||||
usb_slist_t list;
|
||||
struct dwc3_ep *dep;
|
||||
uint32_t start_slot;
|
||||
|
||||
uint8_t epnum;
|
||||
struct dwc3_trb *trb;
|
||||
uintptr_t trb_dma;
|
||||
|
||||
unsigned direction:1;
|
||||
unsigned mapped:1;
|
||||
unsigned queued:1;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* struct dwc3_scratchpad_array - hibernation scratchpad array
|
||||
* (format defined by hw)
|
||||
*/
|
||||
struct dwc3_scratchpad_array {
|
||||
/* dma_addr should be little end. */
|
||||
uintptr_t dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
|
||||
};
|
||||
|
||||
|
||||
struct dwc3 {
|
||||
struct usb_ctrlrequest *ctrl_req;
|
||||
struct dwc3_trb *ep0_trb;
|
||||
void *ep0_bounce;
|
||||
void *scratchbuf;
|
||||
uint8_t *setup_buf;
|
||||
uintptr_t ctrl_req_addr;
|
||||
uintptr_t ep0_trb_addr;
|
||||
uintptr_t ep0_bounce_addr;
|
||||
uintptr_t scratch_addr;
|
||||
struct dwc3_request ep0_usb_req;
|
||||
|
||||
/* The id is USB3_0 or USB3_1 */
|
||||
uint32_t id;
|
||||
|
||||
/* device lock */
|
||||
usb_osal_mutex_t lock;
|
||||
|
||||
struct dwc3_event_buffer **ev_buffs;
|
||||
struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];
|
||||
|
||||
struct usb_gadget gadget;
|
||||
struct usb_gadget_driver *gadget_driver;
|
||||
/*
|
||||
* The regs stores the value of the DWC3 start physical address
|
||||
* Conversely, the regs_vir stores the mapped value of the regs, which can be used in the xHCI driver.
|
||||
*/
|
||||
void *regs;
|
||||
void *regs_vir;
|
||||
uint32_t regs_size;
|
||||
enum usb_dr_mode dr_mode;
|
||||
enum usb_phy_interface hsphy_mode;
|
||||
/* used for suspend/resume */
|
||||
uint32_t dcfg;
|
||||
uint32_t gctl;
|
||||
|
||||
uint32_t nr_scratch;
|
||||
uint32_t num_event_buffers;
|
||||
uint32_t u1u2;
|
||||
uint32_t maximum_speed;
|
||||
uint32_t revision;
|
||||
#define DWC3_REVISION_173A 0x5533173a
|
||||
#define DWC3_REVISION_175A 0x5533175a
|
||||
#define DWC3_REVISION_180A 0x5533180a
|
||||
#define DWC3_REVISION_183A 0x5533183a
|
||||
#define DWC3_REVISION_185A 0x5533185a
|
||||
#define DWC3_REVISION_187A 0x5533187a
|
||||
#define DWC3_REVISION_188A 0x5533188a
|
||||
#define DWC3_REVISION_190A 0x5533190a
|
||||
#define DWC3_REVISION_194A 0x5533194a
|
||||
#define DWC3_REVISION_200A 0x5533200a
|
||||
#define DWC3_REVISION_202A 0x5533202a
|
||||
#define DWC3_REVISION_210A 0x5533210a
|
||||
#define DWC3_REVISION_220A 0x5533220a
|
||||
#define DWC3_REVISION_230A 0x5533230a
|
||||
#define DWC3_REVISION_240A 0x5533240a
|
||||
#define DWC3_REVISION_250A 0x5533250a
|
||||
#define DWC3_REVISION_260A 0x5533260a
|
||||
#define DWC3_REVISION_270A 0x5533270a
|
||||
|
||||
enum dwc3_ep0_next ep0_next_event;
|
||||
enum dwc3_ep0_state ep0state;
|
||||
enum dwc3_link_state link_state;
|
||||
uint16_t isoch_delay;
|
||||
uint16_t u2sel;
|
||||
uint16_t u2pel;
|
||||
uint8_t u1sel;
|
||||
uint8_t u1pel;
|
||||
|
||||
uint8_t speed;
|
||||
|
||||
uint8_t num_out_eps;
|
||||
uint8_t num_in_eps;
|
||||
|
||||
void *mem;
|
||||
struct dwc3_hwparams hwparams;
|
||||
uint8_t test_mode;
|
||||
uint8_t test_mode_nr;
|
||||
uint8_t lpm_nyet_threshold;
|
||||
uint8_t hird_threshold;
|
||||
|
||||
uint32_t delayed_status:1;
|
||||
uint32_t ep0_bounced:1;
|
||||
uint32_t ep0_expect_in:1;
|
||||
uint32_t has_hibernation:1;
|
||||
uint32_t has_lpm_erratum:1;
|
||||
uint32_t is_utmi_l1_suspend:1;
|
||||
uint32_t is_selfpowered:1;
|
||||
uint32_t is_fpga:1;
|
||||
uint32_t needs_fifo_resize:1;
|
||||
uint32_t pullups_connected:1;
|
||||
uint32_t resize_fifos:1;
|
||||
uint32_t setup_packet_pending:1;
|
||||
uint32_t start_config_issued:1;
|
||||
uint32_t three_stage_setup:1;
|
||||
|
||||
uint32_t disable_scramble_quirk:1;
|
||||
uint32_t u2exit_lfps_quirk:1;
|
||||
uint32_t u2ss_inp3_quirk:1;
|
||||
uint32_t req_p1p2p3_quirk:1;
|
||||
uint32_t del_p1p2p3_quirk:1;
|
||||
uint32_t del_phy_power_chg_quirk:1;
|
||||
uint32_t lfps_filter_quirk:1;
|
||||
uint32_t rx_detect_poll_quirk:1;
|
||||
uint32_t dis_u3_susphy_quirk:1;
|
||||
uint32_t dis_u2_susphy_quirk:1;
|
||||
uint32_t dis_u1u2_quirk:1;
|
||||
uint32_t dis_enblslpm_quirk:1;
|
||||
uint32_t dis_u2_freeclk_exists_quirk:1;
|
||||
|
||||
uint32_t tx_de_emphasis_quirk:1;
|
||||
uint32_t tx_de_emphasis:2;
|
||||
uint32_t usb2_phyif_utmi_width:5;
|
||||
int index;
|
||||
usb_slist_t list;
|
||||
};
|
||||
|
||||
struct dwc3_event_type {
|
||||
uint32_t is_devspec:1;
|
||||
uint32_t type:7;
|
||||
uint32_t reserved8_31:24;
|
||||
} __packed;
|
||||
|
||||
#define DWC3_DEPEVT_XFERCOMPLETE 0x01
|
||||
#define DWC3_DEPEVT_XFERINPROGRESS 0x02
|
||||
#define DWC3_DEPEVT_XFERNOTREADY 0x03
|
||||
#define DWC3_DEPEVT_RXTXFIFOEVT 0x04
|
||||
#define DWC3_DEPEVT_STREAMEVT 0x06
|
||||
#define DWC3_DEPEVT_EPCMDCMPLT 0x07
|
||||
|
||||
static inline const char *dwc3_ep_event_string(uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case DWC3_DEPEVT_XFERCOMPLETE:
|
||||
return "Transfer Complete";
|
||||
case DWC3_DEPEVT_XFERINPROGRESS:
|
||||
return "Transfer In-Progress";
|
||||
case DWC3_DEPEVT_XFERNOTREADY:
|
||||
return "Transfer Not Ready";
|
||||
case DWC3_DEPEVT_RXTXFIFOEVT:
|
||||
return "FIFO";
|
||||
case DWC3_DEPEVT_STREAMEVT:
|
||||
return "Stream";
|
||||
case DWC3_DEPEVT_EPCMDCMPLT:
|
||||
return "Endpoint Command Complete";
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
struct dwc3_event_depevt {
|
||||
uint32_t one_bit:1;
|
||||
uint32_t endpoint_number:5;
|
||||
uint32_t endpoint_event:4;
|
||||
uint32_t reserved11_10:2;
|
||||
uint32_t status:4;
|
||||
|
||||
/* Within XferNotReady */
|
||||
#define DEPEVT_STATUS_TRANSFER_ACTIVE (1 << 3)
|
||||
|
||||
/* Within XferComplete */
|
||||
#define DEPEVT_STATUS_BUSERR (1 << 0)
|
||||
#define DEPEVT_STATUS_SHORT (1 << 1)
|
||||
#define DEPEVT_STATUS_IOC (1 << 2)
|
||||
#define DEPEVT_STATUS_LST (1 << 3)
|
||||
|
||||
/* Stream event only */
|
||||
#define DEPEVT_STREAMEVT_FOUND 1
|
||||
#define DEPEVT_STREAMEVT_NOTFOUND 2
|
||||
|
||||
/* Control-only Status */
|
||||
#define DEPEVT_STATUS_CONTROL_DATA 1
|
||||
#define DEPEVT_STATUS_CONTROL_STATUS 2
|
||||
|
||||
uint32_t parameters:16;
|
||||
} __packed;
|
||||
|
||||
|
||||
/**
|
||||
* struct dwc3_event_devt - Device Events
|
||||
* @one_bit: indicates this is a non-endpoint event (not used)
|
||||
* @device_event: indicates it's a device event. Should read as 0x00
|
||||
* @type: indicates the type of device event.
|
||||
* 0 - DisconnEvt
|
||||
* 1 - USBRst
|
||||
* 2 - ConnectDone
|
||||
* 3 - ULStChng
|
||||
* 4 - WkUpEvt
|
||||
* 5 - Reserved
|
||||
* 6 - EOPF
|
||||
* 7 - SOF
|
||||
* 8 - Reserved
|
||||
* 9 - ErrticErr
|
||||
* 10 - CmdCmplt
|
||||
* 11 - EvntOverflow
|
||||
* 12 - VndrDevTstRcved
|
||||
* @reserved15_12: Reserved, not used
|
||||
* @event_info: Information about this event
|
||||
* @reserved31_25: Reserved, not used
|
||||
*/
|
||||
struct dwc3_event_devt {
|
||||
uint32_t one_bit:1;
|
||||
uint32_t device_event:7;
|
||||
uint32_t type:4;
|
||||
uint32_t reserved15_12:4;
|
||||
uint32_t event_info:9;
|
||||
uint32_t reserved31_25:7;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct dwc3_event_gevt - Other Core Events
|
||||
* @one_bit: indicates this is a non-endpoint event (not used)
|
||||
* @device_event: indicates it's (0x03) Carkit or (0x04) I2C event.
|
||||
* @phy_port_number: self-explanatory
|
||||
* @reserved31_12: Reserved, not used.
|
||||
*/
|
||||
struct dwc3_event_gevt {
|
||||
uint32_t one_bit:1;
|
||||
uint32_t device_event:7;
|
||||
uint32_t phy_port_number:4;
|
||||
uint32_t reserved31_12:20;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* union dwc3_event - representation of Event Buffer contents
|
||||
* @raw: raw 32-bit event
|
||||
* @type: the type of the event
|
||||
* @depevt: Device Endpoint Event
|
||||
* @devt: Device Event
|
||||
* @gevt: Global Event
|
||||
*/
|
||||
union dwc3_event {
|
||||
uint32_t raw;
|
||||
struct dwc3_event_type type;
|
||||
struct dwc3_event_depevt depevt;
|
||||
struct dwc3_event_devt devt;
|
||||
struct dwc3_event_gevt gevt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dwc3_gadget_ep_cmd_params - representation of endpoint command
|
||||
* parameters
|
||||
* @param2: third parameter
|
||||
* @param1: second parameter
|
||||
* @param0: first parameter
|
||||
*/
|
||||
struct dwc3_gadget_ep_cmd_params {
|
||||
uint32_t param2;
|
||||
uint32_t param1;
|
||||
uint32_t param0;
|
||||
};
|
||||
|
||||
/*
|
||||
* DWC3 Features to be used as Driver Data
|
||||
*/
|
||||
|
||||
#define DWC3_HAS_PERIPHERAL BIT(0)
|
||||
#define DWC3_HAS_XHCI BIT(1)
|
||||
#define DWC3_HAS_OTG BIT(3)
|
||||
|
||||
void dwc3_of_parse(struct dwc3 *dwc);
|
||||
|
||||
enum usb_phy_interface usb_get_phy_mode(uint32_t id);
|
||||
|
||||
int dwc3_setup_phy(void *dev, struct phy **array, int *num_phys);
|
||||
|
||||
int dwc3_init(struct dwc3 *dwc);
|
||||
|
||||
void dwc3_cache_hwparams(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_core_init(struct dwc3 *dwc);
|
||||
|
||||
void dwc3_core_exit(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_core_soft_reset(struct dwc3 *dwc);
|
||||
|
||||
void dwc3_core_num_eps(struct dwc3 *dwc);
|
||||
|
||||
void dwc3_phy_setup(struct dwc3 *dwc);
|
||||
|
||||
void dwc3_hsphy_mode_setup(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_alloc_scratch_buffers(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_setup_scratch_buffers(struct dwc3 *dwc);
|
||||
|
||||
void dwc3_free_scratch_buffers(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_alloc_event_buffers(struct dwc3 *dwc, uint32_t length);
|
||||
|
||||
struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length);
|
||||
|
||||
void dwc3_free_event_buffers(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_event_buffers_setup(struct dwc3 *dwc);
|
||||
|
||||
void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
|
||||
|
||||
|
||||
int dwc3_core_init_mode(struct dwc3 *dwc);
|
||||
|
||||
void dwc3_set_mode(struct dwc3 *dwc, uint32_t mode);
|
||||
|
||||
int dwc3_host_init(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, uint32_t param);
|
||||
|
||||
void dwc3_dump(struct dwc3 *dwc);
|
||||
|
||||
static inline uint32_t dwc3_readl(void *base, uint32_t offset){
|
||||
uintptr_t offs = offset - DWC3_GLOBALS_REGS_START;
|
||||
uint32_t value;
|
||||
value = readl(base + offs);
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void dwc3_writel(void *base, uint32_t offset, uint32_t value){
|
||||
unsigned long offs = offset - DWC3_GLOBALS_REGS_START;
|
||||
writel(value, base + offs);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,126 @@
|
|||
#ifndef GADGET_H_
|
||||
#define GADGET_H_
|
||||
|
||||
#include <strings.h>
|
||||
#include <stdint.h>
|
||||
#include "usbh_core.h"
|
||||
#include "usb_list.h"
|
||||
|
||||
|
||||
struct usb_ctrlrequest;
|
||||
struct usb_ep;
|
||||
struct usb_ep_caps;
|
||||
struct usb_ep_ops;
|
||||
struct usb_gadget;
|
||||
struct usb_gadget_driver;
|
||||
struct usb_ss_ep_comp_descriptor;
|
||||
|
||||
|
||||
|
||||
struct usb_ctrlrequest {
|
||||
uint8_t bRequestType;
|
||||
uint8_t bRequest;
|
||||
uint8_t wValue;
|
||||
/* wIndex and wLength should be little end. */
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct usb_ep_caps {
|
||||
uint8_t type_control:1;
|
||||
uint8_t type_iso:1;
|
||||
uint8_t type_bulk:1;
|
||||
uint8_t type_int:1;
|
||||
uint8_t dir_in:1;
|
||||
uint8_t dir_out:1;
|
||||
};
|
||||
|
||||
struct usb_ep {
|
||||
void *driver_data;
|
||||
const char *name;
|
||||
const struct usb_ep_ops *ops;
|
||||
usb_slist_t ep_list;
|
||||
struct usb_ep_caps caps;
|
||||
uint32_t maxpacket:16;
|
||||
uint32_t maxpacket_limit:16;
|
||||
uint32_t max_streams:16;
|
||||
uint32_t maxburst:5;
|
||||
/* usb_endpoint_descriptor is included in usb_def.h header files*/
|
||||
const struct usb_endpoint_descriptor *desc;
|
||||
const struct usb_ss_ep_comp_descriptor *comp_desc;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct usb_gadget_ops {
|
||||
int (*get_frame)(struct usb_gadget *);
|
||||
int (*wakeup)(struct usb_gadget *);
|
||||
int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
|
||||
int (*vbus_draw) (struct usb_gadget *, unsigned mA);
|
||||
int (*pullup) (struct usb_gadget *, int is_on);
|
||||
int (*ioctl)(struct usb_gadget *,
|
||||
unsigned code, unsigned long param);
|
||||
int (*udc_start)(struct usb_gadget *,
|
||||
struct usb_gadget_driver *);
|
||||
int (*udc_stop)(struct usb_gadget *);
|
||||
struct usb_ep *(*match_ep)(struct usb_gadget *,
|
||||
struct usb_endpoint_descriptor *,
|
||||
struct usb_ss_ep_comp_descriptor *);
|
||||
void (*udc_set_speed)(struct usb_gadget *gadget,
|
||||
int usb_device_speed);
|
||||
};
|
||||
|
||||
struct usb_gadget_driver {
|
||||
char *function;
|
||||
int speed;
|
||||
int (*bind)(struct usb_gadget *);
|
||||
void (*unbind)(struct usb_gadget *);
|
||||
int (*setup)(struct usb_gadget *,
|
||||
const struct usb_ctrlrequest *);
|
||||
void (*disconnect)(struct usb_gadget *);
|
||||
void (*suspend)(struct usb_gadget *);
|
||||
void (*resume)(struct usb_gadget *);
|
||||
void (*reset)(struct usb_gadget *);
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct usb_gadget {
|
||||
int speed;
|
||||
int max_speed;
|
||||
int state;
|
||||
uint8_t is_dualspeed:1;
|
||||
uint8_t is_otg:1;
|
||||
uint8_t is_a_peripheral:1;
|
||||
uint8_t b_hnp_enable:1;
|
||||
uint8_t a_hnp_support:1;
|
||||
uint8_t a_alt_hnp_support:1;
|
||||
uint8_t quirk_ep_out_aligned_size:1;
|
||||
const char *name;
|
||||
void *dev;
|
||||
};
|
||||
|
||||
|
||||
struct usb_request {
|
||||
void *buf;
|
||||
unsigned length;
|
||||
uintptr_t dma;
|
||||
|
||||
unsigned stream_id:16;
|
||||
unsigned no_interrupt:1;
|
||||
unsigned zero:1;
|
||||
unsigned short_not_ok:1;
|
||||
|
||||
void (*complete)(struct usb_ep *ep,
|
||||
struct usb_request *req);
|
||||
void *context;
|
||||
usb_slist_t list;
|
||||
|
||||
int status;
|
||||
unsigned actual;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
include $(KERNEL_ROOT)/services/drivers/usb/components/usb.mk
|
||||
|
||||
objs += usb_hc_xhci.o xhci.o
|
||||
|
||||
all: ${objs}
|
||||
@echo "generate $^"
|
||||
@mv $^ $(KERNEL_ROOT)/services/drivers/usb/components
|
||||
|
||||
%.o: %.c
|
||||
@echo "cc $^"
|
||||
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,183 @@
|
|||
/*
|
||||
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* FilePath: usb_hc_xhci.h
|
||||
* Date: 2022-07-19 09:26:25
|
||||
* LastEditTime: 2022-07-19 09:26:25
|
||||
* Description: This file is for xhci data structure definition.
|
||||
*
|
||||
* Modify History:
|
||||
* Ver Who Date Changes
|
||||
* ----- ------ -------- --------------------------------------
|
||||
* 1.0 zhugengyu 2022/9/19 init commit
|
||||
* 2.0 zhugengyu 2023/3/29 support usb3.0 device attached at roothub
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: usb_hc_xhci.h
|
||||
Description: the xhci functions to dock with the USB core layer.
|
||||
Others: take CherryUSB v0.1.2/port/xhci/usb_hc_xhci.h for references
|
||||
https://gitee.com/phytium_embedded/phytium-free-rtos-sdk/blob/master/third-party/cherryusb/port/xhci/usb_hc_xhci.h
|
||||
History:
|
||||
1. Date: 2024-06-17
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: rewrite xhci functions to dock with USB core layer, so that the xhci can unbind the USB core.
|
||||
It means the USB core can be esily dock with to other USB IP in future.
|
||||
*************************************************/
|
||||
|
||||
#ifndef USB_HC_XHCI_H_
|
||||
#define USB_HC_XHCI_H_
|
||||
|
||||
#include "xhci.h"
|
||||
#include "usbh_core.h"
|
||||
|
||||
#include "libipc.h"
|
||||
#include "libserial.h"
|
||||
#include "usyscall.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Address of USB3 host control base Register in RK3568.
|
||||
* USB3_ADDR_OFFSET_UPPER_BOUND can be found in <Rockchip RK3568 Technical Reference Manual, Revision 1.0> Part 2,
|
||||
* Table 16-1 USB3 Address Mapping.
|
||||
*/
|
||||
#define USB3_NUM 2
|
||||
#define USB3_0_ID 0
|
||||
#define USB3_1_ID 1
|
||||
#define USB3_0_BASE_ADDR 0xFCC00000
|
||||
#define USB3_1_BASE_ADDR 0xFD000000
|
||||
#define USB3_ADDR_OFFSET_UPPER_BOUND 0x08000
|
||||
/*
|
||||
* The size of all DWC3 registers (including OTG regs) is 0xC00. However, the XiZi AIOT requires the I/O memory size to be aligned to 4096.
|
||||
* So we define USB3_DWC3_ADDR_GAP as 0x01000.
|
||||
*/
|
||||
#define USB3_DWC3_ADDR_GAP 0x01000
|
||||
|
||||
#define USB3_VIRADDR_BASE 0x0000002000000000ULL
|
||||
#define USB3_0_VIRADDR_BASE USB3_VIRADDR_BASE
|
||||
#define USB3_1_VIRADDR_BASE USB3_VIRADDR_BASE + USB3_ADDR_OFFSET_UPPER_BOUND + USB3_DWC3_ADDR_GAP
|
||||
|
||||
#define USB3_0_INTERRUPT_NO 201
|
||||
#define USB3_1_INTERRUPT_NO 202
|
||||
|
||||
/**
|
||||
* @brief xHCI host controller hardware init.
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int xhci_usb_hc_init(uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Get frame number.
|
||||
*
|
||||
* @return frame number.
|
||||
*/
|
||||
uint16_t xhci_usbh_get_frame_number(void);
|
||||
/**
|
||||
* @brief control roothub.
|
||||
*
|
||||
* @param usb usb bus instance
|
||||
* @param setup setup request buffer.
|
||||
* @param buf buf for reading response or write data.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int xhci_usbh_roothub_control(struct usbh_bus *usb, struct usb_setup_packet *setup, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief get port speed.
|
||||
*
|
||||
* @param hport Hub of USB device.
|
||||
* @param port Port index.
|
||||
* @return On success will return speed, and others indicate fail.
|
||||
*/
|
||||
uint8_t xhci_usbh_get_port_speed(struct usbh_hub *hub, const uint8_t port);
|
||||
|
||||
/**
|
||||
* @brief reconfig endpoint pipe.
|
||||
*
|
||||
* @param pipe A memory allocated for pipe.
|
||||
* @param dev_addr device address.
|
||||
* @param ep_mps endpoint max packet size.
|
||||
* @param mult endpoint additional transcation
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int xhci_usbh_ep_pipe_reconfigure(struct usbh_bus *usb, usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
|
||||
|
||||
/**
|
||||
* @brief Allocate pipe for endpoint
|
||||
*
|
||||
* @param pipe A memory location provided by the caller in which to save the allocated pipe.
|
||||
* @param ep_cfg Describes the endpoint info to be allocated.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int xhci_usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg);
|
||||
|
||||
/**
|
||||
* @brief get device address.
|
||||
*
|
||||
* @param pipe A memory allocated for pipe.
|
||||
* @return On success will return device address, and others indicate fail.
|
||||
*/
|
||||
int usbh_get_xhci_devaddr(usbh_pipe_t *pipe);
|
||||
|
||||
/**
|
||||
* @brief Free a pipe in which saves endpoint info.
|
||||
*
|
||||
* @param pipe A memory location provided by the caller in which to free the allocated endpoint info.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int xhci_usbh_pipe_free(usbh_pipe_t pipe);
|
||||
|
||||
/**
|
||||
* @brief Submit a usb transfer request to an xHCI endpoint.
|
||||
*
|
||||
* If timeout is not zero, this function will be in poll transfer mode,
|
||||
* otherwise will be in async transfer mode.
|
||||
*
|
||||
* @param urb Usb request block.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int xhci_usbh_submit_urb(struct usbh_urb *urb);
|
||||
|
||||
/**
|
||||
* @brief Cancel a transfer request.
|
||||
*
|
||||
* This function will call When calls usbh_submit_urb and return -ETIMEOUT or -ESHUTDOWN.
|
||||
*
|
||||
* @param urb Usb request block.
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int xhci_usbh_kill_urb(struct usbh_urb *urb);
|
||||
|
||||
void XHCI_USBH_IRQHandler(void *param);
|
||||
|
||||
__WEAK unsigned long usb_hc_get_register_base(uint32_t id);
|
||||
|
||||
__WEAK int usb_hc_get_register_id(unsigned long base_addr);
|
||||
|
||||
__WEAK unsigned long usb_hc_get_register_vir_base(uint32_t id);
|
||||
|
||||
int bind_xhci_intr(void *para);
|
||||
int create_xhci_intr_service(void *para);
|
||||
|
||||
IPC_SERVICES(IpcXhciIntrHandler, Ipc_xhci_intr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,506 @@
|
|||
/*
|
||||
* Copyright?: (C)?2022?Phytium?Information?Technology,?Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* FilePath: xhci_reg.h
|
||||
* Date: 2022-07-19 09:26:25
|
||||
* LastEditTime: 2022-07-19 09:26:25
|
||||
* Description: ?This file is for xhci register definition.
|
||||
*
|
||||
* Modify?History:
|
||||
* Ver???Who????????Date?????????Changes
|
||||
* -----?------?????--------????--------------------------------------
|
||||
* 1.0 zhugengyu 2022/9/19 init commit
|
||||
* 2.0 zhugengyu 2023/3/29 support usb3.0 device attached at roothub
|
||||
*/
|
||||
|
||||
#ifndef XHCI_REG_H_
|
||||
#define XHCI_REG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__aarch64__)
|
||||
#define BITS_PER_LONG 64U
|
||||
#define XHCI_AARCH64
|
||||
#else
|
||||
#define BITS_PER_LONG 32U
|
||||
#define XHCI_AARCH32
|
||||
#endif
|
||||
|
||||
|
||||
#define XHCI_GENMASK(h, l) \
|
||||
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
|
||||
|
||||
#define XHCI_GENMASK_ULL(h, l) \
|
||||
(((~0ULL) - (1ULL << (l)) + 1) & \
|
||||
(~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
|
||||
|
||||
#define XHCI32_GET_BITS(x, a, b) (uint32_t)((((uint32_t)(x)) & XHCI_GENMASK(a, b)) >> b)
|
||||
#define XHCI32_SET_BITS(x, a, b) (uint32_t)((((uint32_t)(x)) << b) & XHCI_GENMASK(a, b))
|
||||
#define XHCI64_GET_BITS(x, a, b) (uint64_t)((((uint64_t)(x)) & XHCI_GENMASK_ULL(a, b)) >> b)
|
||||
#define XHCI64_SET_BITS(x, a, b) (uint64_t)((((uint64_t)(x)) << b) & XHCI_GENMASK_ULL(a, b))
|
||||
|
||||
/** Capability register length */
|
||||
#define XHCI_CAP_CAPLENGTH 0x00
|
||||
|
||||
/** Host controller interface version number */
|
||||
#define XHCI_CAP_HCIVERSION 0x02
|
||||
|
||||
/** Structural parameters 1 */
|
||||
#define XHCI_CAP_HCSPARAMS1 0x04
|
||||
|
||||
/** Number of device slots */
|
||||
#define XHCI_HCSPARAMS1_SLOTS(params) ( ( (params) >> 0 ) & 0xff )
|
||||
|
||||
/** Number of interrupters */
|
||||
#define XHCI_HCSPARAMS1_INTRS(params) ( ( (params) >> 8 ) & 0x3ff )
|
||||
|
||||
/** Number of ports */
|
||||
#define XHCI_HCSPARAMS1_PORTS(params) ( ( (params) >> 24 ) & 0xff )
|
||||
|
||||
/** Structural parameters 2 */
|
||||
#define XHCI_CAP_HCSPARAMS2 0x08
|
||||
|
||||
/** Number of page-sized scratchpad buffers */
|
||||
#define XHCI_HCSPARAMS2_SCRATCHPADS(params) \
|
||||
( ( ( (params) >> 16 ) & 0x3e0 ) | ( ( (params) >> 27 ) & 0x1f ) )
|
||||
|
||||
/** Capability parameters */
|
||||
#define XHCI_CAP_HCCPARAMS1 0x10
|
||||
|
||||
/** 64-bit addressing capability */
|
||||
#define XHCI_HCCPARAMS1_ADDR64(params) ( ( (params) >> 0 ) & 0x1 )
|
||||
|
||||
/** Context size shift */
|
||||
#define XHCI_HCCPARAMS1_CSZ_SHIFT(params) ( 5 + ( ( (params) >> 2 ) & 0x1 ) )
|
||||
|
||||
/** xHCI extended capabilities pointer */
|
||||
#define XHCI_HCCPARAMS1_XECP(params) ( ( ( (params) >> 16 ) & 0xffff ) << 2 )
|
||||
|
||||
/** Doorbell offset */
|
||||
#define XHCI_CAP_DBOFF 0x14
|
||||
|
||||
/** Runtime register space offset */
|
||||
#define XHCI_CAP_RTSOFF 0x18
|
||||
|
||||
/** xHCI extended capability ID */
|
||||
#define XHCI_XECP_ID(xecp) ( ( (xecp) >> 0 ) & 0xff )
|
||||
|
||||
/** Next xHCI extended capability pointer */
|
||||
#define XHCI_XECP_NEXT(xecp) ( ( ( (xecp) >> 8 ) & 0xff ) << 2 )
|
||||
|
||||
/** USB legacy support extended capability */
|
||||
#define XHCI_XECP_ID_LEGACY 1
|
||||
|
||||
/** USB legacy support BIOS owned semaphore */
|
||||
#define XHCI_USBLEGSUP_BIOS 0x02
|
||||
|
||||
/** USB legacy support BIOS ownership flag */
|
||||
#define XHCI_USBLEGSUP_BIOS_OWNED 0x01
|
||||
|
||||
/** USB legacy support OS owned semaphore */
|
||||
#define XHCI_USBLEGSUP_OS 0x03
|
||||
|
||||
/** USB legacy support OS ownership flag */
|
||||
#define XHCI_USBLEGSUP_OS_OWNED 0x01
|
||||
|
||||
/** USB legacy support control/status */
|
||||
#define XHCI_USBLEGSUP_CTLSTS 0x04
|
||||
|
||||
/** Supported protocol extended capability */
|
||||
#define XHCI_XECP_ID_SUPPORTED 2
|
||||
|
||||
/** Supported protocol revision */
|
||||
#define XHCI_SUPPORTED_REVISION 0x00
|
||||
|
||||
/** Supported protocol minor revision */
|
||||
#define XHCI_SUPPORTED_REVISION_VER(revision) ( ( (revision) >> 16 ) & 0xffff )
|
||||
|
||||
/** Supported protocol name */
|
||||
#define XHCI_SUPPORTED_NAME 0x04
|
||||
|
||||
/** Supported protocol ports */
|
||||
#define XHCI_SUPPORTED_PORTS 0x08
|
||||
|
||||
/** Supported protocol port offset */
|
||||
#define XHCI_SUPPORTED_PORTS_OFFSET(ports) ( ( (ports) >> 0 ) & 0xff )
|
||||
|
||||
/** Supported protocol port count */
|
||||
#define XHCI_SUPPORTED_PORTS_COUNT(ports) ( ( (ports) >> 8 ) & 0xff )
|
||||
|
||||
/** Supported protocol PSI count */
|
||||
#define XHCI_SUPPORTED_PORTS_PSIC(ports) ( ( (ports) >> 28 ) & 0x0f )
|
||||
|
||||
/** Supported protocol slot */
|
||||
#define XHCI_SUPPORTED_SLOT 0x0c
|
||||
|
||||
/** Supported protocol slot type */
|
||||
#define XHCI_SUPPORTED_SLOT_TYPE(slot) ( ( (slot) >> 0 ) & 0x1f )
|
||||
|
||||
/** Supported protocol PSI */
|
||||
#define XHCI_SUPPORTED_PSI(index) ( 0x10 + ( (index) * 4 ) )
|
||||
|
||||
/** Supported protocol PSI value */
|
||||
#define XHCI_SUPPORTED_PSI_VALUE(psi) ( ( (psi) >> 0 ) & 0x0f )
|
||||
|
||||
/** Supported protocol PSI mantissa */
|
||||
#define XHCI_SUPPORTED_PSI_MANTISSA(psi) ( ( (psi) >> 16 ) & 0xffff )
|
||||
|
||||
/** Supported protocol PSI exponent */
|
||||
#define XHCI_SUPPORTED_PSI_EXPONENT(psi) ( ( (psi) >> 4 ) & 0x03 )
|
||||
|
||||
/** Default PSI values */
|
||||
enum {
|
||||
/** Full speed (12Mbps) */
|
||||
XHCI_SPEED_FULL = 1,
|
||||
/** Low speed (1.5Mbps) */
|
||||
XHCI_SPEED_LOW = 2,
|
||||
/** High speed (480Mbps) */
|
||||
XHCI_SPEED_HIGH = 3,
|
||||
/** Super speed */
|
||||
XHCI_SPEED_SUPER = 4,
|
||||
};
|
||||
|
||||
/** USB command register */
|
||||
#define XHCI_OP_USBCMD 0x00
|
||||
|
||||
/** Run/stop */
|
||||
#define XHCI_USBCMD_RUN 0x00000001UL
|
||||
|
||||
/* Interrupter Enable (INTE) 1: enabled - RW */
|
||||
#define XHCI_USBCMD_INTE (1UL << 2)
|
||||
|
||||
/** Host controller reset */
|
||||
#define XHCI_USBCMD_HCRST 0x00000002UL
|
||||
|
||||
/** USB status register */
|
||||
#define XHCI_OP_USBSTS 0x04
|
||||
|
||||
/** Host controller halted */
|
||||
#define XHCI_USBSTS_HCH 0x00000001UL
|
||||
|
||||
/** Interrupt Pending (IP) */
|
||||
#define XHCI_USBSTS_EINT (1UL << 3)
|
||||
|
||||
/** Page size register */
|
||||
#define XHCI_OP_PAGESIZE 0x08
|
||||
|
||||
/** Page size */
|
||||
#define XHCI_PAGESIZE(pagesize) ( (pagesize) << 12 )
|
||||
|
||||
/** Device notifcation control register */
|
||||
#define XHCI_OP_DNCTRL 0x14
|
||||
|
||||
/** Command ring control register */
|
||||
#define XHCI_OP_CRCR 0x18
|
||||
|
||||
/** Command ring cycle state */
|
||||
#define XHCI_CRCR_RCS 0x00000001UL
|
||||
|
||||
/** Command abort */
|
||||
#define XHCI_CRCR_CA 0x00000004UL
|
||||
|
||||
/** Command ring running */
|
||||
#define XHCI_CRCR_CRR 0x00000008UL
|
||||
|
||||
/** Device context base address array pointer */
|
||||
#define XHCI_OP_DCBAAP 0x30
|
||||
|
||||
/** Configure register */
|
||||
#define XHCI_OP_CONFIG 0x38
|
||||
|
||||
/** Maximum device slots enabled */
|
||||
#define XHCI_CONFIG_MAX_SLOTS_EN(slots) ( (slots) << 0 )
|
||||
|
||||
/** Maximum device slots enabled mask */
|
||||
#define XHCI_CONFIG_MAX_SLOTS_EN_MASK \
|
||||
XHCI_CONFIG_MAX_SLOTS_EN ( 0xff )
|
||||
|
||||
/** Port status and control register */
|
||||
#define XHCI_OP_PORTSC(port) ( 0x400 - 0x10 + ( (port) << 4 ) )
|
||||
|
||||
/** Current connect status */
|
||||
#define XHCI_PORTSC_CCS 0x00000001UL
|
||||
|
||||
/** Port enabled */
|
||||
#define XHCI_PORTSC_PED 0x00000002UL
|
||||
|
||||
#define XHCI_PORTSC_OCA (1 << 3)
|
||||
|
||||
/** Port reset */
|
||||
#define XHCI_PORTSC_PR 0x00000010UL
|
||||
|
||||
/** Port link state */
|
||||
#define XHCI_PORTSC_PLS(pls) ( (pls) << 5 )
|
||||
|
||||
/** U0 state */
|
||||
#define XHCI_PORTSC_PLS_U0 XHCI_PORTSC_PLS ( 0 )
|
||||
|
||||
/** Disabled port link state */
|
||||
#define XHCI_PORTSC_PLS_DISABLED XHCI_PORTSC_PLS ( 4 )
|
||||
|
||||
/** RxDetect port link state */
|
||||
#define XHCI_PORTSC_PLS_RXDETECT XHCI_PORTSC_PLS ( 5 )
|
||||
|
||||
/** Polling state */
|
||||
#define XHCI_PORTSC_PLS_POLLING XHCI_PORTSC_PLS ( 7 )
|
||||
|
||||
/** Port link state mask */
|
||||
#define XHCI_PORTSC_PLS_MASK XHCI_PORTSC_PLS ( 0xf )
|
||||
|
||||
/** Port power */
|
||||
#define XHCI_PORTSC_PP 0x00000200UL
|
||||
|
||||
/** Time to delay after enabling power to a port */
|
||||
#define XHCI_PORT_POWER_DELAY_MS 20
|
||||
|
||||
/** Port speed ID value */
|
||||
#define XHCI_PORTSC_PSIV(portsc) ( ( (portsc) >> 10 ) & 0xf )
|
||||
|
||||
/** Port indicator control */
|
||||
#define XHCI_PORTSC_PIC(indicators) ( (indicators) << 14 )
|
||||
|
||||
/** Port indicator control mask */
|
||||
#define XHCI_PORTSC_PIC_MASK XHCI_PORTSC_PIC ( 3 )
|
||||
|
||||
/** Port link state write strobe */
|
||||
#define XHCI_PORTSC_LWS 0x00010000UL
|
||||
|
||||
/** Time to delay after writing the port link state */
|
||||
#define XHCI_LINK_STATE_DELAY_MS 100
|
||||
|
||||
/** Connect status change */
|
||||
#define XHCI_PORTSC_CSC (1 << 17)
|
||||
|
||||
/** Port enabled/disabled change */
|
||||
#define XHCI_PORTSC_PEC (1 << 18)
|
||||
|
||||
/** Warm port reset change */
|
||||
#define XHCI_PORTSC_WRC (1 << 19)
|
||||
|
||||
/** Over-current change */
|
||||
#define XHCI_PORTSC_OCC (1 << 20)
|
||||
|
||||
/** Port reset change */
|
||||
#define XHCI_PORTSC_PRC (1 << 21)
|
||||
|
||||
/** Port link state change */
|
||||
#define XHCI_PORTSC_PLC (1 << 22)
|
||||
|
||||
/** Port config error change */
|
||||
#define XHCI_PORTSC_CEC (1 << 23)
|
||||
|
||||
/* Cold Attach Status 1: Far-end Receiver Terminations were detected */
|
||||
#define XHCI_PORTSC_CAS (1 << 24)
|
||||
|
||||
/* Wake on Connect Enable 1: enable port to be sensitive to device connects */
|
||||
#define XHCI_PORTSC_WCE (1 << 25)
|
||||
|
||||
/* Wake on Disconnect Enable 1: enable port to be sensitive to device disconnects */
|
||||
#define XHCI_PORTSC_WDE (1 << 26)
|
||||
|
||||
/* Wake on Over-current Enable 1: enable port to be sensitive to over-current conditions */
|
||||
#define XHCI_PORTSC_WOE (1 << 27)
|
||||
|
||||
/* Device Removable, 0: Device is removable. 1: Device is non-removable */
|
||||
#define XHCI_PORTSC_DR (1 << 30)
|
||||
|
||||
/* Warm Port Reset 1: follow Warm Reset sequence */
|
||||
#define XHCI_PORTSC_WPR (1 << 31)
|
||||
|
||||
/** Port status change mask */
|
||||
#define XHCI_PORTSC_CHANGE \
|
||||
( XHCI_PORTSC_CSC | XHCI_PORTSC_PEC | XHCI_PORTSC_WRC | \
|
||||
XHCI_PORTSC_OCC | XHCI_PORTSC_PRC | XHCI_PORTSC_PLC | \
|
||||
XHCI_PORTSC_CEC )
|
||||
|
||||
#define XHCI_PORTSC_RW_MASK (XHCI_PORTSC_PR | XHCI_PORTSC_PLS_MASK | XHCI_PORTSC_PP \
|
||||
| XHCI_PORTSC_PIC_MASK | XHCI_PORTSC_LWS | XHCI_PORTSC_WCE \
|
||||
| XHCI_PORTSC_WDE | XHCI_PORTSC_WOE)
|
||||
|
||||
/** Port status and control bits which should be preserved
|
||||
*
|
||||
* The port status and control register is a horrendous mix of
|
||||
* differing semantics. Some bits are written to only when a separate
|
||||
* write strobe bit is set. Some bits should be preserved when
|
||||
* modifying other bits. Some bits will be cleared if written back as
|
||||
* a one. Most excitingly, the "port enabled" bit has the semantics
|
||||
* that 1=enabled, 0=disabled, yet writing a 1 will disable the port.
|
||||
*/
|
||||
#define XHCI_PORTSC_PRESERVE ( XHCI_PORTSC_PP | XHCI_PORTSC_PIC_MASK )
|
||||
|
||||
/** Port power management status and control register */
|
||||
#define XHCI_OP_PORTPMSC(port) ( 0x404 - 0x10 + ( (port) << 4 ) )
|
||||
|
||||
/** Port link info register */
|
||||
#define XHCI_OP_PORTLI(port) ( 0x408 - 0x10 + ( (port) << 4 ) )
|
||||
|
||||
/** Port hardware link power management control register */
|
||||
#define XHCI_OP_PORTHLPMC(port) ( 0x40c - 0x10 + ( (port) << 4 ) )
|
||||
|
||||
/* Doorbell registers are 32 bits in length */
|
||||
#define XHCI_REG_DB_SIZE 4
|
||||
|
||||
/** Interrupter Management Register */
|
||||
#define XHCI_RUN_IR_IMAN(intr) ( 0x20 + ( (intr) << 5 ) )
|
||||
|
||||
/* Interrupt Pending, 1: an interrupt is pending for this Interrupter */
|
||||
#define XHCI_RUN_IR_IMAN_IP (1 << 0)
|
||||
|
||||
/* Interrupt Enable, 1: capable of generating an interrupt. */
|
||||
#define XHCI_RUN_IR_IMAN_IE (1 << 1)
|
||||
|
||||
/** Interrupter Moderation Register */
|
||||
#define XHCI_RUN_IR_IMOD(intr) ( 0x24 + ( (intr) << 5 ) )
|
||||
|
||||
/** Event ring segment table size register */
|
||||
#define XHCI_RUN_ERSTSZ(intr) ( 0x28 + ( (intr) << 5 ) )
|
||||
|
||||
/** Event ring segment table base address register */
|
||||
#define XHCI_RUN_ERSTBA(intr) ( 0x30 + ( (intr) << 5 ) )
|
||||
|
||||
/** Event ring dequeue pointer register */
|
||||
#define XHCI_RUN_ERDP(intr) ( 0x38 + ( (intr) << 5 ) )
|
||||
|
||||
/** Event Handler Busy */
|
||||
#define XHCI_RUN_ERDP_EHB (1 << 3)
|
||||
|
||||
/** Minimum alignment required for data structures
|
||||
*
|
||||
* With the exception of the scratchpad buffer pages (which are
|
||||
* page-aligned), data structures used by xHCI generally require from
|
||||
* 16 to 64 byte alignment and must not cross an (xHCI) page boundary.
|
||||
* We simplify this requirement by aligning each structure on its own
|
||||
* size, with a minimum of a 64 byte alignment.
|
||||
*/
|
||||
#define XHCI_MIN_ALIGN 64
|
||||
|
||||
/** Maximum transfer size */
|
||||
#define XHCI_MTU 65536
|
||||
|
||||
/** Read/Write Data Barrier for ARM */
|
||||
#define BARRIER() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
#ifdef XHCI_AARCH64
|
||||
#define DSB() __asm__ __volatile__("dsb sy": : : "memory")
|
||||
// #define DSB() __asm__ volatile("dsb ish\n\t")
|
||||
#else
|
||||
#define DSB() __asm__ __volatile__("dsb": : : "memory")
|
||||
// #define DSB() __asm__ volatile("dsb ish\n\t")
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Read byte from memory-mapped device
|
||||
*
|
||||
* @v io_addr I/O address
|
||||
* @ret data Value read
|
||||
*/
|
||||
static inline uint8_t readb(void *io_addr ) {
|
||||
uint8_t val = *(volatile const uint8_t *)io_addr;
|
||||
BARRIER();
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 16-bit word from memory-mapped device
|
||||
*
|
||||
* @v io_addr I/O address
|
||||
* @ret data Value read
|
||||
*/
|
||||
static inline uint16_t readw(void * io_addr ) {
|
||||
uint16_t val = *(volatile const uint16_t *)io_addr;
|
||||
BARRIER();
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 32-bit dword from memory-mapped device
|
||||
*
|
||||
* @v io_addr I/O address
|
||||
* @ret data Value read
|
||||
*/
|
||||
static inline uint32_t readl(void * io_addr ) {
|
||||
uint32_t val = *(volatile const uint32_t *)io_addr;
|
||||
BARRIER();
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 64-bit qword from memory-mapped device
|
||||
*
|
||||
* @v io_addr I/O address
|
||||
* @ret data Value read
|
||||
*/
|
||||
static inline uint64_t readq(void * io_addr ) {
|
||||
uint64_t val = *(volatile const uint64_t *)io_addr;
|
||||
BARRIER();
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write byte to memory-mapped device
|
||||
*
|
||||
* @v data Value to write
|
||||
* @v io_addr I/O address
|
||||
*/
|
||||
static inline void writeb(uint8_t data, void * io_addr ) {
|
||||
BARRIER();
|
||||
*(volatile uint8_t *)io_addr = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 16-bit word to memory-mapped device
|
||||
*
|
||||
* @v data Value to write
|
||||
* @v io_addr I/O address
|
||||
*/
|
||||
static inline void writew(uint16_t data, void * io_addr ) {
|
||||
BARRIER();
|
||||
*(volatile uint16_t *)io_addr = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 32-bit dword to memory-mapped device
|
||||
*
|
||||
* @v data Value to writed
|
||||
* @v io_addr I/O address
|
||||
*/
|
||||
static inline void writel(uint32_t data, void * io_addr ) {
|
||||
BARRIER();
|
||||
*(volatile uint32_t *)io_addr = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 64-bit qword to memory-mapped device
|
||||
*
|
||||
* @v data Value to write
|
||||
* @v io_addr I/O address
|
||||
*/
|
||||
static inline void writeq(uint64_t data, void * io_addr ) {
|
||||
BARRIER();
|
||||
*(volatile uint64_t *)io_addr = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byte-order converter for ARM-Little-End
|
||||
*/
|
||||
#define CPU_TO_LE64(x) ((uint64_t)(x))
|
||||
#define LE64_to_CPU(x) ((uint64_t)(x))
|
||||
#define CPU_TO_LE32(x) ((uint32_t)(x))
|
||||
#define LE32_TO_CPU(x) ((uint32_t)(x))
|
||||
#define CPU_TO_LE16(x) ((uint16_t)(x))
|
||||
#define LE16_TO_CPU(x) ((uint16_t)(x))
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,19 @@ user_ldflags = --start-group,-lgcc,-lc,--end-group
|
|||
cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
|
||||
#cflags = -Wall -g -std=c11
|
||||
endif
|
||||
ifeq ($(BOARD), ok1028a-c)
|
||||
toolchain ?= aarch64-none-elf-
|
||||
user_ldflags = -N -Ttext 0
|
||||
cflags = -Wall -g -std=c11 -mtune=cortex-a72 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
|
||||
board_specs = $(KERNEL_ROOT)/services/app/stub.o
|
||||
endif
|
||||
ifeq ($(BOARD), 3568)
|
||||
toolchain ?= aarch64-none-elf-
|
||||
user_ldflags = -N -Ttext 0
|
||||
cflags = -Wall -g -std=c11 -mtune=cortex-a55 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
|
||||
board_specs = $(KERNEL_ROOT)/services/app/stub.o
|
||||
endif
|
||||
|
||||
cc = ${toolchain}gcc
|
||||
ld = ${toolchain}g++
|
||||
objdump = ${toolchain}objdump
|
||||
|
@ -16,21 +29,30 @@ objdump = ${toolchain}objdump
|
|||
c_useropts = -O0
|
||||
|
||||
|
||||
INC_DIR = -I$(KERNEL_ROOT)/services/drivers/usb/components \
|
||||
INC_DIR = -I$(KERNEL_ROOT)/services/drivers/usb/ \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/ \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/class \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/class \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/class/cdc \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/class/hub \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/class/wireless \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/common \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/core \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/dev \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/dev/rk3568 \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/mem \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/osal \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/port \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/port/dwc3 \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/port/xhci \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/components/usb_phy \
|
||||
-I$(KERNEL_ROOT)/services/drivers/usb/usb_service \
|
||||
-I$(KERNEL_ROOT)/services//semaphore \
|
||||
-I$(KERNEL_ROOT)/services/lib/ipc \
|
||||
-I$(KERNEL_ROOT)/services/lib/memory \
|
||||
-I$(KERNEL_ROOT)/services/lib/serial \
|
||||
-I$(KERNEL_ROOT)/services/lib/usyscall \
|
||||
-I$(KERNEL_ROOT)/services/net/libnet \
|
||||
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
|
||||
-I$(KERNEL_ROOT)/services/app
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
include $(KERNEL_ROOT)/services/drivers/usb/components/usb.mk
|
||||
|
||||
objs += usb_phy.o
|
||||
|
||||
all: ${objs}
|
||||
@echo "generate $^"
|
||||
@mv $^ $(KERNEL_ROOT)/services/drivers/usb/components
|
||||
|
||||
%.o: %.c
|
||||
@echo "cc $^"
|
||||
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^
|
|
@ -0,0 +1,12 @@
|
|||
#include "usb_phy.h"
|
||||
|
||||
|
||||
int generic_phy_init(struct phy *phy){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int generic_phy_power_on(struct phy *phy){
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,515 @@
|
|||
#ifndef USB_PHY_H_
|
||||
#define USB_PHY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
enum phy_mode {
|
||||
PHY_MODE_INVALID,
|
||||
PHY_MODE_DP,
|
||||
};
|
||||
|
||||
|
||||
struct phy_attrs {
|
||||
uint32_t bus_width;
|
||||
uint32_t max_link_rate;
|
||||
enum phy_mode mode;
|
||||
};
|
||||
|
||||
|
||||
struct phy {
|
||||
void *dev;
|
||||
uint32_t id;
|
||||
struct phy_attrs attrs;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct phy_configure_opts_mipi_dphy {
|
||||
/**
|
||||
* @clk_miss:
|
||||
*
|
||||
* Timeout, in picoseconds, for receiver to detect absence of
|
||||
* Clock transitions and disable the Clock Lane HS-RX.
|
||||
*
|
||||
* Maximum value: 60000 ps
|
||||
*/
|
||||
unsigned int clk_miss;
|
||||
|
||||
/**
|
||||
* @clk_post:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter continues to
|
||||
* send HS clock after the last associated Data Lane has
|
||||
* transitioned to LP Mode. Interval is defined as the period
|
||||
* from the end of @hs_trail to the beginning of @clk_trail.
|
||||
*
|
||||
* Minimum value: 60000 ps + 52 * @hs_clk_rate period in ps
|
||||
*/
|
||||
unsigned int clk_post;
|
||||
|
||||
/**
|
||||
* @clk_pre:
|
||||
*
|
||||
* Time, in UI, that the HS clock shall be driven by
|
||||
* the transmitter prior to any associated Data Lane beginning
|
||||
* the transition from LP to HS mode.
|
||||
*
|
||||
* Minimum value: 8 UI
|
||||
*/
|
||||
unsigned int clk_pre;
|
||||
|
||||
/**
|
||||
* @clk_prepare:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter drives the Clock
|
||||
* Lane LP-00 Line state immediately before the HS-0 Line
|
||||
* state starting the HS transmission.
|
||||
*
|
||||
* Minimum value: 38000 ps
|
||||
* Maximum value: 95000 ps
|
||||
*/
|
||||
unsigned int clk_prepare;
|
||||
|
||||
/**
|
||||
* @clk_settle:
|
||||
*
|
||||
* Time interval, in picoseconds, during which the HS receiver
|
||||
* should ignore any Clock Lane HS transitions, starting from
|
||||
* the beginning of @clk_prepare.
|
||||
*
|
||||
* Minimum value: 95000 ps
|
||||
* Maximum value: 300000 ps
|
||||
*/
|
||||
unsigned int clk_settle;
|
||||
|
||||
/**
|
||||
* @clk_term_en:
|
||||
*
|
||||
* Time, in picoseconds, for the Clock Lane receiver to enable
|
||||
* the HS line termination.
|
||||
*
|
||||
* Maximum value: 38000 ps
|
||||
*/
|
||||
unsigned int clk_term_en;
|
||||
|
||||
/**
|
||||
* @clk_trail:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter drives the HS-0
|
||||
* state after the last payload clock bit of a HS transmission
|
||||
* burst.
|
||||
*
|
||||
* Minimum value: 60000 ps
|
||||
*/
|
||||
unsigned int clk_trail;
|
||||
|
||||
/**
|
||||
* @clk_zero:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter drives the HS-0
|
||||
* state prior to starting the Clock.
|
||||
*/
|
||||
unsigned int clk_zero;
|
||||
|
||||
/**
|
||||
* @d_term_en:
|
||||
*
|
||||
* Time, in picoseconds, for the Data Lane receiver to enable
|
||||
* the HS line termination.
|
||||
*
|
||||
* Maximum value: 35000 ps + 4 * @hs_clk_rate period in ps
|
||||
*/
|
||||
unsigned int d_term_en;
|
||||
|
||||
/**
|
||||
* @eot:
|
||||
*
|
||||
* Transmitted time interval, in picoseconds, from the start
|
||||
* of @hs_trail or @clk_trail, to the start of the LP- 11
|
||||
* state following a HS burst.
|
||||
*
|
||||
* Maximum value: 105000 ps + 12 * @hs_clk_rate period in ps
|
||||
*/
|
||||
unsigned int eot;
|
||||
|
||||
/**
|
||||
* @hs_exit:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter drives LP-11
|
||||
* following a HS burst.
|
||||
*
|
||||
* Minimum value: 100000 ps
|
||||
*/
|
||||
unsigned int hs_exit;
|
||||
|
||||
/**
|
||||
* @hs_prepare:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter drives the Data
|
||||
* Lane LP-00 Line state immediately before the HS-0 Line
|
||||
* state starting the HS transmission.
|
||||
*
|
||||
* Minimum value: 40000 ps + 4 * @hs_clk_rate period in ps
|
||||
* Maximum value: 85000 ps + 6 * @hs_clk_rate period in ps
|
||||
*/
|
||||
unsigned int hs_prepare;
|
||||
|
||||
/**
|
||||
* @hs_settle:
|
||||
*
|
||||
* Time interval, in picoseconds, during which the HS receiver
|
||||
* shall ignore any Data Lane HS transitions, starting from
|
||||
* the beginning of @hs_prepare.
|
||||
*
|
||||
* Minimum value: 85000 ps + 6 * @hs_clk_rate period in ps
|
||||
* Maximum value: 145000 ps + 10 * @hs_clk_rate period in ps
|
||||
*/
|
||||
unsigned int hs_settle;
|
||||
|
||||
/**
|
||||
* @hs_skip:
|
||||
*
|
||||
* Time interval, in picoseconds, during which the HS-RX
|
||||
* should ignore any transitions on the Data Lane, following a
|
||||
* HS burst. The end point of the interval is defined as the
|
||||
* beginning of the LP-11 state following the HS burst.
|
||||
*
|
||||
* Minimum value: 40000 ps
|
||||
* Maximum value: 55000 ps + 4 * @hs_clk_rate period in ps
|
||||
*/
|
||||
unsigned int hs_skip;
|
||||
|
||||
/**
|
||||
* @hs_trail:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter drives the
|
||||
* flipped differential state after last payload data bit of a
|
||||
* HS transmission burst
|
||||
*
|
||||
* Minimum value: max(8 * @hs_clk_rate period in ps,
|
||||
* 60000 ps + 4 * @hs_clk_rate period in ps)
|
||||
*/
|
||||
unsigned int hs_trail;
|
||||
|
||||
/**
|
||||
* @hs_zero:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter drives the HS-0
|
||||
* state prior to transmitting the Sync sequence.
|
||||
*/
|
||||
unsigned int hs_zero;
|
||||
|
||||
/**
|
||||
* @init:
|
||||
*
|
||||
* Time, in picoseconds for the initialization period to
|
||||
* complete.
|
||||
*
|
||||
* Minimum value: 100000000 ps
|
||||
*/
|
||||
unsigned int init;
|
||||
|
||||
/**
|
||||
* @lpx:
|
||||
*
|
||||
* Transmitted length, in picoseconds, of any Low-Power state
|
||||
* period.
|
||||
*
|
||||
* Minimum value: 50000 ps
|
||||
*/
|
||||
unsigned int lpx;
|
||||
|
||||
/**
|
||||
* @ta_get:
|
||||
*
|
||||
* Time, in picoseconds, that the new transmitter drives the
|
||||
* Bridge state (LP-00) after accepting control during a Link
|
||||
* Turnaround.
|
||||
*
|
||||
* Value: 5 * @lpx
|
||||
*/
|
||||
unsigned int ta_get;
|
||||
|
||||
/**
|
||||
* @ta_go:
|
||||
*
|
||||
* Time, in picoseconds, that the transmitter drives the
|
||||
* Bridge state (LP-00) before releasing control during a Link
|
||||
* Turnaround.
|
||||
*
|
||||
* Value: 4 * @lpx
|
||||
*/
|
||||
unsigned int ta_go;
|
||||
|
||||
/**
|
||||
* @ta_sure:
|
||||
*
|
||||
* Time, in picoseconds, that the new transmitter waits after
|
||||
* the LP-10 state before transmitting the Bridge state
|
||||
* (LP-00) during a Link Turnaround.
|
||||
*
|
||||
* Minimum value: @lpx
|
||||
* Maximum value: 2 * @lpx
|
||||
*/
|
||||
unsigned int ta_sure;
|
||||
|
||||
/**
|
||||
* @wakeup:
|
||||
*
|
||||
* Time, in picoseconds, that a transmitter drives a Mark-1
|
||||
* state prior to a Stop state in order to initiate an exit
|
||||
* from ULPS.
|
||||
*
|
||||
* Minimum value: 1000000000 ps
|
||||
*/
|
||||
unsigned int wakeup;
|
||||
|
||||
/**
|
||||
* @hs_clk_rate:
|
||||
*
|
||||
* Clock rate, in Hertz, of the high-speed clock.
|
||||
*/
|
||||
unsigned long hs_clk_rate;
|
||||
|
||||
/**
|
||||
* @lp_clk_rate:
|
||||
*
|
||||
* Clock rate, in Hertz, of the low-power clock.
|
||||
*/
|
||||
unsigned long lp_clk_rate;
|
||||
|
||||
/**
|
||||
* @lanes:
|
||||
*
|
||||
* Number of active data lanes used for the transmissions.
|
||||
*/
|
||||
unsigned char lanes;
|
||||
};
|
||||
|
||||
|
||||
struct phy_configure_opts_dp {
|
||||
/**
|
||||
* @link_rate:
|
||||
*
|
||||
* Link Rate, in Mb/s, of the main link.
|
||||
*
|
||||
* Allowed values: 1620, 2160, 2430, 2700, 3240, 4320, 5400, 8100 Mb/s
|
||||
*/
|
||||
unsigned int link_rate;
|
||||
|
||||
/**
|
||||
* @lanes:
|
||||
*
|
||||
* Number of active, consecutive, data lanes, starting from
|
||||
* lane 0, used for the transmissions on main link.
|
||||
*
|
||||
* Allowed values: 1, 2, 4
|
||||
*/
|
||||
unsigned int lanes;
|
||||
|
||||
/**
|
||||
* @voltage:
|
||||
*
|
||||
* Voltage swing levels, as specified by DisplayPort specification,
|
||||
* to be used by particular lanes. One value per lane.
|
||||
* voltage[0] is for lane 0, voltage[1] is for lane 1, etc.
|
||||
*
|
||||
* Maximum value: 3
|
||||
*/
|
||||
unsigned int voltage[4];
|
||||
|
||||
/**
|
||||
* @pre:
|
||||
*
|
||||
* Pre-emphasis levels, as specified by DisplayPort specification, to be
|
||||
* used by particular lanes. One value per lane.
|
||||
*
|
||||
* Maximum value: 3
|
||||
*/
|
||||
unsigned int pre[4];
|
||||
|
||||
/**
|
||||
* @ssc:
|
||||
*
|
||||
* Flag indicating, whether or not to enable spread-spectrum clocking.
|
||||
*
|
||||
*/
|
||||
uint8_t ssc : 1;
|
||||
|
||||
/**
|
||||
* @set_rate:
|
||||
*
|
||||
* Flag indicating, whether or not reconfigure link rate and SSC to
|
||||
* requested values.
|
||||
*
|
||||
*/
|
||||
uint8_t set_rate : 1;
|
||||
|
||||
/**
|
||||
* @set_lanes:
|
||||
*
|
||||
* Flag indicating, whether or not reconfigure lane count to
|
||||
* requested value.
|
||||
*
|
||||
*/
|
||||
uint8_t set_lanes : 1;
|
||||
|
||||
/**
|
||||
* @set_voltages:
|
||||
*
|
||||
* Flag indicating, whether or not reconfigure voltage swing
|
||||
* and pre-emphasis to requested values. Only lanes specified
|
||||
* by "lanes" parameter will be affected.
|
||||
*
|
||||
*/
|
||||
uint8_t set_voltages : 1;
|
||||
};
|
||||
|
||||
|
||||
struct phy_configure_opts_pcie {
|
||||
bool is_bifurcation; /* Bifurcation mode support */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* union phy_configure_opts - Opaque generic phy configuration
|
||||
*
|
||||
* @mipi_dphy: Configuration set applicable for phys supporting
|
||||
* the MIPI_DPHY phy mode.
|
||||
* @dp: Configuration set applicable for phys supporting
|
||||
* the DisplayPort protocol.
|
||||
*/
|
||||
union phy_configure_opts {
|
||||
struct phy_configure_opts_mipi_dphy mipi_dphy;
|
||||
struct phy_configure_opts_dp dp;
|
||||
struct phy_configure_opts_pcie pcie;
|
||||
};
|
||||
|
||||
|
||||
struct phy_ops {
|
||||
/**
|
||||
* of_xlate - Translate a client's device-tree (OF) phy specifier.
|
||||
*
|
||||
* The PHY core calls this function as the first step in implementing
|
||||
* a client's generic_phy_get_by_*() call.
|
||||
*
|
||||
* If this function pointer is set to NULL, the PHY core will use a
|
||||
* default implementation, which assumes #phy-cells = <0> or
|
||||
* #phy-cells = <1>, and in the later case that the DT cell
|
||||
* contains a simple integer PHY port ID.
|
||||
*
|
||||
* @phy: The phy struct to hold the translation result.
|
||||
* @args: The phy specifier values from device tree.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
// int (*of_xlate)(struct phy *phy, struct ofnode_phandle_args *args);
|
||||
|
||||
/**
|
||||
* init - initialize the hardware.
|
||||
*
|
||||
* Hardware intialization should not be done in during probe() but
|
||||
* should be implemented in this init() function. It could be starting
|
||||
* PLL, taking a controller out of reset, routing, etc. This function
|
||||
* is typically called only once per PHY port.
|
||||
* If power_on() is not implemented, it must power up the phy.
|
||||
*
|
||||
* @phy: the PHY port to initialize
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*init)(struct phy *phy);
|
||||
|
||||
/**
|
||||
* exit - de-initialize the PHY device
|
||||
*
|
||||
* Hardware de-intialization should be done here. Every step done in
|
||||
* init() should be undone here.
|
||||
* This could be used to suspend the phy to reduce power consumption or
|
||||
* to put the phy in a known condition before booting the OS (though it
|
||||
* is NOT called automatically before booting the OS)
|
||||
* If power_off() is not implemented, it must power down the phy.
|
||||
*
|
||||
* @phy: PHY port to be de-initialized
|
||||
* @return 0 if OK, or a negative error code
|
||||
*/
|
||||
int (*exit)(struct phy *phy);
|
||||
|
||||
/**
|
||||
* reset - resets a PHY device without shutting down
|
||||
*
|
||||
* @phy: PHY port to be reset
|
||||
*
|
||||
* During runtime, the PHY may need to be reset in order to
|
||||
* re-establish connection etc without being shut down or exit.
|
||||
*
|
||||
* @return 0 if OK, or a negative error code
|
||||
*/
|
||||
int (*reset)(struct phy *phy);
|
||||
|
||||
/**
|
||||
* @configure:
|
||||
*
|
||||
* Optional.
|
||||
*
|
||||
* Used to change the PHY parameters. phy_init() must have
|
||||
* been called on the phy.
|
||||
*
|
||||
* Returns: 0 if successful, an negative error code otherwise
|
||||
*/
|
||||
int (*configure)(struct phy *phy, union phy_configure_opts *opts);
|
||||
|
||||
/**
|
||||
* @validate:
|
||||
*
|
||||
* Optional.
|
||||
*
|
||||
* Used to check that the current set of parameters can be
|
||||
* handled by the phy. Implementations are free to tune the
|
||||
* parameters passed as arguments if needed by some
|
||||
* implementation detail or constraints. It must not change
|
||||
* any actual configuration of the PHY, so calling it as many
|
||||
* times as deemed fit by the consumer must have no side
|
||||
* effect.
|
||||
*
|
||||
* Returns: 0 if the configuration can be applied, an negative
|
||||
* error code otherwise
|
||||
*/
|
||||
int (*validate)(struct phy *phy, enum phy_mode mode, int submode,
|
||||
union phy_configure_opts *opts);
|
||||
|
||||
/**
|
||||
* power_on - power on a PHY device
|
||||
*
|
||||
* @phy: PHY port to be powered on
|
||||
*
|
||||
* During runtime, the PHY may need to be powered on or off several
|
||||
* times. This function is used to power on the PHY. It relies on the
|
||||
* setup done in init(). If init() is not implemented, it must take care
|
||||
* of setting up the context (PLLs, ...)
|
||||
*
|
||||
* @return 0 if OK, or a negative error code
|
||||
*/
|
||||
int (*power_on)(struct phy *phy);
|
||||
|
||||
/**
|
||||
* power_off - power off a PHY device
|
||||
*
|
||||
* @phy: PHY port to be powered off
|
||||
*
|
||||
* During runtime, the PHY may need to be powered on or off several
|
||||
* times. This function is used to power off the PHY. Except if
|
||||
* init()/deinit() are not implemented, it must not de-initialize
|
||||
* everything.
|
||||
*
|
||||
* @return 0 if OK, or a negative error code
|
||||
*/
|
||||
int (*power_off)(struct phy *phy);
|
||||
|
||||
int (*set_mode)(struct phy *phy, enum phy_mode mode, int submode);
|
||||
};
|
||||
|
||||
int generic_phy_init(struct phy *phy);
|
||||
int generic_phy_power_on(struct phy *phy);
|
||||
|
||||
#endif
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef USB_CONFIG_H_
|
||||
#define USB_CONFIG_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -1,6 +0,0 @@
|
|||
#include "usb_host.h"
|
||||
|
||||
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef USB_HOST_H_
|
||||
#define USB_HOST_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,170 @@
|
|||
#ifndef USB_CONFIG_H_
|
||||
#define USB_CONFIG_H_
|
||||
|
||||
/*
|
||||
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* FilePath: usb_config.h
|
||||
* Date: 2022-09-19 17:28:44
|
||||
* LastEditTime: 2022-09-19 17:28:45
|
||||
* Description: This file is for usb hc xhci configuration.
|
||||
*
|
||||
* Modify History:
|
||||
* Ver Who Date Changes
|
||||
* ----- ------ -------- --------------------------------------
|
||||
* 1.0 zhugengyu 2022/9/19 init commit
|
||||
* 1.1 liqiaozhong 2023/2/10 update to v0.7.0
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
// void *usb_hc_malloc(size_t size);
|
||||
// void usb_hc_free();
|
||||
// void *usb_hc_malloc_align(size_t align, size_t size);
|
||||
|
||||
// #define usb_malloc(size) usb_hc_malloc(size)
|
||||
// #define usb_free(ptr) usb_hc_free(ptr)
|
||||
// #define usb_align(align, size) usb_hc_malloc_align(align, size)
|
||||
|
||||
#ifndef CONFIG_USB_DBG_LEVEL
|
||||
#define CONFIG_USB_DBG_LEVEL USB_DBG_LOG
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USB_PRINTF
|
||||
#define CONFIG_USB_PRINTF printf
|
||||
#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 max transfer buffer, specially for receiving data from ep0 out */
|
||||
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256
|
||||
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
|
||||
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 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
|
||||
|
||||
// #define CONFIG_USBHOST_GET_STRING_DESC
|
||||
#define CONFIG_USBHOST_GET_DEVICE_DESC
|
||||
|
||||
// #define CONFIG_USBDEV_MSC_THREAD
|
||||
#define CONFIG_INPUT_MOUSE_WHEEL
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#ifndef CONFIG_USBDEV_MSC_STACKSIZE
|
||||
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_PRIO
|
||||
#define CONFIG_USBDEV_MSC_PRIO 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_AUDIO_VERSION
|
||||
#define CONFIG_USBDEV_AUDIO_VERSION 0x0100
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL
|
||||
#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8
|
||||
#endif
|
||||
|
||||
|
||||
/* ================ USB HOST Stack Configuration ================== */
|
||||
|
||||
#define CONFIG_USBHOST_MAX_RHPORTS 2
|
||||
#define CONFIG_USBHOST_MAX_EXTHUBS 2
|
||||
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
||||
#define CONFIG_USBHOST_MAX_INTERFACES 6
|
||||
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
|
||||
#define CONFIG_USBHOST_DEV_NAMELEN 16
|
||||
|
||||
#ifndef CONFIG_USBHOST_PSC_PRIO
|
||||
#define CONFIG_USBHOST_PSC_PRIO 4
|
||||
#endif
|
||||
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
|
||||
#define CONFIG_USBHOST_PSC_STACKSIZE 4096
|
||||
#endif
|
||||
|
||||
/* Ep0 max transfer buffer */
|
||||
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
|
||||
|
||||
#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
|
||||
|
||||
/* do not try to enumrate one interface */
|
||||
#ifndef CONFIG_USBHOST_ENUM_FIRST_INTERFACE_ONLY
|
||||
#define CONFIG_USBHOST_ENUM_FIRST_INTERFACE_ONLY
|
||||
#endif
|
||||
|
||||
/* ================ USB Device Port Configuration ================*/
|
||||
|
||||
#define CONFIG_XHCI_PAGE_SIZE 4096U
|
||||
#define CONFIG_XHCI_PAGE_SHIFT 12U
|
||||
|
||||
/* ================ USB Host Port Configuration ==================*/
|
||||
|
||||
#define CONFIG_USBHOST_PIPE_NUM 10
|
||||
|
||||
/* ================ XHCI Configuration ================ */
|
||||
#define CONFIG_USBHOST_XHCI
|
||||
#define CONFIG_USBHOST_XHCI_NUM 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
include $(KERNEL_ROOT)/services/drivers/usb/components/usb.mk
|
||||
|
||||
objs = usb_host.o
|
||||
objs += $(KERNEL_ROOT)/services/net/libnet/lwip_rndis_service.o
|
||||
|
||||
libserial = $(KERNEL_ROOT)/services/app/libserial.o
|
||||
printf = $(KERNEL_ROOT)/services/app/printf.o
|
||||
libmem = $(KERNEL_ROOT)/services/app/libmem.o
|
||||
usyscall = $(KERNEL_ROOT)/services/app/usyscall.o
|
||||
arch_usyscall = $(KERNEL_ROOT)/services/app/arch_usyscall.o
|
||||
session = $(KERNEL_ROOT)/services/app/session.o
|
||||
libipc = $(KERNEL_ROOT)/services/app/libipc.o
|
||||
libsem = $(KERNEL_ROOT)/services/app/libsemaphore.o
|
||||
|
||||
usb_components = \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/dwc3.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/rk3568_usb.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/rndis_host.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/usb_hc_xhci.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/usb_mem.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/usb_osal.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/usb_phy.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/usbh_core.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/usbh_hub.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/usbh_rndis.o \
|
||||
$(KERNEL_ROOT)/services/drivers/usb/components/xhci.o
|
||||
|
||||
usb_driver_service: ${objs}
|
||||
@echo "generate $^"
|
||||
@${ld} ${user_ldflags} -e main -o $@ $^ ${usb_components} ${libserial} ${printf} ${libmem} ${usyscall} ${arch_usyscall} ${session} ${libipc} ${libsem} ${board_specs}
|
||||
@${objdump} -S $@ > $@.asm
|
||||
@mv $@ $(KERNEL_ROOT)/services/app
|
||||
@mv $@.asm $(KERNEL_ROOT)/services/app
|
||||
|
||||
%.o: %.c
|
||||
@echo "cc $^"
|
||||
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^
|
|
@ -0,0 +1,13 @@
|
|||
#include "libipc.h"
|
||||
#include "rndis_service.h"
|
||||
|
||||
IPC_INTERFACE(Ipc_usbh_rndis_eth_tx, 2, dataptr, tot_len, *(size_t *)tot_len, sizeof(size_t));
|
||||
int ipc_usbh_rndis_eth_tx(struct Session* session, void *dataptr, size_t tot_len){
|
||||
return IPC_CALL(Ipc_usbh_rndis_eth_tx)(session, dataptr, &tot_len);
|
||||
}
|
||||
|
||||
IPC_INTERFACE(Ipc_usbh_rndis_eth_control, 3, cmd, args, len, sizeof(int), *(size_t *)len, sizeof(size_t));
|
||||
int ipc_usbh_rndis_eth_control(struct Session* session, int cmd, void *args, size_t len){
|
||||
return IPC_CALL(Ipc_usbh_rndis_eth_control)(session, &cmd, args, &len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef RNDIS_SERVICE_H_
|
||||
#define RNDIS_SERVICE_H_
|
||||
|
||||
#include "libipc.h"
|
||||
|
||||
IPC_SERVICES(IpcRndisServer, Ipc_usbh_rndis_eth_tx, Ipc_usbh_rndis_eth_control);
|
||||
|
||||
int ipc_usbh_rndis_eth_tx(struct Session* session, void *dataptr, size_t tot_len);
|
||||
int ipc_usbh_rndis_eth_control(struct Session* session, int cmd, void *args, size_t len);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
#include "usb_host.h"
|
||||
#include "usb_mem.h"
|
||||
#include "usb_hc_xhci.h"
|
||||
#include "usyscall.h"
|
||||
#include "libipc.h"
|
||||
#include "rndis_service.h"
|
||||
#include "lwip_rndis_service.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static struct usbh_bus usb[USB3_NUM];
|
||||
|
||||
/* IPC rndis server */
|
||||
int IPC_DO_SERVE_FUNC(Ipc_usbh_rndis_eth_tx)(void *dataptr, size_t *tot_len){
|
||||
return usbh_rndis_eth_tx(dataptr, *tot_len);
|
||||
}
|
||||
|
||||
int IPC_DO_SERVE_FUNC(Ipc_usbh_rndis_eth_control)(int *cmd, void *args, size_t *len){
|
||||
return usbh_rndis_eth_control(*cmd, args, *len);
|
||||
}
|
||||
|
||||
IPC_SERVER_INTERFACE(Ipc_usbh_rndis_eth_tx, 2);
|
||||
IPC_SERVER_INTERFACE(Ipc_usbh_rndis_eth_control, 3);
|
||||
|
||||
IPC_SERVER_REGISTER_INTERFACES(IpcRndisServer, 2, Ipc_usbh_rndis_eth_tx, Ipc_usbh_rndis_eth_control);
|
||||
|
||||
int ipc_rndis_server_init(void *para)
|
||||
{
|
||||
if (register_server("RndisServer") < 0) {
|
||||
printf("register server name: %s failed.\n", "RndisServer");
|
||||
return -1;
|
||||
}
|
||||
ipc_server_loop(&IpcRndisServer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* IPC lwip client */
|
||||
struct Session *g_session_lwip = NULL;
|
||||
|
||||
int ipc_lwip_client_init(void *para)
|
||||
{
|
||||
struct Session *session;
|
||||
|
||||
session = usb_malloc(sizeof(struct Session));
|
||||
if (NULL == session) {
|
||||
printf("No memory to alloc for LWIPServer session\r\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
while (connect_session(session, "LWIPServer", 4096) < 0) {
|
||||
usb_osal_msleep(1000);
|
||||
}
|
||||
printf("connect LWIPServer session success.\r\n");
|
||||
g_session_lwip = session;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lwip_rndis_data_recv(void *dataptr, size_t len)
|
||||
{
|
||||
struct Session* session = g_session_lwip;
|
||||
return ipc_lwip_rndis_data_recv(session, dataptr, len);
|
||||
}
|
||||
|
||||
void ipc_rndis_init(void){
|
||||
int tid;
|
||||
int tid_client;
|
||||
|
||||
tid = thread(ipc_rndis_server_init, "ipc_rndis_server", NULL);
|
||||
if(tid < 0){
|
||||
printf("create thread ipc_rndis_server failed.\r\n");
|
||||
}
|
||||
|
||||
tid_client = thread(ipc_lwip_client_init, "ipc_rndis_lwip_client", NULL);
|
||||
if(tid < 0){
|
||||
printf("create thread ipc_rndis_server failed.\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_check_phymode(int id)
|
||||
{
|
||||
#define PIPE_PHY_GRF0 0xFDC70000
|
||||
#define PIPE_PHY_GRF1 0xFDC80000
|
||||
#define PIPE_PHY_GRF_PIPE_CON0 0x00
|
||||
#define PIPE_PHY_GRF_PIPE_CON3 0x0C
|
||||
#define PIPE_PHY_GRF_VIRADDR_BASE 0x0000002100000000ULL
|
||||
void *base = (void *)PIPE_PHY_GRF0;
|
||||
void *base_vir = (void *)PIPE_PHY_GRF_VIRADDR_BASE;
|
||||
uint32_t con0;
|
||||
uint32_t con3;
|
||||
|
||||
if (USB3_0_ID == id) {
|
||||
base = (void *)PIPE_PHY_GRF0;
|
||||
}
|
||||
if (USB3_1_ID == id) {
|
||||
base = (void *)PIPE_PHY_GRF1;
|
||||
}
|
||||
|
||||
if(!mmap((uintptr_t)base_vir, (uintptr_t)base, 0xFF, true)){
|
||||
USB_LOG_ERR("usb_check_phy mmap fail\n");
|
||||
}
|
||||
|
||||
con0 = readl ( base_vir + PIPE_PHY_GRF_PIPE_CON0 );
|
||||
con3 = readl ( base_vir + PIPE_PHY_GRF_PIPE_CON3 );
|
||||
USB_LOG_DBG("usb_check_phy PIPE_PHY_GRF_PIPE_CON0=%08X PIPE_PHY_GRF_PIPE_CON3=%08X\n", con0, con3);
|
||||
if ( !( (con0 & 0x000C) == 0x0004 && (con3 & 0x8000) == 0) ) {
|
||||
USB_LOG_ERR("usb_check_phy PIPE_PHY_GRF_PIPE_CON0=%08X and CON3=%08X is not USB3 mode\n", con0, con3);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_init(int id)
|
||||
{
|
||||
if (0 == usbh_initialize(id, &usb[id])){
|
||||
printf("Init cherryusb host successfully.\r\n");
|
||||
}
|
||||
else{
|
||||
printf("Init cherryusb host failed.\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* usb main*/
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int id = USB3_0_ID;
|
||||
|
||||
if (argc >= 2) {
|
||||
id = atoi(argv[1]);
|
||||
if (id >= USB3_NUM) {
|
||||
printf("Invalid usb3 id(%d).\r\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
printf("main usb3 id=%d init.\r\n", id);
|
||||
|
||||
usb_check_phymode(id);
|
||||
usb_init(id);
|
||||
#if 0 //debug
|
||||
ipc_rndis_init();
|
||||
#endif
|
||||
while (1){
|
||||
usb_osal_msleep(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue