Skip to content

Instantly share code, notes, and snippets.

@ganboing
Last active February 12, 2024 03:48
Show Gist options
  • Save ganboing/4711483c386623b14d49b75623c7e5b5 to your computer and use it in GitHub Desktop.
Save ganboing/4711483c386623b14d49b75623c7e5b5 to your computer and use it in GitHub Desktop.
jh7110/vf2 OTP Dump

My setup: Visionfive2 1.3b (JH7110). Using U-boot/OpenSBI from starfive's downstream fork (VF2_v3.8.2)

I confirmed my OTP has all 0xffffffff's (not programmed), using both methods.


(A) By using debug print before board_init_f from U-Boot SPL

https://github.com/ganboing/u-boot-starfive/commit/e931cc9856a9c5d5b5b24196fdc82a309db4dfbf

The "driver" I use to access OTP is the following:

static volatile u32 * const otp_sr = (void*)0x17050008;
static volatile u32 * const otp_opr = (void*)0x1705000c;
static volatile u32 * const otp_mem = (void*)0x17050800;
	for (size_t i = 0; i < ARRAY_SIZE(otp_dump_mem); i++) {
		// Set mode to READ
		writel(1, otp_opr);
		// wait for busy to clear
		while(readl(otp_sr) & (1 << 31));
		// read...
		otp_dump_mem[i] = readl(&otp_mem[i]);
		// wait for busy to clear
		while(readl(otp_sr) & (1 << 31));
		// Set mode to standby
		writel(0, otp_opr);
		// wait for busy to clear
		while(readl(otp_sr) & (1 << 31));
	}

This is basically a copy-paste of starfive's driver:

	for (i = 0; i < bytescnt; i++) {
		starfive_otp_setmode(plat->regs, OTP_OPR_READ);

		/* read the value */
		data = readl(base + OTP_MEM_START + offset);
		starfive_otp_regstatus(plat->regs, OTPC_SRR_BUSY);
		starfive_otp_setmode(plat->regs, OTP_OPR_STANDBY);
		databuf[i] = data;
		offset += 4;
	}

The reason I need to hand craft this driver rather than doing a misc read otp@17050000 <offset> <memory buffer> <len> is because the driver starfive provided is incorrect. It doesn't take into account for the real clock setting of the device, but uses the hard-coded value (4Mhz) from dts instead. When doing so, I see the value 0002040b gets programmed to reg[0] of OTP. (See my comment below for the calculation of 0002040b)

In dts:
  otp: otp@17050000 {
    compatible = "starfive,jh7110-otp";
    reg = <0x0 0x17050000 0x0 0x10000>;
    clock-frequency = <4000000>;
    clocks = <&clkgen JH7110_OTPC_CLK_APB>;
    clock-names = "apb";
  };

Driver code:
  div_1us = plat->pclk_hz / OTP_DIV_1US; // pclk_hz = 4Mhz, div_1us = 4
  rd_cyc = div_1us / OTP_TCD_TIME + 2; // OTP_TCD_TIME = 20, rd_cyc = 2

  val = OTP_TPW_TIME; // OTP_TPW_TIME = 11, val = 0xb
  val |= (rd_cyc & OTP_CFGR_RD_CYC_MASK) << OTP_CFGR_RD_CYC_SHIFT; // val = 0x0002000b
  val |= (div_1us & OTP_CFGR_DIV_1US_MASK) << OTP_CFGR_DIV_1US_SHIFT; // val = 0x0002040b

  writel(val, &regs->otp_cfg);

If I use the misc read command in U-Boot, the value I read was different each time:

