1 /* all about mxic factory */
2
3 #include <string.h>
4 #include <stdlib.h>
5 #include <time.h>
6 #include <pthread.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <hal_timer.h>
10
11 #include "inter.h"
12
13 #define NOR_MXIC_CMD_READ_CR 0x15
14 #define NOR_MXIC_CMD_RDSCUR 0x2B
15 #define NOR_MXIC_CMD_WRSCUR 0x2F
16 #define NOR_MXIC_CMD_WPSEL 0x68
17 #define NOR_MXIC_CMD_ESSPB 0xE4
18 #define NOR_MXIC_CMD_RDSPB 0xE2
19 #define NOR_MXIC_CMD_WRSPB 0xE3
20 #define NOR_MXIC_CMD_RDDPB 0xE0
21 #define NOR_MXIC_CMD_WRDPB 0xE1
22 #define NOR_MXIC_WPSEL_BIT BIT(7)
23 #define NOR_MXIC_QE_BIT BIT(6)
24 #define NOR_MXIC_DPB_LOCK (0xFF)
25 #define NOR_MXIC_DPB_UNLOCK (0x00)
26 #define NOR_MXIC_PT_MASK (BIT(3) | BIT(2) | BIT(1) | BIT(0))
27 #define NOR_MXIC_PROTECT_BP_SHIFT 2
28
29 static struct nor_info idt_mxic[] =
30 {
31 {
32 .model = "mx25l6433f",
33 .id = {0xc2, 0x20, 0x17},
34 .total_size = SZ_8M,
35 .flag = SUPPORT_GENERAL | USE_IO_PROG_X4 | SUPPORT_INDIVIDUAL_PROTECT,
36 },
37 {
38 .model = "mx25l12833f",
39 .id = {0xc2, 0x20, 0x18},
40 .total_size = SZ_16M,
41 .flag = SUPPORT_GENERAL | USE_IO_PROG_X4 | SUPPORT_INDIVIDUAL_PROTECT,
42 },
43 {
44 .model = "mx25l51234g",
45 .id = {0xc2, 0x20, 0x1a},
46 .total_size = SZ_64M,
47 .flag = SUPPORT_GENERAL | USE_IO_PROG_X4,
48 }
49 };
50
nor_mxic_quad_mode(struct nor_flash * nor)51 static int nor_mxic_quad_mode(struct nor_flash *nor)
52 {
53 int ret;
54 unsigned char sr;
55
56 ret = nor_read_status(&sr);
57 if (ret)
58 return ret;
59
60 if (sr & NOR_MXIC_QE_BIT)
61 return 0;
62
63 sr |= NOR_MXIC_QE_BIT;
64 /*
65 * If individual protect mode is enable, BP can't not write. If BP bits
66 * are set, write status will go failed, which make QE bit set failed.
67 */
68 if (is_wrlock_work(nor))
69 sr &= ~(NOR_MXIC_PT_MASK << NOR_MXIC_PROTECT_BP_SHIFT);
70 ret = nor_write_status(&sr, 1);
71 if (ret)
72 return ret;
73
74 ret = nor_read_status(&sr);
75 if (ret)
76 return ret;
77
78 if (!(sr & NOR_MXIC_QE_BIT)) {
79 SPINOR_ERR("set mxic QE failed (0x%x)\n", sr);
80 return -EINVAL;
81 }
82 return 0;
83 }
84
nor_mxic_set_wps(void)85 static int nor_mxic_set_wps(void)
86 {
87 int ret;
88 unsigned char cmd, sr;
89
90 cmd = NOR_MXIC_CMD_RDSCUR;
91 ret = nor_transfer(1, &cmd, 1, &sr, 1);
92 if (ret)
93 return ret;
94
95 /* already set before, no need to set again */
96 if (sr & NOR_MXIC_WPSEL_BIT)
97 return 0;
98
99 ret = nor_write_enable();
100 if (ret)
101 return ret;
102
103 ret = nor_send_cmd(NOR_MXIC_CMD_WPSEL);
104 if (ret)
105 return ret;
106
107 ret = nor_wait_ready(10, 100 * 1000);
108 if (ret)
109 return ret;
110
111 cmd = NOR_MXIC_CMD_RDSCUR;
112 ret = nor_transfer(1, &cmd, 1, &sr, 1);
113 if (ret)
114 return ret;
115 return !(sr & NOR_MXIC_WPSEL_BIT);
116 }
117
nor_mxic_reset_spb(void)118 static int nor_mxic_reset_spb(void)
119 {
120 int ret;
121
122 ret = nor_write_enable();
123 if (ret)
124 return ret;
125
126 ret = nor_send_cmd(NOR_MXIC_CMD_ESSPB);
127 if (ret)
128 return ret;
129
130 ret = nor_wait_ready(10, 500);
131 if (ret)
132 return ret;
133
134 return 0;
135 }
136
nor_mxic_init_lock(struct nor_flash * nor)137 static int nor_mxic_init_lock(struct nor_flash *nor)
138 {
139 int ret;
140
141 ret = nor_mxic_set_wps();
142 if (ret)
143 return ret;
144
145 ret = nor_mxic_reset_spb();
146 if (ret)
147 return ret;
148
149 return 0;
150 }
151
nor_mxic_blk_islock(unsigned int addr)152 static bool nor_mxic_blk_islock(unsigned int addr)
153 {
154 int ret;
155 unsigned char tbuf[5], st;
156
157 tbuf[0] = NOR_MXIC_CMD_RDDPB;
158 tbuf[1] = addr >> 24;
159 tbuf[2] = addr >> 16;
160 tbuf[3] = addr >> 8;
161 tbuf[4] = addr & 0xFF;
162 ret = nor_transfer(5, tbuf, 5, &st, 1);
163 if (ret)
164 return ret;
165
166 return st == 0xFF ? true : false;
167 }
168
nor_mxic_blk_unlock(unsigned int addr)169 static int nor_mxic_blk_unlock(unsigned int addr)
170 {
171 int ret;
172 unsigned char tbuf[6];
173
174 ret = nor_write_enable();
175 if (ret)
176 return ret;
177
178 tbuf[0] = NOR_MXIC_CMD_WRDPB;
179 tbuf[1] = addr >> 24;
180 tbuf[2] = addr >> 16;
181 tbuf[3] = addr >> 8;
182 tbuf[4] = addr & 0xFF;
183 tbuf[5] = NOR_MXIC_DPB_UNLOCK;
184 ret = nor_transfer(6, tbuf, 6, NULL, 0);
185 if (ret) {
186 SPINOR_ERR("mxic unlock 0x%x failed - %d\n", addr, ret);
187 return ret;
188 }
189 if (nor_mxic_blk_islock(addr) == true)
190 return -EBUSY;
191 return 0;
192 }
193
nor_mxic_blk_lock(unsigned int addr)194 static int nor_mxic_blk_lock(unsigned int addr)
195 {
196 int ret;
197 unsigned char tbuf[6];
198
199 ret = nor_write_enable();
200 if (ret)
201 return ret;
202
203 tbuf[0] = NOR_MXIC_CMD_WRDPB;
204 tbuf[1] = addr >> 24;
205 tbuf[2] = addr >> 16;
206 tbuf[3] = addr >> 8;
207 tbuf[4] = addr & 0xFF;
208 tbuf[5] = NOR_MXIC_DPB_LOCK;
209 ret = nor_transfer(6, tbuf, 6, NULL, 0);
210 if (ret) {
211 SPINOR_ERR("mxic lock 0x%x failed - %d\n", addr, ret);
212 return ret;
213 }
214 if (nor_mxic_blk_islock(addr) == false)
215 return -EBUSY;
216 return 0;
217 }
218
nor_mxic_lock(struct nor_flash * nor,unsigned int addr,unsigned int len)219 static int nor_mxic_lock(struct nor_flash *nor, unsigned int addr,
220 unsigned int len)
221 {
222 return nor_mxic_blk_lock(addr);
223 }
224
nor_mxic_unlock(struct nor_flash * nor,unsigned int addr,unsigned int len)225 static int nor_mxic_unlock(struct nor_flash *nor, unsigned int addr,
226 unsigned int len)
227 {
228 return nor_mxic_blk_unlock(addr);
229 }
230
nor_mxic_islock(struct nor_flash * nor,unsigned int addr,unsigned int len)231 static bool nor_mxic_islock(struct nor_flash *nor, unsigned int addr,
232 unsigned int len)
233 {
234 return nor_mxic_blk_islock(addr);
235 }
236
237 static struct nor_factory nor_mxic = {
238 .factory = FACTORY_MXIC,
239 .idt = idt_mxic,
240 .idt_cnt = sizeof(idt_mxic),
241
242 .init = NULL,
243 .deinit = NULL,
244 .init_lock = nor_mxic_init_lock,
245 .deinit_lock = NULL,
246 .lock = nor_mxic_lock,
247 .unlock = nor_mxic_unlock,
248 .islock = nor_mxic_islock,
249 .set_quad_mode = nor_mxic_quad_mode,
250 .set_4bytes_addr = NULL,
251 };
252
nor_register_factory_mxic(void)253 int nor_register_factory_mxic(void)
254 {
255 return nor_register_factory(&nor_mxic);
256 }
257