Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /*
0002  * Trivial driver for 16-bit intel flash present on the
0003  * MVME5500/MVME6100 boards.
0004  *
0005  * For recognized devices, look for 'intelDevs'.
0006  *
0007  * This driver currently only supports stride=4 and 16-bit
0008  * mode (width=2).
0009  */
0010 
0011 /*
0012  * Authorship
0013  * ----------
0014  * This software was created by
0015  *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
0016  *     Stanford Linear Accelerator Center, Stanford University.
0017  *
0018  * Acknowledgement of sponsorship
0019  * ------------------------------
0020  * The software was produced by
0021  *     the Stanford Linear Accelerator Center, Stanford University,
0022  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0023  *
0024  * Government disclaimer of liability
0025  * ----------------------------------
0026  * Neither the United States nor the United States Department of Energy,
0027  * nor any of their employees, makes any warranty, express or implied, or
0028  * assumes any legal liability or responsibility for the accuracy,
0029  * completeness, or usefulness of any data, apparatus, product, or process
0030  * disclosed, or represents that its use would not infringe privately owned
0031  * rights.
0032  *
0033  * Stanford disclaimer of liability
0034  * --------------------------------
0035  * Stanford University makes no representations or warranties, express or
0036  * implied, nor assumes any liability for the use of this software.
0037  *
0038  * Stanford disclaimer of copyright
0039  * --------------------------------
0040  * Stanford University, owner of the copyright, hereby disclaims its
0041  * copyright and all other rights in this software.  Hence, anyone may
0042  * freely use it for any purpose without restriction.
0043  *
0044  * Maintenance of notices
0045  * ----------------------
0046  * In the interest of clarity regarding the origin and status of this
0047  * SLAC software, this and all the preceding Stanford University notices
0048  * are to remain affixed to any copy or derivative of this software made
0049  * or distributed by the recipient and are to be affixed to any copy of
0050  * software made or distributed by the recipient that contains a copy or
0051  * derivative of this software.
0052  *
0053  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0054  */
0055 #ifdef TESTING
0056 
0057 #define TIMEOUT_US       100000
0058 #define rtems_task_wake_after(t) sleep(t)
0059 #define CLOCKRATE_GET(p) (*(p)=1)
0060 
0061 #else
0062 
0063 #include <rtems.h>
0064 #define TIMEOUT_US       1000
0065 #define CLOCKRATE_GET(p) *p = rtems_clock_get_ticks_per_second()
0066 
0067 #endif
0068 
0069 #define ERASE_TIMEOUT_S 2
0070 
0071 #include <stdio.h>
0072 #include <inttypes.h>
0073 #include <stdlib.h>
0074 
0075 #include <bsp/flashPgmPvt.h>
0076 
0077 #define  DEBUG      0
0078 #undef   DEBUG
0079 
0080 #ifdef   DEBUG
0081 #define  STATIC
0082 #else
0083 #define  STATIC             static
0084 #endif
0085 
0086 #define NumberOf(arr)       (sizeof(arr)/sizeof(arr[0]))
0087 
0088 /* This driver assumes two 16-bit devices in parallel */
0089 
0090 /********* Register Definitions ****************/
0091 
0092 /* command codes */
0093 #define F_CMD_RD_ARR        0xffffffff  /* back to 'normal' read mode */
0094 #define F_CMD_RD_ID         0x90909090  /* read from ID space         */
0095 #define F_CMD_RD_STA        0x70707070  /* read status register       */
0096 #define F_CMD_WR_STA        0x50505050  /* clear status register      */
0097 #define F_CMD_WR_BUF        0xe8e8e8e8  /* write to buffer            */
0098 #define F_CMD_WR_WRD        0x40404040  /* write word                 */
0099 #define F_CMD_WR_ERA        0x20202020  /* block erase                */
0100 #define F_CMD_WR_LCK        0x60606060  /* lock bit (1st cycle)       */
0101 #define F_CMD_WR_CMD        0xd0d0d0d0  /* commit erase               */
0102 #define F_CMD_WR_LCK_SET    0x01010101  /* lock block commit          */
0103 
0104 /* Status codes (F_CMD_RD_STA result)        */
0105 #define STA_RDY     (1<<7)  /* ready         */
0106 #define STA_ES      (1<<6)  /* erase suspend */
0107 #define STA_EE      (1<<5)  /* erase error   */
0108 #define STA_PE      (1<<4)  /* program error */
0109 #define STA_VE      (1<<3)  /* VPEN < min    */
0110 #define STA_PS      (1<<2)  /* program susp. */
0111 #define STA_LE      (1<<1)  /* block locked  */
0112 #define STA_EFP     (1<<0)  /* buf. EFP stat.*/
0113 
0114 /* Any error                                 */
0115 #define STA_ERROR   (STA_EE|STA_PE|STA_VE|STA_LE)
0116 
0117 /* TODO: Code using RDYRDY assumes flash is 16-bit wide :-( */
0118 #define STA_RDYRDY          0x00800080  /* ready status on both devices */
0119 
0120 /********* Forward Declarations ****************/
0121 
0122 STATIC int
0123 flash_get_id_intel(struct bankdesc *, uint32_t, uint32_t *, uint32_t *);
0124 
0125 STATIC void
0126 flash_unlock_block_intel(struct bankdesc *, uint32_t);
0127 
0128 STATIC void
0129 flash_lock_block_intel(struct bankdesc *, uint32_t);
0130 
0131 STATIC int
0132 flash_erase_block_intel(struct bankdesc *, uint32_t);
0133 
0134 STATIC uint32_t
0135 flash_check_ready_intel(struct bankdesc *, uint32_t);
0136 
0137 STATIC void
0138 flash_print_stat_intel(struct bankdesc *, uint32_t, int);
0139 
0140 STATIC void
0141 flash_array_mode_intel(struct bankdesc *, uint32_t);
0142 
0143 STATIC uint32_t
0144 flash_write_line_intel(struct bankdesc *, uint32_t, const char *, uint32_t);
0145 
0146 /********* Global Variables ********************/
0147 
0148 static struct flash_bank_ops intelOps = {
0149     get_id      : flash_get_id_intel,
0150     unlock_block: flash_unlock_block_intel,
0151     lock_block  : flash_lock_block_intel,
0152     erase_block : flash_erase_block_intel,
0153     check_ready : flash_check_ready_intel,
0154     print_stat  : flash_print_stat_intel,
0155     array_mode  : flash_array_mode_intel,
0156     write_line  : flash_write_line_intel,
0157 };
0158 
0159 static struct devdesc intelDevs[] = {
0160     { 0x8801, "K3 64Mb",         8*1024*1024,   0x40, 0x20000 },
0161     { 0x8802, "K3 128Mb",       16*1024*1024,   0x40, 0x20000 },
0162     { 0x8803, "K3 256Mb",       32*1024*1024,   0x40, 0x20000 },
0163     { 0x8805, "K18 64Mb",        8*1024*1024,   0x40, 0x20000 },
0164     { 0x8806, "K18 128Mb",      16*1024*1024,   0x40, 0x20000 },
0165     { 0x8807, "K18 256Mb",      32*1024*1024,   0x40, 0x20000 },
0166     { 0x0016, "J3 32Mb",         4*1024*1024,   0x20, 0x20000 },
0167     { 0x0017, "J3 64Mb",         8*1024*1024,   0x20, 0x20000 },
0168     { 0x0018, "J3 128Mb",       16*1024*1024,   0x20, 0x20000 },
0169     { 0x001d, "J3 256Mb",       32*1024*1024,   0x20, 0x20000 },
0170     { 0, 0, 0, 0}
0171 };
0172 
0173 struct vendesc BSP_flash_vendor_intel[] =
0174 {
0175     { 0x89, "Intel", intelDevs, &intelOps },
0176     { 0, 0}
0177 };
0178 
0179 /********* Helper Subroutines ******************/
0180 
0181 /* Basic low-level access routine for writing a command to the
0182  * internal state machine.
0183  *
0184  * Flash is slow, so who cares if these access routines
0185  * are not extremely efficient...
0186  */
0187 STATIC uint32_t
0188 BSP_flashReadRaw(uint32_t cmd, uint32_t addr)
0189 {
0190 #if DEBUG > 4
0191     printf("Writing CMD *0x%08"PRIx32" = 0x%08"PRIx32"\n", addr, cmd);
0192 #endif
0193 #ifdef TESTING
0194     return STA_RDYRDY;
0195 #else
0196     if ( cmd & 0xffff0000 ) {
0197         /* 32-bit access */
0198         addr &= ~(sizeof(uint32_t)-1);
0199         *(A32)addr = cmd;
0200         return *(A32)addr;
0201     } else if ( cmd & 0xffffff00 ) {
0202         /* 16-bit access */
0203         addr &= ~(sizeof(uint16_t)-1);
0204         *(A16)addr = cmd;
0205         return *(A16)addr;
0206     } else {
0207         *(A8)addr = cmd;
0208         return *(A8)addr;
0209     }
0210 #endif
0211 }
0212 
0213 STATIC void
0214 BSP_flashWriteRaw(uint32_t val, uint32_t addr)
0215 {
0216 #ifdef TESTING
0217     printf("Writing CNT *0x%08"PRIx32" = 0x%08"PRIx32"\n", addr, val);
0218 #else
0219 /* TODO implicitly assumes FLASH_WIDTH = 2, FLASH_NDEVS = 2 */
0220     /* 32-bit access */
0221     addr &= ~(sizeof(uint32_t)-1);
0222     *(A32)addr = val;
0223 #endif
0224 }
0225 
0226 STATIC uint32_t
0227 flash_pend(struct bankdesc *b, uint32_t a, uint32_t timeout_us)
0228 {
0229 uint32_t then, now, sta;
0230 
0231     then = BSP_flashBspOps.read_us_timer();
0232 
0233     do {
0234         sta = BSP_flashReadRaw(F_CMD_RD_STA, a);
0235         now = BSP_flashBspOps.read_us_timer();
0236         if ( now-then > timeout_us ) {
0237             /* timeout */
0238             sta = -1;
0239             break;
0240         }
0241     } while ( STA_RDYRDY != (STA_RDYRDY & sta) );
0242 
0243     /* switch back to normal mode */
0244     flash_array_mode_intel(b, a);
0245 
0246     return STA_RDYRDY == sta ? 0 : sta;
0247 }
0248 
0249 
0250 /********* Access Methods **********************/
0251 
0252 STATIC void
0253 flash_array_mode_intel(struct bankdesc *b, uint32_t a)
0254 {
0255     BSP_flashReadRaw(F_CMD_RD_ARR, a);
0256 }
0257 
0258 /* Dump status bits (F_CMD_RD_STA results); 'verbose' prints non-error bits, too */
0259 STATIC void
0260 flash_print_stat_intel(struct bankdesc *b, uint32_t sta, int verbose)
0261 {
0262 int ch;
0263     if ( sta & STA_ERROR ) {
0264         ch = ':';
0265         fprintf(stderr,"Errors found");
0266         if ( STA_EE & sta ) {
0267             fprintf(stderr,"%c ERASE",ch);
0268             ch = ',';
0269         }
0270         if ( STA_PE & sta ) {
0271             fprintf(stderr,"%c PROGRAM",ch);
0272             ch = ',';
0273         }
0274         if ( STA_VE & sta ) {
0275             fprintf(stderr,"%c VPEN TOO LOW",ch);
0276             ch = ',';
0277         }
0278         if ( STA_LE & sta ) {
0279             fprintf(stderr,"%c BLOCK LOCKED",ch);
0280             ch = ',';
0281         }
0282         fprintf(stderr,"\n");
0283     }
0284     if ( verbose ) {
0285         fprintf(stderr,"%sREADY\n",STA_RDY & sta ? "" : "NOT ");
0286     }
0287 }
0288 
0289 
0290 /* Query the status of the device and assert it's readiness
0291  * leave off in array-reading mode.
0292  *
0293  * RETURNS: 0 on success, error status (result of status query) on error.
0294  *
0295  *   NOTES: - error message is printed to stderr.
0296  *          - device switched back to array mode on exit.
0297  *          - 'addr' must be 32-bit aligned.
0298  */
0299 STATIC uint32_t
0300 flash_check_ready_intel(struct bankdesc *b, uint32_t addr)
0301 {
0302 uint32_t sta;
0303 
0304     (void)BSP_flashReadRaw(F_CMD_WR_STA, addr);
0305     if ( STA_RDYRDY != (STA_RDYRDY & (sta=BSP_flashReadRaw(F_CMD_RD_STA, addr))) ) {
0306         fprintf(stderr,"Flash not ready (@0x%08"PRIx32")\n", addr);
0307         flash_print_stat_intel(b, sta, 0);
0308     } else {
0309         sta = 0;
0310     }
0311     /* switch back to normal mode */
0312     flash_array_mode_intel(b, addr);
0313     return sta;
0314 }
0315 
0316 /* Erase single block holding 'addr'ess
0317  *
0318  * RETURNS: zero on error, device status on failure.
0319  *
0320  *   NOTES: - device switched back to array mode on exit.
0321  *          - 'addr' must be 32-bit aligned.
0322  */
0323 STATIC int
0324 flash_erase_block_intel(struct bankdesc *b, uint32_t addr)
0325 {
0326 uint32_t       sta;
0327 int            i;
0328 rtems_interval p;
0329 
0330     if ( (sta = flash_check_ready_intel(b, addr)) )
0331         return sta;
0332 
0333     (void)BSP_flashReadRaw(F_CMD_WR_ERA, addr);
0334     (void)BSP_flashReadRaw(F_CMD_WR_CMD, addr);
0335 
0336     CLOCKRATE_GET( &p );
0337     i = p * ERASE_TIMEOUT_S;
0338 
0339     while ( STA_RDYRDY != (STA_RDYRDY & (sta = BSP_flashReadRaw(F_CMD_RD_STA, addr))) && --i > 0 ) {
0340         rtems_task_wake_after(1);
0341     }
0342     /* switch back to 'normal' mode */
0343     (void)flash_array_mode_intel(b, addr);
0344     if ( 0 == i ) {
0345         fprintf(stderr,"Flash erase block: timeout\n");
0346         return -1;
0347     }
0348 
0349     /* Verify */
0350     for ( i = 0; i<b->fblksz; i++ ) {
0351         if ( (char)0xff != ((char*)addr)[i] ) {
0352             fprintf(stderr,"ERROR: Erase verification failed at %p\n",
0353                     ((char*)addr) + i);
0354             return -1;
0355         }
0356     }
0357     return STA_RDYRDY == sta ? 0 : sta;
0358 }
0359 
0360 /* Unlock block holding 'addr'ess
0361  *
0362  *   NOTES: - device switched back to array mode on exit.
0363  *          - 'addr' must be 32-bit aligned.
0364  */
0365 
0366 STATIC void
0367 flash_unlock_block_intel(struct bankdesc *b, uint32_t addr)
0368 {
0369 #ifdef DEBUG
0370     printf("Unlocking block 0x%08"PRIx32"\n", addr);
0371 #endif
0372     (void)BSP_flashReadRaw(F_CMD_WR_LCK, addr);
0373     (void)BSP_flashReadRaw(F_CMD_WR_CMD, addr);
0374     flash_pend(b, addr, TIMEOUT_US);
0375 }
0376 
0377 /* Lock block holding 'addr'ess
0378  *
0379  *   NOTES: - device switched back to array mode on exit.
0380  *          - 'addr' must be 32-bit aligned.
0381  */
0382 
0383 STATIC void
0384 flash_lock_block_intel(struct bankdesc *b, uint32_t addr)
0385 {
0386 #ifdef DEBUG
0387     printf("Locking block 0x%08"PRIx32"\n", addr);
0388 #endif
0389     (void)BSP_flashReadRaw(F_CMD_WR_LCK, addr);
0390     (void)BSP_flashReadRaw(F_CMD_WR_LCK_SET, addr);
0391     flash_pend(b, addr, TIMEOUT_US);
0392 }
0393 
0394 STATIC uint32_t
0395 flash_write_line_intel(struct bankdesc *b, uint32_t a, const char *s, uint32_t N)
0396 {
0397 uint32_t sta, Nspla, nxt, j;
0398 union   {
0399     uint32_t    u;
0400     char        c[sizeof(uint32_t)];
0401 }       buf;
0402 
0403     /* address block */
0404     if ( STA_RDYRDY != (sta = BSP_flashReadRaw(F_CMD_WR_BUF, a)) ) {
0405         return sta;
0406     }
0407 
0408     /* count per device */
0409     N /= FLASH_STRIDE(b);
0410 
0411     /* splat out */
0412     Nspla = (N<<8)  | N;
0413     Nspla = (Nspla<<16) | Nspla;
0414     BSP_flashWriteRaw(Nspla - 0x01010101, a);
0415 
0416     /* fill buffer */
0417     for (nxt = a; N>0; N--) {
0418 #if defined(TESTING) || (DEBUG > 4)
0419         printf("Writing DAT *0x%08"PRIx32" = 0x%08"PRIx32"\n", nxt, *(const uint32_t*)s);
0420 #endif
0421         /* deal with misaligned sources */
0422         for ( j=0; j<sizeof(buf.u); j++ ) {
0423             buf.c[j] = *s++;
0424         }
0425         *(A32)nxt = buf.u;
0426         nxt += FLASH_STRIDE(b);
0427     }
0428 
0429     BSP_flashReadRaw(F_CMD_WR_CMD, a);
0430 
0431     sta = flash_pend(b, a, TIMEOUT_US);
0432 
0433     return sta;
0434 }
0435 
0436 /* Query device for basic information verifying that we talk
0437  * to a 'known'/'supported' device.
0438  *
0439  *   NOTES: - device switched back to array mode on exit.
0440  *          - 'addr' must be 32-bit aligned.
0441  */
0442 
0443 STATIC int
0444 flash_get_id_intel(struct bankdesc *b, uint32_t addr, uint32_t *pVendorId, uint32_t *pDeviceId)
0445 {
0446 uint16_t v,d;
0447 
0448     if ( 4 != FLASH_STRIDE(b) ) {
0449         fprintf(stderr,"intel flash programmer: Strides other than 4 not implemented yet\n");
0450         return -1;
0451     }
0452 
0453     /* Try to read ID */
0454     v = BSP_flashReadRaw(F_CMD_RD_ID, addr);
0455     d = BSP_flashReadRaw(F_CMD_RD_ID, addr + FLASH_STRIDE(b));
0456 
0457     /* switch to array mode */
0458     flash_array_mode_intel(b, addr);
0459 
0460     *pVendorId = v;
0461     *pDeviceId = d;
0462 
0463     return 0;
0464 }