xref: /optee_os/core/drivers/bcm_sotp.c (revision 525c44ee7f3b0f10ca4f3b7f0bb5b899e2bccbc6)
1*525c44eeSSandeep Tripathy // SPDX-License-Identifier: BSD-2-Clause
2*525c44eeSSandeep Tripathy /*
3*525c44eeSSandeep Tripathy  * Copyright 2019 Broadcom.
4*525c44eeSSandeep Tripathy  */
5*525c44eeSSandeep Tripathy 
6*525c44eeSSandeep Tripathy #include <assert.h>
7*525c44eeSSandeep Tripathy #include <drivers/bcm_sotp.h>
8*525c44eeSSandeep Tripathy #include <initcall.h>
9*525c44eeSSandeep Tripathy #include <io.h>
10*525c44eeSSandeep Tripathy #include <kernel/delay.h>
11*525c44eeSSandeep Tripathy #include <mm/core_memprot.h>
12*525c44eeSSandeep Tripathy #include <platform_config.h>
13*525c44eeSSandeep Tripathy #include <util.h>
14*525c44eeSSandeep Tripathy 
15*525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL			0x0
16*525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN	BIT(15)
17*525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL__OTP_DISABLE_ECC	BIT(9)
18*525c44eeSSandeep Tripathy #define SOTP_ADDR__OTP_ROW_ADDR_R		6
19*525c44eeSSandeep Tripathy 
20*525c44eeSSandeep Tripathy #define SOTP_ADDR				0xc
21*525c44eeSSandeep Tripathy 
22*525c44eeSSandeep Tripathy #define SOTP_CTRL_0				0x10
23*525c44eeSSandeep Tripathy #define SOTP_CTRL_0__START			1
24*525c44eeSSandeep Tripathy #define SOTP_READ				0
25*525c44eeSSandeep Tripathy 
26*525c44eeSSandeep Tripathy #define SOTP_STAT_0				0x18
27*525c44eeSSandeep Tripathy #define SOTP_STATUS_0__FDONE			BIT(3)
28*525c44eeSSandeep Tripathy 
29*525c44eeSSandeep Tripathy #define SOTP_STATUS_1				0x1c
30*525c44eeSSandeep Tripathy #define SOTP_STATUS_1__CMD_DONE			BIT(1)
31*525c44eeSSandeep Tripathy #define SOTP_STATUS_1__ECC_DET			BIT(17)
32*525c44eeSSandeep Tripathy 
33*525c44eeSSandeep Tripathy #define SOTP_RDDATA_0				0x20
34*525c44eeSSandeep Tripathy #define SOTP_RDDATA_1				0x24
35*525c44eeSSandeep Tripathy #define SOTP_ADDR_MASK				0x3ff
36*525c44eeSSandeep Tripathy 
37*525c44eeSSandeep Tripathy #define SOTP_ECC_ERR_DETECT			BIT64(63)
38*525c44eeSSandeep Tripathy 
39*525c44eeSSandeep Tripathy #define SOTP_TIMEOUT_US				300
40*525c44eeSSandeep Tripathy 
41*525c44eeSSandeep Tripathy static vaddr_t bcm_sotp_base;
42*525c44eeSSandeep Tripathy 
43*525c44eeSSandeep Tripathy static TEE_Result otp_status_done_wait(vaddr_t addr, uint32_t bit)
44*525c44eeSSandeep Tripathy {
45*525c44eeSSandeep Tripathy 	uint64_t timeout = timeout_init_us(SOTP_TIMEOUT_US);
46*525c44eeSSandeep Tripathy 
47*525c44eeSSandeep Tripathy 	while (!(io_read32(addr) & bit))
48*525c44eeSSandeep Tripathy 		if (timeout_elapsed(timeout))
49*525c44eeSSandeep Tripathy 			return TEE_ERROR_BUSY;
50*525c44eeSSandeep Tripathy 	return TEE_SUCCESS;
51*525c44eeSSandeep Tripathy }
52*525c44eeSSandeep Tripathy 
53*525c44eeSSandeep Tripathy TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, uint32_t sotp_add_ecc,
54*525c44eeSSandeep Tripathy 				uint64_t *rdata)
55*525c44eeSSandeep Tripathy {
56*525c44eeSSandeep Tripathy 	uint64_t read_data = 0;
57*525c44eeSSandeep Tripathy 	uint32_t reg_val = 0;
58*525c44eeSSandeep Tripathy 	TEE_Result ret = TEE_SUCCESS;
59*525c44eeSSandeep Tripathy 
60*525c44eeSSandeep Tripathy 	assert(bcm_sotp_base);
61*525c44eeSSandeep Tripathy 	/* Check for FDONE status */
62*525c44eeSSandeep Tripathy 	ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0),
63*525c44eeSSandeep Tripathy 				   SOTP_STATUS_0__FDONE);
64*525c44eeSSandeep Tripathy 	if (ret) {
65*525c44eeSSandeep Tripathy 		EMSG("FDONE status done wait failed");
66*525c44eeSSandeep Tripathy 		return ret;
67*525c44eeSSandeep Tripathy 	}
68*525c44eeSSandeep Tripathy 
69*525c44eeSSandeep Tripathy 	/* Enable OTP access by CPU */
70*525c44eeSSandeep Tripathy 	io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
71*525c44eeSSandeep Tripathy 		     SOTP_PROG_CONTROL__OTP_CPU_MODE_EN);
72*525c44eeSSandeep Tripathy 
73*525c44eeSSandeep Tripathy 	if (sotp_add_ecc == 1) {
74*525c44eeSSandeep Tripathy 		io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
75*525c44eeSSandeep Tripathy 			     SOTP_PROG_CONTROL__OTP_DISABLE_ECC);
76*525c44eeSSandeep Tripathy 	} else {
77*525c44eeSSandeep Tripathy 		io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
78*525c44eeSSandeep Tripathy 			     SOTP_PROG_CONTROL__OTP_DISABLE_ECC);
79*525c44eeSSandeep Tripathy 	}
80*525c44eeSSandeep Tripathy 
81*525c44eeSSandeep Tripathy 	/* 10 bit row address */
82*525c44eeSSandeep Tripathy 	reg_val = (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R;
83*525c44eeSSandeep Tripathy 	io_write32((bcm_sotp_base + SOTP_ADDR), reg_val);
84*525c44eeSSandeep Tripathy 	reg_val = SOTP_READ;
85*525c44eeSSandeep Tripathy 	io_write32((bcm_sotp_base + SOTP_CTRL_0), reg_val);
86*525c44eeSSandeep Tripathy 
87*525c44eeSSandeep Tripathy 	/* Start bit to tell SOTP to send command to the OTP controller */
88*525c44eeSSandeep Tripathy 	io_setbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START);
89*525c44eeSSandeep Tripathy 
90*525c44eeSSandeep Tripathy 	/* Wait for SOTP command done to be set */
91*525c44eeSSandeep Tripathy 	ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0),
92*525c44eeSSandeep Tripathy 				   SOTP_STATUS_1__CMD_DONE);
93*525c44eeSSandeep Tripathy 	if (ret) {
94*525c44eeSSandeep Tripathy 		EMSG("FDONE cmd done wait failed\n");
95*525c44eeSSandeep Tripathy 		return ret;
96*525c44eeSSandeep Tripathy 	}
97*525c44eeSSandeep Tripathy 
98*525c44eeSSandeep Tripathy 	DMSG("CMD Done\n");
99*525c44eeSSandeep Tripathy 
100*525c44eeSSandeep Tripathy 	/* Clr Start bit after command done */
101*525c44eeSSandeep Tripathy 	io_clrbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START);
102*525c44eeSSandeep Tripathy 	read_data = io_read32(bcm_sotp_base + SOTP_RDDATA_1);
103*525c44eeSSandeep Tripathy 	read_data = ((read_data & 0x1ff) << 32);
104*525c44eeSSandeep Tripathy 	read_data |= io_read32(bcm_sotp_base + SOTP_RDDATA_0);
105*525c44eeSSandeep Tripathy 
106*525c44eeSSandeep Tripathy 	reg_val = io_read32(bcm_sotp_base + SOTP_STATUS_1);
107*525c44eeSSandeep Tripathy 	/* no ECC check till row 15 */
108*525c44eeSSandeep Tripathy 	if ((row_addr > 15) && (reg_val & SOTP_STATUS_1__ECC_DET)) {
109*525c44eeSSandeep Tripathy 		EMSG("SOTP ECC ERROR Detected ROW %d\n", row_addr);
110*525c44eeSSandeep Tripathy 		read_data = SOTP_ECC_ERR_DETECT;
111*525c44eeSSandeep Tripathy 	}
112*525c44eeSSandeep Tripathy 
113*525c44eeSSandeep Tripathy 	/* Command done is cleared */
114*525c44eeSSandeep Tripathy 	io_setbits32((bcm_sotp_base + SOTP_STATUS_1), SOTP_STATUS_1__CMD_DONE);
115*525c44eeSSandeep Tripathy 	io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
116*525c44eeSSandeep Tripathy 		     SOTP_PROG_CONTROL__OTP_CPU_MODE_EN);
117*525c44eeSSandeep Tripathy 	DMSG("read done\n");
118*525c44eeSSandeep Tripathy 
119*525c44eeSSandeep Tripathy 	*rdata = read_data;
120*525c44eeSSandeep Tripathy 	return ret;
121*525c44eeSSandeep Tripathy }
122*525c44eeSSandeep Tripathy 
123*525c44eeSSandeep Tripathy static TEE_Result bcm_sotp_init(void)
124*525c44eeSSandeep Tripathy {
125*525c44eeSSandeep Tripathy 	bcm_sotp_base = (vaddr_t)phys_to_virt(SOTP_BASE, MEM_AREA_IO_SEC);
126*525c44eeSSandeep Tripathy 
127*525c44eeSSandeep Tripathy 	DMSG("bcm_sotp init done\n");
128*525c44eeSSandeep Tripathy 	return TEE_SUCCESS;
129*525c44eeSSandeep Tripathy }
130*525c44eeSSandeep Tripathy 
131*525c44eeSSandeep Tripathy driver_init(bcm_sotp_init);
132