blob: 6ff855453d14de998fd9cc48a51cdd13f25e0573 [file] [log] [blame]
Sheetal Tigadoliad0943e2019-12-18 19:44:43 +05301/*
2 * Copyright (c) 2017 - 2020, Broadcom
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdint.h>
8
9#include <common/debug.h>
10#include <drivers/delay_timer.h>
11#include <lib/mmio.h>
12
13#include <ocotp.h>
14#include <platform_def.h>
15
16#define OTP_MAP 2
17#define OTP_NUM_WORDS 2048
18/*
19 * # of tries for OTP Status. The time to execute a command varies. The slowest
20 * commands are writes which also vary based on the # of bits turned on. Writing
21 * 0xffffffff takes ~3800 us.
22 */
23#define OTPC_RETRIES_US 5000
24
25/* Sequence to enable OTP program */
26#define OTPC_PROG_EN_SEQ { 0xf, 0x4, 0x8, 0xd }
27
28/* OTPC Commands */
29#define OTPC_CMD_READ 0x0
30#define OTPC_CMD_OTP_PROG_ENABLE 0x2
31#define OTPC_CMD_OTP_PROG_DISABLE 0x3
32#define OTPC_CMD_PROGRAM 0x8
33#define OTPC_CMD_ECC 0x10
34#define OTPC_ECC_ADDR 0x1A
35#define OTPC_ECC_VAL 0x00EC0000
36
37/* OTPC Status Bits */
38#define OTPC_STAT_CMD_DONE BIT(1)
39#define OTPC_STAT_PROG_OK BIT(2)
40
41/* OTPC register definition */
42#define OTPC_MODE_REG_OFFSET 0x0
43#define OTPC_MODE_REG_OTPC_MODE 0
44#define OTPC_COMMAND_OFFSET 0x4
45#define OTPC_COMMAND_COMMAND_WIDTH 6
46#define OTPC_CMD_START_OFFSET 0x8
47#define OTPC_CMD_START_START 0
48#define OTPC_CPU_STATUS_OFFSET 0xc
49#define OTPC_CPUADDR_REG_OFFSET 0x28
50#define OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH 16
51#define OTPC_CPU_WRITE_REG_OFFSET 0x2c
52
53#define OTPC_CMD_MASK (BIT(OTPC_COMMAND_COMMAND_WIDTH) - 1)
54#define OTPC_ADDR_MASK (BIT(OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH) - 1)
55
56#define OTPC_MODE_REG OCOTP_REGS_BASE
57
58struct chip_otp_cfg {
59 uint32_t base;
60 uint32_t num_words;
61};
62
63struct chip_otp_cfg ocotp_cfg = {
64 .base = OTPC_MODE_REG,
65 .num_words = 2048,
66};
67
68struct otpc_priv {
69 uint32_t base;
70 struct otpc_map *map;
71 int size;
72 int state;
73};
74
75struct otpc_priv otpc_info;
76
77static inline void set_command(uint32_t base, uint32_t command)
78{
79 mmio_write_32(base + OTPC_COMMAND_OFFSET, command & OTPC_CMD_MASK);
80}
81
82static inline void set_cpu_address(uint32_t base, uint32_t addr)
83{
84 mmio_write_32(base + OTPC_CPUADDR_REG_OFFSET, addr & OTPC_ADDR_MASK);
85}
86
87static inline void set_start_bit(uint32_t base)
88{
89 mmio_write_32(base + OTPC_CMD_START_OFFSET, 1 << OTPC_CMD_START_START);
90}
91
92static inline void reset_start_bit(uint32_t base)
93{
94 mmio_write_32(base + OTPC_CMD_START_OFFSET, 0);
95}
96
97static inline void write_cpu_data(uint32_t base, uint32_t value)
98{
99 mmio_write_32(base + OTPC_CPU_WRITE_REG_OFFSET, value);
100}
101
102static int poll_cpu_status(uint32_t base, uint32_t value)
103{
104 uint32_t status;
105 uint32_t retries;
106
107 for (retries = 0; retries < OTPC_RETRIES_US; retries++) {
108 status = mmio_read_32(base + OTPC_CPU_STATUS_OFFSET);
109 if (status & value)
110 break;
111 udelay(1);
112 }
113 if (retries == OTPC_RETRIES_US)
114 return -1;
115
116 return 0;
117}
118
119static int bcm_otpc_ecc(uint32_t enable)
120{
121 struct otpc_priv *priv = &otpc_info;
122 int ret;
123
124 set_command(priv->base, OTPC_CMD_ECC);
125 set_cpu_address(priv->base, OTPC_ECC_ADDR);
126
127 if (!enable)
128 write_cpu_data(priv->base, OTPC_ECC_VAL);
129 else
130 write_cpu_data(priv->base, ~OTPC_ECC_VAL);
131
132 set_start_bit(priv->base);
133 ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE);
134 if (ret) {
135 ERROR("otp ecc op error: 0x%x", ret);
136 return -1;
137 }
138 reset_start_bit(priv->base);
139
140 return 0;
141}
142
143/*
144 * bcm_otpc_read read otp data in the size of 8 byte rows.
145 * bytes has to be the multiple of 8.
146 * return -1 in error case, return read bytes in success.
147 */
148int bcm_otpc_read(unsigned int offset, void *val, uint32_t bytes,
149 uint32_t ecc_flag)
150{
151 struct otpc_priv *priv = &otpc_info;
152 uint32_t *buf = val;
153 uint32_t bytes_read;
154 uint32_t address = offset / priv->map->word_size;
155 int i, ret;
156
157 if (!priv->state) {
158 ERROR("OCOTP read failed\n");
159 return -1;
160 }
161
162 bcm_otpc_ecc(ecc_flag);
163
164 for (bytes_read = 0; (bytes_read + priv->map->word_size) <= bytes;) {
165 set_command(priv->base, OTPC_CMD_READ);
166 set_cpu_address(priv->base, address++);
167 set_start_bit(priv->base);
168 ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE);
169 if (ret) {
170 ERROR("otp read error: 0x%x", ret);
171 return -1;
172 }
173
174 for (i = 0; i < priv->map->otpc_row_size; i++) {
175 *buf++ = mmio_read_32(priv->base +
176 priv->map->data_r_offset[i]);
177 bytes_read += sizeof(*buf);
178 }
179
180 reset_start_bit(priv->base);
181 }
182
183 return bytes_read;
184}
185
186int bcm_otpc_init(struct otpc_map *map)
187{
188 struct otpc_priv *priv;
189
190 priv = &otpc_info;
191 priv->base = ocotp_cfg.base;
192 priv->map = map;
193
194 priv->size = 4 * ocotp_cfg.num_words;
195
196 /* Enable CPU access to OTPC. */
197 mmio_setbits_32(priv->base + OTPC_MODE_REG_OFFSET,
198 BIT(OTPC_MODE_REG_OTPC_MODE));
199 reset_start_bit(priv->base);
200 priv->state = 1;
201 VERBOSE("OTPC Initialization done\n");
202
203 return 0;
204}