source: rtems/c/src/lib/libbsp/powerpc/shared/flash/intelFlash.c @ f334847b

4.11
Last change on this file since f334847b was f334847b, checked in by Nick Withers <nick.withers@…>, on Jan 17, 2014 at 1:57:08 AM

powerpc/flash: give string variables const attribute

  • Property mode set to 100644
File size: 12.2 KB
Line 
1/*
2 * Trivial driver for 16-bit intel flash present on the
3 * MVME5500/MVME6100 boards.
4 *
5 * For recognized devices, look for 'intelDevs'.
6 *
7 * This driver currently only supports stride=4 and 16-bit
8 * mode (width=2).
9 */
10
11/*
12 * Authorship
13 * ----------
14 * This software was created by
15 *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
16 *         Stanford Linear Accelerator Center, Stanford University.
17 *
18 * Acknowledgement of sponsorship
19 * ------------------------------
20 * The software was produced by
21 *     the Stanford Linear Accelerator Center, Stanford University,
22 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
23 *
24 * Government disclaimer of liability
25 * ----------------------------------
26 * Neither the United States nor the United States Department of Energy,
27 * nor any of their employees, makes any warranty, express or implied, or
28 * assumes any legal liability or responsibility for the accuracy,
29 * completeness, or usefulness of any data, apparatus, product, or process
30 * disclosed, or represents that its use would not infringe privately owned
31 * rights.
32 *
33 * Stanford disclaimer of liability
34 * --------------------------------
35 * Stanford University makes no representations or warranties, express or
36 * implied, nor assumes any liability for the use of this software.
37 *
38 * Stanford disclaimer of copyright
39 * --------------------------------
40 * Stanford University, owner of the copyright, hereby disclaims its
41 * copyright and all other rights in this software.  Hence, anyone may
42 * freely use it for any purpose without restriction.
43 *
44 * Maintenance of notices
45 * ----------------------
46 * In the interest of clarity regarding the origin and status of this
47 * SLAC software, this and all the preceding Stanford University notices
48 * are to remain affixed to any copy or derivative of this software made
49 * or distributed by the recipient and are to be affixed to any copy of
50 * software made or distributed by the recipient that contains a copy or
51 * derivative of this software.
52 *
53 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
54 */
55#ifdef TESTING
56
57#define TIMEOUT_US       100000
58#define rtems_task_wake_after(t) sleep(t)
59#define CLOCKRATE_GET(p) (*(p)=1)
60
61#else
62
63#include <rtems.h>
64#define TIMEOUT_US       1000
65#define CLOCKRATE_GET(p) rtems_clock_get( RTEMS_CLOCK_GET_TICKS_PER_SECOND, p )
66
67#endif
68
69#define ERASE_TIMEOUT_S 2
70
71#include <stdio.h>
72#include <inttypes.h>
73#include <stdlib.h>
74
75#include <bsp/flashPgmPvt.h>
76
77#define  DEBUG          0
78#undef   DEBUG
79
80#ifdef   DEBUG
81#define  STATIC
82#else
83#define  STATIC                         static
84#endif
85
86#define NumberOf(arr)           (sizeof(arr)/sizeof(arr[0]))
87
88/* This driver assumes two 16-bit devices in parallel */
89
90/********* Register Definitions ****************/
91
92/* command codes */
93#define F_CMD_RD_ARR            0xffffffff      /* back to 'normal' read mode */
94#define F_CMD_RD_ID                     0x90909090      /* read from ID space         */
95#define F_CMD_RD_STA            0x70707070      /* read status register       */
96#define F_CMD_WR_STA            0x50505050      /* clear status register      */
97#define F_CMD_WR_BUF            0xe8e8e8e8      /* write to buffer            */
98#define F_CMD_WR_WRD            0x40404040      /* write word                 */
99#define F_CMD_WR_ERA            0x20202020      /* block erase                */
100#define F_CMD_WR_LCK            0x60606060      /* lock bit (1st cycle)       */
101#define F_CMD_WR_CMD            0xd0d0d0d0      /* commit erase               */
102#define F_CMD_WR_LCK_SET        0x01010101      /* lock block commit          */
103
104/* Status codes (F_CMD_RD_STA result)        */
105#define STA_RDY         (1<<7)  /* ready         */
106#define STA_ES          (1<<6)  /* erase suspend */
107#define STA_EE          (1<<5)  /* erase error   */
108#define STA_PE          (1<<4)  /* program error */
109#define STA_VE          (1<<3)  /* VPEN < min    */
110#define STA_PS          (1<<2)  /* program susp. */
111#define STA_LE          (1<<1)  /* block locked  */
112#define STA_EFP         (1<<0)  /* buf. EFP stat.*/
113
114/* Any error                                 */
115#define STA_ERROR       (STA_EE|STA_PE|STA_VE|STA_LE)
116
117/* TODO: Code using RDYRDY assumes flash is 16-bit wide :-( */
118#define STA_RDYRDY                      0x00800080      /* ready status on both devices */
119
120/********* Forward Declarations ****************/
121
122STATIC int
123flash_get_id_intel(struct bankdesc *, uint32_t, uint32_t *, uint32_t *);
124
125STATIC void
126flash_unlock_block_intel(struct bankdesc *, uint32_t);
127
128STATIC void
129flash_lock_block_intel(struct bankdesc *, uint32_t);
130
131STATIC int
132flash_erase_block_intel(struct bankdesc *, uint32_t);
133
134STATIC uint32_t
135flash_check_ready_intel(struct bankdesc *, uint32_t);
136
137STATIC void
138flash_print_stat_intel(struct bankdesc *, uint32_t, int);
139
140STATIC void
141flash_array_mode_intel(struct bankdesc *, uint32_t);
142
143STATIC uint32_t
144flash_write_line_intel(struct bankdesc *, uint32_t, const char *, uint32_t);
145
146/********* Global Variables ********************/
147
148static struct flash_bank_ops intelOps = {
149        get_id      : flash_get_id_intel,
150        unlock_block: flash_unlock_block_intel,
151        lock_block  : flash_lock_block_intel,
152        erase_block : flash_erase_block_intel,
153        check_ready : flash_check_ready_intel,
154        print_stat  : flash_print_stat_intel,
155        array_mode  : flash_array_mode_intel,
156        write_line  : flash_write_line_intel,
157};
158
159static struct devdesc intelDevs[] = {
160        { 0x8801, "K3 64Mb",             8*1024*1024,   0x40, 0x20000 },
161        { 0x8802, "K3 128Mb",           16*1024*1024,   0x40, 0x20000 },
162        { 0x8803, "K3 256Mb",           32*1024*1024,   0x40, 0x20000 },
163        { 0x8805, "K18 64Mb",            8*1024*1024,   0x40, 0x20000 },
164        { 0x8806, "K18 128Mb",          16*1024*1024,   0x40, 0x20000 },
165        { 0x8807, "K18 256Mb",          32*1024*1024,   0x40, 0x20000 },
166        { 0x0016, "J3 32Mb",         4*1024*1024,   0x20, 0x20000 },
167        { 0x0017, "J3 64Mb",         8*1024*1024,   0x20, 0x20000 },
168        { 0x0018, "J3 128Mb",       16*1024*1024,   0x20, 0x20000 },
169        { 0x001d, "J3 256Mb",       32*1024*1024,   0x20, 0x20000 },
170        { 0, 0, 0, 0}
171};
172
173struct vendesc BSP_flash_vendor_intel[] =
174{
175        { 0x89, "Intel", intelDevs, &intelOps },
176        { 0, 0}
177};
178
179/********* Helper Subroutines ******************/
180
181/* Basic low-level access routine for writing a command to the
182 * internal state machine.
183 *
184 * Flash is slow, so who cares if these access routines
185 * are not extremely efficient...
186 */
187STATIC uint32_t
188BSP_flashReadRaw(uint32_t cmd, uint32_t addr)
189{
190#if DEBUG > 4
191        printf("Writing CMD *0x%08"PRIx32" = 0x%08"PRIx32"\n", addr, cmd);
192#endif
193#ifdef TESTING
194        return STA_RDYRDY;
195#else
196        if ( cmd & 0xffff0000 ) {
197                /* 32-bit access */
198                addr &= ~(sizeof(uint32_t)-1);
199                *(A32)addr = cmd;
200                return *(A32)addr;
201        } else if ( cmd & 0xffffff00 ) {
202                /* 16-bit access */
203                addr &= ~(sizeof(uint16_t)-1);
204                *(A16)addr = cmd;
205                return *(A16)addr;
206        } else {
207                *(A8)addr = cmd;
208                return *(A8)addr;
209        }
210#endif
211}
212
213STATIC void
214BSP_flashWriteRaw(uint32_t val, uint32_t addr)
215{
216#ifdef TESTING
217        printf("Writing CNT *0x%08"PRIx32" = 0x%08"PRIx32"\n", addr, val);
218#else
219/* TODO implicitly assumes FLASH_WIDTH = 2, FLASH_NDEVS = 2 */
220        /* 32-bit access */
221        addr &= ~(sizeof(uint32_t)-1);
222        *(A32)addr = val;
223#endif
224}
225
226STATIC uint32_t
227flash_pend(struct bankdesc *b, uint32_t a, uint32_t timeout_us)
228{
229uint32_t then, now, sta;
230
231        then = BSP_flashBspOps.read_us_timer();
232
233        do {
234                sta = BSP_flashReadRaw(F_CMD_RD_STA, a);
235                now = BSP_flashBspOps.read_us_timer();
236                if ( now-then > timeout_us ) {
237                        /* timeout */
238                        sta = -1;
239                        break;
240                }
241        } while ( STA_RDYRDY != (STA_RDYRDY & sta) );
242
243        /* switch back to normal mode */
244        flash_array_mode_intel(b, a);
245
246        return STA_RDYRDY == sta ? 0 : sta;
247}
248
249
250/********* Access Methods **********************/
251
252STATIC void
253flash_array_mode_intel(struct bankdesc *b, uint32_t a)
254{
255        BSP_flashReadRaw(F_CMD_RD_ARR, a);
256}
257
258/* Dump status bits (F_CMD_RD_STA results); 'verbose' prints non-error bits, too */
259STATIC void
260flash_print_stat_intel(struct bankdesc *b, uint32_t sta, int verbose)
261{
262int ch;
263        if ( sta & STA_ERROR ) {
264                ch = ':';
265                fprintf(stderr,"Errors found");
266                if ( STA_EE & sta ) {
267                        fprintf(stderr,"%c ERASE",ch);
268                        ch = ',';
269                }
270                if ( STA_PE & sta ) {
271                        fprintf(stderr,"%c PROGRAM",ch);
272                        ch = ',';
273                }
274                if ( STA_VE & sta ) {
275                        fprintf(stderr,"%c VPEN TOO LOW",ch);
276                        ch = ',';
277                }
278                if ( STA_LE & sta ) {
279                        fprintf(stderr,"%c BLOCK LOCKED",ch);
280                        ch = ',';
281                }
282                fprintf(stderr,"\n");
283        }
284        if ( verbose ) {
285                fprintf(stderr,"%sREADY\n",STA_RDY & sta ? "" : "NOT ");
286        }
287}
288
289
290/* Query the status of the device and assert it's readiness
291 * leave off in array-reading mode.
292 *
293 * RETURNS: 0 on success, error status (result of status query) on error.
294 *
295 *   NOTES: - error message is printed to stderr.
296 *          - device switched back to array mode on exit.
297 *          - 'addr' must be 32-bit aligned.
298 */
299STATIC uint32_t
300flash_check_ready_intel(struct bankdesc *b, uint32_t addr)
301{
302uint32_t sta;
303
304        (void)BSP_flashReadRaw(F_CMD_WR_STA, addr);
305        if ( STA_RDYRDY != (STA_RDYRDY & (sta=BSP_flashReadRaw(F_CMD_RD_STA, addr))) ) {
306                fprintf(stderr,"Flash not ready (@0x%08"PRIx32")\n", addr);
307                flash_print_stat_intel(b, sta, 0);
308        } else {
309                sta = 0;
310        }
311        /* switch back to normal mode */
312        flash_array_mode_intel(b, addr);
313        return sta;
314}
315
316/* Erase single block holding 'addr'ess
317 *
318 * RETURNS: zero on error, device status on failure.
319 *
320 *   NOTES: - device switched back to array mode on exit.
321 *          - 'addr' must be 32-bit aligned.
322 */
323STATIC int
324flash_erase_block_intel(struct bankdesc *b, uint32_t addr)
325{
326uint32_t       sta;
327int            i;
328rtems_interval p;
329
330        if ( (sta = flash_check_ready_intel(b, addr)) )
331                return sta;
332
333        (void)BSP_flashReadRaw(F_CMD_WR_ERA, addr);
334        (void)BSP_flashReadRaw(F_CMD_WR_CMD, addr);
335
336        CLOCKRATE_GET( &p );
337        i = p * ERASE_TIMEOUT_S;
338
339        while ( STA_RDYRDY != (STA_RDYRDY & (sta = BSP_flashReadRaw(F_CMD_RD_STA, addr))) && --i > 0 ) {
340                rtems_task_wake_after(1);
341        }
342        /* switch back to 'normal' mode */
343        (void)flash_array_mode_intel(b, addr);
344        if ( 0 == i ) {
345                fprintf(stderr,"Flash erase block: timeout\n");
346                return -1;
347        }
348
349        /* Verify */
350        for ( i = 0; i<b->fblksz; i++ ) {
351                if ( (char)0xff != ((char*)addr)[i] ) {
352                        fprintf(stderr,"ERROR: Erase verification failed at %p\n",
353                                        ((char*)addr) + i);
354                        return -1;
355                }
356        }
357        return STA_RDYRDY == sta ? 0 : sta;
358}
359
360/* Unlock block holding 'addr'ess
361 *
362 *   NOTES: - device switched back to array mode on exit.
363 *          - 'addr' must be 32-bit aligned.
364 */
365
366STATIC void
367flash_unlock_block_intel(struct bankdesc *b, uint32_t addr)
368{
369#ifdef DEBUG
370        printf("Unlocking block 0x%08"PRIx32"\n", addr);
371#endif
372        (void)BSP_flashReadRaw(F_CMD_WR_LCK, addr);
373        (void)BSP_flashReadRaw(F_CMD_WR_CMD, addr);
374        flash_pend(b, addr, TIMEOUT_US);
375}
376
377/* Lock block holding 'addr'ess
378 *
379 *   NOTES: - device switched back to array mode on exit.
380 *          - 'addr' must be 32-bit aligned.
381 */
382
383STATIC void
384flash_lock_block_intel(struct bankdesc *b, uint32_t addr)
385{
386#ifdef DEBUG
387        printf("Locking block 0x%08"PRIx32"\n", addr);
388#endif
389        (void)BSP_flashReadRaw(F_CMD_WR_LCK, addr);
390        (void)BSP_flashReadRaw(F_CMD_WR_LCK_SET, addr);
391        flash_pend(b, addr, TIMEOUT_US);
392}
393
394STATIC uint32_t
395flash_write_line_intel(struct bankdesc *b, uint32_t a, const char *s, uint32_t N)
396{
397uint32_t sta, Nspla, nxt, j;
398union   {
399        uint32_t        u;
400        char            c[sizeof(uint32_t)];
401}               buf;
402
403        /* address block */
404        if ( STA_RDYRDY != (sta = BSP_flashReadRaw(F_CMD_WR_BUF, a)) ) {
405                return sta;
406        }
407
408        /* count per device */
409        N /= FLASH_STRIDE(b);
410
411        /* splat out */
412        Nspla = (N<<8)  | N;
413        Nspla = (Nspla<<16) | Nspla;
414        BSP_flashWriteRaw(Nspla - 0x01010101, a);
415
416        /* fill buffer */
417        for (nxt = a; N>0; N--) {
418#if defined(TESTING) || (DEBUG > 4)
419                printf("Writing DAT *0x%08"PRIx32" = 0x%08"PRIx32"\n", nxt, *(const uint32_t*)s);
420#endif
421                /* deal with misaligned sources */
422                for ( j=0; j<sizeof(buf.u); j++ ) {
423                        buf.c[j] = *s++;
424                }
425                *(A32)nxt = buf.u;
426                nxt += FLASH_STRIDE(b);
427        }
428
429        BSP_flashReadRaw(F_CMD_WR_CMD, a);
430
431        sta = flash_pend(b, a, TIMEOUT_US);
432
433        return sta;
434}
435
436/* Query device for basic information verifying that we talk
437 * to a 'known'/'supported' device.
438 *
439 *   NOTES: - device switched back to array mode on exit.
440 *          - 'addr' must be 32-bit aligned.
441 */
442
443STATIC int
444flash_get_id_intel(struct bankdesc *b, uint32_t addr, uint32_t *pVendorId, uint32_t *pDeviceId)
445{
446uint16_t v,d;
447
448        if ( 4 != FLASH_STRIDE(b) ) {
449                fprintf(stderr,"intel flash programmer: Strides other than 4 not implemented yet\n");
450                return -1;
451        }
452
453        /* Try to read ID */
454        v = BSP_flashReadRaw(F_CMD_RD_ID, addr);
455        d = BSP_flashReadRaw(F_CMD_RD_ID, addr + FLASH_STRIDE(b));
456
457        /* switch to array mode */
458        flash_array_mode_intel(b, addr);
459
460        *pVendorId = v;
461        *pDeviceId = d;
462
463        return 0;
464}
Note: See TracBrowser for help on using the repository browser.