[dm2.0] add new bsp for rk platform

This commit is contained in:
zhujiale 2024-11-05 10:04:21 +08:00 committed by Meco Man
parent f98f772a84
commit 1572a44055
42 changed files with 17198 additions and 0 deletions

1492
bsp/rockchip/rk3500/.config Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
mainmenu "RT-Thread Project Configuration"
config BSP_DIR
string
option env="BSP_ROOT"
default "."
config RTT_DIR
string
option env="RTT_ROOT"
default "../../.."
config PKGS_DIR
string
option env="PKGS_ROOT"
default "packages"
source "$RTT_DIR/Kconfig"
source "$PKGS_DIR/Kconfig"
source "$BSP_DIR/driver/Kconfig"
config SOC_RK3568
bool
select ARCH_ARMV8
select ARCH_CPU_64BIT
select RT_USING_CACHE
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select ARCH_ARM_BOOTWITH_FLUSH_CACHE
default y

View File

@ -0,0 +1,75 @@
# RK3568 BSP Introduction
[中文页]() | English
## 1. Introduction
RK3568 is a general-purpose SOC, quad-core 64-bit Cortex-A55 processor, with 22nm lithography process, has frequency up to 2.0GHz and Mali G52 GPU, support 4K decoding and 1080P encoding. Support mangy interfaces such as SATA/PCIE/USB3.0, an 0.8T NPU for lightweight AI applications. Support dual Gigabit Ethernet ports, LPDDR4 memory, etc.
This project ported RT-Thread on RK3568, you can use the RADXA ROCK 3A version of the RK3568 in low-priced, which can even replace the Raspberry Pi 4B.
## 2. Compiling
Usage ARM Developer GNU ToolChain, it support Linux and Windows:
```plaintext
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads/
```
Download the `xxx-aarch64-none-elf` of x86_64 hosted platform, set the `RTT_EXEC_PATH` is system environment after decompress the binary.
Enter directory `rt-thread/bsp/qemu-virt64-aarch64` and input:
```plaintext
scons
```
## 3. Execution
RK3568 has different Kernel install methods according to different boardsit, recommend to install into the SD card: ([Official](https://wiki.t-firefly.com/en/ROC-RK3568-PC/hardware_doc.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/install/microSD)).
After install Kernel, storage the `rtthread.bin` to EFI partition (the second partition), and add this line in the front of `boot.cmd` in this partition:
```shell
fatload mmc 1:1 0x208000 /rtthread.bin;dcache flush;go 0x208000
```
After modifying the script, build a binary script `boot.scr ` in this partition:
```shell
# Install the uboot-mkimage package on Linux, or use MSYS2 to install the u-boot-tools package on Windows
mkimage -C none -A arm -T script -d boot.cmd boot.scr
```
According to different boards, the serial port can support up to UART0~9, this project uses UART2 ([Official](https://wiki.t-firefly.com/en/ROC-RK3568-PC/debug.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/dev/serial-console)) by default, the baud rate is 1500000, please make sure that the serial port used supports this baud rate.
```plaintext
heap: [0x002663f0 - 0x042663f0]
\ | /
- RT - Thread Operating System
/ | \ 4.1.0 build Mar 19 2022 17:17:29
2006 - 2022 Copyright by RT-Thread team
Hi, this is RT-Thread!!
msh />
```
## 4. Condition
| Driver | Condition | Remark |
| ------ | --------- | ------- |
| UART | Support | UART0~9 |

View File

@ -0,0 +1,14 @@
# for module compiling
import os
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

View File

@ -0,0 +1,29 @@
import os
import sys
import rtconfig
from rtconfig import RTT_ROOT
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
env['ASCOM'] = env['ASPPCOM']
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
# make a building
DoBuilding(TARGET, objs)

View File

@ -0,0 +1,14 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
group += SConscript(os.path.join(item, 'SConscript'))
Return('group')

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-5-30 Bernard the first version
*/
#include <rtthread.h>
int main(int argc, char** argv)
{
rt_kprintf("Hi, this is RT-Thread!!\n");
return 0;
}

View File

@ -0,0 +1,7 @@
menu "RT-Thread rockchip RK3500 drivers"
source "$BSP_DIR/driver/clk/Kconfig"
source "$BSP_DIR/driver/uart8250/Kconfig"
source "$BSP_DIR/driver/reset/Kconfig"
source "$BSP_DIR/driver/hwtimer/Kconfig"
endmenu

View File

@ -0,0 +1,19 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
list = os.listdir(cwd)
CPPPATH = [cwd]
objs = []
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
objs = objs + group
Return('objs')

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-3-08 GuEe-GUI the first version
*/
#include <setup.h>
#include <board.h>
#include <psci.h>
void rt_hw_board_init(void)
{
#if RT_VER_NUM < 0x50200
rt_fdt_commit_memregion_early(&(rt_region_t)
{
.name = "memheap",
.start = (rt_size_t)rt_kmem_v2p(HEAP_BEGIN),
.end = (rt_size_t)rt_kmem_v2p(HEAP_END),
}, RT_TRUE);
#endif
rt_hw_common_setup();
}
void reboot(void)
{
psci_system_reboot();
}
MSH_CMD_EXPORT(reboot, reboot...);
void rt_hw_cpu_shutdown(void)
{
psci_system_off();
}
MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_shutdown, shutdown, shutdown...);

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-5-30 Bernard the first version
*/
#ifndef __BOARD_H__
#define __BOARD_H__
#include <rtdef.h>
extern unsigned char __bss_start;
extern unsigned char __bss_end;
#define HEAP_BEGIN (void *)&__bss_end
#define HEAP_END ((void *)HEAP_BEGIN + 64 * 1024 * 1024)
void rt_hw_board_init(void);
#endif /* __BOARD_H__ */

View File

@ -0,0 +1,15 @@
menuconfig RT_CLK_ROCKCHIP
bool "Rockchip clock controller common"
select RT_USING_OFW
select RT_USING_RESET
default n
config RT_CLK_ROCKCHIP_RK3568
bool "Rockchip RK3568 clock controller support"
depends on RT_CLK_ROCKCHIP
default n
config RT_CLK_ROCKCHIP_RK3588
bool "Rockchip RK3588 clock controller support"
depends on RT_CLK_ROCKCHIP
default n

View File

@ -0,0 +1,16 @@
from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd]
src = []
if GetDepend(['RT_CLK_ROCKCHIP_RK3568']):
src += ['clk-rk3568.c']
if GetDepend(['RT_CLK_ROCKCHIP_RK3588']):
src += ['clk-rk3588.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-3-08 GuEe-GUI the first version
*/
#define ROCKCHIP_MMC_DELAY_SEL RT_BIT(11)
#define ROCKCHIP_MMC_DEGREE_OFFSET 1
#define ROCKCHIP_MMC_DEGREE_MASK (0x3 << ROCKCHIP_MMC_DEGREE_OFFSET)
#define ROCKCHIP_MMC_DELAYNUM_OFFSET 3
#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
/*
* Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
* simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
*/
#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
#define PSECS_PER_SEC 1000000000000LL
#define RK3288_MMC_CLKGEN_DIV 2
rt_inline rt_ubase_t rk_clk_mmc_recalc(rt_ubase_t parent_rate)
{
return parent_rate / RK3288_MMC_CLKGEN_DIV;
}
static rt_err_t rk_clk_mmc_set_phase(rt_ubase_t rate, void *reg, int shift,
int degrees)
{
rt_uint32_t raw_value, delay;
rt_uint8_t nineties, remainder, delay_num;
/*
* The below calculation is based on the output clock from
* MMC host to the card, which expects the phase clock inherits
* the clock rate from its parent, namely the output clock
* provider of MMC host. However, things may go wrong if
* (1) It is orphan.
* (2) It is assigned to the wrong parent.
*
* This check help debug the case (1), which seems to be the
* most likely problem we often face and which makes it difficult
* for people to debug unstable mmc tuning results.
*/
if (!rate)
{
LOG_E("Invalid CLK rate in phase setting");
return -RT_EINVAL;
}
nineties = degrees / 90;
remainder = (degrees % 90);
/*
* Due to the inexact nature of the "fine" delay, we might
* actually go non-monotonic. We don't go _too_ monotonic
* though, so we should be OK. Here are options of how we may
* work:
*
* Ideally we end up with:
* 1.0, 2.0, ..., 69.0, 70.0, ..., 89.0, 90.0
*
* On one extreme (if delay is actually 44ps):
* .73, 1.5, ..., 50.6, 51.3, ..., 65.3, 90.0
* The other (if delay is actually 77ps):
* 1.3, 2.6, ..., 88.6. 89.8, ..., 114.0, 90
*
* It's possible we might make a delay that is up to 25
* degrees off from what we think we're making. That's OK
* though because we should be REALLY far from any bad range.
*/
/*
* Convert to delay; do a little extra work to make sure we
* don't overflow 32-bit / 64-bit numbers.
*/
delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
delay *= remainder;
delay = RT_DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
delay_num = (rt_uint8_t)rt_min_t(rt_uint32_t, delay, 255);
raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
raw_value |= nineties;
HWREG32(reg) = HIWORD_UPDATE(raw_value, 0x07ff, shift);
return RT_EOK;
}
static rt_base_t rk_clk_mmc_get_phase(rt_ubase_t rate, void *reg, int shift)
{
rt_uint16_t degrees;
rt_uint32_t raw_value, delay_num = 0;
/* Constant signal, no measurable phase shift */
if (!rate)
{
return 0;
}
raw_value = HWREG32(reg) >> shift;
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
if (raw_value & ROCKCHIP_MMC_DELAY_SEL)
{
/* degrees/delaynum * 1000000 */
rt_ubase_t factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
36 * (rate / 10000);
delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
degrees += RT_DIV_ROUND_CLOSEST(delay_num * factor, 1000000);
}
return degrees % 360;
}

View File

@ -0,0 +1,403 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-3-08 GuEe-GUI the first version
*/
/* Define pll mode */
#define RKCLK_PLL_MODE_SLOW 0
#define RKCLK_PLL_MODE_NORMAL 1
#define RKCLK_PLL_MODE_DEEP 2
/* Only support RK3036 type CLK */
#define PLLCON0_FBDIV_MASK 0xfff
#define PLLCON0_FBDIV_SHIFT 0
#define PLLCON0_POSTDIV1_MASK (0x7 << 12)
#define PLLCON0_POSTDIV1_SHIFT 12
#define PLLCON1_LOCK_STATUS (1 << 10)
#define PLLCON1_REFDIV_MASK 0x3f
#define PLLCON1_REFDIV_SHIFT 0
#define PLLCON1_POSTDIV2_MASK (0x7 << 6)
#define PLLCON1_POSTDIV2_SHIFT 6
#define PLLCON1_DSMPD_MASK (0x1 << 12)
#define PLLCON1_DSMPD_SHIFT 12
#define PLLCON2_FRAC_MASK 0xffffff
#define PLLCON2_FRAC_SHIFT 0
#define PLLCON1_PWRDOWN_SHIT 13
#define PLLCON1_PWRDOWN (1 << PLLCON1_PWRDOWN_SHIT)
#define MIN_FOUTVCO_FREQ (800 * MHZ)
#define MAX_FOUTVCO_FREQ (2000 * MHZ)
static struct rk_pll_rate_table auto_table;
static int gcd(int m, int n)
{
while (m > 0)
{
if (n > m)
{
int t = m;
m = n;
n = t;
}
m -= n;
}
return n;
}
/*
* rational_best_approximation(31415, 10000,
* (1 << 8) - 1, (1 << 5) - 1, &n, &d);
*
* you may look at given_numerator as a fixed point number,
* with the fractional part size described in given_denominator.
*
* for theoretical background, see:
* http://en.wikipedia.org/wiki/Continued_fraction
*/
static void rational_best_approximation(rt_ubase_t given_numerator,
rt_ubase_t given_denominator,
rt_ubase_t max_numerator,
rt_ubase_t max_denominator,
rt_ubase_t *best_numerator,
rt_ubase_t *best_denominator)
{
rt_ubase_t n, d, n0, d0, n1, d1;
n = given_numerator;
d = given_denominator;
n0 = 0;
d1 = 0;
n1 = 1;
d0 = 1;
for (;;)
{
rt_ubase_t t, a;
if (n1 > max_numerator || d1 > max_denominator)
{
n1 = n0;
d1 = d0;
break;
}
if (d == 0)
{
break;
}
t = d;
a = n / d;
d = n % d;
n = t;
t = n0 + a * n1;
n0 = n1;
n1 = t;
t = d0 + a * d1;
d0 = d1;
d1 = t;
}
*best_numerator = n1;
*best_denominator = d1;
}
/*
* How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
* Formulas also embedded within the Fractional PLL Verilog model:
* If DSMPD = 1 (DSM is disabled, "integer mode")
* FOUTVCO = FREF / REFDIV * FBDIV
* FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
* Where:
* FOUTVCO = Fractional PLL non-divided output frequency
* FOUTPOSTDIV = Fractional PLL divided output frequency
* (output of second post divider)
* FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
* REFDIV = Fractional PLL input reference clock divider
* FBDIV = Integer value programmed into feedback divide
*/
static int rk_pll_clk_set_postdiv(rt_ubase_t fout_hz, rt_uint32_t *postdiv1,
rt_uint32_t *postdiv2, rt_uint32_t *foutvco)
{
rt_ubase_t freq;
if (fout_hz < MIN_FOUTVCO_FREQ)
{
for (*postdiv1 = 1; *postdiv1 <= 7; ++(*postdiv1))
{
for (*postdiv2 = 1; *postdiv2 <= 7; ++(*postdiv2))
{
freq = fout_hz * (*postdiv1) * (*postdiv2);
if (freq >= MIN_FOUTVCO_FREQ && freq <= MAX_FOUTVCO_FREQ)
{
*foutvco = freq;
return 0;
}
}
}
}
else
{
*postdiv1 = 1;
*postdiv2 = 1;
}
return 0;
}
static struct rk_pll_rate_table *rk_pll_clk_set_by_auto(rt_ubase_t fin_hz, rt_ubase_t fout_hz)
{
struct rk_pll_rate_table *rate_table = &auto_table;
rt_uint32_t foutvco = fout_hz;
rt_ubase_t fin_64, frac_64;
rt_uint32_t f_frac, postdiv1, postdiv2;
rt_ubase_t clk_gcd = 0;
if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz)
{
return RT_NULL;
}
rk_pll_clk_set_postdiv(fout_hz, &postdiv1, &postdiv2, &foutvco);
rate_table->postdiv1 = postdiv1;
rate_table->postdiv2 = postdiv2;
rate_table->dsmpd = 1;
if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz)
{
fin_hz /= MHZ;
foutvco /= MHZ;
clk_gcd = gcd(fin_hz, foutvco);
rate_table->refdiv = fin_hz / clk_gcd;
rate_table->fbdiv = foutvco / clk_gcd;
rate_table->frac = 0;
}
else
{
clk_gcd = gcd(fin_hz / MHZ, foutvco / MHZ);
rate_table->refdiv = fin_hz / MHZ / clk_gcd;
rate_table->fbdiv = foutvco / MHZ / clk_gcd;
rate_table->frac = 0;
f_frac = (foutvco % MHZ);
fin_64 = fin_hz;
fin_64 = fin_64 / rate_table->refdiv;
frac_64 = f_frac << 24;
frac_64 = frac_64 / fin_64;
rate_table->frac = frac_64;
if (rate_table->frac > 0)
{
rate_table->dsmpd = 0;
}
}
return rate_table;
}
static const struct rk_pll_rate_table *rk_get_pll_settings(struct rk_pll_clock *pll, rt_ubase_t rate)
{
struct rk_pll_rate_table *rate_table = pll->rate_table;
while (rate_table->rate)
{
if (rate_table->rate == rate)
{
break;
}
++rate_table;
}
if (rate_table->rate != rate)
{
return rk_pll_clk_set_by_auto(24 * MHZ, rate);
}
else
{
return rate_table;
}
}
static rt_ubase_t rk_pll_get_rate(struct rk_pll_clock *pll, void *base);
static int rk_pll_set_rate(struct rk_pll_clock *pll, void *base, rt_ubase_t drate)
{
const struct rk_pll_rate_table *rate;
if (rk_pll_get_rate(pll, base) == drate)
{
return 0;
}
pll->mode_mask = PLL_MODE_MASK;
rate = rk_get_pll_settings(pll, drate);
if (!rate)
{
return -RT_ERROR;
}
/*
* When power on or changing PLL setting, we must force PLL into slow mode
* to ensure output stable clock.
*/
rk_clrsetreg(base + pll->mode_offset, pll->mode_mask << pll->mode_shift, RKCLK_PLL_MODE_SLOW << pll->mode_shift);
/* Power down */
rk_setreg(base + pll->con_offset + 0x4, 1 << PLLCON1_PWRDOWN_SHIT);
rk_clrsetreg(base + pll->con_offset, (PLLCON0_POSTDIV1_MASK | PLLCON0_FBDIV_MASK),
(rate->postdiv1 << PLLCON0_POSTDIV1_SHIFT) |rate->fbdiv);
rk_clrsetreg(base + pll->con_offset + 0x4, (PLLCON1_POSTDIV2_MASK | PLLCON1_REFDIV_MASK),
(rate->postdiv2 << PLLCON1_POSTDIV2_SHIFT | rate->refdiv << PLLCON1_REFDIV_SHIFT));
if (!rate->dsmpd)
{
rt_uint32_t val;
rk_clrsetreg(base + pll->con_offset + 0x4, PLLCON1_DSMPD_MASK,
rate->dsmpd << PLLCON1_DSMPD_SHIFT);
val = HWREG32(base + pll->con_offset + 0x8) & (~PLLCON2_FRAC_MASK);
HWREG32(base + pll->con_offset + 0x8) = val | (rate->frac << PLLCON2_FRAC_SHIFT);
}
/* Power Up */
rk_clrreg(base + pll->con_offset + 0x4, 1 << PLLCON1_PWRDOWN_SHIT);
/* Waiting for pll lock */
while (!(HWREG32(base + pll->con_offset + 0x4) & (1 << pll->lock_shift)))
{
}
rk_clrsetreg(base + pll->mode_offset, pll->mode_mask << pll->mode_shift, RKCLK_PLL_MODE_NORMAL << pll->mode_shift);
return 0;
}
static rt_ubase_t rk_pll_get_rate(struct rk_pll_clock *pll, void *base)
{
rt_uint32_t refdiv, fbdiv, postdiv1, postdiv2, dsmpd, frac;
rt_uint32_t con = 0, shift, mask;
rt_ubase_t rate;
pll->mode_mask = PLL_MODE_MASK;
con = HWREG32(base + pll->mode_offset);
shift = pll->mode_shift;
mask = pll->mode_mask << shift;
switch ((con & mask) >> shift)
{
case RKCLK_PLL_MODE_SLOW:
return OSC_HZ;
case RKCLK_PLL_MODE_NORMAL:
/* normal mode */
con = HWREG32(base + pll->con_offset);
postdiv1 = (con & PLLCON0_POSTDIV1_MASK) >> PLLCON0_POSTDIV1_SHIFT;
fbdiv = (con & PLLCON0_FBDIV_MASK) >> PLLCON0_FBDIV_SHIFT;
con = HWREG32(base + pll->con_offset + 0x4);
postdiv2 = (con & PLLCON1_POSTDIV2_MASK) >> PLLCON1_POSTDIV2_SHIFT;
refdiv = (con & PLLCON1_REFDIV_MASK) >> PLLCON1_REFDIV_SHIFT;
dsmpd = (con & PLLCON1_DSMPD_MASK) >> PLLCON1_DSMPD_SHIFT;
con = HWREG32(base + pll->con_offset + 0x8);
frac = (con & PLLCON2_FRAC_MASK) >> PLLCON2_FRAC_SHIFT;
rate = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
if (dsmpd == 0)
{
rt_uint64_t frac_rate = OSC_HZ * (rt_uint64_t)frac;
rt_do_div(frac_rate, refdiv);
frac_rate >>= 24;
rt_do_div(frac_rate, postdiv1);
rt_do_div(frac_rate, postdiv1);
rate += frac_rate;
}
return rate;
case RKCLK_PLL_MODE_DEEP:
default:
return 32768;
}
}
static const struct rk_cpu_rate_table *rk_get_cpu_settings(struct rk_cpu_rate_table *cpu_table, rt_ubase_t rate)
{
struct rk_cpu_rate_table *ps = cpu_table;
while (ps->rate)
{
if (ps->rate == rate)
{
break;
}
++ps;
}
if (ps->rate != rate)
{
return RT_NULL;
}
else
{
return ps;
}
}
static rt_base_t rk_clk_pll_round_rate(const struct rk_pll_rate_table *pll_rates,
rt_size_t rate_count, rt_ubase_t drate, rt_ubase_t *prate)
{
int i;
/* Assumming rate_table is in descending order */
for (i = 0; i < rate_count; i++)
{
if (drate >= pll_rates[i].rate)
{
return pll_rates[i].rate;
}
}
/* return minimum supported value */
return pll_rates[i - 1].rate;
}
static void rk_clk_set_default_rates(struct rt_clk *clk,
rt_err_t (*clk_set_rate)(struct rt_clk *, rt_ubase_t, rt_ubase_t), int id)
{
rt_uint32_t rate;
struct rt_ofw_cell_args clk_args;
struct rt_ofw_node *np = clk->fw_node;
const char *rate_propname = "assigned-clock-rates";
if (!rt_ofw_prop_read_bool(np, rate_propname))
{
return;
}
for (int i = 0; ; ++i)
{
if (rt_ofw_parse_phandle_cells(np, "assigned-clocks", "#clock-cells", i, &clk_args))
{
break;
}
rt_ofw_node_put(clk_args.data);
if (clk_args.args[0] != id)
{
continue;
}
if (!rt_ofw_prop_read_u32_index(np, rate_propname, i, &rate))
{
clk_set_rate(clk, rate, 0);
}
break;
}
}

View File

@ -0,0 +1,727 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-11-03 zmshahaha the first version
*/
#define PLL_MODE_MASK 0x3
#define PLL_RK3328_MODE_MASK 0x1
/* Define pll mode */
#define RKCLK_PLL_MODE_SLOW 0
#define RKCLK_PLL_MODE_NORMAL 1
#define RKCLK_PLL_MODE_DEEP 2
/* Only support RK3036 type CLK */
#define RK3036_PLLCON0_FBDIV_MASK 0xfff
#define RK3036_PLLCON0_FBDIV_SHIFT 0
#define RK3036_PLLCON0_POSTDIV1_MASK (0x7 << 12)
#define RK3036_PLLCON0_POSTDIV1_SHIFT 12
#define RK3036_PLLCON1_LOCK_STATUS (1 << 10)
#define RK3036_PLLCON1_REFDIV_MASK 0x3f
#define RK3036_PLLCON1_REFDIV_SHIFT 0
#define RK3036_PLLCON1_POSTDIV2_MASK (0x7 << 6)
#define RK3036_PLLCON1_POSTDIV2_SHIFT 6
#define RK3036_PLLCON1_DSMPD_MASK (0x1 << 12)
#define RK3036_PLLCON1_DSMPD_SHIFT 12
#define RK3036_PLLCON2_FRAC_MASK 0xffffff
#define RK3036_PLLCON2_FRAC_SHIFT 0
#define RK3036_PLLCON1_PWRDOWN_SHIT 13
#define RK3036_PLLCON1_PWRDOWN (1 << RK3036_PLLCON1_PWRDOWN_SHIT)
#define VCO_MAX_HZ (3200UL * MHZ)
#define VCO_MIN_HZ (800UL * MHZ)
#define OUTPUT_MAX_HZ (3200UL * MHZ)
#define OUTPUT_MIN_HZ (24UL * MHZ)
#define MIN_FOUTVCO_FREQ (800UL * MHZ)
#define MAX_FOUTVCO_FREQ (2000UL * MHZ)
#define RK3588_VCO_MIN_HZ (2250UL * MHZ)
#define RK3588_VCO_MAX_HZ (4500UL * MHZ)
#define RK3588_FOUT_MIN_HZ (37UL * MHZ)
#define RK3588_FOUT_MAX_HZ (4500UL * MHZ)
#define RK3588_PLLCON(i) ((i) * 0x4)
#define RK3588_PLLCON0_M_MASK (0x3ff << 0)
#define RK3588_PLLCON0_M_SHIFT 0
#define RK3588_PLLCON1_P_MASK (0x3f << 0)
#define RK3588_PLLCON1_P_SHIFT 0
#define RK3588_PLLCON1_S_MASK (0x7 << 6)
#define RK3588_PLLCON1_S_SHIFT 6
#define RK3588_PLLCON2_K_MASK 0xffff
#define RK3588_PLLCON2_K_SHIFT 0
#define RK3588_PLLCON1_PWRDOWN (1 << 13)
#define RK3588_PLLCON6_LOCK_STATUS (1 << 15)
#define RK3588_B0PLL_CLKSEL_CON(i) ((i) * 0x4 + 0x50000 + 0x300)
#define RK3588_B1PLL_CLKSEL_CON(i) ((i) * 0x4 + 0x52000 + 0x300)
#define RK3588_LPLL_CLKSEL_CON(i) ((i) * 0x4 + 0x58000 + 0x300)
#define RK3588_CORE_DIV_MASK 0x1f
#define RK3588_CORE_L02_DIV_SHIFT 0
#define RK3588_CORE_L13_DIV_SHIFT 7
#define RK3588_CORE_B02_DIV_SHIFT 8
#define RK3588_CORE_B13_DIV_SHIFT 0
static struct rk_pll_rate_table auto_table;
static int gcd(int m, int n)
{
while (m > 0)
{
if (n > m)
{
int t = m;
m = n;
n = t;
}
m -= n;
}
return n;
}
/*
* rational_best_approximation(31415, 10000,
* (1 << 8) - 1, (1 << 5) - 1, &n, &d);
*
* you may look at given_numerator as a fixed point number,
* with the fractional part size described in given_denominator.
*
* for theoretical background, see:
* http://en.wikipedia.org/wiki/Continued_fraction
*/
void rational_best_approximation(rt_ubase_t given_numerator,
rt_ubase_t given_denominator,
rt_ubase_t max_numerator,
rt_ubase_t max_denominator,
rt_ubase_t *best_numerator,
rt_ubase_t *best_denominator)
{
rt_ubase_t n, d, n0, d0, n1, d1;
n = given_numerator;
d = given_denominator;
n0 = 0;
d1 = 0;
n1 = 1;
d0 = 1;
for (;;)
{
rt_ubase_t t, a;
if (n1 > max_numerator || d1 > max_denominator)
{
n1 = n0;
d1 = d0;
break;
}
if (d == 0)
{
break;
}
t = d;
a = n / d;
d = n % d;
n = t;
t = n0 + a * n1;
n0 = n1;
n1 = t;
t = d0 + a * d1;
d0 = d1;
d1 = t;
}
*best_numerator = n1;
*best_denominator = d1;
}
/*
* How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
* Formulas also embedded within the Fractional PLL Verilog model:
* If DSMPD = 1 (DSM is disabled, "integer mode")
* FOUTVCO = FREF / REFDIV * FBDIV
* FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
* Where:
* FOUTVCO = Fractional PLL non-divided output frequency
* FOUTPOSTDIV = Fractional PLL divided output frequency
* (output of second post divider)
* FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
* REFDIV = Fractional PLL input reference clock divider
* FBDIV = Integer value programmed into feedback divide
*/
static int rk_pll_clk_set_postdiv(rt_ubase_t fout_hz, rt_uint32_t *postdiv1,
rt_uint32_t *postdiv2, rt_uint32_t *foutvco)
{
rt_ubase_t freq;
if (fout_hz < MIN_FOUTVCO_FREQ)
{
for (*postdiv1 = 1; *postdiv1 <= 7; ++(*postdiv1))
{
for (*postdiv2 = 1; *postdiv2 <= 7; ++(*postdiv2))
{
freq = fout_hz * (*postdiv1) * (*postdiv2);
if (freq >= MIN_FOUTVCO_FREQ && freq <= MAX_FOUTVCO_FREQ)
{
*foutvco = freq;
return 0;
}
}
}
}
else
{
*postdiv1 = 1;
*postdiv2 = 1;
}
return 0;
}
static struct rk_pll_rate_table *rk_pll_clk_set_by_auto(rt_ubase_t fin_hz, rt_ubase_t fout_hz)
{
struct rk_pll_rate_table *rate_table = &auto_table;
rt_uint32_t foutvco = fout_hz;
rt_ubase_t fin_64, frac_64;
rt_uint32_t f_frac, postdiv1, postdiv2;
rt_ubase_t clk_gcd = 0;
if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz)
{
return RT_NULL;
}
rk_pll_clk_set_postdiv(fout_hz, &postdiv1, &postdiv2, &foutvco);
rate_table->postdiv1 = postdiv1;
rate_table->postdiv2 = postdiv2;
rate_table->dsmpd = 1;
if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz)
{
fin_hz /= MHZ;
foutvco /= MHZ;
clk_gcd = gcd(fin_hz, foutvco);
rate_table->refdiv = fin_hz / clk_gcd;
rate_table->fbdiv = foutvco / clk_gcd;
rate_table->frac = 0;
}
else
{
clk_gcd = gcd(fin_hz / MHZ, foutvco / MHZ);
rate_table->refdiv = fin_hz / MHZ / clk_gcd;
rate_table->fbdiv = foutvco / MHZ / clk_gcd;
rate_table->frac = 0;
f_frac = (foutvco % MHZ);
fin_64 = fin_hz;
fin_64 = fin_64 / rate_table->refdiv;
frac_64 = f_frac << 24;
frac_64 = frac_64 / fin_64;
rate_table->frac = frac_64;
if (rate_table->frac > 0)
{
rate_table->dsmpd = 0;
}
}
return rate_table;
}
static struct rk_pll_rate_table *
rk3588_pll_clk_set_by_auto(rt_ubase_t fin_hz,
rt_ubase_t fout_hz)
{
struct rk_pll_rate_table *rate_table = &auto_table;
rt_uint32_t p, m, s;
rt_ubase_t fvco, fref, fout, ffrac;
if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz)
return NULL;
if (fout_hz > RK3588_FOUT_MAX_HZ || fout_hz < RK3588_FOUT_MIN_HZ)
return NULL;
if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz)
{
for (s = 0; s <= 6; s++)
{
fvco = fout_hz << s;
if (fvco < RK3588_VCO_MIN_HZ ||
fvco > RK3588_VCO_MAX_HZ)
continue;
for (p = 2; p <= 4; p++)
{
for (m = 64; m <= 1023; m++)
{
if (fvco == m * fin_hz / p)
{
rate_table->p = p;
rate_table->m = m;
rate_table->s = s;
rate_table->k = 0;
return rate_table;
}
}
}
}
LOG_E("CANNOT FIND Fout by auto,fout = %lu\n", fout_hz);
} else {
for (s = 0; s <= 6; s++)
{
fvco = fout_hz << s;
if (fvco < RK3588_VCO_MIN_HZ ||
fvco > RK3588_VCO_MAX_HZ)
continue;
for (p = 1; p <= 4; p++)
{
for (m = 64; m <= 1023; m++)
{
if ((fvco >= m * fin_hz / p) && (fvco < (m + 1) * fin_hz / p))
{
rate_table->p = p;
rate_table->m = m;
rate_table->s = s;
fref = fin_hz / p;
ffrac = fvco - (m * fref);
fout = ffrac * 65536;
rate_table->k = fout / fref;
return rate_table;
}
}
}
}
LOG_E("CANNOT FIND Fout by auto,fout = %lu\n", fout_hz);
}
return NULL;
}
static const struct rk_pll_rate_table *rk_get_pll_settings(struct rk_pll_clock *pll, rt_ubase_t rate)
{
struct rk_pll_rate_table *rate_table = pll->rate_table;
while (rate_table->rate)
{
if (rate_table->rate == rate)
{
break;
}
++rate_table;
}
if (rate_table->rate != rate)
{
if (pll->type == pll_rk3588)
return rk3588_pll_clk_set_by_auto(24 * MHZ, rate);
else
return rk_pll_clk_set_by_auto(24 * MHZ, rate);
}
else
{
return rate_table;
}
}
static int rk3036_pll_set_rate(struct rk_pll_clock *pll, void *base, rt_ubase_t pll_id, rt_ubase_t drate)
{
const struct rk_pll_rate_table *rate;
rate = rk_get_pll_settings(pll, drate);
if (!rate)
{
return -RT_ERROR;
}
/*
* When power on or changing PLL setting, we must force PLL into slow mode
* to ensure output stable clock.
*/
rk_clrsetreg(base + pll->mode_offset, pll->mode_mask << pll->mode_shift, RKCLK_PLL_MODE_SLOW << pll->mode_shift);
/* Power down */
rk_setreg(base + pll->con_offset + 0x4, 1 << RK3036_PLLCON1_PWRDOWN_SHIT);
rk_clrsetreg(base + pll->con_offset, (RK3036_PLLCON0_POSTDIV1_MASK | RK3036_PLLCON0_FBDIV_MASK),
(rate->postdiv1 << RK3036_PLLCON0_POSTDIV1_SHIFT) |rate->fbdiv);
rk_clrsetreg(base + pll->con_offset + 0x4, (RK3036_PLLCON1_POSTDIV2_MASK | RK3036_PLLCON1_REFDIV_MASK),
(rate->postdiv2 << RK3036_PLLCON1_POSTDIV2_SHIFT | rate->refdiv << RK3036_PLLCON1_REFDIV_SHIFT));
if (!rate->dsmpd)
{
rt_uint32_t val;
rk_clrsetreg(base + pll->con_offset + 0x4, RK3036_PLLCON1_DSMPD_MASK,
rate->dsmpd << RK3036_PLLCON1_DSMPD_SHIFT);
val = HWREG32(base + pll->con_offset + 0x8) & (~RK3036_PLLCON2_FRAC_MASK);
HWREG32(base + pll->con_offset + 0x8) = val | (rate->frac << RK3036_PLLCON2_FRAC_SHIFT);
}
/* Power Up */
rk_clrreg(base + pll->con_offset + 0x4, 1 << RK3036_PLLCON1_PWRDOWN_SHIT);
/* Waiting for pll lock */
while (!(HWREG32(base + pll->con_offset + 0x4) & (1 << pll->lock_shift)))
{
}
rk_clrsetreg(base + pll->mode_offset, pll->mode_mask << pll->mode_shift, RKCLK_PLL_MODE_NORMAL << pll->mode_shift);
return 0;
}
static rt_ubase_t rk3036_pll_get_rate(struct rk_pll_clock *pll, void *base, rt_ubase_t pll_id)
{
rt_uint32_t refdiv, fbdiv, postdiv1, postdiv2, dsmpd, frac;
rt_uint32_t con = 0, shift, mask;
rt_ubase_t rate;
pll->mode_mask = PLL_MODE_MASK;
con = HWREG32(base + pll->mode_offset);
shift = pll->mode_shift;
mask = pll->mode_mask << shift;
switch ((con & mask) >> shift)
{
case RKCLK_PLL_MODE_SLOW:
return OSC_HZ;
case RKCLK_PLL_MODE_NORMAL:
/* normal mode */
con = HWREG32(base + pll->con_offset);
postdiv1 = (con & RK3036_PLLCON0_POSTDIV1_MASK) >> RK3036_PLLCON0_POSTDIV1_SHIFT;
fbdiv = (con & RK3036_PLLCON0_FBDIV_MASK) >> RK3036_PLLCON0_FBDIV_SHIFT;
con = HWREG32(base + pll->con_offset + 0x4);
postdiv2 = (con & RK3036_PLLCON1_POSTDIV2_MASK) >> RK3036_PLLCON1_POSTDIV2_SHIFT;
refdiv = (con & RK3036_PLLCON1_REFDIV_MASK) >> RK3036_PLLCON1_REFDIV_SHIFT;
dsmpd = (con & RK3036_PLLCON1_DSMPD_MASK) >> RK3036_PLLCON1_DSMPD_SHIFT;
con = HWREG32(base + pll->con_offset + 0x8);
frac = (con & RK3036_PLLCON2_FRAC_MASK) >> RK3036_PLLCON2_FRAC_SHIFT;
rate = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
if (dsmpd == 0)
{
rt_uint64_t frac_rate = OSC_HZ * (rt_uint64_t)frac;
rt_do_div(frac_rate, refdiv);
frac_rate >>= 24;
rt_do_div(frac_rate, postdiv1);
rt_do_div(frac_rate, postdiv1);
rate += frac_rate;
}
return rate;
case RKCLK_PLL_MODE_DEEP:
default:
return 32768;
}
}
static int rk3588_pll_set_rate(struct rk_pll_clock *pll,
void *base, rt_ubase_t pll_id,
rt_ubase_t drate)
{
const struct rk_pll_rate_table *rate;
rate = rk_get_pll_settings(pll, drate);
if (!rate)
{
LOG_D("%s unsupported rate\n", __func__);
return -RT_EINVAL;
}
LOG_D("%s: rate settings for %lu p: %d, m: %d, s: %d, k: %d\n",
__func__, rate->rate, rate->p, rate->m, rate->s, rate->k);
/*
* When power on or changing PLL setting,
* we must force PLL into slow mode to ensure output stable clock.
*/
if (pll_id == 3)
rk_clrsetreg(base + 0x84c, 0x1 << 1, 0x1 << 1);
rk_clrsetreg(base + pll->mode_offset,
pll->mode_mask << pll->mode_shift,
RKCLK_PLL_MODE_SLOW << pll->mode_shift);
if (pll_id == 0)
rk_clrsetreg(base + RK3588_B0PLL_CLKSEL_CON(0),
pll->mode_mask << 6,
RKCLK_PLL_MODE_SLOW << 6);
else if (pll_id == 1)
rk_clrsetreg(base + RK3588_B1PLL_CLKSEL_CON(0),
pll->mode_mask << 6,
RKCLK_PLL_MODE_SLOW << 6);
else if (pll_id == 2)
rk_clrsetreg(base + RK3588_LPLL_CLKSEL_CON(5),
pll->mode_mask << 14,
RKCLK_PLL_MODE_SLOW << 14);
/* Power down */
rk_setreg(base + pll->con_offset + RK3588_PLLCON(1),
RK3588_PLLCON1_PWRDOWN);
rk_clrsetreg(base + pll->con_offset,
RK3588_PLLCON0_M_MASK,
(rate->m << RK3588_PLLCON0_M_SHIFT));
rk_clrsetreg(base + pll->con_offset + RK3588_PLLCON(1),
(RK3588_PLLCON1_P_MASK |
RK3588_PLLCON1_S_MASK),
(rate->p << RK3588_PLLCON1_P_SHIFT |
rate->s << RK3588_PLLCON1_S_SHIFT));
if (rate->k)
{
rk_clrsetreg(base + pll->con_offset + RK3588_PLLCON(2),
RK3588_PLLCON2_K_MASK,
rate->k << RK3588_PLLCON2_K_SHIFT);
}
/* Power up */
rk_clrreg(base + pll->con_offset + RK3588_PLLCON(1),
RK3588_PLLCON1_PWRDOWN);
/* waiting for pll lock */
while (!(HWREG32(base + pll->con_offset + RK3588_PLLCON(6)) &
RK3588_PLLCON6_LOCK_STATUS))
{
}
rk_clrsetreg(base + pll->mode_offset, pll->mode_mask << pll->mode_shift,
RKCLK_PLL_MODE_NORMAL << pll->mode_shift);
if (pll_id == 0)
{
rk_clrsetreg(base + RK3588_B0PLL_CLKSEL_CON(0),
pll->mode_mask << 6,
2 << 6);
rk_clrsetreg(base + RK3588_B0PLL_CLKSEL_CON(0),
RK3588_CORE_DIV_MASK << RK3588_CORE_B02_DIV_SHIFT,
0 << RK3588_CORE_B02_DIV_SHIFT);
rk_clrsetreg(base + RK3588_B0PLL_CLKSEL_CON(1),
RK3588_CORE_DIV_MASK << RK3588_CORE_B13_DIV_SHIFT,
0 << RK3588_CORE_B13_DIV_SHIFT);
} else if (pll_id == 1)
{
rk_clrsetreg(base + RK3588_B1PLL_CLKSEL_CON(0),
pll->mode_mask << 6,
2 << 6);
rk_clrsetreg(base + RK3588_B1PLL_CLKSEL_CON(0),
RK3588_CORE_DIV_MASK << RK3588_CORE_B02_DIV_SHIFT,
0 << RK3588_CORE_B02_DIV_SHIFT);
rk_clrsetreg(base + RK3588_B1PLL_CLKSEL_CON(1),
RK3588_CORE_DIV_MASK << RK3588_CORE_B13_DIV_SHIFT,
0 << RK3588_CORE_B13_DIV_SHIFT);
} else if (pll_id == 2)
{
rk_clrsetreg(base + RK3588_LPLL_CLKSEL_CON(5),
pll->mode_mask << 14,
2 << 14);
rk_clrsetreg(base + RK3588_LPLL_CLKSEL_CON(6),
RK3588_CORE_DIV_MASK << RK3588_CORE_L13_DIV_SHIFT,
0 << RK3588_CORE_L13_DIV_SHIFT);
rk_clrsetreg(base + RK3588_LPLL_CLKSEL_CON(6),
RK3588_CORE_DIV_MASK << RK3588_CORE_L02_DIV_SHIFT,
0 << RK3588_CORE_L02_DIV_SHIFT);
rk_clrsetreg(base + RK3588_LPLL_CLKSEL_CON(7),
RK3588_CORE_DIV_MASK << RK3588_CORE_L13_DIV_SHIFT,
0 << RK3588_CORE_L13_DIV_SHIFT);
rk_clrsetreg(base + RK3588_LPLL_CLKSEL_CON(7),
RK3588_CORE_DIV_MASK << RK3588_CORE_L02_DIV_SHIFT,
0 << RK3588_CORE_L02_DIV_SHIFT);
}
if (pll_id == 3)
rk_clrsetreg(base + 0x84c, 0x1 << 1, 0);
LOG_D("PLL at %p: con0=%x con1= %x con2= %x mode= %x\n",
pll, HWREG32(base + pll->con_offset),
HWREG32(base + pll->con_offset + 0x4),
HWREG32(base + pll->con_offset + 0x8),
HWREG32(base + pll->mode_offset));
return 0;
}
static rt_ubase_t rk3588_pll_get_rate(struct rk_pll_clock *pll,
void *base, rt_ubase_t pll_id)
{
rt_uint32_t m, p, s, k;
rt_uint32_t con = 0, shift, mode;
rt_uint64_t rate, postdiv;
con = HWREG32(base + pll->mode_offset);
shift = pll->mode_shift;
if (pll_id == 8)
mode = RKCLK_PLL_MODE_NORMAL;
else
mode = (con & (pll->mode_mask << shift)) >> shift;
switch (mode)
{
case RKCLK_PLL_MODE_SLOW:
return OSC_HZ;
case RKCLK_PLL_MODE_NORMAL:
/* normal mode */
con = HWREG32(base + pll->con_offset);
m = (con & RK3588_PLLCON0_M_MASK) >>
RK3588_PLLCON0_M_SHIFT;
con = HWREG32(base + pll->con_offset + RK3588_PLLCON(1));
p = (con & RK3588_PLLCON1_P_MASK) >>
RK3036_PLLCON0_FBDIV_SHIFT;
s = (con & RK3588_PLLCON1_S_MASK) >>
RK3588_PLLCON1_S_SHIFT;
con = HWREG32(base + pll->con_offset + RK3588_PLLCON(2));
k = (con & RK3588_PLLCON2_K_MASK) >>
RK3588_PLLCON2_K_SHIFT;
rate = OSC_HZ / p;
rate *= m;
if (k)
{
/* fractional mode */
rt_uint64_t frac_rate64 = OSC_HZ * k;
postdiv = p * 65536;
rt_do_div(frac_rate64, postdiv);
rate += frac_rate64;
}
rate = rate >> s;
return rate;
case RKCLK_PLL_MODE_DEEP:
default:
return 32768;
}
}
rt_ubase_t rk_pll_get_rate(struct rk_pll_clock *pll,
void *base,
rt_ubase_t pll_id)
{
rt_ubase_t rate = 0;
switch (pll->type)
{
case pll_rk3036:
pll->mode_mask = PLL_MODE_MASK;
rate = rk3036_pll_get_rate(pll, base, pll_id);
break;
case pll_rk3328:
pll->mode_mask = PLL_RK3328_MODE_MASK;
rate = rk3036_pll_get_rate(pll, base, pll_id);
break;
case pll_rk3588:
pll->mode_mask = PLL_MODE_MASK;
rate = rk3588_pll_get_rate(pll, base, pll_id);
break;
default:
LOG_D("%s: Unknown pll type for pll clk %ld\n",
__func__, pll_id);
}
return rate;
}
int rk_pll_set_rate(struct rk_pll_clock *pll,
void *base, rt_ubase_t pll_id,
rt_ubase_t drate)
{
int ret = 0;
if (rk_pll_get_rate(pll, base, pll_id) == drate)
return 0;
switch (pll->type)
{
case pll_rk3036:
pll->mode_mask = PLL_MODE_MASK;
ret = rk3036_pll_set_rate(pll, base, pll_id, drate);
break;
case pll_rk3328:
pll->mode_mask = PLL_RK3328_MODE_MASK;
ret = rk3036_pll_set_rate(pll, base, pll_id, drate);
break;
case pll_rk3588:
pll->mode_mask = PLL_MODE_MASK;
ret = rk3588_pll_set_rate(pll, base, pll_id, drate);
break;
default:
LOG_D("%s: Unknown pll type for pll clk %ld\n",
__func__, pll_id);
}
return ret;
}
const struct rk_cpu_rate_table *rk_get_cpu_settings(struct rk_cpu_rate_table *cpu_table, rt_ubase_t rate)
{
struct rk_cpu_rate_table *ps = cpu_table;
while (ps->rate)
{
if (ps->rate == rate)
{
break;
}
++ps;
}
if (ps->rate != rate)
{
return RT_NULL;
}
else
{
return ps;
}
}
rt_base_t rk_clk_pll_round_rate(const struct rk_pll_rate_table *pll_rates,
rt_size_t rate_count, rt_ubase_t drate, rt_ubase_t *prate)
{
int i;
/* Assumming rate_table is in descending order */
for (i = 0; i < rate_count; i++)
{
if (drate >= pll_rates[i].rate)
{
return pll_rates[i].rate;
}
}
/* return minimum supported value */
return pll_rates[i - 1].rate;
}
void rk_clk_set_default_rates(struct rt_clk *clk,
rt_err_t (*clk_set_rate)(struct rt_clk *, rt_ubase_t, rt_ubase_t), int id)
{
rt_uint32_t rate;
struct rt_ofw_cell_args clk_args;
struct rt_ofw_node *np = clk->fw_node;
const char *rate_propname = "assigned-clock-rates";
if (!rt_ofw_prop_read_bool(np, rate_propname))
{
return;
}
for (int i = 0; ; ++i)
{
if (rt_ofw_parse_phandle_cells(np, "assigned-clocks", "#clock-cells", i, &clk_args))
{
break;
}
rt_ofw_node_put(clk_args.data);
if (clk_args.args[0] != id)
{
continue;
}
if (!rt_ofw_prop_read_u32_index(np, rate_propname, i, &rate))
{
clk_set_rate(clk, rate, 0);
}
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-3-08 GuEe-GUI the first version
*/
#ifndef __ROCKCHIP_CLK3568_H__
#define __ROCKCHIP_CLK3568_H__
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "reset/reset.h"
#include <stdlib.h>
#include "../rockchip.h"
#define HZ 100
#define KHZ 1000
#define MHZ 1000000
#define OSC_HZ (24 * MHZ)
struct rk_cpu_rate_table
{
rt_ubase_t rate;
rt_uint32_t aclk_div;
rt_uint32_t pclk_div;
};
struct rk_pll_rate_table
{
rt_ubase_t rate;
rt_uint32_t nr;
rt_uint32_t nf;
rt_uint32_t no;
rt_uint32_t nb;
rt_uint32_t fbdiv;
rt_uint32_t postdiv1;
rt_uint32_t refdiv;
rt_uint32_t postdiv2;
rt_uint32_t dsmpd;
rt_uint32_t frac;
};
struct rk_pll_clock
{
rt_uint32_t id;
rt_uint32_t con_offset;
rt_uint32_t mode_offset;
rt_uint32_t mode_shift;
rt_uint32_t lock_shift;
rt_uint32_t pll_flags;
struct rk_pll_rate_table *rate_table;
rt_uint32_t mode_mask;
};
struct rk_clk_gate
{
const char *name;
const char *parent_name;
int con_idx;
int con_bit;
};
#define GATE(_id, _name, \
_pname, _con_idx, _con_bit) \
[_id] = \
{ \
.name = _name, \
.parent_name = _pname, \
.con_idx = _con_idx, \
.con_bit = _con_bit, \
}
#define CPUCLK_RATE(_rate, \
_aclk_div, _pclk_div) \
{ \
.rate = _rate##U, \
.aclk_div = _aclk_div, \
.pclk_div = _pclk_div, \
}
#define 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 PLL(_id, _con, _mode, _mshift, \
_lshift, _pflags, _rtable) \
{ \
.id = _id, \
.con_offset = _con, \
.mode_offset = _mode, \
.mode_shift = _mshift, \
.lock_shift = _lshift, \
.pll_flags = _pflags, \
.rate_table = _rtable, \
}
#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
#define ROCKCHIP_SOFTRST_HIWORD_MASK RT_BIT(0)
#endif /* __ROCKCHIP_CLK3568_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-3-08 GuEe-GUI the first version
*/
#ifndef __ROCKCHIP_CLK_H__
#define __ROCKCHIP_CLK_H__
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "reset/reset.h"
#include <stdlib.h>
#include "../rockchip.h"
#define HZ 100
#define KHZ 1000
#define MHZ 1000000
#define OSC_HZ (24 * MHZ)
struct rk_cpu_rate_table
{
rt_ubase_t rate;
rt_uint32_t aclk_div;
rt_uint32_t pclk_div;
};
struct rk_pll_rate_table
{
rt_ubase_t rate;
union {
struct {
/* for RK3066 */
rt_uint32_t nr;
rt_uint32_t nf;
rt_uint32_t no;
rt_uint32_t nb;
};
struct {
/* for RK3036/RK3399 */
rt_uint32_t fbdiv;
rt_uint32_t postdiv1;
rt_uint32_t refdiv;
rt_uint32_t postdiv2;
rt_uint32_t dsmpd;
rt_uint32_t frac;
};
struct {
/* for RK3588 */
rt_uint32_t m;
rt_uint32_t p;
rt_uint32_t s;
rt_uint32_t k;
};
};
};
enum rk_pll_type {
pll_rk3036,
pll_rk3066,
pll_rk3328,
pll_rk3366,
pll_rk3399,
pll_rk3588,
};
typedef rt_uint32_t rk_pll_type_t;
struct rk_pll_clock
{
rt_uint32_t id;
rt_uint32_t con_offset;
rt_uint32_t mode_offset;
rt_uint32_t mode_shift;
rt_uint32_t lock_shift;
rk_pll_type_t type;
rt_uint32_t pll_flags;
struct rk_pll_rate_table *rate_table;
rt_uint32_t mode_mask;
};
struct rk_clk_gate
{
const char *name;
const char *parent_name;
int con_idx;
int con_bit;
};
#define GATE(_id, _name, \
_pname, _con_idx, _con_bit) \
[_id] = \
{ \
.name = _name, \
.parent_name = _pname, \
.con_idx = _con_idx, \
.con_bit = _con_bit, \
}
#define CPUCLK_RATE(_rate, \
_aclk_div, _pclk_div) \
{ \
.rate = _rate##U, \
.aclk_div = _aclk_div, \
.pclk_div = _pclk_div, \
}
#define RK3036_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 PLL(_type, _id, _con, _mode, _mshift, \
_lshift, _pflags, _rtable) \
{ \
.type = _type, \
.id = _id, \
.con_offset = _con, \
.mode_offset = _mode, \
.mode_shift = _mshift, \
.lock_shift = _lshift, \
.pll_flags = _pflags, \
.rate_table = _rtable, \
}
#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
#define ROCKCHIP_SOFTRST_HIWORD_MASK RT_BIT(0)
#endif /* __ROCKCHIP_CLK_H__ */