StarFive # misc read otp@17050000 0 60000000 10
StarFive # md.l 60000000 4                     
60000000: ffffffff 200c94db 2004149b 282cdddb  ....... ... ..,(

StarFive # misc read otp@17050000 0 60000000 10
StarFive # md.l 60000000 4                     
60000000: ffffffff 200c9ddb 00000001 200c149b  ....... ....... 

StarFive # misc read otp@17050000 0 60000000 10
StarFive # md.l 60000000 4                     
60000000: ffffffff 20000001 20000009 2000040b  ....... ... ... 

StarFive # misc read otp@17050000 0 60000000 10
StarFive # md.l 60000000 4                     
60000000: ffffffff 2004049b 2000000b 2000000b  ....... ... ... 

The driver's assumption would be corrent had it been run before board_init_f, because OTP might really be running at 4Mhz (Need to confirm) before BUS ROOT switched to PLL2. To be absolutely sure about the value the ROM would read, I read OTP before board_init_f. At that time, no clock switching from U-boot has happened, and I assume OTP is running at the same frequency as the previous boot stage (ROM). This gives the following during boot:

#OTP:
17050000: 0002040b 00000003 00000000 00000000
otp000: ffffffff ffffffff ffffffff ffffffff
otp010: ffffffff ffffffff ffffffff ffffffff
otp020: ffffffff ffffffff ffffffff ffffffff
...
otp7f0: ffffffff ffffffff ffffffff ffffffff

(B) By "fixing" the driver's OTP clock register programming

As shown previously, the driver wrongly assumed platform clock pclk_hz is 4Mhz. Now, I fix that by programming reg[0] again. In U-Boot, modify memory mm.l 17050000 (reg[0]) to the value

  0x0004320b; // Calculated using the same logic in driver, but let pclk_hz = 49.5Mhz (actual clock)

misc read otp@17050000 0 60000000 800 now shows all ffffffff's.


Appendix: OTP clock hierarchy (after clock switch)

 root          0  [ + ]   root_driver           root_driver
 clk           0  [ + ]   fixed_clock           |-- osc
 clk          22  [ + ]   ccf_clk_fixed_factor  |   |-- pll2_out
 clk          29  [ + ]   ccf_clk_mux           |   |   |-- bus_root
 clk          30  [ + ]   ccf_clk_divider       |   |   |   |-- axi_cfg0
 clk          31  [ + ]   ccf_clk_divider       |   |   |   |   |-- stg_axiahb
 clk          34  [ + ]   ccf_clk_divider       |   |   |   |   |   |-- apb_bus_func
 clk          40  [ + ]   ccf_clk_fixed_factor  |   |   |   |   |   |   `-- aon_apb
 clk          89  [   ]   clk_gate              |   |   |   |   |   |       `-- u0_otpc_clk_apb


Appendix: CRG register dumps before board_init_f

#STG CRG:
10230000: 00000000 00000000 00000000 00000000
10230010: 00000002 00000004 00000000 00000002
10230020: 00000000 00000000 00000000 00000000
10230030: 00000000 00000000 80000000 00000000
10230040: 00000000 80000000 80000000 80000000
10230050: 80000000 80000000 80000000 80000000
10230060: 00000018 80000000 00000000 00000000
10230070: 00000000 007ffffe 00000001 00000000
#SYS CRG:
13020000: 00000000 00000001 00000002 00000000  // CPU ROOT -> clk_osc
13020010: 00000002 00000000 00000003 00000003  // Peripheral ROOT -> clk_pll0, BUS ROOT -> clk_osc
13020020: 00000002 80000000 80000000 00000004
13020030: 80000000 00000002 00000002 00000002
13020040: 00000002 0000000c 00000000 00000000
13020050: 00000002 00000002 80000014 80000010
13020060: 8000000c 80000000 80000000 80000000
13020070: 80000000 80000000 80000000 00000006
13020080: 80000000 80000000 80000000 80000000
13020090: 80000000 80000000 80000000 80000000
130200a0: 00000002 00000002 00000002 00000000
130200b0: 80000000 00000003 00000000 00000000
130200c0: 00000000 0000000c 00000000 00000000
130200d0: 00000000 80000000 00000003 00000002
130200e0: 80000000 80000000 00000000 00000002
130200f0: 00000000 00000000 00000000 00000000
13020100: 00000002 00000006 00000000 00000006
13020110: 00000000 00000003 00000000 00000003
13020120: 00000002 00000000 80000000 80000000
13020130: 00000000 00000005 00000000 00000005
13020140: 00000005 00000000 00000000 80000000
13020150: 80000000 80000000 80000000 80000000
13020160: 80000000 0000000a 80000000 80000000
13020170: 80000000 80000002 80000002 00000008
13020180: 00000000 00000000 00000000 00000002
13020190: 00000008 00000002 0000000a 00000020
130201a0: 40000000 00000000 40000000 00000020
130201b0: 00000008 0000000a 0000000a 00000020
130201c0: 80000000 80000000 80000000 00000000
130201d0: 00000018 00000008 00000000 00000018
130201e0: 00000008 00000000 80000000 80000000
130201f0: 80000000 80000000 80000000 00000000
13020200: 00000000 00000000 00000018 00000000
13020210: 00000000 00000000 00000000 00000000
13020220: 00000000 00000000 00000000 00000000
13020230: 00000000 00000000 00000000 00000000
13020240: 00000000 80000000 80000000 00000000
13020250: 00000000 00000000 00000000 00000000
13020260: 00000a00 00000000 00000a00 00000000
13020270: 00000a00 00000000 0000000c 00000000
13020280: 00000000 00000000 00000004 40000000
13020290: 00000040 00000000 40000000 00000000
130202a0: 00000000 00000004 40000000 00000040
130202b0: 00000000 40000000 00000000 00000000
130202c0: 00000004 40000000 00000040 00000000
130202d0: 40000000 00000000 00000008 00000000
130202e0: 00000000 00000000 00000001 00000000
130202f0: 40000000 00000004 00600000 07e7fe00
13020300: ffe7efcc 1fffffff ff9fffff f80001ff
13020310: 00181033 20000000 
#AON CRG
17000000: 00000004 00000000 00000000 00000000 // AON APB Func Clock -> clk_osc_div4
17000010: 00000002 00000000 40000000 00000020
17000020: 40000000 80000000 80000000 000002ee
17000030: 00000000 00000000 000000e3 0000001c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment