There is a misunderstanding of the chip version detection in the
rt-loader. For all SoCs the data is gathered from the registers
MODEL_NAME_INFO and CHIP_INFO. Sadly the bits are shuffled around
with each hardware. Currently the loader gathers the wrong bits
for RTL839x and RTL93xx. Fix that.
While we are here write the if statements vice versa for better
readability and give some variables better names. Align the
ouput with that from the kernel.
Fixes: ccbff8b ("realtek: add rt-loader (runtime loader)"
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/21994
Signed-off-by: Robert Marko <robimarko@gmail.com>
116 lines
2.9 KiB
C
116 lines
2.9 KiB
C
/*
|
|
* rt-loader board functions
|
|
* (c) 2025 Markus Stockhausen
|
|
*/
|
|
|
|
#include "globals.h"
|
|
#include "memory.h"
|
|
#include "nanoprintf.h"
|
|
|
|
#define UART_BUFFER_REG 0xb8002000
|
|
#define UART_LINE_STATUS_REG 0xb8002014
|
|
#define UART_TX_READY (1 << 29)
|
|
|
|
#define RTL83XX_DRAM_CONFIG_REG 0xb8001004
|
|
#define RTL838X_ENABLE_RW_MASK 0x3
|
|
#define RTL838X_INT_RW_CTRL_REG 0xbb000058
|
|
#define RTL838X_MODEL_NAME_INFO_REG 0xbb0000d4
|
|
#define RTL839X_MODEL_NAME_INFO_REG 0xbb000ff0
|
|
#define RTL83XX_CHIP_INFO_EN 0xa0000000
|
|
#define RTL931X_DRAM_CONFIG_REG 0xb814304c
|
|
#define RTL93XX_MODEL_NAME_INFO_REG 0xbb000004
|
|
#define RTL93XX_CHIP_INFO_EN 0xa0000
|
|
|
|
|
|
/*
|
|
* board_putchar() is the central function to write to serial console of the device. This is
|
|
* linked to printf() and the provider library via globals.h.
|
|
*/
|
|
|
|
void board_putchar(int ch, void *ctx)
|
|
{
|
|
while (!(ioread32(UART_LINE_STATUS_REG) & UART_TX_READY));
|
|
iowrite32(((int)ch) << 24, UART_BUFFER_REG);
|
|
|
|
if (ch == '\n')
|
|
board_putchar('\r', ctx);
|
|
}
|
|
|
|
/*
|
|
* board_get_memory() does what it is named after. On Realtek switches the DRAM config register
|
|
* has information about bank count, bus width, ... From that the memory size can be derived.
|
|
*/
|
|
|
|
unsigned int board_get_memory(void)
|
|
{
|
|
unsigned int dcr, bits;
|
|
|
|
if ((ioread32(RTL93XX_MODEL_NAME_INFO_REG) & 0xfffc0000) == 0x93100000) {
|
|
dcr = ioread32(RTL931X_DRAM_CONFIG_REG);
|
|
bits = (dcr >> 12) + ((dcr >> 6) & 0x3f) + (dcr & 0x3f);
|
|
} else {
|
|
dcr = ioread32(RTL83XX_DRAM_CONFIG_REG);
|
|
bits = ((dcr >> 28) & 0x3) + ((dcr >> 24) & 0x3) +
|
|
((dcr >> 20) & 0xf) + ((dcr >> 16) & 0xf) + 20;
|
|
}
|
|
|
|
return 1 << bits;
|
|
}
|
|
|
|
/*
|
|
* board_get_system() generates a readable system name that will be printed during startup.
|
|
* Formatting can be whatever is helpful.
|
|
*/
|
|
|
|
void board_get_system(char *buffer, int len)
|
|
{
|
|
unsigned int chip_id, model_id, model_version, chip_version;
|
|
unsigned int reg, act, minfo, cinfo;
|
|
|
|
act = RTL93XX_CHIP_INFO_EN;
|
|
reg = RTL93XX_MODEL_NAME_INFO_REG;
|
|
minfo = ioread32(reg);
|
|
|
|
if ((minfo & 0xffec0000) == 0x93000000)
|
|
goto found;
|
|
|
|
act = RTL83XX_CHIP_INFO_EN;
|
|
reg = RTL839X_MODEL_NAME_INFO_REG;
|
|
minfo = ioread32(reg);
|
|
if ((minfo & 0xfff80000) == 0x83900000)
|
|
goto found;
|
|
|
|
iowrite32(0x3, RTL838X_INT_RW_CTRL_REG);
|
|
reg = RTL838X_MODEL_NAME_INFO_REG;
|
|
minfo = ioread32(reg);
|
|
found:
|
|
iowrite32(act, reg + 4);
|
|
cinfo = ioread32(reg + 4);
|
|
|
|
model_id = minfo >> 16;
|
|
model_version = (minfo >> 11) & 0x1f;
|
|
chip_id = cinfo & 0xffff;
|
|
|
|
if (model_id >= 0x9300)
|
|
chip_version = minfo & 0xf;
|
|
else if (model_id >= 0x8390)
|
|
chip_version = (minfo >> 1) & 0x1f;
|
|
else
|
|
chip_version = ((cinfo >> 16) & 0x1f) - 1;
|
|
|
|
snprintf(buffer, len, "RTL%04X%c rev %c (%04x)", model_id,
|
|
model_version ? model_version + 64 : 0, chip_version + 65, chip_id);
|
|
}
|
|
|
|
/*
|
|
* board_panic() is called in critical cases. Whatever is needed can be done here. Maybe
|
|
* an automatic reboot can be issued some day. For now just halt processing.
|
|
*/
|
|
|
|
void board_panic(void)
|
|
{
|
|
printf("halt system\n");
|
|
while (1) {
|
|
}
|
|
}
|