View File

@ -0,0 +1,926 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DT_BINDINGS_CLK_ROCKCHIP_RK3568_H__
#define __DT_BINDINGS_CLK_ROCKCHIP_RK3568_H__
/* pmucru-clocks indices */
/* pmucru plls */
#define PLL_PPLL 1
#define PLL_HPLL 2
/* pmucru clocks */
#define XIN_OSC0_DIV 4
#define CLK_RTC_32K 5
#define CLK_PMU 6
#define CLK_I2C0 7
#define CLK_RTC32K_FRAC 8
#define CLK_UART0_DIV 9
#define CLK_UART0_FRAC 10
#define SCLK_UART0 11
#define DBCLK_GPIO0 12
#define CLK_PWM0 13
#define CLK_CAPTURE_PWM0_NDFT 14
#define CLK_PMUPVTM 15
#define CLK_CORE_PMUPVTM 16
#define CLK_REF24M 17
#define XIN_OSC0_USBPHY0_G 18
#define CLK_USBPHY0_REF 19
#define XIN_OSC0_USBPHY1_G 20
#define CLK_USBPHY1_REF 21
#define XIN_OSC0_MIPIDSIPHY0_G 22
#define CLK_MIPIDSIPHY0_REF 23
#define XIN_OSC0_MIPIDSIPHY1_G 24
#define CLK_MIPIDSIPHY1_REF 25
#define CLK_WIFI_DIV 26
#define CLK_WIFI_OSC0 27
#define CLK_WIFI 28
#define CLK_PCIEPHY0_DIV 29
#define CLK_PCIEPHY0_OSC0 30
#define CLK_PCIEPHY0_REF 31
#define CLK_PCIEPHY1_DIV 32
#define CLK_PCIEPHY1_OSC0 33
#define CLK_PCIEPHY1_REF 34
#define CLK_PCIEPHY2_DIV 35
#define CLK_PCIEPHY2_OSC0 36
#define CLK_PCIEPHY2_REF 37
#define CLK_PCIE30PHY_REF_M 38
#define CLK_PCIE30PHY_REF_N 39
#define CLK_HDMI_REF 40
#define XIN_OSC0_EDPPHY_G 41
#define PCLK_PDPMU 42
#define PCLK_PMU 43
#define PCLK_UART0 44
#define PCLK_I2C0 45
#define PCLK_GPIO0 46
#define PCLK_PMUPVTM 47
#define PCLK_PWM0 48
#define CLK_PDPMU 49
#define SCLK_32K_IOE 50
#define CLKPMU_NR_CLKS (SCLK_32K_IOE + 1)
/* cru-clocks indices */
/* cru plls */
#define PLL_APLL 1
#define PLL_DPLL 2
#define PLL_CPLL 3
#define PLL_GPLL 4
#define PLL_VPLL 5
#define PLL_NPLL 6
/* cru clocks */
#define CPLL_333M 9
#define ARMCLK 10
#define USB480M 11
#define ACLK_CORE_NIU2BUS 18
#define CLK_CORE_PVTM 19
#define CLK_CORE_PVTM_CORE 20
#define CLK_CORE_PVTPLL 21
#define CLK_GPU_SRC 22
#define CLK_GPU_PRE_NDFT 23
#define CLK_GPU_PRE_MUX 24
#define ACLK_GPU_PRE 25
#define PCLK_GPU_PRE 26
#define CLK_GPU 27
#define CLK_GPU_NP5 28
#define PCLK_GPU_PVTM 29
#define CLK_GPU_PVTM 30
#define CLK_GPU_PVTM_CORE 31
#define CLK_GPU_PVTPLL 32
#define CLK_NPU_SRC 33
#define CLK_NPU_PRE_NDFT 34
#define CLK_NPU 35
#define CLK_NPU_NP5 36
#define HCLK_NPU_PRE 37
#define PCLK_NPU_PRE 38
#define ACLK_NPU_PRE 39
#define ACLK_NPU 40
#define HCLK_NPU 41
#define PCLK_NPU_PVTM 42
#define CLK_NPU_PVTM 43
#define CLK_NPU_PVTM_CORE 44
#define CLK_NPU_PVTPLL 45
#define CLK_DDRPHY1X_SRC 46
#define CLK_DDRPHY1X_HWFFC_SRC 47
#define CLK_DDR1X 48
#define CLK_MSCH 49
#define CLK24_DDRMON 50
#define ACLK_GIC_AUDIO 51
#define HCLK_GIC_AUDIO 52
#define HCLK_SDMMC_BUFFER 53
#define DCLK_SDMMC_BUFFER 54
#define ACLK_GIC600 55
#define ACLK_SPINLOCK 56
#define HCLK_I2S0_8CH 57
#define HCLK_I2S1_8CH 58
#define HCLK_I2S2_2CH 59
#define HCLK_I2S3_2CH 60
#define CLK_I2S0_8CH_TX_SRC 61
#define CLK_I2S0_8CH_TX_FRAC 62
#define MCLK_I2S0_8CH_TX 63
#define I2S0_MCLKOUT_TX 64
#define CLK_I2S0_8CH_RX_SRC 65
#define CLK_I2S0_8CH_RX_FRAC 66
#define MCLK_I2S0_8CH_RX 67
#define I2S0_MCLKOUT_RX 68
#define CLK_I2S1_8CH_TX_SRC 69
#define CLK_I2S1_8CH_TX_FRAC 70
#define MCLK_I2S1_8CH_TX 71
#define I2S1_MCLKOUT_TX 72
#define CLK_I2S1_8CH_RX_SRC 73
#define CLK_I2S1_8CH_RX_FRAC 74
#define MCLK_I2S1_8CH_RX 75
#define I2S1_MCLKOUT_RX 76
#define CLK_I2S2_2CH_SRC 77
#define CLK_I2S2_2CH_FRAC 78
#define MCLK_I2S2_2CH 79
#define I2S2_MCLKOUT 80
#define CLK_I2S3_2CH_TX_SRC 81
#define CLK_I2S3_2CH_TX_FRAC 82
#define MCLK_I2S3_2CH_TX 83
#define I2S3_MCLKOUT_TX 84
#define CLK_I2S3_2CH_RX_SRC 85
#define CLK_I2S3_2CH_RX_FRAC 86
#define MCLK_I2S3_2CH_RX 87
#define I2S3_MCLKOUT_RX 88
#define HCLK_PDM 89
#define MCLK_PDM 90
#define HCLK_VAD 91
#define HCLK_SPDIF_8CH 92
#define MCLK_SPDIF_8CH_SRC 93
#define MCLK_SPDIF_8CH_FRAC 94
#define MCLK_SPDIF_8CH 95
#define HCLK_AUDPWM 96
#define SCLK_AUDPWM_SRC 97
#define SCLK_AUDPWM_FRAC 98
#define SCLK_AUDPWM 99
#define HCLK_ACDCDIG 100
#define CLK_ACDCDIG_I2C 101
#define CLK_ACDCDIG_DAC 102
#define CLK_ACDCDIG_ADC 103
#define ACLK_SECURE_FLASH 104
#define HCLK_SECURE_FLASH 105
#define ACLK_CRYPTO_NS 106
#define HCLK_CRYPTO_NS 107
#define CLK_CRYPTO_NS_CORE 108
#define CLK_CRYPTO_NS_PKA 109
#define CLK_CRYPTO_NS_RNG 110
#define HCLK_TRNG_NS 111
#define CLK_TRNG_NS 112
#define PCLK_OTPC_NS 113
#define CLK_OTPC_NS_SBPI 114
#define CLK_OTPC_NS_USR 115
#define HCLK_NANDC 116
#define NCLK_NANDC 117
#define HCLK_SFC 118
#define HCLK_SFC_XIP 119
#define SCLK_SFC 120
#define ACLK_EMMC 121
#define HCLK_EMMC 122
#define BCLK_EMMC 123
#define CCLK_EMMC 124
#define TCLK_EMMC 125
#define ACLK_PIPE 126
#define PCLK_PIPE 127
#define PCLK_PIPE_GRF 128
#define ACLK_PCIE20_MST 129
#define ACLK_PCIE20_SLV 130
#define ACLK_PCIE20_DBI 131
#define PCLK_PCIE20 132
#define CLK_PCIE20_AUX_NDFT 133
#define CLK_PCIE20_AUX_DFT 134
#define CLK_PCIE20_PIPE_DFT 135
#define ACLK_PCIE30X1_MST 136
#define ACLK_PCIE30X1_SLV 137
#define ACLK_PCIE30X1_DBI 138
#define PCLK_PCIE30X1 139
#define CLK_PCIE30X1_AUX_NDFT 140
#define CLK_PCIE30X1_AUX_DFT 141
#define CLK_PCIE30X1_PIPE_DFT 142
#define ACLK_PCIE30X2_MST 143
#define ACLK_PCIE30X2_SLV 144
#define ACLK_PCIE30X2_DBI 145
#define PCLK_PCIE30X2 146
#define CLK_PCIE30X2_AUX_NDFT 147
#define CLK_PCIE30X2_AUX_DFT 148
#define CLK_PCIE30X2_PIPE_DFT 149
#define ACLK_SATA0 150
#define CLK_SATA0_PMALIVE 151
#define CLK_SATA0_RXOOB 152
#define CLK_SATA0_PIPE_NDFT 153
#define CLK_SATA0_PIPE_DFT 154
#define ACLK_SATA1 155
#define CLK_SATA1_PMALIVE 156
#define CLK_SATA1_RXOOB 157
#define CLK_SATA1_PIPE_NDFT 158
#define CLK_SATA1_PIPE_DFT 159
#define ACLK_SATA2 160
#define CLK_SATA2_PMALIVE 161
#define CLK_SATA2_RXOOB 162
#define CLK_SATA2_PIPE_NDFT 163
#define CLK_SATA2_PIPE_DFT 164
#define ACLK_USB3OTG0 165
#define CLK_USB3OTG0_REF 166
#define CLK_USB3OTG0_SUSPEND 167
#define ACLK_USB3OTG1 168
#define CLK_USB3OTG1_REF 169
#define CLK_USB3OTG1_SUSPEND 170
#define CLK_XPCS_EEE 171
#define PCLK_XPCS 172
#define ACLK_PHP 173
#define HCLK_PHP 174
#define PCLK_PHP 175
#define HCLK_SDMMC0 176
#define CLK_SDMMC0 177
#define HCLK_SDMMC1 178
#define CLK_SDMMC1 179
#define ACLK_GMAC0 180
#define PCLK_GMAC0 181
#define CLK_MAC0_2TOP 182
#define CLK_MAC0_OUT 183
#define CLK_MAC0_REFOUT 184
#define CLK_GMAC0_PTP_REF 185
#define ACLK_USB 186
#define HCLK_USB 187
#define PCLK_USB 188
#define HCLK_USB2HOST0 189
#define HCLK_USB2HOST0_ARB 190
#define HCLK_USB2HOST1 191
#define HCLK_USB2HOST1_ARB 192
#define HCLK_SDMMC2 193
#define CLK_SDMMC2 194
#define ACLK_GMAC1 195
#define PCLK_GMAC1 196
#define CLK_MAC1_2TOP 197
#define CLK_MAC1_OUT 198
#define CLK_MAC1_REFOUT 199
#define CLK_GMAC1_PTP_REF 200
#define ACLK_PERIMID 201
#define HCLK_PERIMID 202
#define ACLK_VI 203
#define HCLK_VI 204
#define PCLK_VI 205
#define ACLK_VICAP 206
#define HCLK_VICAP 207
#define DCLK_VICAP 208
#define ICLK_VICAP_G 209
#define ACLK_ISP 210
#define HCLK_ISP 211
#define CLK_ISP 212
#define PCLK_CSI2HOST1 213
#define CLK_CIF_OUT 214
#define CLK_CAM0_OUT 215
#define CLK_CAM1_OUT 216
#define ACLK_VO 217
#define HCLK_VO 218
#define PCLK_VO 219
#define ACLK_VOP_PRE 220
#define ACLK_VOP 221
#define HCLK_VOP 222
#define DCLK_VOP0 223
#define DCLK_VOP1 224
#define DCLK_VOP2 225
#define CLK_VOP_PWM 226
#define ACLK_HDCP 227
#define HCLK_HDCP 228
#define PCLK_HDCP 229
#define PCLK_HDMI_HOST 230
#define CLK_HDMI_SFR 231
#define PCLK_DSITX_0 232
#define PCLK_DSITX_1 233
#define PCLK_EDP_CTRL 234
#define CLK_EDP_200M 235
#define ACLK_VPU_PRE 236
#define HCLK_VPU_PRE 237
#define ACLK_VPU 238
#define HCLK_VPU 239
#define ACLK_RGA_PRE 240
#define HCLK_RGA_PRE 241
#define PCLK_RGA_PRE 242
#define ACLK_RGA 243
#define HCLK_RGA 244
#define CLK_RGA_CORE 245
#define ACLK_IEP 246
#define HCLK_IEP 247
#define CLK_IEP_CORE 248
#define HCLK_EBC 249
#define DCLK_EBC 250
#define ACLK_JDEC 251
#define HCLK_JDEC 252
#define ACLK_JENC 253
#define HCLK_JENC 254
#define PCLK_EINK 255
#define HCLK_EINK 256
#define ACLK_RKVENC_PRE 257
#define HCLK_RKVENC_PRE 258
#define ACLK_RKVENC 259
#define HCLK_RKVENC 260
#define CLK_RKVENC_CORE 261
#define ACLK_RKVDEC_PRE 262
#define HCLK_RKVDEC_PRE 263
#define ACLK_RKVDEC 264
#define HCLK_RKVDEC 265
#define CLK_RKVDEC_CA 266
#define CLK_RKVDEC_CORE 267
#define CLK_RKVDEC_HEVC_CA 268
#define ACLK_BUS 269
#define PCLK_BUS 270
#define PCLK_TSADC 271
#define CLK_TSADC_TSEN 272
#define CLK_TSADC 273
#define PCLK_SARADC 274
#define CLK_SARADC 275
#define PCLK_SCR 276
#define PCLK_WDT_NS 277
#define TCLK_WDT_NS 278
#define ACLK_DMAC0 279
#define ACLK_DMAC1 280
#define ACLK_MCU 281
#define PCLK_INTMUX 282
#define PCLK_MAILBOX 283
#define PCLK_UART1 284
#define CLK_UART1_SRC 285
#define CLK_UART1_FRAC 286
#define SCLK_UART1 287
#define PCLK_UART2 288
#define CLK_UART2_SRC 289
#define CLK_UART2_FRAC 290
#define SCLK_UART2 291
#define PCLK_UART3 292
#define CLK_UART3_SRC 293
#define CLK_UART3_FRAC 294
#define SCLK_UART3 295
#define PCLK_UART4 296
#define CLK_UART4_SRC 297
#define CLK_UART4_FRAC 298
#define SCLK_UART4 299
#define PCLK_UART5 300
#define CLK_UART5_SRC 301
#define CLK_UART5_FRAC 302
#define SCLK_UART5 303
#define PCLK_UART6 304
#define CLK_UART6_SRC 305
#define CLK_UART6_FRAC 306
#define SCLK_UART6 307
#define PCLK_UART7 308
#define CLK_UART7_SRC 309
#define CLK_UART7_FRAC 310
#define SCLK_UART7 311
#define PCLK_UART8 312
#define CLK_UART8_SRC 313
#define CLK_UART8_FRAC 314
#define SCLK_UART8 315
#define PCLK_UART9 316
#define CLK_UART9_SRC 317
#define CLK_UART9_FRAC 318
#define SCLK_UART9 319
#define PCLK_CAN0 320
#define CLK_CAN0 321
#define PCLK_CAN1 322
#define CLK_CAN1 323
#define PCLK_CAN2 324
#define CLK_CAN2 325
#define CLK_I2C 326
#define PCLK_I2C1 327
#define CLK_I2C1 328
#define PCLK_I2C2 329
#define CLK_I2C2 330
#define PCLK_I2C3 331
#define CLK_I2C3 332
#define PCLK_I2C4 333
#define CLK_I2C4 334
#define PCLK_I2C5 335
#define CLK_I2C5 336
#define PCLK_SPI0 337
#define CLK_SPI0 338
#define PCLK_SPI1 339
#define CLK_SPI1 340
#define PCLK_SPI2 341
#define CLK_SPI2 342
#define PCLK_SPI3 343
#define CLK_SPI3 344
#define PCLK_PWM1 345
#define CLK_PWM1 346
#define CLK_PWM1_CAPTURE 347
#define PCLK_PWM2 348
#define CLK_PWM2 349
#define CLK_PWM2_CAPTURE 350
#define PCLK_PWM3 351
#define CLK_PWM3 352
#define CLK_PWM3_CAPTURE 353
#define DBCLK_GPIO 354
#define PCLK_GPIO1 355
#define DBCLK_GPIO1 356
#define PCLK_GPIO2 357
#define DBCLK_GPIO2 358
#define PCLK_GPIO3 359
#define DBCLK_GPIO3 360
#define PCLK_GPIO4 361
#define DBCLK_GPIO4 362
#define OCC_SCAN_CLK_GPIO 363
#define PCLK_TIMER 364
#define CLK_TIMER0 365
#define CLK_TIMER1 366
#define CLK_TIMER2 367
#define CLK_TIMER3 368
#define CLK_TIMER4 369
#define CLK_TIMER5 370
#define ACLK_TOP_HIGH 371
#define ACLK_TOP_LOW 372
#define HCLK_TOP 373
#define PCLK_TOP 374
#define PCLK_PCIE30PHY 375
#define CLK_OPTC_ARB 376
#define PCLK_MIPICSIPHY 377
#define PCLK_MIPIDSIPHY0 378
#define PCLK_MIPIDSIPHY1 379
#define PCLK_PIPEPHY0 380
#define PCLK_PIPEPHY1 381
#define PCLK_PIPEPHY2 382
#define PCLK_CPU_BOOST 383
#define CLK_CPU_BOOST 384
#define PCLK_OTPPHY 385
#define SCLK_GMAC0 386
#define SCLK_GMAC0_RGMII_SPEED 387
#define SCLK_GMAC0_RMII_SPEED 388
#define SCLK_GMAC0_RX_TX 389
#define SCLK_GMAC1 390
#define SCLK_GMAC1_RGMII_SPEED 391
#define SCLK_GMAC1_RMII_SPEED 392
#define SCLK_GMAC1_RX_TX 393
#define SCLK_SDMMC0_DRV 394
#define SCLK_SDMMC0_SAMPLE 395
#define SCLK_SDMMC1_DRV 396
#define SCLK_SDMMC1_SAMPLE 397
#define SCLK_SDMMC2_DRV 398
#define SCLK_SDMMC2_SAMPLE 399
#define SCLK_EMMC_DRV 400
#define SCLK_EMMC_SAMPLE 401
#define PCLK_EDPPHY_GRF 402
#define CLK_HDMI_CEC 403
#define CLK_I2S0_8CH_TX 404
#define CLK_I2S0_8CH_RX 405
#define CLK_I2S1_8CH_TX 406
#define CLK_I2S1_8CH_RX 407
#define CLK_I2S2_2CH 408
#define CLK_I2S3_2CH_TX 409
#define CLK_I2S3_2CH_RX 410
#define CPLL_500M 411
#define CPLL_250M 412
#define CPLL_125M 413
#define CPLL_62P5M 414
#define CPLL_50M 415
#define CPLL_25M 416
#define CPLL_100M 417
#define SCLK_DDRCLK 418
#define PCLK_CORE_PVTM 450
#define CLK_NR_CLKS (PCLK_CORE_PVTM + 1)
/* pmu soft-reset indices */
/* pmucru_softrst_con0 */
#define SRST_P_PDPMU_NIU 0
#define SRST_P_PMUCRU 1
#define SRST_P_PMUGRF 2
#define SRST_P_I2C0 3
#define SRST_I2C0 4
#define SRST_P_UART0 5
#define SRST_S_UART0 6
#define SRST_P_PWM0 7
#define SRST_PWM0 8
#define SRST_P_GPIO0 9
#define SRST_GPIO0 10
#define SRST_P_PMUPVTM 11
#define SRST_PMUPVTM 12
/* soft-reset indices */
/* cru_softrst_con0 */
#define SRST_NCORERESET0 0
#define SRST_NCORERESET1 1
#define SRST_NCORERESET2 2
#define SRST_NCORERESET3 3
#define SRST_NCPUPORESET0 4
#define SRST_NCPUPORESET1 5
#define SRST_NCPUPORESET2 6
#define SRST_NCPUPORESET3 7
#define SRST_NSRESET 8
#define SRST_NSPORESET 9
#define SRST_NATRESET 10
#define SRST_NGICRESET 11
#define SRST_NPRESET 12
#define SRST_NPERIPHRESET 13
/* cru_softrst_con1 */
#define SRST_A_CORE_NIU2DDR 16
#define SRST_A_CORE_NIU2BUS 17
#define SRST_P_DBG_NIU 18
#define SRST_P_DBG 19
#define SRST_P_DBG_DAPLITE 20
#define SRST_DAP 21
#define SRST_A_ADB400_CORE2GIC 22
#define SRST_A_ADB400_GIC2CORE 23
#define SRST_P_CORE_GRF 24
#define SRST_P_CORE_PVTM 25
#define SRST_CORE_PVTM 26
#define SRST_CORE_PVTPLL 27
/* cru_softrst_con2 */
#define SRST_GPU 32
#define SRST_A_GPU_NIU 33
#define SRST_P_GPU_NIU 34
#define SRST_P_GPU_PVTM 35
#define SRST_GPU_PVTM 36
#define SRST_GPU_PVTPLL 37
#define SRST_A_NPU_NIU 40
#define SRST_H_NPU_NIU 41
#define SRST_P_NPU_NIU 42
#define SRST_A_NPU 43
#define SRST_H_NPU 44
#define SRST_P_NPU_PVTM 45
#define SRST_NPU_PVTM 46
#define SRST_NPU_PVTPLL 47
/* cru_softrst_con3 */
#define SRST_A_MSCH 51
#define SRST_HWFFC_CTRL 52
#define SRST_DDR_ALWAYSON 53
#define SRST_A_DDRSPLIT 54
#define SRST_DDRDFI_CTL 55
#define SRST_A_DMA2DDR 57
/* cru_softrst_con4 */
#define SRST_A_PERIMID_NIU 64
#define SRST_H_PERIMID_NIU 65
#define SRST_A_GIC_AUDIO_NIU 66
#define SRST_H_GIC_AUDIO_NIU 67
#define SRST_A_GIC600 68
#define SRST_A_GIC600_DEBUG 69
#define SRST_A_GICADB_CORE2GIC 70
#define SRST_A_GICADB_GIC2CORE 71
#define SRST_A_SPINLOCK 72
#define SRST_H_SDMMC_BUFFER 73
#define SRST_D_SDMMC_BUFFER 74
#define SRST_H_I2S0_8CH 75
#define SRST_H_I2S1_8CH 76
#define SRST_H_I2S2_2CH 77
#define SRST_H_I2S3_2CH 78
/* cru_softrst_con5 */
#define SRST_M_I2S0_8CH_TX 80
#define SRST_M_I2S0_8CH_RX 81
#define SRST_M_I2S1_8CH_TX 82
#define SRST_M_I2S1_8CH_RX 83
#define SRST_M_I2S2_2CH 84
#define SRST_M_I2S3_2CH_TX 85
#define SRST_M_I2S3_2CH_RX 86
#define SRST_H_PDM 87
#define SRST_M_PDM 88
#define SRST_H_VAD 89
#define SRST_H_SPDIF_8CH 90
#define SRST_M_SPDIF_8CH 91
#define SRST_H_AUDPWM 92
#define SRST_S_AUDPWM 93
#define SRST_H_ACDCDIG 94
#define SRST_ACDCDIG 95
/* cru_softrst_con6 */
#define SRST_A_SECURE_FLASH_NIU 96
#define SRST_H_SECURE_FLASH_NIU 97
#define SRST_A_CRYPTO_NS 103
#define SRST_H_CRYPTO_NS 104
#define SRST_CRYPTO_NS_CORE 105
#define SRST_CRYPTO_NS_PKA 106
#define SRST_CRYPTO_NS_RNG 107
#define SRST_H_TRNG_NS 108
#define SRST_TRNG_NS 109
/* cru_softrst_con7 */
#define SRST_H_NANDC 112
#define SRST_N_NANDC 113
#define SRST_H_SFC 114
#define SRST_H_SFC_XIP 115
#define SRST_S_SFC 116
#define SRST_A_EMMC 117
#define SRST_H_EMMC 118
#define SRST_B_EMMC 119
#define SRST_C_EMMC 120
#define SRST_T_EMMC 121
/* cru_softrst_con8 */
#define SRST_A_PIPE_NIU 128
#define SRST_P_PIPE_NIU 130
#define SRST_P_PIPE_GRF 133
#define SRST_A_SATA0 134
#define SRST_SATA0_PIPE 135
#define SRST_SATA0_PMALIVE 136
#define SRST_SATA0_RXOOB 137
#define SRST_A_SATA1 138
#define SRST_SATA1_PIPE 139
#define SRST_SATA1_PMALIVE 140
#define SRST_SATA1_RXOOB 141
/* cru_softrst_con9 */
#define SRST_A_SATA2 144
#define SRST_SATA2_PIPE 145
#define SRST_SATA2_PMALIVE 146
#define SRST_SATA2_RXOOB 147
#define SRST_USB3OTG0 148
#define SRST_USB3OTG1 149
#define SRST_XPCS 150
#define SRST_XPCS_TX_DIV10 151
#define SRST_XPCS_RX_DIV10 152
#define SRST_XPCS_XGXS_RX 153
/* cru_softrst_con10 */
#define SRST_P_PCIE20 160
#define SRST_PCIE20_POWERUP 161
#define SRST_MSTR_ARESET_PCIE20 162
#define SRST_SLV_ARESET_PCIE20 163
#define SRST_DBI_ARESET_PCIE20 164
#define SRST_BRESET_PCIE20 165
#define SRST_PERST_PCIE20 166
#define SRST_CORE_RST_PCIE20 167
#define SRST_NSTICKY_RST_PCIE20 168
#define SRST_STICKY_RST_PCIE20 169
#define SRST_PWR_RST_PCIE20 170
/* cru_softrst_con11 */
#define SRST_P_PCIE30X1 176
#define SRST_PCIE30X1_POWERUP 177
#define SRST_M_ARESET_PCIE30X1 178
#define SRST_S_ARESET_PCIE30X1 179
#define SRST_D_ARESET_PCIE30X1 180
#define SRST_BRESET_PCIE30X1 181
#define SRST_PERST_PCIE30X1 182
#define SRST_CORE_RST_PCIE30X1 183
#define SRST_NSTC_RST_PCIE30X1 184
#define SRST_STC_RST_PCIE30X1 185
#define SRST_PWR_RST_PCIE30X1 186
/* cru_softrst_con12 */
#define SRST_P_PCIE30X2 192
#define SRST_PCIE30X2_POWERUP 193
#define SRST_M_ARESET_PCIE30X2 194
#define SRST_S_ARESET_PCIE30X2 195
#define SRST_D_ARESET_PCIE30X2 196
#define SRST_BRESET_PCIE30X2 197
#define SRST_PERST_PCIE30X2 198
#define SRST_CORE_RST_PCIE30X2 199
#define SRST_NSTC_RST_PCIE30X2 200
#define SRST_STC_RST_PCIE30X2 201
#define SRST_PWR_RST_PCIE30X2 202
/* cru_softrst_con13 */
#define SRST_A_PHP_NIU 208
#define SRST_H_PHP_NIU 209
#define SRST_P_PHP_NIU 210
#define SRST_H_SDMMC0 211
#define SRST_SDMMC0 212
#define SRST_H_SDMMC1 213
#define SRST_SDMMC1 214
#define SRST_A_GMAC0 215
#define SRST_GMAC0_TIMESTAMP 216
/* cru_softrst_con14 */
#define SRST_A_USB_NIU 224
#define SRST_H_USB_NIU 225
#define SRST_P_USB_NIU 226
#define SRST_P_USB_GRF 227
#define SRST_H_USB2HOST0 228
#define SRST_H_USB2HOST0_ARB 229
#define SRST_USB2HOST0_UTMI 230
#define SRST_H_USB2HOST1 231
#define SRST_H_USB2HOST1_ARB 232
#define SRST_USB2HOST1_UTMI 233
#define SRST_H_SDMMC2 234
#define SRST_SDMMC2 235
#define SRST_A_GMAC1 236
#define SRST_GMAC1_TIMESTAMP 237
/* cru_softrst_con15 */
#define SRST_A_VI_NIU 240
#define SRST_H_VI_NIU 241
#define SRST_P_VI_NIU 242
#define SRST_A_VICAP 247
#define SRST_H_VICAP 248
#define SRST_D_VICAP 249
#define SRST_I_VICAP 250
#define SRST_P_VICAP 251
#define SRST_H_ISP 252
#define SRST_ISP 253
#define SRST_P_CSI2HOST1 255
/* cru_softrst_con16 */
#define SRST_A_VO_NIU 256
#define SRST_H_VO_NIU 257
#define SRST_P_VO_NIU 258
#define SRST_A_VOP_NIU 259
#define SRST_A_VOP 260
#define SRST_H_VOP 261
#define SRST_VOP0 262
#define SRST_VOP1 263
#define SRST_VOP2 264
#define SRST_VOP_PWM 265
#define SRST_A_HDCP 266
#define SRST_H_HDCP 267
#define SRST_P_HDCP 268
#define SRST_P_HDMI_HOST 270
#define SRST_HDMI_HOST 271
/* cru_softrst_con17 */
#define SRST_P_DSITX_0 272
#define SRST_P_DSITX_1 273
#define SRST_P_EDP_CTRL 274
#define SRST_EDP_24M 275
#define SRST_A_VPU_NIU 280
#define SRST_H_VPU_NIU 281
#define SRST_A_VPU 282
#define SRST_H_VPU 283
#define SRST_H_EINK 286
#define SRST_P_EINK 287
/* cru_softrst_con18 */
#define SRST_A_RGA_NIU 288
#define SRST_H_RGA_NIU 289
#define SRST_P_RGA_NIU 290
#define SRST_A_RGA 292
#define SRST_H_RGA 293
#define SRST_RGA_CORE 294
#define SRST_A_IEP 295
#define SRST_H_IEP 296
#define SRST_IEP_CORE 297
#define SRST_H_EBC 298
#define SRST_D_EBC 299
#define SRST_A_JDEC 300
#define SRST_H_JDEC 301
#define SRST_A_JENC 302
#define SRST_H_JENC 303
/* cru_softrst_con19 */
#define SRST_A_VENC_NIU 304
#define SRST_H_VENC_NIU 305
#define SRST_A_RKVENC 307
#define SRST_H_RKVENC 308
#define SRST_RKVENC_CORE 309
/* cru_softrst_con20 */
#define SRST_A_RKVDEC_NIU 320
#define SRST_H_RKVDEC_NIU 321
#define SRST_A_RKVDEC 322
#define SRST_H_RKVDEC 323
#define SRST_RKVDEC_CA 324
#define SRST_RKVDEC_CORE 325
#define SRST_RKVDEC_HEVC_CA 326
/* cru_softrst_con21 */
#define SRST_A_BUS_NIU 336
#define SRST_P_BUS_NIU 338
#define SRST_P_CAN0 340
#define SRST_CAN0 341
#define SRST_P_CAN1 342
#define SRST_CAN1 343
#define SRST_P_CAN2 344
#define SRST_CAN2 345
#define SRST_P_GPIO1 346
#define SRST_GPIO1 347
#define SRST_P_GPIO2 348
#define SRST_GPIO2 349
#define SRST_P_GPIO3 350
#define SRST_GPIO3 351
/* cru_softrst_con22 */
#define SRST_P_GPIO4 352
#define SRST_GPIO4 353
#define SRST_P_I2C1 354
#define SRST_I2C1 355
#define SRST_P_I2C2 356
#define SRST_I2C2 357
#define SRST_P_I2C3 358
#define SRST_I2C3 359
#define SRST_P_I2C4 360
#define SRST_I2C4 361
#define SRST_P_I2C5 362
#define SRST_I2C5 363
#define SRST_P_OTPC_NS 364
#define SRST_OTPC_NS_SBPI 365
#define SRST_OTPC_NS_USR 366
/* cru_softrst_con23 */
#define SRST_P_PWM1 368
#define SRST_PWM1 369
#define SRST_P_PWM2 370
#define SRST_PWM2 371
#define SRST_P_PWM3 372
#define SRST_PWM3 373
#define SRST_P_SPI0 374
#define SRST_SPI0 375
#define SRST_P_SPI1 376
#define SRST_SPI1 377
#define SRST_P_SPI2 378
#define SRST_SPI2 379
#define SRST_P_SPI3 380
#define SRST_SPI3 381
/* cru_softrst_con24 */
#define SRST_P_SARADC 384
#define SRST_P_TSADC 385
#define SRST_TSADC 386
#define SRST_P_TIMER 387
#define SRST_TIMER0 388
#define SRST_TIMER1 389
#define SRST_TIMER2 390
#define SRST_TIMER3 391
#define SRST_TIMER4 392
#define SRST_TIMER5 393
#define SRST_P_UART1 394
#define SRST_S_UART1 395
/* cru_softrst_con25 */
#define SRST_P_UART2 400
#define SRST_S_UART2 401
#define SRST_P_UART3 402
#define SRST_S_UART3 403
#define SRST_P_UART4 404
#define SRST_S_UART4 405
#define SRST_P_UART5 406
#define SRST_S_UART5 407
#define SRST_P_UART6 408
#define SRST_S_UART6 409
#define SRST_P_UART7 410
#define SRST_S_UART7 411
#define SRST_P_UART8 412
#define SRST_S_UART8 413
#define SRST_P_UART9 414
#define SRST_S_UART9 415
/* cru_softrst_con26 */
#define SRST_P_GRF 416
#define SRST_P_GRF_VCCIO12 417
#define SRST_P_GRF_VCCIO34 418
#define SRST_P_GRF_VCCIO567 419
#define SRST_P_SCR 420
#define SRST_P_WDT_NS 421
#define SRST_T_WDT_NS 422
#define SRST_P_DFT2APB 423
#define SRST_A_MCU 426
#define SRST_P_INTMUX 427
#define SRST_P_MAILBOX 428
/* cru_softrst_con27 */
#define SRST_A_TOP_HIGH_NIU 432
#define SRST_A_TOP_LOW_NIU 433
#define SRST_H_TOP_NIU 434
#define SRST_P_TOP_NIU 435
#define SRST_P_TOP_CRU 438
#define SRST_P_DDRPHY 439
#define SRST_DDRPHY 440
#define SRST_P_MIPICSIPHY 442
#define SRST_P_MIPIDSIPHY0 443
#define SRST_P_MIPIDSIPHY1 444
#define SRST_P_PCIE30PHY 445
#define SRST_PCIE30PHY 446
#define SRST_P_PCIE30PHY_GRF 447
/* cru_softrst_con28 */
#define SRST_P_APB2ASB_LEFT 448
#define SRST_P_APB2ASB_BOTTOM 449
#define SRST_P_ASB2APB_LEFT 450
#define SRST_P_ASB2APB_BOTTOM 451
#define SRST_P_PIPEPHY0 452
#define SRST_PIPEPHY0 453
#define SRST_P_PIPEPHY1 454
#define SRST_PIPEPHY1 455
#define SRST_P_PIPEPHY2 456
#define SRST_PIPEPHY2 457
#define SRST_P_USB2PHY0_GRF 458
#define SRST_P_USB2PHY1_GRF 459
#define SRST_P_CPU_BOOST 460
#define SRST_CPU_BOOST 461
#define SRST_P_OTPPHY 462
#define SRST_OTPPHY 463
/* cru_softrst_con29 */
#define SRST_USB2PHY0_POR 464
#define SRST_USB2PHY0_USB3OTG0 465
#define SRST_USB2PHY0_USB3OTG1 466
#define SRST_USB2PHY1_POR 467
#define SRST_USB2PHY1_USB2HOST0 468
#define SRST_USB2PHY1_USB2HOST1 469
#define SRST_P_EDPPHY_GRF 470
#define SRST_TSADCPHY 471
#define SRST_GMAC0_DELAYLINE 472
#define SRST_GMAC1_DELAYLINE 473
#define SRST_OTPC_ARB 474
#define SRST_P_PIPEPHY0_GRF 475
#define SRST_P_PIPEPHY1_GRF 476
#define SRST_P_PIPEPHY2_GRF 477
#endif /* __DT_BINDINGS_CLK_ROCKCHIP_RK3568_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-26 GuEe-GUI first version
*/
struct rockchip_softrst
{
void *regs;
int num_per_reg;
rt_uint8_t flags;
struct rt_spinlock lock;
};
static rt_err_t rockchip_softrst_assert(struct rt_reset_control *rstc)
{
int bank, offset;
struct rockchip_softrst *softrst = rstc->rstcer->priv;
bank = rstc->id / softrst->num_per_reg;
offset = rstc->id % softrst->num_per_reg;
if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK)
{
HWREG32(softrst->regs + (bank * 4)) = RT_BIT(offset) | (RT_BIT(offset) << 16);
}
else
{
rt_uint32_t reg;
rt_ubase_t level;
level = rt_spin_lock_irqsave(&softrst->lock);
reg = HWREG32(softrst->regs + (bank * 4));
HWREG32(softrst->regs + (bank * 4)) = reg | RT_BIT(offset);
rt_spin_unlock_irqrestore(&softrst->lock, level);
}
return RT_EOK;
}
static rt_err_t rockchip_softrst_deassert(struct rt_reset_control *rstc)
{
int bank, offset;
struct rockchip_softrst *softrst = rstc->rstcer->priv;
bank = rstc->id / softrst->num_per_reg;
offset = rstc->id % softrst->num_per_reg;
if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK)
{
HWREG32(softrst->regs + (bank * 4)) = (RT_BIT(offset) << 16);
}
else
{
rt_uint32_t reg;
rt_ubase_t level;
level = rt_spin_lock_irqsave(&softrst->lock);
reg = HWREG32(softrst->regs + (bank * 4));
HWREG32(softrst->regs + (bank * 4)) = reg & ~RT_BIT(offset);
rt_spin_unlock_irqrestore(&softrst->lock, level);
}
return RT_EOK;
}
static const struct rt_reset_control_ops rockchip_softrst_ops =
{
.assert = rockchip_softrst_assert,
.deassert = rockchip_softrst_deassert,
};
static rt_err_t rk_register_softrst(struct rt_reset_controller *rstcer,
struct rt_ofw_node *np, void *regs, rt_uint8_t flags)
{
rt_err_t err;
struct rockchip_softrst *softrst = rt_calloc(1, sizeof(*softrst));
if (!softrst)
{
return -RT_ENOMEM;
}
rstcer->priv = softrst;
rt_spin_lock_init(&softrst->lock);
softrst->regs = regs;
softrst->flags = flags;
softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16 : 32;
rstcer->ofw_node = np;
rstcer->ops = &rockchip_softrst_ops;
if ((err = rt_reset_controller_register(rstcer)))
{
rt_free(softrst);
}
return err;
}

