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] - Diff between revs 4 and 13

Show entire file | Details | Blame | View Log

Rev 4 Rev 13
Line 28... Line 28...
#include <stdio.h>
#include <stdio.h>
#include <xspi.h>
#include <xspi.h>
#include "spansion_flash.h"
#include "spansion_flash.h"
#include "uprintf.h"
#include "uprintf.h"
 
 
 
#define SPANSION_CFG_REG_QUAD           (1<<1)
 
#define SPANSION_CFG_REG_OTP_MASK       (0x3c)
 
#define SPANSION_BANK_REG_EXT_ADDR      (1<<7)
 
#define SPANSION_CFG_REG_BP_SHIFT       2
 
#define SPANSION_CFG_REG_BP_MASK        (0x7 << SPANSION_CFG_REG_BP_SHIFT)
 
#define SPANSION_STAT_REG_WIP           (1<<0)
 
#define SPANSION_CFG_REG_LC_MASK        (0xc0)
 
#define SPANSION_CFG_REG_LC_DEFAULT     0
 
static int spansion_flash_cmd_wen(struct spansion_flash *sf);
 
static int spansion_flash_get_cr1(struct spansion_flash *sf, u8 *cr1);
 
static int spansion_flash_get_sr1(struct spansion_flash *sf, u8 *sr1);
 
 
int spansion_flash_init (struct spansion_flash *sf, XSpi *spi, int slave_num)
int spansion_flash_init (struct spansion_flash *sf, XSpi *spi, int slave_num)
{
{
 
        u8 rCfg;
 
 
        sf->spi = spi;
        sf->spi = spi;
        sf->slave_select = (1<<slave_num);
        sf->slave_select = (1<<slave_num);
        int res;
        int ret;
 
 
        res = XSpi_SetOptions(sf->spi, (XSP_MASTER_OPTION | \
        ret = XSpi_SetOptions(sf->spi, (XSP_MASTER_OPTION | \
                                                XSP_MANUAL_SSELECT_OPTION | \
                                                XSP_MANUAL_SSELECT_OPTION | \
                                                XSP_CLK_PHASE_1_OPTION | \
                                                XSP_CLK_PHASE_1_OPTION | \
                                                XSP_CLK_ACTIVE_LOW_OPTION));
                                                XSP_CLK_ACTIVE_LOW_OPTION));
        if(res)
        if(ret)
                return res;
                return ret;
 
 
        res = XSpi_SetSlaveSelect(sf->spi, sf->slave_select);
        ret = XSpi_SetSlaveSelect(sf->spi, sf->slave_select);
        if(res)
        if(ret)
                return res;
                return ret;
 
 
        res = XSpi_Start(sf->spi);
        ret = XSpi_Start(sf->spi);
        return res;
        if (ret)
 
                return ret;
 
 
 
        /* Put spi to polled mode */
 
        XSpi_IntrGlobalDisable(sf->spi);
 
 
 
        /* Check latency is as expected */
 
        ret = spansion_flash_get_cr1(sf, &rCfg);
 
        if(ret)
 
                return ret;
 
 
 
        if ((rCfg & SPANSION_CFG_REG_LC_MASK) != SPANSION_CFG_REG_LC_DEFAULT) {
 
                uprintf("Flash is configured with non-default latency code. Cannot read flash\r\n");
 
                return -1;
 
        }
 
        return 0;
}
}
 
 
static int spansion_flash_transfer(struct spansion_flash *sf, uint8_t *wr_buf, uint8_t *rd_buf, int len)
static int spansion_flash_transfer(struct spansion_flash *sf, uint8_t *wr_buf, uint8_t *rd_buf, int len)
{
{
        int res;
        int res;
Line 62... Line 90...
 
 
        return XST_SUCCESS;
        return XST_SUCCESS;
}
}
 
 
 
 
/* Get status and control register and set QSPI*/
/*
 
 * Get status and control register value
 
 * and set QSPI mode. It needs to be done
 
 * after each configuration flash programming
 
 * using Xilinx tools as they erase this flag.
 
 *
 
 * !!!BEWARE: This is potentially dangerous
 
 * operation as if power is lost during write to
 
 * status and configuration register, both can be
 
 * set to all ones. It may set OTP bits that may render
 
 * flash unusable. As quad mode flag is non-volatile
 
 * it is necessary to do this once only during board
 
 *
 
 */
