WIP (temporary): framebuffer text logger and abort dump for bring-up
This commit is contained in:
@@ -194,6 +194,12 @@ void do_bad_error(struct pt_regs *pt_regs)
|
||||
*/
|
||||
void do_sync(struct pt_regs *pt_regs)
|
||||
{
|
||||
extern void krane_fb_log_abort(unsigned long esr, unsigned long elr);
|
||||
|
||||
/* TEMPORARY bring-up diagnostics (krane Round 30) — do not
|
||||
* upstream: draw the abort registers on the panel. */
|
||||
krane_fb_log_abort(pt_regs->esr, pt_regs->elr);
|
||||
|
||||
if (CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) &&
|
||||
smh_emulate_trap(pt_regs))
|
||||
return;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <dm.h>
|
||||
#include <video.h>
|
||||
#include <video_font.h> /* Get font data, width and height */
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/unaligned.h>
|
||||
@@ -33,8 +34,6 @@
|
||||
* src/drivers/video/mtk_ddp.c (ChromeOS R93, the generation shipped on
|
||||
* kukui); both agree on 0x000c for OVL_EN. The 2L sub-engine enable
|
||||
* (DISP_REG_OVL0_2L_EN) lives in the same register block on MT8183.
|
||||
* The layer-0 source address register (DISP_REG_OVL_L0_ADDR) is not reset
|
||||
* by depthcharge's stop() and holds the live scanout address.
|
||||
*/
|
||||
#define DISP_REG_OVL_L0_ADDR 0x0f40
|
||||
#define DISP_REG_OVL_EN 0x000c
|
||||
@@ -42,6 +41,111 @@
|
||||
|
||||
/* TEMPORARY bring-up diagnostics (krane Round 24) — do not upstream:
|
||||
* paint a band into the live depthcharge scanout. */
|
||||
|
||||
/* TEMPORARY bring-up diagnostics (krane Round 30) — do not upstream:
|
||||
* minimal framebuffer text logger using the built-in 8x16 font, so
|
||||
* abort dumps and probe logs are readable on the panel even before
|
||||
* the console exists. */
|
||||
static void krane_fb_log_char(const struct video_fontdata *f,
|
||||
u32 base, u32 x0, u32 y0, char c, u32 color)
|
||||
{
|
||||
const u8 *glyph = &f->video_fontdata[(u8)c * f->height];
|
||||
u32 r, b;
|
||||
|
||||
if (c < 32 || c > 126)
|
||||
c = '?';
|
||||
glyph = &f->video_fontdata[(u8)c * f->height];
|
||||
|
||||
for (r = 0; r < (u32)f->height; r++) {
|
||||
u32 *row = (u32 *)(uintptr_t)(base +
|
||||
(u64)(y0 + r) * 4800 + (u64)x0 * 4);
|
||||
u8 bits = glyph[r];
|
||||
|
||||
for (b = 0; b < (u32)f->width; b++)
|
||||
if (bits & (0x80 >> b))
|
||||
row[b] = color;
|
||||
}
|
||||
}
|
||||
|
||||
static void krane_fb_log(const char *s)
|
||||
{
|
||||
const struct video_fontdata *f = &fonts[0];
|
||||
static u32 line, col;
|
||||
u32 base = readl((void __iomem *)0x14008f40);
|
||||
|
||||
if (base < 0x40000000)
|
||||
return;
|
||||
|
||||
if (dcache_status())
|
||||
mmu_map_region(base, 0x8ca000, false);
|
||||
|
||||
for (; *s; s++) {
|
||||
if (*s == '\n' || col + f->width > 1200) {
|
||||
line++;
|
||||
col = 0;
|
||||
if (*s == '\n')
|
||||
continue;
|
||||
}
|
||||
krane_fb_log_char(f, base, col, 1700 + line * f->height,
|
||||
*s, 0x00ffffff);
|
||||
col += f->width;
|
||||
}
|
||||
|
||||
if (dcache_status())
|
||||
flush_dcache_range((uintptr_t)(base + 1690ULL * 4800),
|
||||
(uintptr_t)(base + 1920ULL * 4800));
|
||||
}
|
||||
|
||||
static void krane_fb_log_hex(const char *prefix, unsigned long v)
|
||||
{
|
||||
char buf[32], *p = buf;
|
||||
int i;
|
||||
const char hexdigits[] = "0123456789abcdef";
|
||||
|
||||
for (i = 0; prefix[i] && i < 15; i++)
|
||||
*p++ = prefix[i];
|
||||
*p++ = '0';
|
||||
*p++ = 'x';
|
||||
for (i = (sizeof(v) * 8) - 4; i >= 0; i -= 4)
|
||||
*p++ = hexdigits[(v >> i) & 0xf];
|
||||
*p = 0;
|
||||
krane_fb_log(buf);
|
||||
krane_fb_log("\n");
|
||||
}
|
||||
|
||||
/* Called from the arm64 abort handlers (temporary wiring in
|
||||
* arch/arm/lib/interrupts_64.c): draw ESR/ELR/FAR on the panel. */
|
||||
void krane_fb_log_abort(unsigned long esr, unsigned long elr)
|
||||
{
|
||||
unsigned long far, cvel;
|
||||
|
||||
asm volatile("mrs %0, CurrentEL" : "=r"(cvel));
|
||||
switch (cvel >> 2) {
|
||||
case 1:
|
||||
asm volatile("mrs %0, far_el1" : "=r"(far));
|
||||
break;
|
||||
case 3:
|
||||
asm volatile("mrs %0, far_el3" : "=r"(far));
|
||||
break;
|
||||
default:
|
||||
asm volatile("mrs %0, far_el2" : "=r"(far));
|
||||
}
|
||||
|
||||
krane_fb_log("\nABORT!\n");
|
||||
krane_fb_log_hex("ESR=", esr);
|
||||
krane_fb_log_hex("ELR=", elr);
|
||||
krane_fb_log_hex("FAR=", far);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Backlight GPIOs. The MT8183 GPIO controller is at 0x10005000; the dout
|
||||
* block starts at +0x100 with 16 bytes per 32-pin group and set@+4 (layout
|
||||
* of GpioRegs/GpioValRegs in device-era depthcharge src/drivers/gpio/
|
||||
* mt8183.h). On kukui the backlight is driven by two dedicated GPIOs:
|
||||
*
|
||||
* TEMPORARY bring-up diagnostics (krane Round 24) — do not upstream:
|
||||
* paint a band into the live depthcharge scanout. */
|
||||
static void krane_diag_band(u32 y0, u32 rows, u32 color)
|
||||
{
|
||||
u32 base = readl((void __iomem *)0x14008f40);
|
||||
@@ -60,12 +164,7 @@ static void krane_diag_band(u32 y0, u32 rows, u32 color)
|
||||
if (dcache_status())
|
||||
flush_dcache_range((uintptr_t)p, (uintptr_t)(p + n));
|
||||
}
|
||||
|
||||
/*
|
||||
* Backlight GPIOs. The MT8183 GPIO controller is at 0x10005000; the dout
|
||||
* block starts at +0x100 with 16 bytes per 32-pin group and set@+4 (layout
|
||||
* of GpioRegs/GpioValRegs in device-era depthcharge src/drivers/gpio/
|
||||
* mt8183.h). On kukui the backlight is driven by two dedicated GPIOs:
|
||||
* DISP_PWM (pin 43) and EN_LCD_BL (PERIPHERAL_EN13, pin 176); depthcharge's
|
||||
* kukui_backlight_update() drives both high to turn the backlight on.
|
||||
*/
|
||||
@@ -169,6 +268,7 @@ static int mt8183_scanout_probe(struct udevice *dev)
|
||||
int ret;
|
||||
|
||||
krane_diag_band(500, 40, 0x00ff00ff); /* magenta: probe entered */
|
||||
krane_fb_log("PROBE");
|
||||
|
||||
ovl = dev_read_addr(dev);
|
||||
if (ovl == FDT_ADDR_T_NONE) {
|
||||
@@ -189,6 +289,7 @@ static int mt8183_scanout_probe(struct udevice *dev)
|
||||
writel(MTK_GPIO_DOUT_BIT(PAD_EN_LCD_BL),
|
||||
(void __iomem *)MTK_GPIO_DOUT_SET(PAD_EN_LCD_BL));
|
||||
krane_diag_band(520, 20, 0x0000ff80); /* mint: revival writes done */
|
||||
krane_fb_log(" REVIVE");
|
||||
|
||||
/*
|
||||
* The coreboot table sits above the DRAM window described by the
|
||||
@@ -196,6 +297,7 @@ static int mt8183_scanout_probe(struct udevice *dev)
|
||||
*/
|
||||
mmu_map_region(COREBOOT_TABLE_ADDR, SZ_4K, false);
|
||||
krane_diag_band(540, 20, 0x008000ff); /* violet: table mapped */
|
||||
krane_fb_log(" MAPTBL");
|
||||
|
||||
ret = find_framebuffer(COREBOOT_TABLE_ADDR, &fb);
|
||||
if (ret) {
|
||||
@@ -203,6 +305,7 @@ static int mt8183_scanout_probe(struct udevice *dev)
|
||||
return log_msg_ret("lbio", ret);
|
||||
}
|
||||
krane_diag_band(560, 20, 0x00ffff80); /* pale yellow: LBIO found */
|
||||
krane_fb_log(" LBIO");
|
||||
|
||||
if (fb.bits_per_pixel != 32 || fb.red_pos != 16 || fb.red_size != 8 ||
|
||||
fb.green_pos != 8 || fb.green_size != 8 ||
|
||||
@@ -211,6 +314,7 @@ static int mt8183_scanout_probe(struct udevice *dev)
|
||||
return log_msg_ret("fmt", -ENOTSUPP);
|
||||
}
|
||||
krane_diag_band(580, 20, 0x0080ffff); /* pale cyan: fmt OK */
|
||||
krane_fb_log(" FMT");
|
||||
|
||||
/*
|
||||
* Use the address from the coreboot table when it is a plausible
|
||||
@@ -227,6 +331,7 @@ static int mt8183_scanout_probe(struct udevice *dev)
|
||||
return log_msg_ret("scanout", -ENODEV);
|
||||
}
|
||||
krane_diag_band(620, 40, 0x00aaaaaa); /* gray: geometry resolved */
|
||||
krane_fb_log(" GEO");
|
||||
|
||||
plat->base = addr;
|
||||
plat->size = fb.bytes_per_line * fb.y_resolution;
|
||||
|
||||
Reference in New Issue
Block a user