1
2
3
4
5
6
7#include <config.h>
8#include <common.h>
9#include <asm/io.h>
10#include <linux/delay.h>
11#include <mach/mbox.h>
12#include <mach/soc.h>
13
14#define OTP_NB_REG_BASE ((void __iomem *)MVEBU_REGISTER(0x12600))
15#define OTP_SB_REG_BASE ((void __iomem *)MVEBU_REGISTER(0x1A200))
16
17#define OTP_CONTROL_OFF 0x00
18#define OTP_MODE_BIT BIT(15)
19#define OTP_RPTR_RST_BIT BIT(14)
20#define OTP_POR_B_BIT BIT(13)
21#define OTP_PRDT_BIT BIT(3)
22#define OTP_READ_PORT_OFF 0x04
23#define OTP_READ_POINTER_OFF 0x08
24#define OTP_PTR_INC_BIT BIT(8)
25
26static void otp_read_parallel(void __iomem *base, u32 *data, u32 count)
27{
28 u32 regval;
29
30
31 regval = readl(base + OTP_CONTROL_OFF);
32 regval &= ~OTP_MODE_BIT;
33 writel(regval, base + OTP_CONTROL_OFF);
34
35
36 regval = readl(base + OTP_CONTROL_OFF);
37 regval |= OTP_POR_B_BIT;
38 writel(regval, base + OTP_CONTROL_OFF);
39
40
41 regval = readl(base + OTP_READ_POINTER_OFF);
42 regval |= OTP_PTR_INC_BIT;
43 writel(regval, base + OTP_READ_POINTER_OFF);
44
45
46 regval = readl(base + OTP_CONTROL_OFF);
47 regval |= OTP_RPTR_RST_BIT;
48 writel(regval, base + OTP_CONTROL_OFF);
49
50 regval = readl(base + OTP_CONTROL_OFF);
51 regval &= ~OTP_RPTR_RST_BIT;
52 writel(regval, base + OTP_CONTROL_OFF);
53
54
55
56
57
58
59
60 regval = readl(base + OTP_CONTROL_OFF);
61 regval |= OTP_PRDT_BIT;
62 writel(regval, base + OTP_CONTROL_OFF);
63
64 regval = readl(base + OTP_CONTROL_OFF);
65 regval &= ~OTP_PRDT_BIT;
66 writel(regval, base + OTP_CONTROL_OFF);
67
68 ndelay(100);
69
70 regval = readl(base + OTP_CONTROL_OFF);
71 regval |= OTP_PRDT_BIT;
72 writel(regval, base + OTP_CONTROL_OFF);
73
74 while (count-- > 0) {
75
76 ndelay(100000);
77 *(data++) = readl(base + OTP_READ_PORT_OFF);
78 }
79}
80
81static int rwtm_otp_read(u8 row, u32 word, u32 *data)
82{
83 u32 out[3];
84 u32 in[2];
85 int res = -EINVAL;
86
87 if (word < 2) {
88
89
90
91
92
93
94 in[0] = row;
95 in[1] = word * 32;
96 res = mbox_do_cmd(MBOX_CMD_OTP_READ_32B, in, 2, out, 1);
97 if (!res)
98 *data = out[0];
99 } else if (word == 2) {
100
101
102
103
104
105
106
107 in[0] = row;
108 res = mbox_do_cmd(MBOX_CMD_OTP_READ, in, 1, out, 3);
109 if (!res)
110 *data = out[2];
111 }
112
113 return res;
114}
115
116static int rwtm_otp_write(u8 row, u32 word, u32 data)
117{
118 u32 in[4];
119 int res = -EINVAL;
120
121 if (word < 2) {
122
123
124
125
126
127
128
129 in[0] = row;
130 in[1] = word * 32;
131 in[2] = data;
132 res = mbox_do_cmd(MBOX_CMD_OTP_WRITE_32B, in, 3, NULL, 0);
133 } else if (word == 2 && !(data & ~0x1)) {
134
135
136
137
138
139
140
141 in[0] = row;
142 in[1] = 0;
143 in[2] = 0;
144 in[3] = data;
145 res = mbox_do_cmd(MBOX_CMD_OTP_WRITE, in, 4, NULL, 0);
146 }
147
148 return res;
149}
150
151
152
153
154
155
156
157#define RWTM_ROWS 44
158#define RWTM_MAX_BANK (RWTM_ROWS - 1)
159#define RWTM_ROW_WORDS 3
160#define OTP_NB_BANK RWTM_ROWS
161#define OTP_NB_WORDS 3
162#define OTP_SB_BANK (RWTM_ROWS + 1)
163#define OTP_SB_WORDS 4
164
165int fuse_read(u32 bank, u32 word, u32 *val)
166{
167 if (bank <= RWTM_MAX_BANK) {
168 if (word >= RWTM_ROW_WORDS)
169 return -EINVAL;
170 return rwtm_otp_read(bank, word, val);
171 } else if (bank == OTP_NB_BANK) {
172 u32 data[OTP_NB_WORDS];
173 if (word >= OTP_NB_WORDS)
174 return -EINVAL;
175 otp_read_parallel(OTP_NB_REG_BASE, data, OTP_NB_WORDS);
176 *val = data[word];
177 return 0;
178 } else if (bank == OTP_SB_BANK) {
179 u32 data[OTP_SB_WORDS];
180 if (word >= OTP_SB_WORDS)
181 return -EINVAL;
182 otp_read_parallel(OTP_SB_REG_BASE, data, OTP_SB_WORDS);
183 *val = data[word];
184 return 0;
185 } else {
186 return -EINVAL;
187 }
188}
189
190int fuse_prog(u32 bank, u32 word, u32 val)
191{
192 if (bank <= RWTM_MAX_BANK) {
193 if (word >= RWTM_ROW_WORDS)
194 return -EINVAL;
195 return rwtm_otp_write(bank, word, val);
196 } else if (bank == OTP_NB_BANK) {
197
198 return -ENOSYS;
199 } else if (bank == OTP_SB_BANK) {
200
201 return -ENOSYS;
202 } else {
203 return -EINVAL;
204 }
205}
206
207int fuse_sense(u32 bank, u32 word, u32 *val)
208{
209
210 return -ENOSYS;
211}
212
213int fuse_override(u32 bank, u32 word, u32 val)
214{
215
216 return -ENOSYS;
217}
218