View File

@ -0,0 +1,5 @@
config RT_HWTIMER_ROCKCHIP
bool "RockChip Timer"
depends on RT_USING_DM
depends on RT_USING_HWTIMER
default n

View File

@ -0,0 +1,13 @@
from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd]
src = []
if GetDepend(['RT_HWTIMER_ROCKCHIP']):
src += ['hwtimer-rockchip_timer.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,393 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-12-06 GuEe-GUI first version
*/
#define DBG_TAG "drv.rk_timer"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#ifdef RT_USING_KTIME
#include <ktime.h>
#endif
#define HZ 100
#define KHZ 1000
#define MHZ 1000000
#define OSC_HZ (24 * MHZ)
#define TIMER_LOAD_COUNT0 0x00
#define TIMER_LOAD_COUNT1 0x04
#define TIMER_CURRENT_VALUE0 0x08
#define TIMER_CURRENT_VALUE1 0x0c
#define TIMER_CONTROL_REG3288 0x10
#define TIMER_CONTROL_REG3399 0x1c
#define TIMER_INT_STATUS 0x18
#define TIMER_DISABLE 0x0
#define TIMER_ENABLE 0x1
#define TIMER_MODE_FREE_RUNNING (0 << 1)
#define TIMER_MODE_USER_DEFINED_COUNT (1 << 1)
#define TIMER_INT_UNMASK (1 << 2)
struct rk_timer
{
struct rt_hwtimer_device parent;
void *base;
void *ctrl;
struct rt_clk *clk;
struct rt_clk *pclk;
int irq;
rt_uint32_t freq;
rt_uint32_t cycle;
rt_bool_t status;
struct rt_hwtimer_info info;
};
#ifdef RT_USING_KTIME
struct hrt_timer
{
struct rk_timer *timer;
uint64_t cnt;
void (*outcb)(void *param);
void *param;
};
static struct hrt_timer _timer0 = {0};
static struct rt_spinlock _spinlock;
#endif
#define raw_to_rk_timer(raw) rt_container_of(raw, struct rk_timer, parent)
struct rk_timer_data
{
rt_uint32_t ctrl_reg;
};
rt_inline void rk_timer_disable(struct rk_timer *timer)
{
HWREG32(timer->ctrl) = TIMER_DISABLE;
}
rt_inline void rk_timer_enable(struct rk_timer *timer, rt_uint32_t flags)
{
HWREG32(timer->ctrl) = TIMER_ENABLE | flags;
}
rt_inline rt_uint32_t rk_timer_current_value(struct rk_timer *timer)
{
return HWREG32(timer->base + TIMER_CURRENT_VALUE0);
}
static void rk_timer_update_counter(unsigned long cycles, struct rk_timer *timer)
{
HWREG32(timer->base + TIMER_LOAD_COUNT0) = cycles;
HWREG32(timer->base + TIMER_LOAD_COUNT1) = 0;
}
static void rk_timer_interrupt_clear(struct rk_timer *timer)
{
HWREG32(timer->base + TIMER_INT_STATUS) = 1;
}
static void rk_timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
{
}
static rt_err_t rk_timer_start(struct rt_hwtimer_device *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
{
rt_err_t err = RT_EOK;
struct rk_timer *rk_timer = raw_to_rk_timer(timer);
switch (mode)
{
case HWTIMER_MODE_ONESHOT:
rk_timer_disable(rk_timer);
rk_timer_update_counter(cnt, rk_timer);
rk_timer_enable(rk_timer, TIMER_MODE_USER_DEFINED_COUNT | TIMER_INT_UNMASK);
break;
case HWTIMER_MODE_PERIOD:
rk_timer_disable(rk_timer);
rk_timer_update_counter(rk_timer->freq / HZ - 1, rk_timer);
rk_timer_enable(rk_timer, TIMER_MODE_FREE_RUNNING | TIMER_INT_UNMASK);
break;
default:
err = -RT_EINVAL;
break;
}
if (!err)
{
rk_timer->cycle = cnt;
rk_timer->status = RT_TRUE;
}
return err;
}
static void rk_timer_stop(struct rt_hwtimer_device *timer)
{
struct rk_timer *rk_timer = raw_to_rk_timer(timer);
rk_timer->status = RT_FALSE;
rk_timer_disable(rk_timer);
}
static rt_uint32_t rk_timer_count_get(struct rt_hwtimer_device *timer)
{
struct rk_timer *rk_timer = raw_to_rk_timer(timer);
return rk_timer_current_value(rk_timer);
}
static rt_err_t rk_timer_ctrl(struct rt_hwtimer_device *timer, rt_uint32_t cmd, void *args)
{
rt_err_t err = RT_EOK;
struct rk_timer *rk_timer = raw_to_rk_timer(timer);
switch (cmd)
{
case HWTIMER_CTRL_FREQ_SET:
err = -RT_ENOSYS;
break;
case HWTIMER_CTRL_STOP:
rk_timer_stop(timer);
break;
case HWTIMER_CTRL_INFO_GET:
if (args)
{
rt_memcpy(args, &rk_timer->info, sizeof(rk_timer->info));
}
else
{
err = -RT_ERROR;
}
break;
case HWTIMER_CTRL_MODE_SET:
err = rk_timer_start(timer, rk_timer->cycle, (rt_hwtimer_mode_t)args);
break;
default:
err = -RT_EINVAL;
break;
}
return err;
}
const static struct rt_hwtimer_ops rk_timer_ops =
{
.init = rk_timer_init,
.start = rk_timer_start,
.stop = rk_timer_stop,
.count_get = rk_timer_count_get,
.control = rk_timer_ctrl,
};
static void rk_timer_isr(int irqno, void *param)
{
struct hrt_timer *timer = &_timer0;
struct rk_timer *time = timer->timer;
rk_timer_interrupt_clear(time);
rt_ktime_hrtimer_process();
}
void rt_ktime_hrtimer_bind(rt_bitmap_t *affinity)
{
struct rk_timer *timer = _timer0.timer;
if (rt_pic_irq_set_affinity(timer->irq, affinity) == -RT_ENOSYS)
{
LOG_E("timer irq affinity init fail\n");
}
else
{
LOG_D("timer irq(%d) binding done\n", timer->irq);
}
}
static rt_err_t rk_timer_probe(struct rt_platform_device *pdev)
{
rt_err_t err = RT_EOK;
const char *dev_name;
struct rt_device *dev = &pdev->parent;
struct rk_timer *timer = rt_calloc(1, sizeof(*timer));
const struct rk_timer_data *timer_data = pdev->id->data;
if (!timer)
{
return -RT_ENOMEM;
}
#ifdef RT_USING_KTIME
_timer0.timer = timer;
rt_spin_lock_init(&_spinlock);
#endif
if (!(timer->pclk = rt_clk_get_by_name(dev, "pclk")))
{
err = -RT_EIO;
goto _fail;
}
if (!(timer->clk = rt_clk_get_by_name(dev, "timer")))
{
err = -RT_EIO;
goto _fail;
}
timer->base = rt_dm_dev_iomap(dev, 0);
if (!timer->base)
{
err = -RT_EIO;
goto _fail;
}
timer->ctrl = timer->base + timer_data->ctrl_reg;
rt_clk_enable(timer->pclk);
rt_clk_enable(timer->clk);
timer->freq = rt_clk_get_rate(timer->clk);
timer->irq = rt_dm_dev_get_irq(dev, 0);
rk_timer_interrupt_clear(timer);
rk_timer_disable(timer);
timer->parent.ops = &rk_timer_ops;
timer->parent.info = &timer->info;
timer->info.maxfreq = timer->freq;
timer->info.minfreq = timer->freq;
timer->info.maxcnt = 0xffffffff;
timer->info.cntmode = HWTIMER_CNTMODE_DW;
rt_dm_dev_set_name_auto(&timer->parent.parent, "timer");
dev_name = rt_dm_dev_get_name(&timer->parent.parent);
rt_device_hwtimer_register(&timer->parent, dev_name, RT_NULL);
RT_BITMAP_DECLARE(affinity, RT_CPUS_NR) = { 0 };
rt_bitmap_set_bit(affinity, RT_CPUS_NR - 1);
rt_ktime_hrtimer_bind(affinity);
rt_pic_attach_irq(timer->irq, rk_timer_isr, timer, dev_name, RT_IRQ_F_NONE);
rt_pic_irq_unmask(timer->irq);
#if KTIMER_BIND_CPU
RT_BITMAP_DECLARE(affinity, RT_CPUS_NR) = {0};
rt_bitmap_set_bit(affinity, 1);
rt_pic_irq_set_affinity(timer->irq, affinity);
#endif
return err;
_fail:
if (timer->base)
{
rt_iounmap(timer->base);
}
if (timer->pclk)
{
rt_clk_put(timer->pclk);
}
if (timer->clk)
{
rt_clk_put(timer->clk);
}
rt_free(timer);
return err;
}
static const struct rk_timer_data rk3288_timer_data =
{
.ctrl_reg = TIMER_CONTROL_REG3288,
};
static const struct rk_timer_data rk3399_timer_data =
{
.ctrl_reg = TIMER_CONTROL_REG3399,
};
#ifdef RT_USING_KTIME
uint64_t rt_ktime_hrtimer_getfrq(void)
{
return (24 * 1000 * 1000UL);
}
uint64_t rt_ktime_hrtimer_getres(void)
{
return ((1000UL * 1000 * 1000) * RT_KTIME_RESMUL) / (24 * 1000 * 1000UL);
}
uint64_t rt_ktime_hrtimer_getcnt(void)
{
return rk_timer_current_value(_timer0.timer);
}
/**
* @brief set the timeout function for hrtimer framework
*
* @warning application should not call this API directly
*
* @param cnt the count of timer dealy
* @return rt_err_t 0 forever
*/
rt_err_t rt_ktime_hrtimer_settimeout(unsigned long cnt)
{
struct hrt_timer *timer = &_timer0;
struct rk_timer *time = timer->timer;
timer->cnt = cnt;
if (cnt)
{
rk_timer_disable(time);
rk_timer_update_counter(cnt, time);
rk_timer_enable(time, TIMER_MODE_USER_DEFINED_COUNT | TIMER_INT_UNMASK);
}
return 0;
}
#endif
static const struct rt_ofw_node_id rk_timer_ofw_ids[] =
{
{ .compatible = "rockchip,rk3288-timer", .data = &rk3288_timer_data },
{ .compatible = "rockchip,rk3399-timer", .data = &rk3399_timer_data },
{ /* sentinel */ }
};
static struct rt_platform_driver rk_timer_driver =
{
.name = "hwtimer-rockchip",
.ids = rk_timer_ofw_ids,
.probe = rk_timer_probe,
};
static int rk_timer_drv_register(void)
{
rt_platform_driver_register(&rk_timer_driver);
return 0;
}
INIT_DRIVER_EARLY_EXPORT(rk_timer_drv_register);

View File

@ -0,0 +1,5 @@
config RT_USING_RESET
bool "Using Reset Controller support"
depends on RT_USING_DM
select RT_USING_OFW
default n

View File

@ -0,0 +1,13 @@
from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd]
src = []
if GetDepend(['RT_USING_RESET']):
src += ['reset.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,429 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-26 GuEe-GUI first version
*/
#include <rtthread.h>
#include <rtservice.h>
#define DBG_TAG "rtdm.reset"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include <drivers/ofw.h>
#include "reset.h"
struct reset_control_array
{
struct rt_reset_control captain;
rt_size_t count;
struct rt_reset_control *rstcs[];
};
#define reset_control_to_array(rstc) rt_container_of(rstc, struct reset_control_array, captain)
static struct rt_spinlock _rstcer_lock = { 0 };
static rt_list_t _rstcer_nodes = RT_LIST_OBJECT_INIT(_rstcer_nodes);
rt_err_t rt_reset_controller_register(struct rt_reset_controller *rstcer)
{
rt_ubase_t level;
if (!rstcer)
{
return -RT_EINVAL;
}
rt_list_init(&rstcer->list);
rt_list_init(&rstcer->rstc_nodes);
rt_spin_lock_init(&rstcer->spinlock);
level = rt_spin_lock_irqsave(&_rstcer_lock);
rt_list_insert_after(&_rstcer_nodes, &rstcer->list);
rt_spin_unlock_irqrestore(&_rstcer_lock, level);
if (rstcer->ofw_node)
{
if (!rt_ofw_data(rstcer->ofw_node))
{
rt_ofw_data(rstcer->ofw_node) = rstcer;
}
}
return RT_EOK;
}
rt_err_t rt_reset_controller_unregister(struct rt_reset_controller *rstcer)
{
if (rstcer)
{
rt_spin_lock(&_rstcer_lock);
rt_list_remove(&rstcer->list);
rt_spin_unlock(&_rstcer_lock);
return RT_EOK;
}
return -RT_EINVAL;
}
rt_err_t rt_reset_control_reset(struct rt_reset_control *rstc)
{
rt_err_t err;
if (!rstc)
{
return -RT_EINVAL;
}
if (rstc->rstcer->ops->reset)
{
if ((err = rstc->rstcer->ops->reset(rstc)))
{
return err;
}
}
if (rstc->is_array)
{
struct reset_control_array *rstc_arr = reset_control_to_array(rstc);
for (int i = 0; i < rstc_arr->count; ++i)
{
if ((err = rt_reset_control_reset(rstc_arr->rstcs[i])))
{
return err;
}
}
}
return RT_EOK;
}
rt_err_t rt_reset_control_assert(struct rt_reset_control *rstc)
{
rt_err_t err;
if (!rstc)
{
return -RT_EINVAL;
}
if (rstc->deassert && rstc->rstcer->ops->assert)
{
if ((err = rstc->rstcer->ops->assert(rstc)))
{
return err;
}
rstc->deassert = RT_FALSE;
}
if (rstc->is_array)
{
struct reset_control_array *rstc_arr = reset_control_to_array(rstc);
for (int i = 0; i < rstc_arr->count; ++i)
{
if ((err = rt_reset_control_assert(rstc_arr->rstcs[i])))
{
if (rstc->rstcer->ops->deassert)
{
rstc->rstcer->ops->deassert(rstc);
rstc->deassert = RT_TRUE;
}
while (i --> 0)
{
rt_reset_control_deassert(rstc_arr->rstcs[i]);
}
return err;
}
}
}
return RT_EOK;
}
rt_err_t rt_reset_control_deassert(struct rt_reset_control *rstc)
{
rt_err_t err;
if (!rstc)
{
return -RT_EINVAL;
}
if (!rstc->deassert && rstc->rstcer->ops->deassert)
{
if ((err = rstc->rstcer->ops->deassert(rstc)))
{
return err;
}
rstc->deassert = RT_TRUE;
}
if (rstc->is_array)
{
struct reset_control_array *rstc_arr = reset_control_to_array(rstc);
for (int i = 0; i < rstc_arr->count; ++i)
{
if ((err = rt_reset_control_deassert(rstc_arr->rstcs[i])))
{
if (rstc->rstcer->ops->assert)
{
rstc->rstcer->ops->assert(rstc);
rstc->deassert = RT_FALSE;
}
while (i --> 0)
{
rt_reset_control_assert(rstc_arr->rstcs[i]);
}
return err;
}
}
}
return RT_EOK;
}
int rt_reset_control_status(struct rt_reset_control *rstc)
{
if (!rstc)
{
return -RT_EINVAL;
}
if (rstc->rstcer->ops->status)
{
return rstc->rstcer->ops->status(rstc);
}
return -RT_ENOSYS;
}
static void reset_free(struct rt_reset_control *rstc)
{
if (rstc->is_array)
{
struct reset_control_array *rstc_arr = reset_control_to_array(rstc);
for (int i = 0; i < rstc_arr->count; ++i)
{
rt_reset_control_put(rstc_arr->rstcs[i]);
}
}
rt_free(rstc);
}
struct rt_reset_control *rt_reset_control_get_array(struct rt_device *dev)
{
return rt_ofw_get_reset_control_array(dev->ofw_node);
}
struct rt_reset_control *rt_reset_control_get_by_index(struct rt_device *dev, int index)
{
return rt_ofw_get_reset_control_by_index(dev->ofw_node, index);
}
struct rt_reset_control *rt_reset_control_get_by_name(struct rt_device *dev, const char *name)
{
return rt_ofw_get_reset_control_by_name(dev->ofw_node, name);
}
void rt_reset_control_put(struct rt_reset_control *rstc)
{
struct rt_reset_controller *rstcer;
if (!rstc)
{
return;
}
rstcer = rstc->rstcer;
rt_spin_lock(&rstcer->spinlock);
rt_list_remove(&rstc->list);
rt_spin_unlock(&rstcer->spinlock);
reset_free(rstc);
}
static struct rt_reset_control *ofw_get_reset_control(struct rt_ofw_node *np, int index,
const char *name, rt_bool_t is_array)
{
struct rt_reset_control *rstc;
struct rt_ofw_cell_args reset_args = {};
struct rt_reset_controller *rstcer = RT_NULL;
if (is_array)
{
rt_size_t rstc_nr;
struct reset_control_array *rstc_arr;
rstc_nr = rt_ofw_count_phandle_cells(np, "resets", "#reset-cells");
if (!rstc_nr)
{
return RT_NULL;
}
rstc_arr = rt_calloc(1, sizeof(*rstc_arr) + sizeof(struct rt_reset_control *) * rstc_nr);
if (!rstc_arr)
{
LOG_E("No memory to create %s[%d] reset control",
rt_ofw_node_full_name(np), index);
return RT_NULL;
}
rstc_arr->count = rstc_nr - 1;
for (int i = 0; i < rstc_arr->count; ++i)
{
rstc_arr->rstcs[i] = ofw_get_reset_control(np, i + 1, RT_NULL, RT_FALSE);
if (!rstc_arr->rstcs[i])
{
while (i --> 0)
{
rt_reset_control_put(rstc_arr->rstcs[i]);
}
rt_free(rstc_arr);
rstc_arr = RT_NULL;
return RT_NULL;
}
}
rstc = &rstc_arr->captain;
rstc->is_array = RT_TRUE;
}
else
{
rstc = rt_calloc(1, sizeof(*rstc));
if (!rstc)
{
LOG_E("No memory to create %s[%d] reset control",
rt_ofw_node_full_name(np), index);
return RT_NULL;
}
}
if (!rt_ofw_parse_phandle_cells(np, "resets", "#reset-cells", index, &reset_args))
{
void *rt_data = rt_ofw_data(reset_args.data);
if (rt_data)
{
/* check is clk */
if (rt_ofw_prop_read_bool(reset_args.data, "#clock-cells"))
{
struct rt_reset_controller_clk_node *rstcer_clk = rt_data;
rstcer = &rstcer_clk->rstcer;
}
else
{
rstcer = rt_data;
}
}
rt_ofw_node_put(reset_args.data);
}
if (!rstcer)
{
goto _fail;
}
if (!name && rt_ofw_prop_read_bool(np, "reset-names"))
{
rt_ofw_prop_read_string_index(np, "reset-names", index, &name);
}
rstc->con_id = name;
rstc->rstcer = rstcer;
if (rstcer->ops->ofw_parse)
{
rt_err_t err = rstcer->ops->ofw_parse(rstc, &reset_args);
if (err)
{
LOG_E("Parse %s reset control error = %s",
rt_ofw_node_full_name(np), rt_strerror(err));
goto _fail;
}
}
rstc->id = reset_args.args[0];
rt_list_init(&rstc->list);
rt_spin_lock(&rstcer->spinlock);
rt_list_insert_after(&rstcer->rstc_nodes, &rstc->list);
rt_spin_unlock(&rstcer->spinlock);
return rstc;
_fail:
if (rstc && !rstc->is_array)
{
rt_free(rstc);
}
return RT_NULL;
}
struct rt_reset_control *rt_ofw_get_reset_control_array(struct rt_ofw_node *np)
{
return ofw_get_reset_control(np, 0, RT_NULL, RT_TRUE);
}
struct rt_reset_control *rt_ofw_get_reset_control_by_index(struct rt_ofw_node *np, int index)
{
return ofw_get_reset_control(np, index, RT_NULL, RT_FALSE);
}
struct rt_reset_control *rt_ofw_get_reset_control_by_name(struct rt_ofw_node *np, const char *name)
{
if (np)
{
int index = rt_ofw_prop_index_of_string(np, "reset-names", name);
if (index >= 0)
{
return ofw_get_reset_control(np, index, name, RT_FALSE);
}
}
return RT_NULL;
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-26 GuEe-GUI first version
*/
#ifndef __RESET_H__
#define __RESET_H__
#include <rthw.h>
#include <rtthread.h>
#include <drivers/ofw.h>
#include <drivers/clk.h>
struct rt_reset_control_ops;
struct rt_reset_controller
{
rt_list_t list;
rt_list_t rstc_nodes;
const char *name;
const struct rt_reset_control_ops *ops;
struct rt_ofw_node *ofw_node;
void *priv;
struct rt_spinlock spinlock;
};
/*
* It seems that most reset controllers are coupled to CLK.
* So we need a generic extends object.
*/
struct rt_reset_controller_clk_node
{
struct rt_clk_node parent;
struct rt_reset_controller rstcer;
};
struct rt_reset_control
{
rt_list_t list;
struct rt_reset_controller *rstcer;
int id;
const char *con_id;
rt_bool_t is_array;
rt_bool_t deassert;
void *priv;
};
struct rt_reset_control_ops
{
/*
* rt_ofw_cell_args return:
* args[0] = rstc.id
*/
rt_err_t (*ofw_parse)(struct rt_reset_control *, struct rt_ofw_cell_args *args);
/* API */
rt_err_t (*reset)(struct rt_reset_control *rstc);
rt_err_t (*assert)(struct rt_reset_control *rstc);
rt_err_t (*deassert)(struct rt_reset_control *rstc);
int (*status)(struct rt_reset_control *rstc);
};
rt_err_t rt_reset_controller_register(struct rt_reset_controller *rstcer);
rt_err_t rt_reset_controller_unregister(struct rt_reset_controller *rstcer);
rt_err_t rt_reset_control_reset(struct rt_reset_control *rstc);
rt_err_t rt_reset_control_assert(struct rt_reset_control *rstc);
rt_err_t rt_reset_control_deassert(struct rt_reset_control *rstc);
int rt_reset_control_status(struct rt_reset_control *rstc);
rt_ssize_t rt_reset_control_get_count(struct rt_device *dev);
struct rt_reset_control *rt_reset_control_get_array(struct rt_device *dev);
struct rt_reset_control *rt_reset_control_get_by_index(struct rt_device *dev, int index);
struct rt_reset_control *rt_reset_control_get_by_name(struct rt_device *dev, const char *name);
void rt_reset_control_put(struct rt_reset_control *rstc);
struct rt_reset_control *rt_ofw_get_reset_control_array(struct rt_ofw_node *np);
struct rt_reset_control *rt_ofw_get_reset_control_by_index(struct rt_ofw_node *np, int index);
struct rt_reset_control *rt_ofw_get_reset_control_by_name(struct rt_ofw_node *np, const char *name);
#endif /* __RESET_H__ */

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-3-08 GuEe-GUI the first version
*/
#ifndef __ROCKCHIP_H__
#define __ROCKCHIP_H__
#include <rthw.h>
#define rk_clrsetreg(addr, clr, set) HWREG32(addr) = (((clr) | (set)) << 16 | (set))
#define rk_clrreg(addr, clr) HWREG32(addr) = ((clr) << 16)
#define rk_setreg(addr, set) HWREG32(addr) = ((set) << 16 | (set))
#define HIWORD_UPDATE(val, mask, shift) ((val) << (shift) | (mask) << ((shift) + 16))
#endif /* __ROCKCHIP_H__ */

View File

@ -0,0 +1,341 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-22 GuEe-GUI first version
*/
/*
* The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
* LCR is written whilst busy. If it is, then a busy detect interrupt is
* raised, the LCR needs to be rewritten and the uart status register read.
*/
#include <rtthread.h>
#include "8250.h"
/* Offsets for the DesignWare specific registers */
#define DW_UART_USR 0x1f /* UART Status Register */
#define DW_UART_DMASA 0xa8 /* DMA Software Ack */
#define OCTEON_UART_USR 0x27 /* UART Status Register */
#define RZN1_UART_TDMACR 0x10c /* DMA Control Register Transmit Mode */
#define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */
/* DesignWare specific register fields */
#define DW_UART_MCR_SIRE RT_BIT(6)
/* Renesas specific register fields */
#define RZN1_UART_xDMACR_DMA_EN RT_BIT(0)
#define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1)
#define RZN1_UART_xDMACR_4_WORD_BURST (1 << 1)
#define RZN1_UART_xDMACR_8_WORD_BURST (2 << 1)
#define RZN1_UART_xDMACR_BLK_SZ(x) ((x) << 3)
/* Quirks */
#define DW_UART_QUIRK_OCTEON RT_BIT(0)
#define DW_UART_QUIRK_ARMADA_38X RT_BIT(1)
#define DW_UART_QUIRK_SKIP_SET_RATE RT_BIT(2)
#define DW_UART_QUIRK_IS_DMA_FC RT_BIT(3)
struct dw8250_platform_data
{
rt_uint8_t usr_reg;
rt_uint32_t cpr_val;
rt_uint32_t quirks;
};
struct dw8250
{
struct serial8250 parent;
struct rt_spinlock spinlock;
struct rt_clk *pclk;
rt_bool_t uart_16550_compatible;
struct dw8250_platform_data *platform_data;
};
#define to_dw8250(serial8250) rt_container_of(serial8250, struct dw8250, parent)
static void dw8250_check_lcr(struct serial8250 *serial, int value)
{
void *offset = (void *)(serial->base + (UART_LCR << serial->regshift));
int tries = 1000;
/* Make sure LCR write wasn't ignored */
while (tries--)
{
rt_uint32_t lcr = serial->serial_in(serial, UART_LCR);
if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
{
break;
}
serial->serial_out(serial, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial->serial_in(serial, UART_RX);
if (serial->iotype == PORT_MMIO32)
{
HWREG32(offset) = value;
}
else if (serial->iotype == PORT_MMIO32BE)
{
HWREG32(offset) = rt_cpu_to_be32(value);
}
else
{
HWREG8(offset) = value;
}
}
}
static void dw8250_serial_out32(struct serial8250 *serial, int offset, int value)
{
struct dw8250 *dw8250 = to_dw8250(serial);
HWREG32(serial->base + (offset << serial->regshift)) = value;
if (offset == UART_LCR && !dw8250->uart_16550_compatible)
{
dw8250_check_lcr(serial, value);
}
}
static rt_uint32_t dw8250_serial_in32(struct serial8250 *serial, int offset)
{
return HWREG32(serial->base + (offset << serial->regshift));
}
static rt_err_t dw8250_isr(struct serial8250 *serial, int irq)
{
unsigned int iir, status;
struct dw8250 *dw8250 = to_dw8250(serial);
iir = serial8250_in(serial, UART_IIR);
/*
* If don't do this in non-DMA mode then the "RX TIMEOUT" interrupt will
* fire forever.
*/
if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)
{
rt_base_t level = rt_spin_lock_irqsave(&dw8250->spinlock);
status = serial8250_in(serial, UART_LSR);
if (!(status & (UART_LSR_DR | UART_LSR_BI)))
{
serial8250_in(serial, UART_RX);
}
rt_spin_unlock_irqrestore(&dw8250->spinlock, level);
}
if (!(iir & UART_IIR_NO_INT))
{
rt_hw_serial_isr(&serial->parent, RT_SERIAL_EVENT_RX_IND);
}
if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY)
{
/* Clear the USR */
serial8250_in(serial, dw8250->platform_data->usr_reg);
}
return RT_EOK;
}
static void dw8250_free_resource(struct dw8250 *dw8250)
{
struct serial8250 *serial = &dw8250->parent;
if (serial->base)
{
rt_iounmap(serial->base);
}
if (serial->clk)
{
rt_clk_disable_unprepare(serial->clk);
rt_clk_put(serial->clk);
}
if (dw8250->pclk)
{
rt_clk_disable_unprepare(dw8250->pclk);
rt_clk_put(dw8250->pclk);
}
rt_free(dw8250);
}
static void dw8250_remove(struct serial8250 *serial)
{
struct dw8250 *dw8250 = to_dw8250(serial);
dw8250_free_resource(dw8250);
}
static rt_err_t dw8250_probe(struct rt_platform_device *pdev)
{
rt_err_t err;
rt_uint32_t val;
struct serial8250 *serial;
struct rt_device *dev = &pdev->parent;
struct dw8250 *dw8250 = serial8250_alloc(dw8250);
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
if (!dw8250)
{
return -RT_ENOMEM;
}
serial = &dw8250->parent;
serial->base = rt_dm_dev_iomap(dev, 0);
if (!serial->base)
{
err = -RT_EIO;
goto _free_res;
}
serial->irq = rt_dm_dev_get_irq(dev, 0);
if (serial->irq < 0)
{
err = serial->irq;
goto _free_res;
}
serial->clk = rt_clk_get_by_name(dev, "baudclk");
dw8250->pclk = rt_clk_get_by_name(dev, "apb_pclk");
if (!serial->clk)
{
if ((err = rt_dm_dev_prop_read_u32(dev, "clock-frequency", &serial->freq)))
{
goto _free_res;
}
}
else
{
if ((err = rt_clk_prepare_enable(serial->clk)))
{
goto _free_res;
}
serial->freq = rt_clk_get_rate(serial->clk);
}
if (!dw8250->pclk)
{
err = -RT_EIO;
goto _free_res;
}
if ((err = rt_clk_prepare_enable(dw8250->pclk)))
{
goto _free_res;
}
rt_dm_dev_prop_read_u32(dev, "reg-shift", &serial->regshift);
if (!rt_dm_dev_prop_read_u32(dev, "reg-io-width", &val) && val == 4)
{
serial->iotype = PORT_MMIO32;
serial->serial_in = &dw8250_serial_in32;
serial->serial_out = &dw8250_serial_out32;
}
dw8250->uart_16550_compatible = rt_dm_dev_prop_read_bool(dev, "snps,uart-16550-compatible");
dw8250->platform_data = (struct dw8250_platform_data *)pdev->id->data;
rt_dm_dev_bind_fwdata(&serial->parent.parent, pdev->parent.ofw_node, &serial->parent);
serial = &dw8250->parent;
serial->parent.ops = &serial8250_uart_ops;
serial->parent.config = config;
serial->handle_irq = &dw8250_isr;
serial->remove = &dw8250_remove;
serial->data = dw8250;
rt_spin_lock_init(&dw8250->spinlock);
if ((err = serial8250_setup(serial)))
{
goto _free_res;
}
return RT_EOK;
_free_res:
dw8250_free_resource(dw8250);
return err;
}
static const struct dw8250_platform_data dw8250_dw_apb =
{
.usr_reg = DW_UART_USR,
};
static const struct dw8250_platform_data dw8250_octeon_3860_data =
{
.usr_reg = OCTEON_UART_USR,
.quirks = DW_UART_QUIRK_OCTEON,
};
static const struct dw8250_platform_data dw8250_armada_38x_data =
{
.usr_reg = DW_UART_USR,
.quirks = DW_UART_QUIRK_ARMADA_38X,
};
static const struct dw8250_platform_data dw8250_renesas_rzn1_data =
{
.usr_reg = DW_UART_USR,
.cpr_val = 0x00012f32,
.quirks = DW_UART_QUIRK_IS_DMA_FC,
};
static const struct dw8250_platform_data dw8250_starfive_jh7100_data =
{
.usr_reg = DW_UART_USR,
.quirks = DW_UART_QUIRK_SKIP_SET_RATE,
};
static const struct rt_ofw_node_id dw8250_ofw_ids[] =
{
{ .type = "ttyS", .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
{ .type = "ttyS", .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
{ .type = "ttyS", .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
{ .type = "ttyS", .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
{ .type = "ttyS", .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data },
{ /* sentinel */ }
};
static struct rt_platform_driver dw8250_driver =
{
.name = "dw-apb-uart",
.ids = dw8250_ofw_ids,
.probe = dw8250_probe,
};
static int dw8250_drv_register(void)
{
rt_platform_driver_register(&dw8250_driver);
return 0;
}
INIT_DRIVER_EARLY_EXPORT(dw8250_drv_register);

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-16 GuEe-GUI first version
*/
#ifndef __SERIAL_8250_H__
#define __SERIAL_8250_H__
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <ioremap.h>
#include "regs.h"
#include "serial_dm.h"
enum
{
PORT_IO,
PORT_MMIO,
PORT_MMIO16,
PORT_MMIO32,
PORT_MMIO32BE,
};
struct serial8250
{
struct rt_serial_device parent;
struct rt_clk *clk;
int irq;
void *base;
rt_size_t size;
rt_uint32_t freq; /* frequency */
rt_uint32_t regshift; /* reg offset shift */
rt_uint8_t iotype; /* io access style */
struct rt_spinlock spinlock;
rt_uint32_t (*serial_in)(struct serial8250 *, int offset);
void (*serial_out)(struct serial8250 *, int offset, int value);
rt_err_t (*handle_irq)(struct serial8250 *, int irq);
/* Free all resource (and parent) by child */
void (*remove)(struct serial8250 *);
void *data;
};
#define serial8250_alloc(obj) rt_calloc(1, sizeof(typeof(*obj)))
#define raw_to_serial8250(raw_serial) rt_container_of(raw_serial, struct serial8250, parent)
rt_err_t serial8250_config(struct serial8250 *serial, const char *options);
rt_err_t serial8250_setup(struct serial8250 *serial);
rt_err_t serial8250_remove(struct serial8250 *serial);
rt_uint32_t serial8250_in(struct serial8250 *serial, int offset);
void serial8250_out(struct serial8250 *serial, int offset, int value);
rt_err_t serial8250_uart_configure(struct rt_serial_device *raw_serial, struct serial_configure *cfg);
rt_err_t serial8250_uart_control(struct rt_serial_device *raw_serial, int cmd, void *arg);
int serial8250_uart_putc(struct rt_serial_device *raw_serial, char c);
int serial8250_uart_getc(struct rt_serial_device *raw_serial);
int serial8250_early_putc(struct rt_serial_device *raw_serial, char c);
rt_err_t serial8250_early_fdt_setup(struct serial8250 *serial, struct rt_fdt_earlycon *con, const char *options);
extern struct serial8250 early_serial8250;
extern const struct rt_uart_ops serial8250_uart_ops;
#endif /* __SERIAL_8250_H__ */

View File

@ -0,0 +1,3 @@
config RT_SERIAL_8250
bool "8250 Serila Family"
default n

View File

@ -0,0 +1,13 @@
from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd]
src = ['core.c', 'early.c']
if GetDepend(['RT_SERIAL_8250']):
src += ['8250-dw.c']
src += ['fiq-debugger.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,303 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-16 GuEe-GUI first version
*/
#include "8250.h"
rt_err_t serial8250_config(struct serial8250 *serial, const char *options)
{
rt_err_t ret = -RT_EINVAL;
if (serial)
{
char *arg;
rt_bool_t has_iotype = RT_FALSE;
/*
* uart8250,io,<addr>[,options]
* uart8250,mmio,<addr>[,options]
* uart8250,mmio16,<addr>[,options]
* uart8250,mmio32,<addr>[,options]
* uart8250,mmio32be,<addr>[,options]
* uart8250,0x<addr>[,options]
*/
serial_for_each_args(arg, options)
{
if (!rt_strcmp(arg, "uart8250"))
{
ret = RT_EOK;
continue;
}
/* user call error */
if (ret)
{
break;
}
if (!rt_strncmp(arg, "0x", 2))
{
serial->base = serial_base_from_args(arg);
continue;
}
if (!has_iotype)
{
const struct
{
char *param;
int type;
} iotype_table[] =
{
{ "io", PORT_IO },
{ "mmio", PORT_MMIO },
{ "mmio16", PORT_MMIO16 },
{ "mmio32", PORT_MMIO32 },
{ "mmio32be", PORT_MMIO32BE },
};
serial->iotype = PORT_MMIO32;
for (int i = 0; i < RT_ARRAY_SIZE(iotype_table); ++i)
{
if (!rt_strcmp(arg, iotype_table[i].param))
{
serial->iotype = iotype_table[i].type;
break;
}
}
has_iotype = RT_TRUE;
continue;
}
serial->parent.config = serial_cfg_from_args(arg);
}
if (!serial->size)
{
serial->size = 0x1000;
}
}
return ret;
}
static void serial8250_isr(int irqno, void *param)
{
struct serial8250 *serial = (struct serial8250 *)param;
if (serial->handle_irq)
{
serial->handle_irq(serial, irqno);
}
else
{
rt_hw_serial_isr(&serial->parent, RT_SERIAL_EVENT_RX_IND);
}
}
rt_err_t serial8250_setup(struct serial8250 *serial)
{
rt_err_t ret = RT_EOK;
const char *uart_name;
char dev_name[RT_NAME_MAX];
if (serial)
{
rt_spin_lock_init(&serial->spinlock);
serial->serial_in = serial->serial_in ? : &serial8250_in;
serial->serial_out = serial->serial_out ? : &serial8250_out;
serial_dev_set_name(&serial->parent);
uart_name = rt_dm_dev_get_name(&serial->parent.parent);
rt_hw_serial_register(&serial->parent, uart_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, serial->data);
rt_snprintf(dev_name, sizeof(dev_name), "%s-8250", uart_name);
rt_pic_attach_irq(serial->irq, serial8250_isr, serial, dev_name, RT_IRQ_F_NONE);
}
else
{
ret = -RT_EINVAL;
}
return ret;
}
rt_err_t serial8250_remove(struct serial8250 *serial)
{
rt_err_t err;
rt_iounmap((void *)serial->base);
serial->base = RT_NULL;
rt_pic_irq_mask(serial->irq);
rt_pic_detach_irq(serial->irq, serial);
err = rt_device_unregister(&serial->parent.parent);
if (!err && serial->remove)
{
serial->remove(serial);
}
return err;
}
rt_uint32_t serial8250_in(struct serial8250 *serial, int offset)
{
rt_uint32_t ret = 0;
offset <<= serial->regshift;
switch (serial->iotype)
{
case PORT_MMIO:
ret = HWREG8(serial->base + offset);
break;
case PORT_MMIO16:
ret = HWREG16(serial->base + offset);
break;
case PORT_MMIO32:
ret = HWREG32(serial->base + offset);
break;
case PORT_MMIO32BE:
ret = rt_cpu_to_be32(HWREG32(serial->base + offset));
break;
#ifdef ARCH_SUPPORT_PIO
case PORT_IO:
ret = inb(serial->base + offset, value);
break;
#endif
default:
break;
}
return ret;
}
void serial8250_out(struct serial8250 *serial, int offset, int value)
{
offset <<= serial->regshift;
switch (serial->iotype)
{
case PORT_MMIO:
HWREG8(serial->base + offset) = value;
break;
case PORT_MMIO16:
HWREG16(serial->base + offset) = value;
break;
case PORT_MMIO32:
HWREG32(serial->base + offset) = value;
break;
case PORT_MMIO32BE:
HWREG32(serial->base + offset) = rt_cpu_to_be32(value);
break;
#ifdef ARCH_SUPPORT_PIO
case PORT_IO:
outb(serial->base + offset, value);
break;
#endif
default:
break;
}
}
rt_err_t serial8250_uart_configure(struct rt_serial_device *raw_serial, struct serial_configure *cfg)
{
rt_err_t err = RT_EOK;
struct serial8250 *serial = raw_to_serial8250(raw_serial);
/* Disable interrupt */
serial->serial_out(serial, UART_IER, !UART_IER_RDI);
/* Enable FIFO, Clear FIFO*/
serial->serial_out(serial, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
/* DTR + RTS */
serial->serial_out(serial, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
if (serial->freq)
{
rt_uint32_t wlen = cfg->data_bits - DATA_BITS_5 + UART_LCR_WLEN5;
rt_uint32_t divisor = serial->freq / 16 / cfg->baud_rate;
/* Enable access DLL & DLH */
serial->serial_out(serial, UART_LCR, serial->serial_in(serial, UART_LCR) | UART_LCR_DLAB);
serial->serial_out(serial, UART_DLL, (divisor & 0xff));
serial->serial_out(serial, UART_DLM, (divisor >> 8) & 0xff);
/* Clear DLAB bit */
serial->serial_out(serial, UART_LCR, serial->serial_in(serial, UART_LCR) & (~UART_LCR_DLAB));
serial->serial_out(serial, UART_LCR, (serial->serial_in(serial, UART_LCR) & (~wlen)) | wlen);
serial->serial_out(serial, UART_LCR, serial->serial_in(serial, UART_LCR) & (~UART_LCR_STOP));
serial->serial_out(serial, UART_LCR, serial->serial_in(serial, UART_LCR) & (~UART_LCR_PARITY));
}
serial->serial_out(serial, UART_IER, UART_IER_RDI);
return err;
}
rt_err_t serial8250_uart_control(struct rt_serial_device *raw_serial, int cmd, void *arg)
{
rt_err_t err = RT_EOK;
struct serial8250 *serial = raw_to_serial8250(raw_serial);
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* disable rx irq */
serial->serial_out(serial, UART_IER, !UART_IER_RDI);
rt_pic_irq_mask(serial->irq);
break;
case RT_DEVICE_CTRL_SET_INT:
/* enable rx irq */
serial->serial_out(serial, UART_IER, UART_IER_RDI);
rt_pic_irq_unmask(serial->irq);
break;
}
return err;
}
int serial8250_uart_putc(struct rt_serial_device *raw_serial, char c)
{
struct serial8250 *serial = raw_to_serial8250(raw_serial);
while (!(serial->serial_in(serial, UART_LSR) & 0x20))
{
rt_hw_cpu_relax();
}
serial->serial_out(serial, UART_TX, c);
return 1;
}
int serial8250_uart_getc(struct rt_serial_device *raw_serial)
{
int ch = -1;
struct serial8250 *serial = raw_to_serial8250(raw_serial);
if ((serial->serial_in(serial, UART_LSR) & 0x1))
{
ch = serial->serial_in(serial, UART_RX) & 0xff;
}
return ch;
}
const struct rt_uart_ops serial8250_uart_ops =
{
.configure = serial8250_uart_configure,
.control = serial8250_uart_control,
.putc = serial8250_uart_putc,
.getc = serial8250_uart_getc,
};

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-16 GuEe-GUI first version
*/
#include "8250.h"
struct serial8250 early_serial8250 = { 0 };
static rt_uint32_t serial8250_early_in(struct serial8250 *serial, int offset)
{
return serial8250_in(serial, offset);
}
static void serial8250_early_out(struct serial8250 *serial, int offset, int value)
{
serial8250_out(serial, offset, value);
}
int serial8250_early_putc(struct rt_serial_device *raw_serial, char c)
{
if (raw_serial)
{
/* FIFO and shifting register empty */
const int uart_lsr_both_empty = (UART_LSR_TEMT | UART_LSR_THRE);
struct serial8250 *serial = rt_container_of(raw_serial, struct serial8250, parent);
serial8250_early_out(serial, UART_TX, c);
while ((serial8250_early_in(serial, UART_LSR) & uart_lsr_both_empty) != uart_lsr_both_empty)
{
rt_hw_cpu_relax();
}
}
return 1;
}
static void init_serial(struct serial8250 *serial)
{
unsigned char c;
rt_uint32_t ier, divisor;
serial8250_early_out(serial, UART_LCR, 0x3); /* 8n1 */
ier = serial8250_early_in(serial, UART_IER);
serial8250_early_out(serial, UART_IER, ier & UART_IER_UUE); /* no interrupt */
serial8250_early_out(serial, UART_FCR, 0); /* no fifo */
serial8250_early_out(serial, UART_MCR, 0x3); /* DTR + RTS */
if (serial->freq)
{
divisor = RT_DIV_ROUND_CLOSEST(serial->freq, 16 * serial->parent.config.baud_rate);
c = serial8250_early_in(serial, UART_LCR);
serial8250_early_out(serial, UART_LCR, c | UART_LCR_DLAB);
serial8250_early_out(serial, UART_DLL, divisor & 0xff);
serial8250_early_out(serial, UART_DLM, (divisor >> 8) & 0xff);
serial8250_early_out(serial, UART_LCR, c & ~UART_LCR_DLAB);
}
}
static void serial8250_early_kick(struct rt_fdt_earlycon *con, int why)
{
struct serial8250 *serial = raw_to_serial8250(con->data);
switch (why)
{
case FDT_EARLYCON_KICK_UPDATE:
serial->base = rt_ioremap((void *)con->mmio, con->size);
break;
case FDT_EARLYCON_KICK_COMPLETED:
rt_iounmap(serial->base);
break;
default:
break;
}
}
rt_err_t serial8250_early_fdt_setup(struct serial8250 *serial, struct rt_fdt_earlycon *con, const char *options)
{
rt_err_t ret = RT_EOK;
if (!serial->base && con)
{
serial8250_config(serial, options);
con->mmio = (rt_ubase_t)serial->base;
con->size = serial->size;
}
if (serial->base && con)
{
serial->base = rt_ioremap_early((void *)serial->base, serial->size);
}
if (serial->base && con)
{
con->console_putc = (typeof(con->console_putc))&serial8250_early_putc;
con->console_kick = serial8250_early_kick;
con->data = &serial->parent;
if (!serial->parent.config.baud_rate)
{
/* assume the device was initialized, only mask interrupts */
rt_uint32_t ier = serial8250_early_in(serial, UART_IER);
serial8250_early_out(serial, UART_IER, ier & UART_IER_UUE);
}
else
{
init_serial(serial);
}
}
else
{
ret = -RT_ERROR;
}
return ret;
}
static void common_init(struct serial8250 *serial, struct rt_fdt_earlycon *con)
{
serial->base = (void *)con->mmio;
serial->size = con->size;
serial->iotype = PORT_MMIO32;
}
static rt_err_t common_early_setup(struct rt_fdt_earlycon *con, const char *options)
{
struct serial8250 *serial = &early_serial8250;
common_init(serial, con);
serial->regshift = 2;
fdt_getprop_u32(con->fdt, con->nodeoffset, "reg-shift", &serial->regshift, RT_NULL);
return serial8250_early_fdt_setup(serial, con, options);
}
RT_FDT_EARLYCON_EXPORT(bcm2835aux, "uart8250", "brcm,bcm2835-aux-uart", common_early_setup);
RT_FDT_EARLYCON_EXPORT(tegra20, "uart8250", "nvidia,tegra20-uart", common_early_setup);
RT_FDT_EARLYCON_EXPORT(dw8250, "uart8250", "snps,dw-apb-uart", common_early_setup);
RT_FDT_EARLYCON_EXPORT(ns16550a, "uart8250", "ns16550a", common_early_setup);
RT_FDT_EARLYCON_EXPORT(ns16550, "uart8250", "ns16550", common_early_setup);
#ifdef RT_USING_8250_OMAP
static rt_err_t omap8250_early_setup(struct rt_fdt_earlycon *con, const char *options)
{
struct serial8250 *serial = &early_serial8250;
common_init(serial, con);
serial->regshift = 2;
return serial8250_early_fdt_setup(serial, con, options);
}
RT_FDT_EARLYCON_EXPORT(omap8250, "uart8250", "ti,omap2-uart", omap8250_early_setup);
RT_FDT_EARLYCON_EXPORT(omap8250, "uart8250", "ti,omap3-uart", omap8250_early_setup);
RT_FDT_EARLYCON_EXPORT(omap8250, "uart8250", "ti,omap4-uart", omap8250_early_setup);
#endif /* RT_USING_8250_OMAP */

View File

@ -0,0 +1,378 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-21 GuEe-GUI first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <ioremap.h>
#include <cpuport.h>
#include "regs.h"
#include "serial_dm.h"
#define UART_USR 0x1f /* In: UART Status Register */
#define UART_USR_RX_FIFO_FULL 0x10 /* Receive FIFO full */
#define UART_USR_RX_FIFO_NOT_EMPTY 0x08 /* Receive FIFO not empty */
#define UART_USR_TX_FIFO_EMPTY 0x04 /* Transmit FIFO empty */
#define UART_USR_TX_FIFO_NOT_FULL 0x02 /* Transmit FIFO not full */
#define UART_USR_BUSY 0x01 /* UART busy indicator */
#define UART_SRR 0x22 /* software reset register */
#define FIQ_DEBUGGER_NO_CHAR -1
#define FIQ_DEBUGGER_BREAK -2
struct rockchip_fiq_debugger
{
struct rt_serial_device parent;
int irq;
int baudrate;
void *debug_port_base;
rt_bool_t break_seen;
};
#define raw_to_fiq_debugger(raw) rt_container_of(raw, struct rockchip_fiq_debugger, parent)
rt_inline void rockchip_fiq_write(struct rockchip_fiq_debugger *t, rt_uint32_t val, int off)
{
HWREG32(t->debug_port_base + off * 4) = val;
}
rt_inline rt_uint32_t rockchip_fiq_read(struct rockchip_fiq_debugger *t, int off)
{
return HWREG32(t->debug_port_base + off * 4);
}
rt_inline rt_uint32_t rockchip_fiq_read_lsr(struct rockchip_fiq_debugger *t)
{
rt_uint32_t ret = rockchip_fiq_read(t, UART_LSR);
if (ret & UART_LSR_BI)
{
t->break_seen = true;
}
return ret;
}
static void fiq_debugger_isr(int irqno, void *param)
{
rt_uint32_t usr;
struct rt_serial_device *serial = (struct rt_serial_device*)param;
struct rockchip_fiq_debugger *t = raw_to_fiq_debugger(serial);
usr = rockchip_fiq_read(t, UART_USR);
if ((usr & UART_USR_RX_FIFO_NOT_EMPTY) == UART_USR_RX_FIFO_NOT_EMPTY)
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
if ((usr & UART_USR_BUSY) == UART_USR_BUSY)
{
/* Clear the USR */
(void)rockchip_fiq_read(t, UART_USR);
}
}
static rt_err_t fiq_debugger_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
int dll = 0, dlm = 0;
rt_uint32_t count = 10000;
struct rockchip_fiq_debugger *t = raw_to_fiq_debugger(serial);
if (rockchip_fiq_read(t, UART_LSR) & UART_LSR_DR)
{
(void)rockchip_fiq_read(t, UART_RX);
}
while (!(rockchip_fiq_read(t, UART_LSR) & UART_LSR_TEMT) && count--)
{
rt_hw_us_delay(10);
}
switch (t->baudrate)
{
case 1500000:
dll = 0x1;
break;
case 115200:
default:
dll = 0xd;
break;
}
/* reset uart */
rockchip_fiq_write(t, (1 << 1) | (1 << 2), UART_SRR);
rt_hw_us_delay(10);
/* set uart to loop back mode */
rockchip_fiq_write(t, 0x10, UART_MCR);
rockchip_fiq_write(t, 0x83, UART_LCR);
/* set baud rate */
rockchip_fiq_write(t, dll, UART_DLL);
rockchip_fiq_write(t, dlm, UART_DLM);
rockchip_fiq_write(t, 0x03, UART_LCR);
/* enable rx interrupt */
rockchip_fiq_write(t, UART_IER_RDI, UART_IER);
/*
* interrupt on every character when received, but we can enable fifo for TX
* I found that if we enable the RX fifo, some problem may vanish such as
* when you continuously input characters in the command line the uart irq
* may be disable because of the uart irq is served when CPU is at IRQ
* exception, but it is found unregistered, so it is disable.
*/
rockchip_fiq_write(t, 0x01, UART_FCR);
/* disbale loop back mode */
rockchip_fiq_write(t, 0x0, UART_MCR);
return RT_EOK;
}
static rt_err_t fiq_debugger_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct rockchip_fiq_debugger *t = raw_to_fiq_debugger(serial);
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
rt_pic_irq_mask(t->irq);
break;
case RT_DEVICE_CTRL_SET_INT:
rt_pic_irq_unmask(t->irq);
break;
}
return RT_EOK;
}
static int fiq_debugger_uart_putc(struct rt_serial_device *serial, char c)
{
struct rockchip_fiq_debugger *t = raw_to_fiq_debugger(serial);
rt_uint32_t count = 10000;
while (!(rockchip_fiq_read(t, UART_USR) & UART_USR_TX_FIFO_NOT_FULL) && count--)
{
rt_hw_cpu_relax();
}
rockchip_fiq_write(t, c, UART_TX);
return 1;
}
static int fiq_debugger_uart_getc(struct rt_serial_device *serial)
{
int ch = FIQ_DEBUGGER_NO_CHAR;
rt_uint32_t lsr, temp;
static rt_uint32_t n = 0;
static char buf[32] = {};
struct rockchip_fiq_debugger *t = raw_to_fiq_debugger(serial);
/* Clear uart interrupt status */
rockchip_fiq_read(t, UART_USR);
lsr = rockchip_fiq_read_lsr(t);
if (lsr & UART_LSR_DR)
{
temp = rockchip_fiq_read(t, UART_RX);
buf[n & 0x1f] = temp;
n++;
if (temp == 'q' && n > 2)
{
if ((buf[(n - 2) & 0x1f] == 'i') && (buf[(n - 3) & 0x1f] == 'f'))
{
ch = FIQ_DEBUGGER_BREAK;
}
else
{
ch = temp;
}
}
else
{
ch = temp;
}
}
return ch;
}
static const struct rt_uart_ops fiq_debugger_uart_ops =
{
.configure = fiq_debugger_uart_configure,
.control = fiq_debugger_uart_control,
.putc = fiq_debugger_uart_putc,
.getc = fiq_debugger_uart_getc,
};
struct rockchip_fiq_debugger *rk_serial_debug_init(void *base, rt_ubase_t paddr,
int irq, int signal_irq, int wakeup_irq, rt_uint32_t baudrate)
{
struct rockchip_fiq_debugger *t = rt_calloc(1, sizeof(*t));
if (t)
{
const char *name;
t->parent.ops = &fiq_debugger_uart_ops;
t->parent.config = (struct serial_configure)RT_SERIAL_CONFIG_DEFAULT;
t->parent.config.baud_rate = baudrate;
t->irq = irq;
t->baudrate = baudrate;
t->debug_port_base = base;
t->break_seen = RT_FALSE;
serial_dev_set_name(&t->parent);
name = rt_dm_dev_get_name(&t->parent.parent);
rt_hw_serial_register(&t->parent, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, t);
rt_pic_attach_irq(t->irq, fiq_debugger_isr, &t->parent, name, RT_IRQ_F_NONE);
}
return t;
}
static rt_err_t rockchip_fiq_debugger_probe(struct rt_platform_device *pdev)
{
rt_err_t err = RT_EOK;
void *base;
rt_uint64_t regs[2];
struct rt_clk *clk, *pclk;
rt_bool_t found = RT_FALSE;
char dev_name[RT_NAME_MAX];
int irq, signal_irq = -1;
rt_uint32_t serial_id, baudrate = 0, irq_mode = 0, wake_irq = -1;
struct rt_ofw_node *np = pdev->parent.ofw_node;
if (rt_ofw_prop_read_u32(np, "rockchip,serial-id", &serial_id) || serial_id == -1)
{
return -RT_EINVAL;
}
if (rt_ofw_prop_read_u32(np, "rockchip,irq-mode-enable", &irq_mode))
{
irq_mode = -1;
}
if (irq_mode == 1)
{
signal_irq = -1;
}
else if (!(signal_irq = rt_ofw_get_irq(np, 0)))
{
return -RT_EINVAL;
}
if (rt_ofw_prop_read_u32(np, "rockchip,wake-irq", &wake_irq))
{
wake_irq = -1;
}
if (rt_ofw_prop_read_u32(np, "rockchip,baudrate", &baudrate))
{
baudrate = 1500000;
}
rt_snprintf(dev_name, RT_NAME_MAX, "serial%d", serial_id);
np = RT_NULL;
do {
np = rt_ofw_find_node_by_tag(np, "serial");
if (np && rt_ofw_get_alias_id(np, "serial") == serial_id)
{
found = RT_TRUE;
break;
}
} while(np);
if (!found)
{
return -RT_EINVAL;
}
rt_memset(regs, 0, sizeof(regs));
rt_ofw_get_address_array(np, 1, regs);
pclk = rt_ofw_get_clk_by_name(np, "apb_pclk");
clk = rt_ofw_get_clk_by_name(np, "baudclk");
if (!pclk || !clk)
{
err = -RT_ERROR;
goto _fail;
}
rt_clk_enable(clk);
rt_clk_enable(pclk);
if ((irq = rt_ofw_get_irq(np, 0)) < 0)
{
err = -RT_ERROR;
goto _fail;
}
if ((base = rt_ioremap((void *)regs[0], regs[1])))
{
struct rockchip_fiq_debugger *t = rk_serial_debug_init(base,
(rt_ubase_t)regs[0], irq, signal_irq, wake_irq, baudrate);
if (t)
{
rt_dm_dev_bind_fwdata(&t->parent.parent, pdev->parent.ofw_node, &t->parent);
}
}
return err;
_fail:
if (clk)
{
rt_clk_disable(clk);
rt_clk_put(clk);
}
if (pclk)
{
rt_clk_disable(pclk);
rt_clk_put(pclk);
}
return err;
}
static const struct rt_ofw_node_id rockchip_fiq_debugger_ofw_ids[] =
{
{ .type = "ttyFIQ", .compatible = "rockchip,fiq-debugger" },
{ /* sentinel */ }
};
static struct rt_platform_driver rockchip_fiq_debugger_driver =
{
.name = "rockchip-fiq-debugger",
.ids = rockchip_fiq_debugger_ofw_ids,
.probe = rockchip_fiq_debugger_probe,
};
static int rockchip_fiq_debugger_drv_register(void)
{
rt_platform_driver_register(&rockchip_fiq_debugger_driver);
return 0;
}
INIT_DRIVER_EARLY_EXPORT(rockchip_fiq_debugger_drv_register);

View File

@ -0,0 +1,365 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __SERIAL_8250_REGS_H__
#define __SERIAL_8250_REGS_H__
/*
* DLAB=0
*/
#define UART_RX 0 /* In: Receive buffer */
#define UART_TX 0 /* Out: Transmit buffer */
#define UART_IER 1 /* Out: Interrupt Enable Register */
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
/*
* Sleep mode for ST16650 and TI16750. For the ST16650, EFR[4]=1
*/
#define UART_IERX_SLEEP 0x10 /* Enable sleep mode */
#define UART_IIR 2 /* In: Interrupt ID Register */
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
#define UART_IIR_ID 0x0e /* Mask for the interrupt ID */
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
#define UART_IIR_BUSY 0x07 /* DesignWare APB Busy Detect */
#define UART_IIR_RX_TIMEOUT 0x0c /* OMAP RX Timeout interrupt */
#define UART_IIR_XOFF 0x10 /* OMAP XOFF/Special Character */
#define UART_IIR_CTS_RTS_DSR 0x20 /* OMAP CTS/RTS/DSR Change */
#define UART_FCR 2 /* Out: FIFO Control Register */
#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
/*
* Note: The FIFO trigger levels are chip specific:
* RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
* PC16550D: 1 4 8 14 xx xx xx xx
* TI16C550A: 1 4 8 14 xx xx xx xx
* TI16C550C: 1 4 8 14 xx xx xx xx
* ST16C550: 1 4 8 14 xx xx xx xx
* ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
* NS16C552: 1 4 8 14 xx xx xx xx
* ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
* TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
* TI16C752: 8 16 56 60 8 16 32 56
* OX16C950: 16 32 112 120 16 32 64 112 PORT_16C950
* Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
*/
#define UART_FCR_R_TRIG_00 0x00
#define UART_FCR_R_TRIG_01 0x40
#define UART_FCR_R_TRIG_10 0x80
#define UART_FCR_R_TRIG_11 0xc0
#define UART_FCR_T_TRIG_00 0x00
#define UART_FCR_T_TRIG_01 0x10
#define UART_FCR_T_TRIG_10 0x20
#define UART_FCR_T_TRIG_11 0x30
#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
/* 16650 definitions */
#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */
#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */
#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */
#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */
#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */
#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */
#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */
#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode (TI16C750 and some Freescale UARTs) */
#define UART_FCR_R_TRIG_SHIFT 6
#define UART_FCR_R_TRIG_BITS(x) (((x) & UART_FCR_TRIGGER_MASK) >> UART_FCR_R_TRIG_SHIFT)
#define UART_FCR_R_TRIG_MAX_STATE 4
#define UART_LCR 3 /* Out: Line Control Register */
/*
* Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
* UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
*/
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
#define UART_LCR_SBC 0x40 /* Set break control */
#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
#define UART_LCR_EPAR 0x10 /* Even parity select */
#define UART_LCR_PARITY 0x08 /* Parity Enable */
#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 bit, 1=2 bits */
#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
/*
* Access to some registers depends on register access / configuration mode.
*/
#define UART_LCR_CONF_MODE_A UART_LCR_DLAB /* Configutation mode A */
#define UART_LCR_CONF_MODE_B 0xBF /* Configutation mode B */
#define UART_MCR 4 /* Out: Modem Control Register */
#define UART_MCR_CLKSEL 0x80 /* Divide clock by 4 (TI16C752, EFR[4]=1) */
#define UART_MCR_TCRTLR 0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
#define UART_MCR_XONANY 0x20 /* Enable Xon Any (TI16C752, EFR[4]=1) */
#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C550C/TI16C750) */
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
#define UART_MCR_OUT2 0x08 /* Out2 complement */
#define UART_MCR_OUT1 0x04 /* Out1 complement */
#define UART_MCR_RTS 0x02 /* RTS complement */
#define UART_MCR_DTR 0x01 /* DTR complement */
#define UART_LSR 5 /* In: Line Status Register */
#define UART_LSR_FIFOE 0x80 /* Fifo error */
#define UART_LSR_TEMT 0x40 /* Transmitter empty */
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
#define UART_LSR_BI 0x10 /* Break interrupt indicator */
#define UART_LSR_FE 0x08 /* Frame error indicator */
#define UART_LSR_PE 0x04 /* Parity error indicator */
#define UART_LSR_OE 0x02 /* Overrun error indicator */
#define UART_LSR_DR 0x01 /* Receiver data ready */
#define UART_LSR_BRK_ERROR_BITS (UART_LSR_BI|UART_LSR_FE|UART_LSR_PE|UART_LSR_OE)
#define UART_MSR 6 /* In: Modem Status Register */
#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
#define UART_MSR_RI 0x40 /* Ring Indicator */
#define UART_MSR_DSR 0x20 /* Data Set Ready */
#define UART_MSR_CTS 0x10 /* Clear to Send */
#define UART_MSR_DDCD 0x08 /* Delta DCD */
#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
#define UART_MSR_DDSR 0x02 /* Delta DSR */
#define UART_MSR_DCTS 0x01 /* Delta CTS */
#define UART_MSR_ANY_DELTA (UART_MSR_DDCD|UART_MSR_TERI|UART_MSR_DDSR|UART_MSR_DCTS)
#define UART_SCR 7 /* I/O: Scratch Register */
/*
* DLAB=1
*/
#define UART_DLL 0 /* Out: Divisor Latch Low */
#define UART_DLM 1 /* Out: Divisor Latch High */
#define UART_DIV_MAX 0xFFFF /* Max divisor value */
/*
* LCR=0xBF (or DLAB=1 for 16C660)
*/
#define UART_EFR 2 /* I/O: Extended Features Register */
#define UART_XR_EFR 9 /* I/O: Extended Features Register (XR17D15x) */
#define UART_EFR_CTS 0x80 /* CTS flow control */
#define UART_EFR_RTS 0x40 /* RTS flow control */
#define UART_EFR_SCD 0x20 /* Special character detect */
#define UART_EFR_ECB 0x10 /* Enhanced control bit */
/*
* the low four bits control software flow control
*/
/*
* LCR=0xBF, TI16C752, ST16650, ST16650A, ST16654
*/
#define UART_XON1 4 /* I/O: Xon character 1 */
#define UART_XON2 5 /* I/O: Xon character 2 */
#define UART_XOFF1 6 /* I/O: Xoff character 1 */
#define UART_XOFF2 7 /* I/O: Xoff character 2 */
/*
* EFR[4]=1 MCR[6]=1, TI16C752
*/
#define UART_TI752_TCR 6 /* I/O: transmission control register */
#define UART_TI752_TLR 7 /* I/O: trigger level register */
/*
* LCR=0xBF, XR16C85x
*/
#define UART_TRG 0 /* FCTR bit 7 selects Rx or Tx In: Fifo count Out: Fifo custom trigger levels */
/*
* These are the definitions for the Programmable Trigger Register
*/
#define UART_TRG_1 0x01
#define UART_TRG_4 0x04
#define UART_TRG_8 0x08
#define UART_TRG_16 0x10
#define UART_TRG_32 0x20
#define UART_TRG_64 0x40
#define UART_TRG_96 0x60
#define UART_TRG_120 0x78
#define UART_TRG_128 0x80
#define UART_FCTR 1 /* Feature Control Register */
#define UART_FCTR_RTS_NODELAY 0x00 /* RTS flow control delay */
#define UART_FCTR_RTS_4DELAY 0x01
#define UART_FCTR_RTS_6DELAY 0x02
#define UART_FCTR_RTS_8DELAY 0x03
#define UART_FCTR_IRDA 0x04 /* IrDa data encode select */
#define UART_FCTR_TX_INT 0x08 /* Tx interrupt type select */
#define UART_FCTR_TRGA 0x00 /* Tx/Rx 550 trigger table select */
#define UART_FCTR_TRGB 0x10 /* Tx/Rx 650 trigger table select */
#define UART_FCTR_TRGC 0x20 /* Tx/Rx 654 trigger table select */
#define UART_FCTR_TRGD 0x30 /* Tx/Rx 850 programmable trigger select */
#define UART_FCTR_SCR_SWAP 0x40 /* Scratch pad register swap */
#define UART_FCTR_RX 0x00 /* Programmable trigger mode select */
#define UART_FCTR_TX 0x80 /* Programmable trigger mode select */
/*
* LCR=0xBF, FCTR[6]=1
*/
#define UART_EMSR 7 /* Extended Mode Select Register */
#define UART_EMSR_FIFO_COUNT 0x01 /* Rx/Tx select */
#define UART_EMSR_ALT_COUNT 0x02 /* Alternating count select */
/*
* The Intel XScale on-chip UARTs define these bits
*/
#define UART_IER_DMAE 0x80 /* DMA Requests Enable */
#define UART_IER_UUE 0x40 /* UART Unit Enable */
#define UART_IER_NRZE 0x20 /* NRZ coding Enable */
#define UART_IER_RTOIE 0x10 /* Receiver Time Out Interrupt Enable */
#define UART_IIR_TOD 0x08 /* Character Timeout Indication Detected */
#define UART_FCR_PXAR1 0x00 /* receive FIFO threshold = 1 */
#define UART_FCR_PXAR8 0x40 /* receive FIFO threshold = 8 */
#define UART_FCR_PXAR16 0x80 /* receive FIFO threshold = 16 */
#define UART_FCR_PXAR32 0xc0 /* receive FIFO threshold = 32 */
/*
* These register definitions are for the 16C950
*/
#define UART_ASR 0x01 /* Additional Status Register */
#define UART_RFL 0x03 /* Receiver FIFO level */
#define UART_TFL 0x04 /* Transmitter FIFO level */
#define UART_ICR 0x05 /* Index Control Register */
/* The 16950 ICR registers */
#define UART_ACR 0x00 /* Additional Control Register */
#define UART_CPR 0x01 /* Clock Prescalar Register */
#define UART_TCR 0x02 /* Times Clock Register */
#define UART_CKS 0x03 /* Clock Select Register */
#define UART_TTL 0x04 /* Transmitter Interrupt Trigger Level */
#define UART_RTL 0x05 /* Receiver Interrupt Trigger Level */
#define UART_FCL 0x06 /* Flow Control Level Lower */
#define UART_FCH 0x07 /* Flow Control Level Higher */
#define UART_ID1 0x08 /* ID #1 */
#define UART_ID2 0x09 /* ID #2 */
#define UART_ID3 0x0A /* ID #3 */
#define UART_REV 0x0B /* Revision */
#define UART_CSR 0x0C /* Channel Software Reset */
#define UART_NMR 0x0D /* Nine-bit Mode Register */
#define UART_CTR 0xFF
/*
* The 16C950 Additional Control Register
*/
#define UART_ACR_RXDIS 0x01 /* Receiver disable */
#define UART_ACR_TXDIS 0x02 /* Transmitter disable */
#define UART_ACR_DSRFC 0x04 /* DSR Flow Control */
#define UART_ACR_TLENB 0x20 /* 950 trigger levels enable */
#define UART_ACR_ICRRD 0x40 /* ICR Read enable */
#define UART_ACR_ASREN 0x80 /* Additional status enable */
/*
* These definitions are for the RSA-DV II/S card, from
*
* Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
*/
#define UART_RSA_BASE (-8)
#define UART_RSA_MSR ((UART_RSA_BASE) + 0) /* I/O: Mode Select Register */
#define UART_RSA_MSR_SWAP (1 << 0) /* Swap low/high 8 bytes in I/O port addr */
#define UART_RSA_MSR_FIFO (1 << 2) /* Enable the external FIFO */
#define UART_RSA_MSR_FLOW (1 << 3) /* Enable the auto RTS/CTS flow control */
#define UART_RSA_MSR_ITYP (1 << 4) /* Level (1) / Edge triger (0) */
#define UART_RSA_IER ((UART_RSA_BASE) + 1) /* I/O: Interrupt Enable Register */
#define UART_RSA_IER_Rx_FIFO_H (1 << 0) /* Enable Rx FIFO half full int. */
#define UART_RSA_IER_Tx_FIFO_H (1 << 1) /* Enable Tx FIFO half full int. */
#define UART_RSA_IER_Tx_FIFO_E (1 << 2) /* Enable Tx FIFO empty int. */
#define UART_RSA_IER_Rx_TOUT (1 << 3) /* Enable char receive timeout int */
#define UART_RSA_IER_TIMER (1 << 4) /* Enable timer interrupt */
#define UART_RSA_SRR ((UART_RSA_BASE) + 2) /* IN: Status Read Register */
#define UART_RSA_SRR_Tx_FIFO_NEMP (1 << 0) /* Tx FIFO is not empty (1) */
#define UART_RSA_SRR_Tx_FIFO_NHFL (1 << 1) /* Tx FIFO is not half full (1) */
#define UART_RSA_SRR_Tx_FIFO_NFUL (1 << 2) /* Tx FIFO is not full (1) */
#define UART_RSA_SRR_Rx_FIFO_NEMP (1 << 3) /* Rx FIFO is not empty (1) */
#define UART_RSA_SRR_Rx_FIFO_NHFL (1 << 4) /* Rx FIFO is not half full (1) */
#define UART_RSA_SRR_Rx_FIFO_NFUL (1 << 5) /* Rx FIFO is not full (1) */
#define UART_RSA_SRR_Rx_TOUT (1 << 6) /* Character reception timeout occurred (1) */
#define UART_RSA_SRR_TIMER (1 << 7) /* Timer interrupt occurred */
#define UART_RSA_FRR ((UART_RSA_BASE) + 2) /* OUT: FIFO Reset Register */
#define UART_RSA_TIVSR ((UART_RSA_BASE) + 3) /* I/O: Timer Interval Value Set Register */
#define UART_RSA_TCR ((UART_RSA_BASE) + 4) /* OUT: Timer Control Register */
#define UART_RSA_TCR_SWITCH (1 << 0) /* Timer on */
/*
* The RSA DSV/II board has two fixed clock frequencies. One is the
* standard rate, and the other is 8 times faster.
*/
#define SERIAL_RSA_BAUD_BASE (921600)
#define SERIAL_RSA_BAUD_BASE_LO (SERIAL_RSA_BAUD_BASE / 8)
/* Extra registers for TI DA8xx/66AK2x */
#define UART_DA830_PWREMU_MGMT 12
/* PWREMU_MGMT register bits */
#define UART_DA830_PWREMU_MGMT_FREE (1 << 0) /* Free-running mode */
#define UART_DA830_PWREMU_MGMT_URRST (1 << 13) /* Receiver reset/enable */
#define UART_DA830_PWREMU_MGMT_UTRST (1 << 14) /* Transmitter reset/enable */
/*
* Extra serial register definitions for the internal UARTs
* in TI OMAP processors.
*/
#define OMAP1_UART1_BASE 0xfffb0000
#define OMAP1_UART2_BASE 0xfffb0800
#define OMAP1_UART3_BASE 0xfffb9800
#define UART_OMAP_MDR1 0x08 /* Mode definition register */
#define UART_OMAP_MDR2 0x09 /* Mode definition register 2 */
#define UART_OMAP_SCR 0x10 /* Supplementary control register */
#define UART_OMAP_SSR 0x11 /* Supplementary status register */
#define UART_OMAP_EBLR 0x12 /* BOF length register */
#define UART_OMAP_OSC_12M_SEL 0x13 /* OMAP1510 12MHz osc select */
#define UART_OMAP_MVER 0x14 /* Module version register */
#define UART_OMAP_SYSC 0x15 /* System configuration register */
#define UART_OMAP_SYSS 0x16 /* System status register */
#define UART_OMAP_WER 0x17 /* Wake-up enable register */
#define UART_OMAP_TX_LVL 0x1a /* TX FIFO level register */
/*
* These are the definitions for the MDR1 register
*/
#define UART_OMAP_MDR1_16X_MODE 0x00 /* UART 16x mode */
#define UART_OMAP_MDR1_SIR_MODE 0x01 /* SIR mode */
#define UART_OMAP_MDR1_16X_ABAUD_MODE 0x02 /* UART 16x auto-baud */
#define UART_OMAP_MDR1_13X_MODE 0x03 /* UART 13x mode */
#define UART_OMAP_MDR1_MIR_MODE 0x04 /* MIR mode */
#define UART_OMAP_MDR1_FIR_MODE 0x05 /* FIR mode */
#define UART_OMAP_MDR1_CIR_MODE 0x06 /* CIR mode */
#define UART_OMAP_MDR1_DISABLE 0x07 /* Disable (default state) */
/*
* These are definitions for the Altera ALTR_16550_F32/F64/F128
* Normalized from 0x100 to 0x40 because of shift by 2 (32 bit regs).
*/
#define UART_ALTR_AFR 0x40 /* Additional Features Register */
#define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */
#define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */
#endif /* __SERIAL_8250_REGS_H__ */

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-16 GuEe-GUI first version
*/
#ifndef __SERIAL_DM_H__
#define __SERIAL_DM_H__
#include <rtthread.h>
#include <rtdevice.h>
#include <posix/string.h>
int serial_dev_set_name(struct rt_serial_device *sdev);
void *serial_base_from_args(char *str);
struct serial_configure serial_cfg_from_args(char *str);
#define serial_for_each_args(arg, args) \
for (char *context = (arg = (typeof(arg))args, (void *)RT_NULL), \
*context_end = strchrnul((char *)args, ' '); \
(arg = strtok_r(arg, ",", &context)) && arg < context_end; \
arg = RT_NULL)
#endif /* __SERIAL_DM_H__ */

View File

@ -0,0 +1,568 @@
#ifndef RT_CONFIG_H__
#define RT_CONFIG_H__
/* RT-Thread Kernel */
#define RT_NAME_MAX 8
#define RT_USING_SMART
#define RT_USING_SMP
#define RT_CPUS_NR 4
#define RT_ALIGN_SIZE 8
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
#define RT_TICK_PER_SECOND 1000
#define RT_USING_HOOK
#define RT_HOOK_USING_FUNC_PTR
#define RT_USING_HOOKLIST
#define RT_USING_IDLE_HOOK
#define RT_IDLE_HOOK_LIST_SIZE 4
#define IDLE_THREAD_STACK_SIZE 16384
#define SYSTEM_THREAD_STACK_SIZE 16384
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
#define RT_TIMER_THREAD_STACK_SIZE 32768
#define RT_USING_TIMER_ALL_SOFT
#define RT_USING_CPU_USAGE_TRACER
/* kservice optimization */
/* end of kservice optimization */
/* klibc optimization */
#define RT_KLIBC_USING_PRINTF_LONGLONG
/* end of klibc optimization */
#define RT_USING_DEBUG
#define RT_DEBUGING_COLOR
/* Inter-Thread communication */
#define RT_USING_SEMAPHORE
#define RT_USING_MUTEX
#define RT_USING_EVENT
#define RT_USING_MAILBOX
#define RT_USING_MESSAGEQUEUE
#define RT_USING_MESSAGEQUEUE_PRIORITY
/* end of Inter-Thread communication */
/* Memory Management */
#define RT_PAGE_MAX_ORDER 11
#define RT_USING_SLAB
#define RT_USING_MEMHEAP
#define RT_MEMHEAP_FAST_MODE
#define RT_USING_MEMHEAP_AS_HEAP
#define RT_USING_MEMHEAP_AUTO_BINDING
#define RT_USING_HEAP
/* end of Memory Management */
#define RT_USING_DEVICE
#define RT_USING_DEVICE_OPS
#define RT_USING_THREADSAFE_PRINTF
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 1024
#define RT_CONSOLE_DEVICE_NAME "uart2"
#define RT_VER_NUM 0x50200
#define RT_USING_STDC_ATOMIC
#define RT_BACKTRACE_LEVEL_MAX_NR 32
/* end of RT-Thread Kernel */
/* AArch64 Architecture Configuration */
#define ARCH_TEXT_OFFSET 0x00480000
#define ARCH_RAM_OFFSET 0x200000
#define ARCH_SECONDARY_CPU_STACK_SIZE 16384
#define ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS
#define ARCH_USING_GENERIC_CPUID
#define ARCH_HEAP_SIZE 0x4000000
#define ARCH_INIT_PAGE_SIZE 0x200000
/* end of AArch64 Architecture Configuration */
#define ARCH_CPU_64BIT
#define RT_USING_CACHE
#define ARCH_ARM_BOOTWITH_FLUSH_CACHE
#define RT_USING_CPU_FFS
#define ARCH_MM_MMU
#define ARCH_ARM
#define ARCH_ARM_MMU
#define KERNEL_VADDR_START 0xffff000000000000
#define ARCH_ARMV8
#define ARCH_USING_HW_THREAD_SELF
#define ARCH_USING_IRQ_CTX_LIST
/* RT-Thread Components */
#define RT_USING_COMPONENTS_INIT
#define RT_USING_USER_MAIN
#define RT_MAIN_THREAD_STACK_SIZE 16384
#define RT_MAIN_THREAD_PRIORITY 10
#define RT_USING_MSH
#define RT_USING_FINSH
#define FINSH_USING_MSH
#define FINSH_THREAD_NAME "tshell"
#define FINSH_THREAD_PRIORITY 20
#define FINSH_THREAD_STACK_SIZE 16384
#define FINSH_USING_HISTORY
#define FINSH_HISTORY_LINES 5
#define FINSH_USING_SYMTAB
#define FINSH_CMD_SIZE 80
#define MSH_USING_BUILT_IN_COMMANDS
#define FINSH_USING_DESCRIPTION
#define FINSH_ARG_MAX 10
#define FINSH_USING_OPTION_COMPLETION
/* DFS: device virtual file system */
#define RT_USING_DFS
#define DFS_USING_POSIX
#define DFS_USING_WORKDIR
#define DFS_FD_MAX 512
#define RT_USING_DFS_V2
#define RT_USING_DFS_DEVFS
#define RT_USING_DFS_PTYFS
#define RT_USING_DFS_CROMFS
#define RT_USING_DFS_TMPFS
#define RT_USING_DFS_MQUEUE
#define RT_USING_PAGECACHE
/* page cache config */
#define RT_PAGECACHE_COUNT 128
#define RT_PAGECACHE_ASPACE_COUNT 32
#define RT_PAGECACHE_PRELOAD 4
#define RT_PAGECACHE_HASH_NR 180
#define RT_PAGECACHE_GC_WORK_LEVEL 90
#define RT_PAGECACHE_GC_STOP_LEVEL 70
/* end of page cache config */
/* end of DFS: device virtual file system */
/* Device Drivers */
#define RT_USING_DM
#define RT_USING_DEV_BUS
#define RT_USING_DEVICE_IPC
#define RT_UNAMED_PIPE_NUMBER 64
#define RT_USING_SYSTEM_WORKQUEUE
#define RT_SYSTEM_WORKQUEUE_STACKSIZE 16384
#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
#define RT_USING_SERIAL
#define RT_USING_SERIAL_V1
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_NULL
#define RT_USING_ZERO
#define RT_USING_RANDOM
#define RT_USING_RTC
#define RT_USING_SOFT_RTC
#define RT_USING_SDIO
#define RT_SDIO_STACK_SIZE 16384
#define RT_SDIO_THREAD_PRIORITY 15
#define RT_MMCSD_STACK_SIZE 16384
#define RT_MMCSD_THREAD_PREORITY 22
#define RT_MMCSD_MAX_PARTITION 16
#define RT_USING_OFW
#define RT_FDT_EARLYCON_MSG_SIZE 128
#define RT_USING_OFW_BUS_RANGES_NUMBER 8
#define RT_USING_PIC
#define MAX_HANDLERS 1024
#define RT_PIC_ARM_GIC_V3
#define RT_USING_PIN
#define RT_USING_PINCTRL
#define RT_USING_KTIME
#define RT_USING_CLK
#define RT_USING_HWTIMER
#define RT_HWTIMER_ARM_ARCH
/* end of Device Drivers */
/* C/C++ and POSIX layer */
/* ISO-ANSI C layer */
/* Timezone and Daylight Saving Time */
#define RT_LIBC_USING_LIGHT_TZ_DST
#define RT_LIBC_TZ_DEFAULT_HOUR 8
#define RT_LIBC_TZ_DEFAULT_MIN 0
#define RT_LIBC_TZ_DEFAULT_SEC 0
/* end of Timezone and Daylight Saving Time */
/* end of ISO-ANSI C layer */
/* POSIX (Portable Operating System Interface) layer */
#define RT_USING_POSIX_FS
#define RT_USING_POSIX_DEVIO
#define RT_USING_POSIX_STDIO
#define RT_USING_POSIX_POLL
#define RT_USING_POSIX_SELECT
#define RT_USING_POSIX_EVENTFD
#define RT_USING_POSIX_EPOLL
#define RT_USING_POSIX_SIGNALFD
#define RT_SIGNALFD_MAX_NUM 10
#define RT_USING_POSIX_TIMERFD
#define RT_USING_POSIX_SOCKET
#define RT_USING_POSIX_TERMIOS
#define RT_USING_POSIX_MMAN
#define RT_USING_POSIX_DELAY
#define RT_USING_POSIX_CLOCK
#define RT_USING_POSIX_TIMER
/* Interprocess Communication (IPC) */
#define RT_USING_POSIX_PIPE
#define RT_USING_POSIX_PIPE_SIZE 2048
#define RT_USING_POSIX_MESSAGE_QUEUE
/* Socket is in the 'Network' category */
/* end of Interprocess Communication (IPC) */
/* end of POSIX (Portable Operating System Interface) layer */
/* end of C/C++ and POSIX layer */
/* Network */
#define RT_USING_SAL
#define SAL_INTERNET_CHECK
/* Docking with protocol stacks */
#define SAL_USING_LWIP
/* end of Docking with protocol stacks */
#define SAL_USING_POSIX
#define RT_USING_NETDEV
#define NETDEV_USING_IFCONFIG
#define NETDEV_USING_PING
#define NETDEV_USING_NETSTAT
#define NETDEV_USING_AUTO_DEFAULT
#define NETDEV_IPV4 1
#define NETDEV_IPV6 0
#define RT_USING_LWIP
#define RT_USING_LWIP212
#define RT_USING_LWIP_VER_NUM 0x20102
#define RT_LWIP_MEM_ALIGNMENT 8
#define RT_LWIP_IGMP
#define RT_LWIP_ICMP
#define RT_LWIP_DNS
#define RT_LWIP_DHCP
#define IP_SOF_BROADCAST 1
#define IP_SOF_BROADCAST_RECV 1
/* Static IPv4 Address */
#define RT_LWIP_IPADDR "192.168.1.30"
#define RT_LWIP_GWADDR "192.168.1.1"
#define RT_LWIP_MSKADDR "255.255.255.0"
/* end of Static IPv4 Address */
#define RT_LWIP_UDP
#define RT_LWIP_TCP
#define RT_LWIP_RAW
#define RT_MEMP_NUM_NETCONN 64
#define RT_LWIP_PBUF_NUM 320
#define RT_LWIP_RAW_PCB_NUM 32
#define RT_LWIP_UDP_PCB_NUM 32
#define RT_LWIP_TCP_PCB_NUM 64
#define RT_LWIP_TCP_SEG_NUM 480
#define RT_LWIP_TCP_SND_BUF 65535
#define RT_LWIP_TCP_WND 49512
#define RT_LWIP_TCPTHREAD_PRIORITY 8
#define RT_LWIP_TCPTHREAD_MBOX_SIZE 256
#define RT_LWIP_TCPTHREAD_STACKSIZE 65536
#define LWIP_NO_TX_THREAD
#define RT_LWIP_ETHTHREAD_PRIORITY 9
#define RT_LWIP_ETHTHREAD_STACKSIZE 16384
#define RT_LWIP_ETHTHREAD_MBOX_SIZE 256
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define RT_LWIP_NETIF_NAMESIZE 6
#define SO_REUSE 1
#define LWIP_SO_RCVTIMEO 1
#define LWIP_SO_SNDTIMEO 1
#define LWIP_SO_RCVBUF 1
#define LWIP_SO_LINGER 0
#define RT_LWIP_NETIF_LOOPBACK
#define LWIP_NETIF_LOOPBACK 1
#define RT_LWIP_USING_HW_CHECKSUM
#define RT_LWIP_USING_PING
/* end of Network */
/* Memory protection */
/* end of Memory protection */
/* Utilities */
#define RT_USING_UTEST
#define UTEST_THR_STACK_SIZE 32768
#define UTEST_THR_PRIORITY 20
#define RT_USING_RESOURCE_ID
#define RT_USING_ADT
#define RT_USING_ADT_AVL
#define RT_USING_ADT_BITMAP
#define RT_USING_ADT_HASHMAP
#define RT_USING_ADT_REF
/* end of Utilities */
#define RT_USING_LWP
#define LWP_DEBUG
#define LWP_DEBUG_INIT
#define RT_LWP_MAX_NR 128
#define LWP_TASK_STACK_SIZE 32768
#define RT_CH_MSG_MAX_NR 1024
#define LWP_TID_MAX_NR 128
#define RT_LWP_SHM_MAX_NR 64
#define RT_USING_LDSO
#define LWP_USING_TERMINAL
#define LWP_PTY_MAX_PARIS_LIMIT 64
#define RT_USING_VDSO
/* Memory management */
#define RT_USING_MEMBLOCK
#define RT_INIT_MEMORY_REGIONS 128
/* end of Memory management */
/* Using USB legacy version */
/* end of Using USB legacy version */
/* end of RT-Thread Components */
/* RT-Thread Utestcases */
#define RT_USING_UTESTCASES
/* Utest Self Testcase */
/* end of Utest Self Testcase */
/* Kernel Testcase */
/* Kernel SMP Testcase */
/* end of Kernel SMP Testcase */
/* end of Kernel Testcase */
/* CPP11 Testcase */
/* end of CPP11 Testcase */
/* Utest Serial Testcase */
/* end of Utest Serial Testcase */
/* Utest IPC Testcase */
/* end of Utest IPC Testcase */
/* RTT Posix Testcase */
/* end of RTT Posix Testcase */
/* Memory Management Subsytem Testcase */
/* end of Memory Management Subsytem Testcase */
/* Tmpfs Testcase */
/* end of Tmpfs Testcase */
/* SMP-Call Testcase */
#define UTEST_SMP_CALL_FUNC
/* end of SMP-Call Testcase */
/* end of RT-Thread Utestcases */
/* RT-Thread online packages */
/* IoT - internet of things */
/* Wi-Fi */
/* Marvell WiFi */
/* end of Marvell WiFi */
/* Wiced WiFi */
/* end of Wiced WiFi */
/* CYW43012 WiFi */
/* end of CYW43012 WiFi */
/* BL808 WiFi */
/* end of BL808 WiFi */
/* CYW43439 WiFi */
/* end of CYW43439 WiFi */
/* end of Wi-Fi */
/* IoT Cloud */
/* end of IoT Cloud */
/* end of IoT - internet of things */
/* security packages */
/* end of security packages */
/* language packages */
/* JSON: JavaScript Object Notation, a lightweight data-interchange format */
/* end of JSON: JavaScript Object Notation, a lightweight data-interchange format */
/* XML: Extensible Markup Language */
/* end of XML: Extensible Markup Language */
/* end of language packages */
/* multimedia packages */
/* LVGL: powerful and easy-to-use embedded GUI library */
/* end of LVGL: powerful and easy-to-use embedded GUI library */
/* u8g2: a monochrome graphic library */
/* end of u8g2: a monochrome graphic library */
/* end of multimedia packages */
/* tools packages */
/* end of tools packages */
/* system packages */
/* enhanced kernel services */
/* end of enhanced kernel services */
/* acceleration: Assembly language or algorithmic acceleration packages */
/* end of acceleration: Assembly language or algorithmic acceleration packages */
/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
/* Micrium: Micrium software products porting for RT-Thread */
/* end of Micrium: Micrium software products porting for RT-Thread */
/* end of system packages */
/* peripheral libraries and drivers */
/* HAL & SDK Drivers */
/* STM32 HAL & SDK Drivers */
/* end of STM32 HAL & SDK Drivers */
/* Kendryte SDK */
/* end of Kendryte SDK */
/* end of HAL & SDK Drivers */
/* sensors drivers */
/* end of sensors drivers */
/* touch drivers */
/* end of touch drivers */
/* end of peripheral libraries and drivers */
/* AI packages */
/* end of AI packages */
/* Signal Processing and Control Algorithm Packages */
/* end of Signal Processing and Control Algorithm Packages */
/* miscellaneous packages */
/* project laboratory */
/* end of project laboratory */
/* samples: kernel and components samples */
/* end of samples: kernel and components samples */
/* entertainment: terminal games and other interesting software packages */
/* end of entertainment: terminal games and other interesting software packages */
#define PKG_USING_ZLIB
#define PKG_USING_ZLIB_LATEST_VERSION
/* end of miscellaneous packages */
/* Arduino libraries */
/* Projects and Demos */
/* end of Projects and Demos */
/* Sensors */
/* end of Sensors */
/* Display */
/* end of Display */
/* Timing */
/* end of Timing */
/* Data Processing */
/* end of Data Processing */
/* Data Storage */
/* Communication */
/* end of Communication */
/* Device Control */
/* end of Device Control */
/* Other */
/* end of Other */
/* Signal IO */
/* end of Signal IO */
/* Uncategorized */
/* end of Arduino libraries */
/* end of RT-Thread online packages */
/* Privated Packages of RealThread */
/* Network Utilities */
/* end of Network Utilities */
/* RT-Thread Smart */
/* end of RT-Thread Smart */
/* end of Privated Packages of RealThread */
/* RT-Thread rockchip RK3500 drivers */
#define RT_CLK_ROCKCHIP
#define RT_CLK_ROCKCHIP_RK3568
#define RT_CLK_ROCKCHIP_RK3588
#define RT_SERIAL_8250
#define RT_USING_RESET
#define RT_HWTIMER_ROCKCHIP
/* end of RT-Thread rockchip RK3500 drivers */
#define SOC_RK3568
#endif

View File

@ -0,0 +1,57 @@
import os
# toolchains options
ARCH ='aarch64'
CPU ='cortex-a'
CROSS_TOOL ='gcc'
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.join(os.getcwd(), '..', '..', '..')
if os.getenv('RTT_CC'):
CROSS_TOOL = os.getenv('RTT_CC')
PLATFORM = 'gcc'
EXEC_PATH = r'/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/'
EXEC_PATH = os.getenv('RTT_EXEC_PATH') or '/usr/bin'
BUILD = 'release'
if PLATFORM == 'gcc':
# toolchains
PREFIX = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-'
CC = PREFIX + 'gcc'
CXX = PREFIX + 'g++'
CPP = PREFIX + 'cpp'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
TARGET_EXT = 'elf'
SIZE = PREFIX + 'size'
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
DEVICE = ' -g -march=armv8.2-a -mtune=cortex-a55 -fdiagnostics-color=always'
CPPFLAGS= ' -E -P -x assembler-with-cpp'
CFLAGS = DEVICE + ' -Wall -Wno-cpp'
AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__'
LFLAGS = DEVICE + ' -nostartfiles -Wl,--no-warn-rwx-segments -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'
CPATH = ''
LPATH = ''
if BUILD == 'debug':
CFLAGS += ' -O0 -ggdb'
CPPFLAGS += ' -O0 -ggdb'
AFLAGS += ' -ggdb'
else:
CFLAGS += ' -O2 -ggdb'
CPPFLAGS += ' -O2 -ggdb'
CXXFLAGS = CFLAGS
DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
POST_ACTION += 'md5sum rtthread.bin\n'