Skip to content

Commit eb5f0ff

Browse files
widgetiiclaude
andcommitted
clocks: add V4A family (CV500 / AV300) — 4 PLLs + HPM
Adds a `clocks_family_v4a` table covering Hi3516CV500 / Hi3516AV300 / Hi3516DV300 etc. (chip_generation = HISI_V4A = 0x3516C500). Register map sourced first-party from the V4A mask-ROM reverse engineering at widgetii/HI3516CV500-SDK sdk/bootrom/bootrom-re/ regmap-crg.h (CRG offsets) and the V4A SDK HI3516CV500-SDK/sdk/fastburn/fastboot/Source/ddr_training.c (HPM register addresses + bit layout). Decoded on V4A: - APLL/DPLL/EPLL/VPLL register pairs at (CRG+0x00..0x1C). All four use the same Hi3516A APLL bit layout (FBDIV at ctrl_reg2[11:0], REFDIV at ctrl_reg2[17:12], POSTDIV1/POSTDIV2 at ctrl_reg1[26:24]/[30:28]), unlike V4 where DPLL/EPLL had a different (still-unverified) layout. - Per-PLL lock state from PERI_CRG_PLL122 (CRG+0x1E8). APLL=bit0, DPLL=bit1, EPLL=bit3 (V4A bootrom RE polls `& 0xB == 0xB`); bit 2 inferred as VPLL since the field board reads 0x0F (all four locked). - HPM characterization at HPM_CHECK_REG = 0x12020098 (SC_CTRL region, not CRG): sys_hpm_core at bits [24:16] is 9-bit on V4A (vs 10-bit on V4), and the aux fingerprint moves to HPM_CORE_REG0 = 0x120300D8 in the MISC region. Same 150-350 validity window, same 190-310 nominal binning range as V4. Not yet decoded on V4A (kept out per "decypher or remove" rule from PR #163): - DDR cksel mux. PERI_CRG31 at 0x7C reads non-zero on hi3516av300 but the bit positions for the cksel field aren't in the bootrom RE and the V4A SDK clock driver doesn't expose DDR as a tunable Linux clock. Skip until a board with known DDR rate anchors it. Brief survey on V4A therefore omits `ddr.data_rate_mbps` -- it falls back to `cpu_pll.freq_mhz + hpm.bin`. Also tightens the brief-mode emit: only the first PLL (by convention the CPU/APLL) is shown in the survey output. DPLL/EPLL/VPLL on V4A are detail and only appear in the full `ipctool clocks` output. The V4 brief output is unchanged (V4 only has one PLL entry anyway). Verified on openipc-hi3516av300.dlab.doty.ru (dual-core Cortex-A7, SMP, Linux 4.9.37): - brief: cpu_pll.freq_mhz=900, hpm.bin=mid (5 lines after `clocks:`) - full: APLL=900 / DPLL=594 / EPLL=528 / VPLL=552 MHz, all locked; HPM value=260 (mid bin), aux_value=0x81090109 - cpubench median 899 MHz (within 0.1% of register-decoded APLL, triangulated from dep_add/indep_add/dep_mul) V4 boards re-verified: hi3516ev300 OpenIPC + gk7205v300 OpenIPC both still produce the 8-line brief block they did in #163. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f7a640e commit eb5f0ff

3 files changed

Lines changed: 118 additions & 1 deletion

File tree

‎CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ set(IPCTOOL_SRC
9191
src/firmware.c
9292
src/firmware.h
9393
src/hal/hisi/clocks_v4.c
94+
src/hal/hisi/clocks_v4a.c
9495
src/hal/hisi/ethernet.c
9596
src/hal/hisi/ethernet.h
9697
src/hal/hisi/ispreg.c

‎src/clocks.c‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
#include "tools.h"
1616

1717
extern const struct clock_family clocks_family_v4;
18+
extern const struct clock_family clocks_family_v4a;
1819

19-
/* TODO: add V1/V2/V3/V3A/V4A/OT/3536C/3536D tables — they share the
20+
/* TODO: add V1/V2/V3/V3A/OT/3536C/3536D tables — they share the
2021
* CRG-table approach but use different bases and bit layouts. */
2122
static const struct clock_family *const families[] = {
2223
&clocks_family_v4,
24+
&clocks_family_v4a,
2325
};
2426

2527
static const struct clock_family *family_for_chip(int chip_id) {
@@ -271,6 +273,12 @@ cJSON *clocks_build_json(bool brief) {
271273
cJSON *j_inner = cJSON_CreateObject();
272274

273275
for (size_t i = 0; i < fam->n_plls; i++) {
276+
/* Brief survey only shows the headline (CPU) PLL -- by convention
277+
* the first entry in the family's pll table. Other PLLs (DDR /
278+
* ETH / VIDEO) are detail and only emitted by the full `ipctool
279+
* clocks` output. */
280+
if (brief && i > 0)
281+
continue;
274282
cJSON *p = decode_pll(&fam->plls[i], brief);
275283
cJSON_AddItemToObject(j_inner, fam->plls[i].name, p);
276284
}

‎src/hal/hisi/clocks_v4a.c‎

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* Clock / PLL register map for the Hisilicon V4A family
2+
* (3516CV500, 3516AV300, 3516DV300 etc. — chip_generation HISI_V4A,
3+
* 0x3516C500).
4+
*
5+
* First-party register map from the V4A mask-ROM reverse engineering at
6+
* widgetii/HI3516CV500-SDK sdk/bootrom/bootrom-re/regmap-crg.h:
7+
*
8+
* APLL_CONFIG_0 = CRG_BASE + 0x00 (PERI_CRG_PLL0) CPU PLL
9+
* APLL_CONFIG_1 = CRG_BASE + 0x04 (PERI_CRG_PLL1)
10+
* DPLL_CONFIG_0 = CRG_BASE + 0x08 (PERI_CRG_PLL2) DDR PLL
11+
* DPLL_CONFIG_1 = CRG_BASE + 0x0C (PERI_CRG_PLL3)
12+
* EPLL_CONFIG_0 = CRG_BASE + 0x10 (PERI_CRG_PLL4) Ethernet PLL
13+
* EPLL_CONFIG_1 = CRG_BASE + 0x14 (PERI_CRG_PLL5)
14+
* VPLL_CONFIG_0 = CRG_BASE + 0x18 (PERI_CRG_PLL6) Video PLL
15+
* VPLL_CONFIG_1 = CRG_BASE + 0x1C (PERI_CRG_PLL7)
16+
* CPU_CONFIG = CRG_BASE + 0x78 (PERI_CRG30)
17+
* DDR_SDRAM_CFG = CRG_BASE + 0x7C (PERI_CRG31)
18+
* SOC_FREQ_STAT = CRG_BASE + 0x1E0 (PERI_CRG120)
19+
* PLL_LOCK_STAT = CRG_BASE + 0x1E8 (PERI_CRG_PLL122)
20+
*
21+
* On V4A all four PLLs share the same bit layout as APLL on V4 (per
22+
* `struct hi3516a_pll_clock` in the Hi3516A SDK kernel patch):
23+
* ctrl_reg1: FRACDIV[23:0], POSTDIV1[26:24], POSTDIV2[30:28]
24+
* ctrl_reg2: FBDIV[11:0], REFDIV[17:12]
25+
* f = 24 MHz * FBDIV / (REFDIV * POSTDIV1 * POSTDIV2)
26+
*
27+
* Validated on hi3516av300 (chip_generation=HISI_V4A, chip ID
28+
* SC_CTRL[0xEE0]=0x3516A300):
29+
* APLL (0x12000000, 0x0100104B): FBDIV=75 REFDIV=1 PDIV1=2 PDIV2=1 -> 900 MHz
30+
* DPLL (0x14000000, 0x01001063): FBDIV=99 REFDIV=1 PDIV1=4 PDIV2=1 -> 594 MHz
31+
* EPLL (0x12000000, 0x0000102C): FBDIV=44 REFDIV=1 PDIV1=2 PDIV2=1 -> 528 MHz
32+
* VPLL (0x12000000, 0x0100102E): FBDIV=46 REFDIV=1 PDIV1=2 PDIV2=1 -> 552 MHz
33+
* PLL_LOCK_STAT = 0x0F: bits 0/1/2/3 all set
34+
* bit 0 = APLL, bit 1 = DPLL, bit 3 = EPLL (per V4A bootrom RE check
35+
* `& 0xB == 0xB`; bit 2 inferred as VPLL since 0x0F shows all four
36+
* PLLs locked and only VPLL is left unaccounted for).
37+
*
38+
* HPM characterization on V4A lives in a different subsystem than on V4
39+
* (HI3516CV500-SDK/sdk/fastburn/fastboot/Source/ddr_training.c):
40+
* HPM_CHECK_REG = 0x12020098 (SC_CTRL), sys_hpm_core at bits [24:16]
41+
* (9-bit on V4A, not 10-bit like V4); hpm_core_err at
42+
* bit 26
43+
* HPM_CORE_REG0 = 0x120300D8 (MISC), per-die fingerprint
44+
* HPM_CORE_REG1 = 0x120300DC (MISC), additional per-die channels
45+
* Validity window 150..350 (per the SDK clamp); same nominal binning
46+
* range 190..310 used to classify low/mid/high.
47+
*
48+
* NOT yet decoded on V4A:
49+
* - DDR cksel mux. PERI_CRG31 at 0x7C reads non-zero on the test
50+
* board but bit positions for the cksel field aren't in the bootrom
51+
* RE and the V4A SDK clock driver doesn't expose DDR as a tunable
52+
* Linux clock. Skip until a board with known DDR rate anchors it.
53+
*
54+
* Brief survey shows cpu_pll.freq_mhz + hpm.bin. Full `ipctool clocks`
55+
* additionally shows DPLL/EPLL/VPLL frequencies and lock states.
56+
*/
57+
58+
#include "clocks.h"
59+
#include "hal/hisi/hal_hisi.h"
60+
61+
#define V4A_CRG_BASE 0x12010000
62+
#define V4A_LOCK_REG (V4A_CRG_BASE + 0x1E8)
63+
64+
/* All four PLLs share the Hi3516A APLL bit layout, so only the
65+
* ctrl_reg* addresses and the lock_bit differ between them. */
66+
#define V4A_PLL_BITS(REG0_OFF, REG1_OFF, LOCK_BIT) \
67+
.ctrl_reg1 = V4A_CRG_BASE + (REG0_OFF), .frac_shift = 0, .frac_width = 24, \
68+
.postdiv1_shift = 24, .postdiv1_width = 3, .postdiv2_shift = 28, \
69+
.postdiv2_width = 3, .ctrl_reg2 = V4A_CRG_BASE + (REG1_OFF), \
70+
.fbdiv_shift = 0, .fbdiv_width = 12, .refdiv_shift = 12, \
71+
.refdiv_width = 6, .input_khz = 24000, .lock_reg = V4A_LOCK_REG, \
72+
.lock_bit = (LOCK_BIT)
73+
74+
static const struct pll_info v4a_plls[] = {
75+
{.name = "cpu_pll", .label = "CPU PLL (APLL)", V4A_PLL_BITS(0x00, 0x04, 0)},
76+
{.name = "ddr_pll", .label = "DDR PLL (DPLL)", V4A_PLL_BITS(0x08, 0x0C, 1)},
77+
{.name = "eth_pll",
78+
.label = "Ethernet PLL (EPLL)",
79+
V4A_PLL_BITS(0x10, 0x14, 3)},
80+
{.name = "video_pll",
81+
.label = "Video PLL (VPLL)",
82+
V4A_PLL_BITS(0x18, 0x1C, 2)},
83+
};
84+
85+
static const struct hpm_info v4a_hpms[] = {
86+
{
87+
.name = "hpm",
88+
.label = "HPM core",
89+
.reg = 0x12020098, /* HPM_CHECK_REG (SC_CTRL region) */
90+
.value_shift = 16,
91+
.value_mask = 0x01FF, /* 9-bit sys_hpm_core on V4A (vs 10-bit on V4) */
92+
.window_min = 150, /* HPM_CORE_MIN (SDK clamp) */
93+
.window_max = 350, /* HPM_CORE_MAX */
94+
.bin_min = 190, /* nominal binning low */
95+
.bin_max = 310, /* nominal binning high */
96+
.aux_reg = 0x120300D8, /* HPM_CORE_REG0 (MISC region) */
97+
.aux_name = "hpm_core_reg0",
98+
},
99+
};
100+
101+
const struct clock_family clocks_family_v4a = {
102+
.chip_id = HISI_V4A,
103+
.label = "Hisilicon V4A (CV500 / AV300)",
104+
.plls = v4a_plls,
105+
.n_plls = sizeof(v4a_plls) / sizeof(v4a_plls[0]),
106+
.hpms = v4a_hpms,
107+
.n_hpms = sizeof(v4a_hpms) / sizeof(v4a_hpms[0]),
108+
};

0 commit comments

Comments
 (0)