OpenCores
URL https://opencores.org/ocsvn/xenie/xenie/trunk

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [mb_fw/] [xenie_eth_test_womtd/] [src/] [spansion_flash.c] - Blame information for rev 13

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 DFC
/******************************************************************************
2
**
3
** (C) Copyright 2017 DFC Design, s.r.o., Brno, Czech Republic
4
** Author: Marek Kvas (m.kvas@dspfpga.com)
5
**
6
****************************************************************************
7
**
8
** This file is part of Xenia Ethernet Example project.
9
**
10
** Xenia Ethernet Example project is free software: you can
11
** redistribute it and/or modify it under the terms of
12
** the GNU Lesser General Public License as published by the Free
13
** Software Foundation, either version 3 of the License, or
14
** (at your option) any later version.
15
**
16
** Xenia Ethernet Example project is distributed in the hope that
17
** it will be useful, but WITHOUT ANY WARRANTY; without even
18
** the implied warranty of MERCHANTABILITY or FITNESS FOR A
19
** PARTICULAR PURPOSE.  See the GNU Lesser General Public License
20
** for more details.
21
**
22
** You should have received a copy of the GNU Lesser General Public
23
** License along with Xenia Ethernet Example project.  If not,
24
** see <http://www.gnu.org/licenses/>.
25
****************************************************************************
26
*/
27
 
28
#include <stdio.h>
29
#include <xspi.h>
30
#include "spansion_flash.h"
31
#include "uprintf.h"
32
 
33 13 DFC
#define SPANSION_CFG_REG_QUAD           (1<<1)
34
#define SPANSION_CFG_REG_OTP_MASK       (0x3c)
35
#define SPANSION_BANK_REG_EXT_ADDR      (1<<7)
36
#define SPANSION_CFG_REG_BP_SHIFT       2
37
#define SPANSION_CFG_REG_BP_MASK        (0x7 << SPANSION_CFG_REG_BP_SHIFT)
38
#define SPANSION_STAT_REG_WIP           (1<<0)
39
#define SPANSION_CFG_REG_LC_MASK        (0xc0)
40
#define SPANSION_CFG_REG_LC_DEFAULT     0
41
static int spansion_flash_cmd_wen(struct spansion_flash *sf);
42
static int spansion_flash_get_cr1(struct spansion_flash *sf, u8 *cr1);
43
static int spansion_flash_get_sr1(struct spansion_flash *sf, u8 *sr1);
44 4 DFC
 
45
int spansion_flash_init (struct spansion_flash *sf, XSpi *spi, int slave_num)
46
{
47 13 DFC
        u8 rCfg;
48
 
49 4 DFC
        sf->spi = spi;
50
        sf->slave_select = (1<<slave_num);
51 13 DFC
        int ret;
52 4 DFC
 
53 13 DFC
        ret = XSpi_SetOptions(sf->spi, (XSP_MASTER_OPTION | \
54 4 DFC
                                                XSP_MANUAL_SSELECT_OPTION | \
55
                                                XSP_CLK_PHASE_1_OPTION | \
56
                                                XSP_CLK_ACTIVE_LOW_OPTION));
57 13 DFC
        if(ret)
58
                return ret;
59 4 DFC
 
60 13 DFC
        ret = XSpi_SetSlaveSelect(sf->spi, sf->slave_select);
61
        if(ret)
62
                return ret;
63 4 DFC
 
64 13 DFC
        ret = XSpi_Start(sf->spi);
65
        if (ret)
66
                return ret;
67
 
68
        /* Put spi to polled mode */
69
        XSpi_IntrGlobalDisable(sf->spi);
70
 
71
        /* Check latency is as expected */
72
        ret = spansion_flash_get_cr1(sf, &rCfg);
73
        if(ret)
74
                return ret;
75
 
76
        if ((rCfg & SPANSION_CFG_REG_LC_MASK) != SPANSION_CFG_REG_LC_DEFAULT) {
77
                uprintf("Flash is configured with non-default latency code. Cannot read flash\r\n");
78
                return -1;
79
        }
80
        return 0;
81 4 DFC
}
82
 
83
static int spansion_flash_transfer(struct spansion_flash *sf, uint8_t *wr_buf, uint8_t *rd_buf, int len)
84
{
85
        int res;
86
 
87
        res = XSpi_Transfer(sf->spi, wr_buf, rd_buf, len);
88
        if(res)
89
                return res;
90
 
91
        return XST_SUCCESS;
92
}
93
 
