rtwo: replace 7-segment debug digits with a boot progress bar

The bring-up instrumentation drew two big 7-segment digits per code zone
from hot paths (board.c, serial_msm_geni.c, clk-uclass.c, clock-qcom.c),
firing dozens of times per second and slowing the boot noticeably. Drop
it and draw a 0-100% progress bar instead: rtwo_boot_progress_step() once
per initcall entry, rtwo_boot_progress_done() at the end of the boot.

The kalama-gcc-v2 GCC compatible fix from the previous commit stays.

This is the tree built with ~/pmos/uboot-chainload/build-uboot.sh
(patches/0001-rtwo-fixes-and-boot-progress-bar.patch) that produces the
u-boot-nodtb.bin currently running on the phone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnHwDU5yL8L6qgPEN5CV5m
This commit is contained in:
2026-09-26 20:03:48 -03:00
co-authored by Claude Opus 5.5
parent 01a9184178
commit 41802fcbd9
6 changed files with 85 additions and 129 deletions
+77 -70
View File
@@ -519,6 +519,8 @@ void __weak qcom_late_init(void)
#define lmb_alloc(size, addr) lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
void rtwo_boot_progress_done(void);
/* Stolen from arch/arm/mach-apple/board.c */
int board_late_init(void)
{
@@ -578,6 +580,8 @@ int board_late_init(void)
/* Configure the dfu_string for capsule updates */
qcom_configure_capsule_updates();
rtwo_boot_progress_done();
return 0;
}
@@ -756,36 +760,42 @@ void enable_caches(void)
}
/*
* Instrumentacion temporal de bring-up (rtwo, SM8550): sin UART, la unica
* senal visible que este ABL deja disponible es el framebuffer que deja
* prendido en 0xb8000000 (splash_region). Cada zona de codigo (board_init_f
* generico, board_init_r generico, probe de serial, camino de clk_enable)
* llama a rtwo_debug_blink_zone() con su propio numero de zona, que se
* dibuja como DOS DIGITOS GRANDES ESTILO 7-SEGMENTOS (blanco sobre negro,
* el numero de zona en decimal, directo). Los esquemas anteriores (bandas
* horizontales para contar, luego un codigo binario de 6 barras) resultaron
* fragiles con luz/reflejo del vidrio: dos lecturas distintas del mismo
* codigo de barras (una por foto, otra mirando el telefono directo) sobre
* la misma pantalla congelada -- ver memoria rtwo-uboot-chainload. Un
* numero grande no necesita interpretacion. Cada sitio instrumentado en
* board.c/serial_msm_geni.c/clk-uclass.c/clock-qcom.c/clock-sm8550.c tiene
* su propio numero GLOBAL y UNICO de zona (1, 2 para los INITCALL
* genericos de board_init_f/board_init_r; 10-39 para los pasos de probe de
* serial y del camino de clk_enable). rtwo_debug_blink() (zona 1/2 segun
* GD_FLG_RELOC) es la que llama include/initcall.h en cada INITCALL de
* board_init_f/board_init_r.
* Mantenimiento de cache manual porque el framebuffer lo lee el
* controlador de display directamente de DRAM, sin pasar por la CPU.
* Barra de progreso de arranque (rtwo, SM8550): dibuja en el framebuffer que
* el ABL deja prendido en 0xb8000000 (splash_region), la unica senal visible
* sin UART. Reemplaza la instrumentacion de bring-up anterior (digitos de
* 7 segmentos por zona de codigo en board.c/serial_msm_geni.c/clk-uclass.c/
* clock-qcom.c/clock-sm8550.c, ver historial en memoria rtwo-uboot-chainload)
* una vez confirmado que el chainload arranca: aquella instrumentacion vivia
* dentro de rutas calientes (clk_enable/qcom_gate_clk_en/probe de serial, con
* un flush de cache de los 10 MiB completos del framebuffer en CADA llamada)
* y se disparaba decenas de veces por segundo, alargando bastante el arranque.
* Esta version solo se engancha una vez por paso de `include/initcall.h`
* (rtwo_boot_progress_step(), UN llamado por entrada de
* init_sequence_f[]/init_sequence_r[], no por operacion de bajo nivel) y solo
* toca/flushea el rectangulo de la barra, no la pantalla entera.
* Mantenimiento de cache manual porque el framebuffer lo lee el controlador
* de display directamente de DRAM, sin pasar por la CPU.
*/
#define RTWO_FB_BASE 0xb8000000UL
#define RTWO_FB_SIZE 0xA00000UL /* 10 MiB: cubre 1080x2400x4 con margen */
#define RTWO_FB_STRIDE_WORDS 1080UL /* ancho en palabras de 32 bits */
#define RTWO_DIGIT_W 360UL
#define RTWO_DIGIT_H 700UL
#define RTWO_DIGIT_THICK 70UL
#define RTWO_DIGIT_GAP 60UL
#define RTWO_DIGIT_Y0 850UL /* deja libre la zona de la camara punch-hole arriba */
#define RTWO_BAR_X0 140UL
#define RTWO_BAR_X1 940UL /* 800 px de ancho, centrada */
#define RTWO_BAR_Y0 1150UL
#define RTWO_BAR_Y1 1250UL /* 100 px de alto */
#define RTWO_BAR_BORDER 6UL
/*
* Estimacion aproximada de cuantos pasos de INITCALL hay entre
* board_init_f() y board_init_r() en esta config -- no hace falta que sea
* exacta, solo que la barra avance de forma pareja y no llegue a 100% antes
* de tiempo. rtwo_boot_progress_done() (llamada al final de
* board_late_init(), justo antes de bootcmd) la fuerza a 100% siempre, sin
* depender de haber contado bien.
*/
#define RTWO_BOOT_STEPS_ESTIMATE 40U
#define RTWO_BOOT_PROGRESS_CAP 96U /* tope hasta el 100% explicito */
static void rtwo_fill_rect(volatile unsigned int *fb, unsigned long x0, unsigned long y0,
unsigned long x1, unsigned long y1, unsigned int color)
@@ -800,59 +810,56 @@ static void rtwo_fill_rect(volatile unsigned int *fb, unsigned long x0, unsigned
}
}
/* Mascara de segmentos por digito: bit0=A(arriba) bit1=B(sup-der)
* bit2=C(inf-der) bit3=D(abajo) bit4=E(inf-izq) bit5=F(sup-izq) bit6=G(medio),
* codificacion estandar de un display de 7 segmentos.
*/
static void rtwo_draw_digit(volatile unsigned int *fb, unsigned long x0, unsigned int digit)
static void rtwo_flush_bar_cache(void)
{
static const unsigned char segs[10] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,
};
unsigned char m = digit < 10 ? segs[digit] : 0;
unsigned long y0 = RTWO_DIGIT_Y0;
unsigned long yh = y0 + RTWO_DIGIT_H / 2;
unsigned long y1 = y0 + RTWO_DIGIT_H;
unsigned long t = RTWO_DIGIT_THICK;
unsigned int on = 0xFFFFFFFFu;
if (m & 0x01) /* A */
rtwo_fill_rect(fb, x0 + t, y0, x0 + RTWO_DIGIT_W - t, y0 + t, on);
if (m & 0x40) /* G */
rtwo_fill_rect(fb, x0 + t, yh - t / 2, x0 + RTWO_DIGIT_W - t, yh + t / 2, on);
if (m & 0x08) /* D */
rtwo_fill_rect(fb, x0 + t, y1 - t, x0 + RTWO_DIGIT_W - t, y1, on);
if (m & 0x20) /* F */
rtwo_fill_rect(fb, x0, y0, x0 + t, yh + t / 2, on);
if (m & 0x02) /* B */
rtwo_fill_rect(fb, x0 + RTWO_DIGIT_W - t, y0, x0 + RTWO_DIGIT_W, yh + t / 2, on);
if (m & 0x10) /* E */
rtwo_fill_rect(fb, x0, yh - t / 2, x0 + t, y1, on);
if (m & 0x04) /* C */
rtwo_fill_rect(fb, x0 + RTWO_DIGIT_W - t, yh - t / 2, x0 + RTWO_DIGIT_W, y1, on);
}
void rtwo_debug_blink_zone(unsigned int zone)
{
volatile unsigned int *fb = (volatile unsigned int *)RTWO_FB_BASE;
const unsigned long total_words = RTWO_FB_SIZE / 4;
const unsigned long total_rows = total_words / RTWO_FB_STRIDE_WORDS;
const unsigned long margin_left = (RTWO_FB_STRIDE_WORDS - (2 * RTWO_DIGIT_W + RTWO_DIGIT_GAP)) / 2;
unsigned long addr;
rtwo_fill_rect(fb, 0, 0, RTWO_FB_STRIDE_WORDS, total_rows, 0u); /* fondo negro */
rtwo_draw_digit(fb, margin_left, zone / 10U);
rtwo_draw_digit(fb, margin_left + RTWO_DIGIT_W + RTWO_DIGIT_GAP, zone % 10U);
unsigned long start = RTWO_FB_BASE + RTWO_BAR_Y0 * RTWO_FB_STRIDE_WORDS * 4;
unsigned long end = RTWO_FB_BASE + RTWO_BAR_Y1 * RTWO_FB_STRIDE_WORDS * 4;
asm volatile("dsb sy" ::: "memory");
for (addr = RTWO_FB_BASE; addr < RTWO_FB_BASE + RTWO_FB_SIZE; addr += 64)
for (addr = start & ~63UL; addr < end; addr += 64)
asm volatile("dc civac, %0" :: "r"(addr) : "memory");
asm volatile("dsb sy" ::: "memory");
asm volatile("isb" ::: "memory");
}
void rtwo_debug_blink(void)
static void rtwo_draw_progress_bar(unsigned int percent)
{
rtwo_debug_blink_zone((gd->flags & GD_FLG_RELOC) ? 2U : 1U);
volatile unsigned int *fb = (volatile unsigned int *)RTWO_FB_BASE;
unsigned long fill_x1;
if (percent > 100U)
percent = 100U;
/* borde blanco */
rtwo_fill_rect(fb, RTWO_BAR_X0, RTWO_BAR_Y0, RTWO_BAR_X1, RTWO_BAR_Y1, 0xFFFFFFFFu);
/* fondo negro, dentro del borde */
rtwo_fill_rect(fb, RTWO_BAR_X0 + RTWO_BAR_BORDER, RTWO_BAR_Y0 + RTWO_BAR_BORDER,
RTWO_BAR_X1 - RTWO_BAR_BORDER, RTWO_BAR_Y1 - RTWO_BAR_BORDER, 0u);
fill_x1 = RTWO_BAR_X0 + RTWO_BAR_BORDER +
(RTWO_BAR_X1 - RTWO_BAR_X0 - 2 * RTWO_BAR_BORDER) * percent / 100U;
if (fill_x1 > RTWO_BAR_X0 + RTWO_BAR_BORDER)
rtwo_fill_rect(fb, RTWO_BAR_X0 + RTWO_BAR_BORDER, RTWO_BAR_Y0 + RTWO_BAR_BORDER,
fill_x1, RTWO_BAR_Y1 - RTWO_BAR_BORDER, 0xFFFFFFFFu);
rtwo_flush_bar_cache();
}
void rtwo_boot_progress_step(void)
{
static unsigned int steps;
unsigned int percent;
steps++;
percent = steps * RTWO_BOOT_PROGRESS_CAP / RTWO_BOOT_STEPS_ESTIMATE;
if (percent > RTWO_BOOT_PROGRESS_CAP)
percent = RTWO_BOOT_PROGRESS_CAP;
rtwo_draw_progress_bar(percent);
}
void rtwo_boot_progress_done(void)
{
rtwo_draw_progress_bar(100U);
}