xref: /optee_os/core/drivers/bcm_sotp.c (revision c2e4eb43b7b7211345cd38ceceac97773bd78d2c)
1525c44eeSSandeep Tripathy // SPDX-License-Identifier: BSD-2-Clause
2525c44eeSSandeep Tripathy /*
3525c44eeSSandeep Tripathy  * Copyright 2019 Broadcom.
4525c44eeSSandeep Tripathy  */
5525c44eeSSandeep Tripathy 
6525c44eeSSandeep Tripathy #include <assert.h>
7525c44eeSSandeep Tripathy #include <drivers/bcm_sotp.h>
8525c44eeSSandeep Tripathy #include <initcall.h>
9525c44eeSSandeep Tripathy #include <io.h>
10525c44eeSSandeep Tripathy #include <kernel/delay.h>
11525c44eeSSandeep Tripathy #include <mm/core_memprot.h>
12525c44eeSSandeep Tripathy #include <platform_config.h>
13525c44eeSSandeep Tripathy #include <util.h>
14525c44eeSSandeep Tripathy 
15525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL			0x0
16525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN	BIT(15)
17525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL__OTP_DISABLE_ECC	BIT(9)
18525c44eeSSandeep Tripathy #define SOTP_ADDR__OTP_ROW_ADDR_R		6
19525c44eeSSandeep Tripathy 
20525c44eeSSandeep Tripathy #define SOTP_ADDR				0xc
21525c44eeSSandeep Tripathy 
22525c44eeSSandeep Tripathy #define SOTP_CTRL_0				0x10
23525c44eeSSandeep Tripathy #define SOTP_CTRL_0__START			1
24525c44eeSSandeep Tripathy #define SOTP_READ				0
25525c44eeSSandeep Tripathy 
26525c44eeSSandeep Tripathy #define SOTP_STAT_0				0x18
27525c44eeSSandeep Tripathy #define SOTP_STATUS_0__FDONE			BIT(3)
28525c44eeSSandeep Tripathy 
29525c44eeSSandeep Tripathy #define SOTP_STATUS_1				0x1c
30525c44eeSSandeep Tripathy #define SOTP_STATUS_1__CMD_DONE			BIT(1)
31525c44eeSSandeep Tripathy #define SOTP_STATUS_1__ECC_DET			BIT(17)
32525c44eeSSandeep Tripathy 
33525c44eeSSandeep Tripathy #define SOTP_RDDATA_0				0x20
34525c44eeSSandeep Tripathy #define SOTP_RDDATA_1				0x24
35525c44eeSSandeep Tripathy #define SOTP_ADDR_MASK				0x3ff
36525c44eeSSandeep Tripathy 
37525c44eeSSandeep Tripathy #define SOTP_ECC_ERR_DETECT			BIT64(63)
38525c44eeSSandeep Tripathy 
39525c44eeSSandeep Tripathy #define SOTP_TIMEOUT_US				300
40525c44eeSSandeep Tripathy 
41525c44eeSSandeep Tripathy static vaddr_t bcm_sotp_base;
42525c44eeSSandeep Tripathy 
43525c44eeSSandeep Tripathy static TEE_Result otp_status_done_wait(vaddr_t addr, uint32_t bit)
44525c44eeSSandeep Tripathy {
45525c44eeSSandeep Tripathy 	uint64_t timeout = timeout_init_us(SOTP_TIMEOUT_US);
46525c44eeSSandeep Tripathy 
47525c44eeSSandeep Tripathy 	while (!(io_read32(addr) & bit))
48525c44eeSSandeep Tripathy 		if (timeout_elapsed(timeout))
49525c44eeSSandeep Tripathy 			return TEE_ERROR_BUSY;
50525c44eeSSandeep Tripathy 	return TEE_SUCCESS;
51525c44eeSSandeep Tripathy }
52525c44eeSSandeep Tripathy 
53525c44eeSSandeep Tripathy TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, uint32_t sotp_add_ecc,
54525c44eeSSandeep Tripathy 				uint64_t *rdata)
55525c44eeSSandeep Tripathy {
56525c44eeSSandeep Tripathy 	uint64_t read_data = 0;
57525c44eeSSandeep Tripathy 	uint32_t reg_val = 0;
58525c44eeSSandeep Tripathy 	TEE_Result ret = TEE_SUCCESS;
59525c44eeSSandeep Tripathy 
60525c44eeSSandeep Tripathy 	assert(bcm_sotp_base);
61525c44eeSSandeep Tripathy 	/* Check for FDONE status */
62525c44eeSSandeep Tripathy 	ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0),
63525c44eeSSandeep Tripathy 				   SOTP_STATUS_0__FDONE);
64525c44eeSSandeep Tripathy 	if (ret) {
65525c44eeSSandeep Tripathy 		EMSG("FDONE status done wait failed");
66525c44eeSSandeep Tripathy 		return ret;
67525c44eeSSandeep Tripathy 	}
68525c44eeSSandeep Tripathy 
69525c44eeSSandeep Tripathy 	/* Enable OTP access by CPU */
70525c44eeSSandeep Tripathy 	io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
71525c44eeSSandeep Tripathy 		     SOTP_PROG_CONTROL__OTP_CPU_MODE_EN);
72525c44eeSSandeep Tripathy 
734afc3781SBharat Kumar Reddy Gooty 	/* ROWS does not support ECC */
744afc3781SBharat Kumar Reddy Gooty 	if (row_addr <= SOTP_NO_ECC_ROWS)
754afc3781SBharat Kumar Reddy Gooty 		sotp_add_ecc = 0;
764afc3781SBharat Kumar Reddy Gooty 
77525c44eeSSandeep Tripathy 	if (sotp_add_ecc == 1) {
78525c44eeSSandeep Tripathy 		io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
79525c44eeSSandeep Tripathy 			     SOTP_PROG_CONTROL__OTP_DISABLE_ECC);
80525c44eeSSandeep Tripathy 	} else {
81525c44eeSSandeep Tripathy 		io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
82525c44eeSSandeep Tripathy 			     SOTP_PROG_CONTROL__OTP_DISABLE_ECC);
83525c44eeSSandeep Tripathy 	}
84525c44eeSSandeep Tripathy 
85525c44eeSSandeep Tripathy 	/* 10 bit row address */
86525c44eeSSandeep Tripathy 	reg_val = (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R;
87525c44eeSSandeep Tripathy 	io_write32((bcm_sotp_base + SOTP_ADDR), reg_val);
88525c44eeSSandeep Tripathy 	reg_val = SOTP_READ;
89525c44eeSSandeep Tripathy 	io_write32((bcm_sotp_base + SOTP_CTRL_0), reg_val);
90525c44eeSSandeep Tripathy 
91525c44eeSSandeep Tripathy 	/* Start bit to tell SOTP to send command to the OTP controller */
92525c44eeSSandeep Tripathy 	io_setbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START);
93525c44eeSSandeep Tripathy 
94525c44eeSSandeep Tripathy 	/* Wait for SOTP command done to be set */
95525c44eeSSandeep Tripathy 	ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0),
96525c44eeSSandeep Tripathy 				   SOTP_STATUS_1__CMD_DONE);
97525c44eeSSandeep Tripathy 	if (ret) {
98525c44eeSSandeep Tripathy 		EMSG("FDONE cmd done wait failed\n");
99525c44eeSSandeep Tripathy 		return ret;
100525c44eeSSandeep Tripathy 	}
101525c44eeSSandeep Tripathy 
102525c44eeSSandeep Tripathy 	DMSG("CMD Done\n");
103525c44eeSSandeep Tripathy 
104525c44eeSSandeep Tripathy 	/* Clr Start bit after command done */
105525c44eeSSandeep Tripathy 	io_clrbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START);
106525c44eeSSandeep Tripathy 	read_data = io_read32(bcm_sotp_base + SOTP_RDDATA_1);
107525c44eeSSandeep Tripathy 	read_data = ((read_data & 0x1ff) << 32);
108525c44eeSSandeep Tripathy 	read_data |= io_read32(bcm_sotp_base + SOTP_RDDATA_0);
109525c44eeSSandeep Tripathy 
110525c44eeSSandeep Tripathy 	reg_val = io_read32(bcm_sotp_base + SOTP_STATUS_1);
1114afc3781SBharat Kumar Reddy Gooty 	/* No ECC check till SOTP_NO_ECC_ROWS */
1124afc3781SBharat Kumar Reddy Gooty 	if (row_addr > SOTP_NO_ECC_ROWS &&
1134afc3781SBharat Kumar Reddy Gooty 	    reg_val & SOTP_STATUS_1__ECC_DET) {
114525c44eeSSandeep Tripathy 		EMSG("SOTP ECC ERROR Detected ROW %d\n", row_addr);
115525c44eeSSandeep Tripathy 		read_data = SOTP_ECC_ERR_DETECT;
116525c44eeSSandeep Tripathy 	}
117525c44eeSSandeep Tripathy 
118525c44eeSSandeep Tripathy 	/* Command done is cleared */
119525c44eeSSandeep Tripathy 	io_setbits32((bcm_sotp_base + SOTP_STATUS_1), SOTP_STATUS_1__CMD_DONE);
120525c44eeSSandeep Tripathy 	io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
121525c44eeSSandeep Tripathy 		     SOTP_PROG_CONTROL__OTP_CPU_MODE_EN);
122525c44eeSSandeep Tripathy 	DMSG("read done\n");
123525c44eeSSandeep Tripathy 
124525c44eeSSandeep Tripathy 	*rdata = read_data;
125525c44eeSSandeep Tripathy 	return ret;
126525c44eeSSandeep Tripathy }
127525c44eeSSandeep Tripathy 
128525c44eeSSandeep Tripathy static TEE_Result bcm_sotp_init(void)
129525c44eeSSandeep Tripathy {
130*c2e4eb43SAnton Rybakov 	bcm_sotp_base = (vaddr_t)phys_to_virt(SOTP_BASE, MEM_AREA_IO_SEC, 1);
131525c44eeSSandeep Tripathy 
132525c44eeSSandeep Tripathy 	DMSG("bcm_sotp init done\n");
133525c44eeSSandeep Tripathy 	return TEE_SUCCESS;
134525c44eeSSandeep Tripathy }
135525c44eeSSandeep Tripathy 
13619ac2e24SVahid Dukandar service_init(bcm_sotp_init);
137