94
 
95 13 DFC
/*
96
 * Get status and control register value
97
 * and set QSPI mode. It needs to be done
98
 * after each configuration flash programming
99
 * using Xilinx tools as they erase this flag.
100
 *
101
 * !!!BEWARE: This is potentially dangerous
102
 * operation as if power is lost during write to
103
 * status and configuration register, both can be
104
 * set to all ones. It may set OTP bits that may render
105
 * flash unusable. As quad mode flag is non-volatile
106
 * it is necessary to do this once only during board
107
 *
108
 */
109 4 DFC
int spansion_flash_quad_mode(struct spansion_flash *sf)
110
{
111
        int ret;
112 13 DFC
        int tmo_cnt;
113
        u8 rCfg;
114
        u8 rSt;
115 4 DFC
        u8 wCfgBuf[3];
116
 
117 13 DFC
        ret = spansion_flash_get_cr1(sf, &rCfg);
118 4 DFC
        if(ret)
119
                return ret;
120
 
121 13 DFC
        if (rCfg & SPANSION_CFG_REG_QUAD) {
122
                return 0;
123
        }
124
 
125
        ret = spansion_flash_get_sr1(sf, &rSt);
126 4 DFC
        if(ret)
127
                return ret;
128
 
129 13 DFC
        ret = spansion_flash_cmd_wen(sf);
130 4 DFC
        if(ret)
131
                return ret;
132
 
133
 
134 13 DFC
        uprintf("WARNING: Setting flash quad mode in flash configuration\r\n"
135
                        "registers. If power is lost at that moment flash can be\r\n"
136
                        "corrupted permanently.\r\n");
137 4 DFC
        wCfgBuf[0] = 0x01;
138 13 DFC
        wCfgBuf[1] = rSt;
139
        wCfgBuf[2] = rCfg | SPANSION_CFG_REG_QUAD;
140 4 DFC
 
141
        ret = spansion_flash_transfer(sf, wCfgBuf, wCfgBuf, 3);
142
        if(ret)
143
                return ret;
144
 
145 13 DFC
        /* Wait until flash finishes write with timeout */
146
        tmo_cnt = 1000;
147
        do {
148
                ret = spansion_flash_get_sr1(sf, &rSt);
149
                if (ret)
150
                        return ret;
151 4 DFC
 
152 13 DFC
                if(tmo_cnt)
153
                        tmo_cnt--;
154
                else
155
                        return -1;
156
        } while (rSt & SPANSION_STAT_REG_WIP);
157 4 DFC
 
158 13 DFC
        /* Reread CFG reg */
159
        ret = spansion_flash_get_cr1(sf, &rCfg);
160
        if (ret)
161 4 DFC
                return ret;
162
 
163 13 DFC
        if (rCfg & SPANSION_CFG_REG_QUAD) {
164
                uprintf("Flash quad mode set successfully.\r\n");
165
                return 0;
166 4 DFC
        } else {
167 13 DFC
                uprintf("Flash quad mode was not set, cannot read flash.\r\n");
168
                return -1;
169 4 DFC
        }
170
 
171
}
172
 
173 13 DFC
 
174 4 DFC
/*
175
 *  Use Quad IO 4 byte address read command to read block of data.
176
 *  spi - SPI core instance to be used
177
 *  flash_addr - 32 bit start address in flash
178
 *  buf - pointer to buffer where data shall be stored; must be 8 byte longer then length of data
179
 *        rad data are placed at buf+8 address.
180
 *  len - number of bytes to be read from flash; must be 8 bytes lower than true buf len
181
 */
182
int spansion_flash_quad_io_read(struct spansion_flash *sf, uint32_t flash_addr, uint8_t *buf, int len)
183
{
184
        XSpi *spi = sf->spi;
185
        u8 *cmdbuf = buf;
186
 
187
        /* Quad IO read with 32 bit address */
188
        *(cmdbuf++) = 0xec;
189
        /* Address MSB first */
190
        *(cmdbuf++) = flash_addr >> 24;
191
        *(cmdbuf++) = flash_addr >> 16;
192
        *(cmdbuf++) = flash_addr >> 8;
193
        *(cmdbuf++) = flash_addr;
194
        /* 3 Dummy bytes - 6 cycle for latency code 00b */
195
        *(cmdbuf++) = 0;
196
        *(cmdbuf++) = 0;
197
        *(cmdbuf++) = 0;
198
 
199
        return XSpi_Transfer(spi, buf, buf, len + 8);
200
}
201 13 DFC
 