int spansion_flash_quad_mode(struct spansion_flash *sf)
int spansion_flash_quad_mode(struct spansion_flash *sf)
{
{
#define SPANSION_CFG_REG_QUAD           (1<<1)
 
        int ret;
        int ret;
        u8 rCfgBuf[2];
        int tmo_cnt;
        u8 rStBuf[2];
        u8 rCfg;
 
        u8 rSt;
        u8 wCfgBuf[3];
        u8 wCfgBuf[3];
        u8 wEnBuf[1];
 
 
 
        rCfgBuf[0] = 0x35;
        ret = spansion_flash_get_cr1(sf, &rCfg);
        ret = spansion_flash_transfer(sf, rCfgBuf, rCfgBuf, 2);
 
        if(ret)
        if(ret)
                return ret;
                return ret;
 
 
        rStBuf[0] = 0x05;
        if (rCfg & SPANSION_CFG_REG_QUAD) {
        ret = spansion_flash_transfer(sf, rStBuf, rStBuf, 2);
                return 0;
 
        }
 
 
 
        ret = spansion_flash_get_sr1(sf, &rSt);
        if(ret)
        if(ret)
                return ret;
                return ret;
 
 
        wEnBuf[0] = 0x6;
        ret = spansion_flash_cmd_wen(sf);
        ret = spansion_flash_transfer(sf, wEnBuf, wEnBuf, 1);
 
        if(ret)
        if(ret)
                return ret;
                return ret;
 
 
 
 
 
        uprintf("WARNING: Setting flash quad mode in flash configuration\r\n"
 
                        "registers. If power is lost at that moment flash can be\r\n"
 
                        "corrupted permanently.\r\n");
        wCfgBuf[0] = 0x01;
        wCfgBuf[0] = 0x01;
        wCfgBuf[1] = rStBuf[1];
        wCfgBuf[1] = rSt;
        wCfgBuf[2] = rCfgBuf[1] | SPANSION_CFG_REG_QUAD;
        wCfgBuf[2] = rCfg | SPANSION_CFG_REG_QUAD;
 
 
        ret = spansion_flash_transfer(sf, wCfgBuf, wCfgBuf, 3);
        ret = spansion_flash_transfer(sf, wCfgBuf, wCfgBuf, 3);
        if(ret)
        if(ret)
                return ret;
                return ret;
 
 
        /* Reread CFG reg */
        /* Wait until flash finishes write with timeout */
        rCfgBuf[0] = 0x35;
        tmo_cnt = 1000;
        ret = spansion_flash_transfer(sf, rCfgBuf, rCfgBuf, 2);
        do {
 
                ret = spansion_flash_get_sr1(sf, &rSt);
        if(ret)
        if(ret)
                return ret;
                return ret;
 
 
        return 0;
                if(tmo_cnt)
}
                        tmo_cnt--;
 
                else
/* Set extended addressing mode in Flash and in Xilisf */
                        return -1;
/* !!! Doesn't work well for quad command 6b */
        } while (rSt & SPANSION_STAT_REG_WIP);
int spansion_flash_extended_addressing(struct spansion_flash *sf, int onOff)
 
{
 
#define SPANSION_BANK_REG_EXT_ADDR              (1<<7)
 
        int ret;
 
        u8 buf[2];
 
        XSpi *spi = sf->spi;
 
 
 
        /* Read bank register*/
        /* Reread CFG reg */
        buf[0] = 0x16;
        ret = spansion_flash_get_cr1(sf, &rCfg);
        ret = XSpi_Transfer(spi, buf, buf, 2);
 
        if(ret)
        if(ret)
                return ret;
                return ret;
 
 
        /* Write bank register with extended addressing setting */
        if (rCfg & SPANSION_CFG_REG_QUAD) {
        buf[0] = 0x17;
                uprintf("Flash quad mode set successfully.\r\n");
        if (onOff) {
                return 0;
                buf[1] |=  SPANSION_BANK_REG_EXT_ADDR;
 
        } else {
        } else {
                buf[1] &=  ~SPANSION_BANK_REG_EXT_ADDR;
                uprintf("Flash quad mode was not set, cannot read flash.\r\n");
 
                return -1;
        }
        }
        ret = XSpi_Transfer(spi, buf, buf, 2);
 
        if(ret)
 
                return ret;
 
 
 
        /* Read bank register*/
 
        buf[0] = 0x16;
 
        ret = XSpi_Transfer(spi, buf, buf, 2);
 
        if(ret)
 
                return ret;
 
        uprintf("Modified bank register 0x%02x\r\n", buf[1]);
 
 
 
        return 0;
 
}
}
 
 
 
 
/*
/*
 *  Use Quad IO 4 byte address read command to read block of data.
 *  Use Quad IO 4 byte address read command to read block of data.
 *  spi - SPI core instance to be used
 *  spi - SPI core instance to be used
 *  flash_addr - 32 bit start address in flash
 *  flash_addr - 32 bit start address in flash
 *  buf - pointer to buffer where data shall be stored; must be 8 byte longer then length of data
 *  buf - pointer to buffer where data shall be stored; must be 8 byte longer then length of data
Line 169... Line 197...
        *(cmdbuf++) = 0;
        *(cmdbuf++) = 0;
 
 
        return XSpi_Transfer(spi, buf, buf, len + 8);
        return XSpi_Transfer(spi, buf, buf, len + 8);
}
}
 
 
 No newline at end of file
 No newline at end of file
 
/*
 
 * Read and print flash configuration and status.
 
 */
 
