merge 5g_usb

This commit is contained in:
TXuian 2024-11-01 10:36:51 +08:00
commit 02f6a412de
114 changed files with 45668 additions and 412 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,4 @@
SRC_DIR := hal
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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 $^

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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, &REG);
* and HAL_DBG("pinctrl: readback register %p = 0x%lx\n", &REG, 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 */

View File

@ -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 */

View File

@ -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 */
// }

View File

@ -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 = &ethConfigTable[id];
if (!eth) {
return HAL_ERROR;
}
pGMAC = &eth->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(&eth->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 = &ethConfigTable[bus];
HAL_DBG("new pGmac\n");
if (eth) {
pGMAC = &eth->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;
// }

View File

@ -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
/** @} */
/** @} */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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
/** @} */
/** @} */

View File

@ -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
/** @} */
/** @} */

View File

@ -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

View File

@ -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 */

View File

@ -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
/** @} */
/** @} */

View File

@ -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

View File

@ -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
/** @} */
/** @} */

View File

@ -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

View File

@ -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 */

View File

@ -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_ */

View File

@ -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
}
/**

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -1,4 +1,8 @@
SRC_DIR := $(BOARD)
ifeq ($(BOARD), 3568)
SRC_DIR += usb
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,3 +1,3 @@
SRC_DIR := components
SRC_DIR := components usb_service
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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

View File

@ -1,4 +1,4 @@
SRC_DIR := hub
SRC_DIR := hub wireless
include $(KERNEL_ROOT)/compiler.mk
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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_ */

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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

View File

@ -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 $^

View File

@ -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_ */
/** @} */

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -1,8 +0,0 @@
#ifndef USB_MEM_H_
#define USB_MEM_H_
#endif

View File

@ -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

View File

@ -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 */

View File

@ -0,0 +1,4 @@
SRC_DIR := rk3568
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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 $^

View File

@ -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;
}

View File

@ -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

View File

@ -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 $^

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -1 +0,0 @@
#include "usb_osal.h"

View File

@ -0,0 +1,4 @@
SRC_DIR := xhci dwc3
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
USB3.0: xhci dwc3
USB2.0: ehci dwc2
USB1.1: ohci uhci

View File

@ -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 $^

View File

@ -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) );
}

View File

@ -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

View File

@ -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

View File

@ -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 $^

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 $^

View File

@ -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;
}

View File

@ -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

View File

@ -1,17 +0,0 @@
#ifndef USB_CONFIG_H_
#define USB_CONFIG_H_
#endif

View File

@ -1,6 +0,0 @@
#include "usb_host.h"
int main(){
return 0;
}

View File

@ -1,9 +0,0 @@
#ifndef USB_HOST_H_
#define USB_HOST_H_
#endif

View File

@ -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

View File

@ -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 $^

View File

@ -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);
}

View File

@ -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

View File

@ -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