202
/*
203
 * Read and print flash configuration and status.
204
 */
205
int spansion_flash_print_status(struct spansion_flash *sf)
206
{
207
        int ret;
208
        u8 rCfgBuf[2];
209
        u8 rStBuf[2];
210
        u8 rRDID[4];
211
 
212
        rRDID[0] = 0x9f;
213
        ret = spansion_flash_transfer(sf, rRDID, rRDID, 4);
214
        if(ret)
215
                return ret;
216
        uprintf("RDID: 0x%02x 0x%02x 0x%02x\r\n", rRDID[1], rRDID[2], rRDID[3]);
217
 
218
        rStBuf[0] = 0x05;
219
        ret = spansion_flash_transfer(sf, rStBuf, rStBuf, 2);
220
        if(ret)
221
                return ret;
222
        uprintf("Status reg 1: 0x%02x\r\n", rStBuf[1]);
223
 
224
        rStBuf[0] = 0x07;
225
        ret = spansion_flash_transfer(sf, rStBuf, rStBuf, 2);
226
        if(ret)
227
                return ret;
228
        uprintf("Status reg 2: 0x%02x\r\n", rStBuf[1]);
229
 
230
        rCfgBuf[0] = 0x35;
231
        ret = spansion_flash_transfer(sf, rCfgBuf, rCfgBuf, 2);
232
        if(ret)
233
                return ret;
234
        uprintf("Configuration reg: 0x%02x\r\n", rCfgBuf[1]);
235
 
236
        return 0;
237
}
238
 
239
/* Send write enable command - needed for register write */
240
static int spansion_flash_cmd_wen(struct spansion_flash *sf)
241
{
242
        int ret;
243
        u8 wEnBuf[1];
244
 
245
        wEnBuf[0] = 0x6;
246
        ret = spansion_flash_transfer(sf, wEnBuf, wEnBuf, 1);
247
 
248
        return ret;
249
}
250
 
251
/* Send Bulk erase command*/
252
static int spansion_flash_cmd_be(struct spansion_flash *sf)
253
{
254
        int ret;
255
        u8 buf[1];
256
 
257
        buf[0] = 0x60;
258
        ret = spansion_flash_transfer(sf, buf, buf, 1);
259
 
260
        return ret;
261
}
262
 
263
/* Send get status register sr1*/
264
static int spansion_flash_get_sr1(struct spansion_flash *sf, u8 *sr1)
265
{
266
        int ret;
267
        u8 rStBuf[2];
268
 
269
        rStBuf[0] = 0x05;
270
        ret = spansion_flash_transfer(sf, rStBuf, rStBuf, 2);
271
 
272
        *sr1 = rStBuf[1];
273
 
274
        return ret;
275
}
276
 
277
/* Send get configuration register */
278
static int spansion_flash_get_cr1(struct spansion_flash *sf, u8 *cr1)
279
{
280
        int ret;
281
        u8 rCfgBuf[2];
282
 
283
        rCfgBuf[0] = 0x35;
284
        ret = spansion_flash_transfer(sf, rCfgBuf, rCfgBuf, 2);
285
 
286
        *cr1 = rCfgBuf[1];
287
 
288
        return ret;
289
}
290
 
291
 
292
 
293
/*
294
 * Erase whole device using bulk erase.
295
 */
296
int spansion_flash_bulk_erase(struct spansion_flash *sf)
297
{
298
        int ret;
299
        u8 sr;
300
        int i;
301
 
302
        ret = spansion_flash_cmd_wen(sf);
303
        if(ret)
304
                return ret;
305
 
306
        ret = spansion_flash_cmd_be(sf);
307
        if(ret)
308
                return ret;
309
 
310
        i = 0;
311
        do {
312
                ret = spansion_flash_get_sr1(sf, &sr);
313
                i++;
314
        } while (sr & SPANSION_STAT_REG_WIP);
315
 
316
        return ret;
317
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.