int spansion_flash_print_status(struct spansion_flash *sf)
 
{
 
        int ret;
 
        u8 rCfgBuf[2];
 
        u8 rStBuf[2];
 
        u8 rRDID[4];
 
 
 
        rRDID[0] = 0x9f;
 
        ret = spansion_flash_transfer(sf, rRDID, rRDID, 4);
 
        if(ret)
 
                return ret;
 
        uprintf("RDID: 0x%02x 0x%02x 0x%02x\r\n", rRDID[1], rRDID[2], rRDID[3]);
 
 
 
        rStBuf[0] = 0x05;
 
        ret = spansion_flash_transfer(sf, rStBuf, rStBuf, 2);
 
        if(ret)
 
                return ret;
 
        uprintf("Status reg 1: 0x%02x\r\n", rStBuf[1]);
 
 
 
        rStBuf[0] = 0x07;
 
        ret = spansion_flash_transfer(sf, rStBuf, rStBuf, 2);
 
        if(ret)
 
                return ret;
 
        uprintf("Status reg 2: 0x%02x\r\n", rStBuf[1]);
 
 
 
        rCfgBuf[0] = 0x35;
 
        ret = spansion_flash_transfer(sf, rCfgBuf, rCfgBuf, 2);
 
        if(ret)
 
                return ret;
 
        uprintf("Configuration reg: 0x%02x\r\n", rCfgBuf[1]);
 
 
 
        return 0;
 
}
 
 
 
/* Send write enable command - needed for register write */
 
static int spansion_flash_cmd_wen(struct spansion_flash *sf)
 
{
 
        int ret;
 
        u8 wEnBuf[1];
 
 
 
        wEnBuf[0] = 0x6;
 
        ret = spansion_flash_transfer(sf, wEnBuf, wEnBuf, 1);
 
 
 
        return ret;
 
}
 
 
 
/* Send Bulk erase command*/
 
static int spansion_flash_cmd_be(struct spansion_flash *sf)
 
{
 
        int ret;
 
        u8 buf[1];
 
 
 
        buf[0] = 0x60;
 
        ret = spansion_flash_transfer(sf, buf, buf, 1);
 
 
 
        return ret;
 
}
 
 
 
/* Send get status register sr1*/
 
static int spansion_flash_get_sr1(struct spansion_flash *sf, u8 *sr1)
 
{
 
        int ret;
 
        u8 rStBuf[2];
 
 
 
        rStBuf[0] = 0x05;
 
        ret = spansion_flash_transfer(sf, rStBuf, rStBuf, 2);
 
 
 
        *sr1 = rStBuf[1];
 
 
 
        return ret;
 
}
 
 
 
/* Send get configuration register */
 
static int spansion_flash_get_cr1(struct spansion_flash *sf, u8 *cr1)
 
{
 
        int ret;
 
        u8 rCfgBuf[2];
 
 
 
        rCfgBuf[0] = 0x35;
 
        ret = spansion_flash_transfer(sf, rCfgBuf, rCfgBuf, 2);
 
 
 
        *cr1 = rCfgBuf[1];
 
 
 
        return ret;
 
}
 
 
 
 
 
 
 
/*
 
 * Erase whole device using bulk erase.
 
 */
 
int spansion_flash_bulk_erase(struct spansion_flash *sf)
 
{
 
        int ret;
 
        u8 sr;
 
        int i;
 
 
 
        ret = spansion_flash_cmd_wen(sf);
 
        if(ret)
 
                return ret;
 
 
 
        ret = spansion_flash_cmd_be(sf);
 
        if(ret)
 
                return ret;
 
 
 
        i = 0;
 
        do {
 
                ret = spansion_flash_get_sr1(sf, &sr);
 
                i++;
 
        } while (sr & SPANSION_STAT_REG_WIP);
 
 
 
        return ret;
 
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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