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.
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, ®s->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
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
.
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
#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