Skip to content

Commit 0efd377

Browse files
IRISZZWWayne Ren
authored andcommitted
board: iotdk: add smic_bootspi driver
Signed-off-by: Watson Zeng <[email protected]>
1 parent 435564b commit 0efd377

File tree

4 files changed

+465
-2
lines changed

4 files changed

+465
-2
lines changed
Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
/* ------------------------------------------
2+
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
3+
4+
* Redistribution and use in source and binary forms, with or without modification,
5+
* are permitted provided that the following conditions are met:
6+
7+
* 1) Redistributions of source code must retain the above copyright notice, this
8+
* list of conditions and the following disclaimer.
9+
10+
* 2) Redistributions in binary form must reproduce the above copyright notice,
11+
* this list of conditions and the following disclaimer in the documentation and/or
12+
* other materials provided with the distribution.
13+
14+
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
15+
* be used to endorse or promote products derived from this software without
16+
* specific prior written permission.
17+
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
*
29+
--------------------------------------------- */
30+
31+
#include "arc.h"
32+
#include "arc_builtin.h"
33+
#include "embARC_toolchain.h"
34+
#include "embARC_error.h"
35+
#include "embARC_debug.h"
36+
37+
#include "smic_bootspi.h"
38+
#include "string.h"
39+
40+
// QSPI status
41+
#define SMIC_BOOTSPI_CHECK_EXP_NORTN(EXPR) CHECK_EXP_NOERCD(EXPR, error_exit)
42+
#define SMIC_BOOTSPI_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
43+
44+
#define SMIC_BOOTSPI_MMA_MASK (1<<0)
45+
#define SMIC_BOOTSPI_NBR_MASK (1<<1)
46+
#define SMIC_BOOTSPI_RMMCS_MASK (1<<7)
47+
48+
// read command
49+
#define SMIC_BOOTSPI_NOR_CMD_SREAD 0x03 // Normal read
50+
#define SMIC_BOOTSPI_NOR_CMD_DREAD 0x3B // Dual read
51+
#define SMIC_BOOTSPI_NOR_CMD_QREAD 0x6B // quad read
52+
53+
// program command
54+
#define SMIC_BOOTSPI_NOR_CMD_PP 0x02 // Page Program
55+
56+
// erase command
57+
#define SMIC_BOOTSPI_NOR_CMD_SE 0x20 // Sector Erase
58+
#define SMIC_BOOTSPI_NOR_CMD_BE_32K 0x52 // 32KB Block Erase
59+
#define SMIC_BOOTSPI_NOR_CMD_BE_64K 0xD8 // 64KB Block Erase
60+
#define SMIC_BOOTSPI_NOR_CMD_CE 0x60 // Chip Erase(0x60/0xC7)
61+
62+
#define SMIC_BOOTSPI_NOR_RD_ID 0x9F // JEDEC ID
63+
64+
// nor flash common command
65+
#define SMIC_BOOTSPI_NOR_CMD_RSTEN 0x66 // Reset enable
66+
#define SMIC_BOOTSPI_NOR_CMD_RST 0x99 // Reset memory
67+
68+
#define SMIC_BOOTSPI_NOR_CMD_RDSR 0x05 // Read status register(macornix)
69+
// Read Status Register-1(winbond)
70+
// Read Status Register-1(issi)
71+
72+
#define SMIC_BOOTSPI_NOR_CMD_WREN 0x06 // Write Enable
73+
#define SMIC_BOOTSPI_NOR_CMD_WRDI 0x04 // Write Disable
74+
#define SMIC_BOOTSPI_NOR_CMD_WRSR 0x01 // Write status register
75+
76+
77+
static void bootspi_release_cs(SMIC_BOOTSPI_DEF_PTR obj)
78+
{
79+
uint32_t reg_val;
80+
obj->bootspi_reg->MMS = SMIC_BOOTSPI_RMMCS_MASK;
81+
// check the NBR
82+
while (1)
83+
{
84+
reg_val = obj->bootspi_reg->MMS;
85+
if ((reg_val & SMIC_BOOTSPI_MMA_MASK) != SMIC_BOOTSPI_MMA_MASK)
86+
{
87+
break;
88+
}
89+
}
90+
}
91+
92+
static void bootspi_write_data(SMIC_BOOTSPI_DEF_PTR obj, uint8_t data)
93+
{
94+
uint32_t reg_val;
95+
obj->bootspi_reg->MMDW = data;
96+
// check the NBR
97+
while (1)
98+
{
99+
reg_val = obj->bootspi_reg->MMS;
100+
if (reg_val & SMIC_BOOTSPI_NBR_MASK)
101+
{
102+
break;
103+
}
104+
}
105+
}
106+
107+
static uint8_t bootspi_read_data(SMIC_BOOTSPI_DEF_PTR obj)
108+
{
109+
bootspi_write_data(obj, 0x00);
110+
return (obj->bootspi_reg->MMDR & 0xFF);
111+
}
112+
113+
static uint8_t bootspi_read_st(SMIC_BOOTSPI_DEF_PTR obj)
114+
{
115+
uint8_t st;
116+
117+
bootspi_release_cs(obj);
118+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_RDSR);
119+
st = bootspi_read_data(obj);
120+
bootspi_release_cs(obj);
121+
122+
return st;
123+
}
124+
125+
static uint8_t bootspi_chk_st(SMIC_BOOTSPI_DEF_PTR obj)
126+
{
127+
uint8_t st;
128+
129+
while (1)
130+
{
131+
st = bootspi_read_st(obj);
132+
if ((st&1) == 0)
133+
{
134+
return st;
135+
}
136+
}
137+
}
138+
139+
static void bootspi_reset(SMIC_BOOTSPI_DEF_PTR obj)
140+
{
141+
bootspi_release_cs(obj);
142+
// issue write enable command
143+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_WREN);
144+
// issue reset enable command
145+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_RSTEN);
146+
// issue reset command
147+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_RST);
148+
// check status
149+
bootspi_chk_st(obj);
150+
bootspi_release_cs(obj);
151+
}
152+
153+
static void bootspi_read_id(SMIC_BOOTSPI_DEF_PTR obj, uint8_t *p_id, uint32_t size)
154+
{
155+
uint32_t i;
156+
157+
bootspi_release_cs(obj);
158+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_RD_ID);
159+
for (i = 0; i < size; i++)
160+
{
161+
p_id[i] = bootspi_read_data(obj);
162+
}
163+
bootspi_release_cs(obj);
164+
}
165+
166+
static void bootspi_chip_erase(SMIC_BOOTSPI_DEF_PTR obj)
167+
{
168+
bootspi_release_cs(obj);
169+
// issue write enable command
170+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_WREN);
171+
bootspi_release_cs(obj);
172+
// issue chip erase command
173+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_CE);
174+
// check status
175+
bootspi_chk_st(obj);
176+
bootspi_release_cs(obj);
177+
}
178+
179+
static void bootspi_sec_erase(SMIC_BOOTSPI_DEF_PTR obj, uint32_t addr)
180+
{
181+
int32_t i;
182+
183+
bootspi_release_cs(obj);
184+
// issue write enable command
185+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_WREN);
186+
bootspi_release_cs(obj);
187+
// issue sector erase command
188+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_SE);
189+
// issue address
190+
for (i = 2; i >= 0; i--)
191+
{
192+
bootspi_write_data(obj, (addr >> (i<<3)) & 0xFF);
193+
}
194+
// check status
195+
bootspi_chk_st(obj);
196+
bootspi_release_cs(obj);
197+
}
198+
199+
static void bootspi_blk_erase(SMIC_BOOTSPI_DEF_PTR obj, uint32_t addr)
200+
{
201+
int32_t i;
202+
203+
bootspi_release_cs(obj);
204+
// issue write enable command
205+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_WREN);
206+
bootspi_release_cs(obj);
207+
// issue sector erase command
208+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_BE_64K);
209+
// issue address
210+
for (i = 2; i >= 0; i--)
211+
{
212+
bootspi_write_data(obj, (addr >> (i<<3)) & 0xFF);
213+
}
214+
// check status
215+
bootspi_chk_st(obj);
216+
bootspi_release_cs(obj);
217+
}
218+
219+
220+
221+
int32_t smic_bootspi_open(SMIC_BOOTSPI_DEF_PTR obj)
222+
{
223+
int32_t ercd = E_OK;
224+
225+
SMIC_BOOTSPI_CHECK_EXP(obj != NULL, E_OBJ);
226+
SMIC_BOOTSPI_CHECK_EXP(obj->bootspi_open_cnt == 0, E_OPNED);
227+
obj->bootspi_open_cnt++;
228+
//Sclk 1.17 MHz, Fsystem/64 (low rate)
229+
obj->bootspi_reg->MMC = 0x0;
230+
//Manual Mode Enable
231+
obj->bootspi_reg->MME = 0x01;
232+
233+
error_exit:
234+
return ercd;
235+
}
236+
237+
int32_t smic_bootspi_close(SMIC_BOOTSPI_DEF_PTR obj)
238+
{
239+
int32_t ercd = E_OK;
240+
241+
SMIC_BOOTSPI_CHECK_EXP(obj != NULL, E_OBJ);
242+
SMIC_BOOTSPI_CHECK_EXP(obj->bootspi_open_cnt != 0, E_OPNED);
243+
//Manual Mode Disable
244+
obj->bootspi_reg->MME = 0x00;
245+
obj->bootspi_open_cnt = 0;
246+
247+
error_exit:
248+
return ercd;
249+
}
250+
251+
int32_t smic_bootspi_read(SMIC_BOOTSPI_DEF_PTR obj, uint32_t addr, uint32_t len, uint8_t *val)
252+
{
253+
int32_t ercd = E_OK;
254+
int32_t i;
255+
256+
SMIC_BOOTSPI_CHECK_EXP(obj != NULL, E_OBJ);
257+
SMIC_BOOTSPI_CHECK_EXP(obj != NULL, E_OBJ);
258+
SMIC_BOOTSPI_CHECK_EXP(obj->bootspi_open_cnt != 0, E_OPNED);
259+
260+
bootspi_release_cs(obj);
261+
// issue read command
262+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_SREAD);
263+
// issue address
264+
for (i = 2; i >= 0; i--)
265+
{
266+
bootspi_write_data(obj, (addr >> (i<<3)) & 0xFF);
267+
}
268+
// read data
269+
for (i = 0; i < len; i++)
270+
{
271+
val[i] = bootspi_read_data(obj);
272+
}
273+
bootspi_release_cs(obj);
274+
275+
return (int32_t)(len);
276+
error_exit:
277+
return ercd;
278+
}
279+
280+
static void bootspi_write(SMIC_BOOTSPI_DEF_PTR obj, uint32_t addr, uint32_t len, uint8_t *val)
281+
{
282+
int32_t i;
283+
uint8_t st;
284+
bootspi_release_cs(obj);
285+
// issue write enable command
286+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_WREN);
287+
bootspi_release_cs(obj);
288+
// issue page program command
289+
bootspi_write_data(obj, SMIC_BOOTSPI_NOR_CMD_PP);
290+
// issue address
291+
for (i = 2; i >= 0; i--)
292+
{
293+
bootspi_write_data(obj, (addr >> (i<<3)) & 0xFF);
294+
}
295+
// write data
296+
for (i = 0; i < len; i++)
297+
{
298+
bootspi_write_data(obj, val[i]);
299+
}
300+
bootspi_release_cs(obj);
301+
// check status
302+
st = bootspi_chk_st(obj);
303+
bootspi_release_cs(obj);
304+
}
305+
306+
int32_t smic_bootspi_write(SMIC_BOOTSPI_DEF_PTR obj, uint32_t addr, uint32_t len, uint8_t *val)
307+
{
308+
int32_t ercd = E_OK;
309+
uint32_t first = 0;
310+
uint32_t size_orig = len;
311+
312+
SMIC_BOOTSPI_CHECK_EXP(obj != NULL, E_OBJ);
313+
SMIC_BOOTSPI_CHECK_EXP(obj->bootspi_open_cnt != 0, E_OPNED);
314+
315+
first = SMIC_BOOTSPI_PAGE_SIZE - (addr & (SMIC_BOOTSPI_PAGE_SIZE - 1));
316+
do {
317+
first = first < len ? first : len;
318+
bootspi_write(obj, addr, first, val);
319+
len -= first;
320+
addr += first;
321+
val += first;
322+
first = SMIC_BOOTSPI_PAGE_SIZE;
323+
} while(len);
324+
325+
return (int32_t)(size_orig);
326+
error_exit:
327+
return ercd;
328+
}
329+
330+
int32_t smic_bootspi_control(SMIC_BOOTSPI_DEF_PTR obj, uint32_t ctrl_cmd, void *param)
331+
{
332+
int32_t ercd = E_OK;
333+
uint32_t addr = 0;
334+
SMIC_BOOTSPI_CHECK_EXP(obj != NULL, E_OBJ);
335+
SMIC_BOOTSPI_CHECK_EXP(obj->bootspi_open_cnt != 0, E_OPNED);
336+
337+
if(ctrl_cmd != SMIC_BOOTSPI_RESET && ctrl_cmd != SMIC_BOOTSPI_READ_ID &&
338+
ctrl_cmd != SMIC_BOOTSPI_CHIP_REASE && ctrl_cmd != SMIC_BOOTSPI_BLK_ERASE &&
339+
ctrl_cmd != SMIC_BOOTSPI_SEC_ERASE) {
340+
ercd = E_PAR;
341+
goto error_exit;
342+
}
343+
344+
switch (ctrl_cmd) {
345+
case SMIC_BOOTSPI_RESET:
346+
bootspi_reset(obj);
347+
break;
348+
case SMIC_BOOTSPI_READ_ID:
349+
bootspi_read_id(obj, (uint8_t*)param, 3);
350+
break;
351+
case SMIC_BOOTSPI_CHIP_REASE:
352+
bootspi_chip_erase(obj);
353+
break;
354+
case SMIC_BOOTSPI_BLK_ERASE:
355+
addr = (uint32_t)param;
356+
addr &= ~(SMIC_BOOTSPI_BLK_SIZE-1);
357+
bootspi_blk_erase(obj, addr);
358+
break;
359+
case SMIC_BOOTSPI_SEC_ERASE:
360+
addr = (uint32_t)param;
361+
addr &= ~(SMIC_BOOTSPI_SEC_SIZE-1);
362+
bootspi_sec_erase(obj, addr);
363+
break;
364+
default:
365+
break;
366+
}
367+
368+
error_exit:
369+
return ercd;
370+
}

0 commit comments

Comments
 (0)