Commit 968294bd authored by Tom Rini's avatar Tom Rini

Merge branch 'master' of git://git.denx.de/u-boot-spi

parents b770e88a c4a79632
......@@ -170,7 +170,7 @@ static const struct dpll_params per_dpll_params_768mhz_es2[NUM_SYS_CLKS] = {
static const struct dpll_params per_dpll_params_768mhz_dra7xx[NUM_SYS_CLKS] = {
{32, 0, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1}, /* 12 MHz */
{96, 4, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1}, /* 20 MHz */
{96, 4, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1}, /* 20 MHz */
{160, 6, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1}, /* 16.8 MHz */
{20, 0, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1}, /* 19.2 MHz */
{192, 12, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1}, /* 26 MHz */
......@@ -426,6 +426,10 @@ void enable_basic_clocks(void)
#ifdef CONFIG_DRIVER_TI_CPSW
(*prcm)->cm_gmac_gmac_clkctrl,
#endif
#ifdef CONFIG_TI_QSPI
(*prcm)->cm_l4per_qspi_clkctrl,
#endif
0
};
......@@ -454,6 +458,10 @@ void enable_basic_clocks(void)
clk_modules_explicit_en_essential,
1);
#ifdef CONFIG_TI_QSPI
setbits_le32((*prcm)->cm_l4per_qspi_clkctrl, (1<<24));
#endif
/* Enable SCRM OPT clocks for PER and CORE dpll */
setbits_le32((*prcm)->cm_wkupaon_scrm_clkctrl,
OPTFCLKEN_SCRM_PER_MASK);
......
......@@ -921,6 +921,7 @@ struct prcm_regs const dra7xx_prcm = {
.cm_l4per_gpio8_clkctrl = 0x4a009818,
.cm_l4per_mmcsd3_clkctrl = 0x4a009820,
.cm_l4per_mmcsd4_clkctrl = 0x4a009828,
.cm_l4per_qspi_clkctrl = 0x4a009838,
.cm_l4per_uart1_clkctrl = 0x4a009840,
.cm_l4per_uart2_clkctrl = 0x4a009848,
.cm_l4per_uart3_clkctrl = 0x4a009850,
......
......@@ -22,7 +22,7 @@ struct exynos_spi {
unsigned int rx_data; /* 0x1c */
unsigned int pkt_cnt; /* 0x20 */
unsigned char reserved2[4];
unsigned char reserved3[4];
unsigned int swap_cfg; /* 0x28 */
unsigned int fb_clk; /* 0x2c */
unsigned char padding[0xffd0];
};
......@@ -62,5 +62,14 @@ struct exynos_spi {
/* Packet Count */
#define SPI_PACKET_CNT_EN (1 << 16)
/* Swap config */
#define SPI_TX_SWAP_EN (1 << 0)
#define SPI_TX_BYTE_SWAP (1 << 2)
#define SPI_TX_HWORD_SWAP (1 << 3)
#define SPI_TX_BYTE_SWAP (1 << 2)
#define SPI_RX_SWAP_EN (1 << 4)
#define SPI_RX_BYTE_SWAP (1 << 6)
#define SPI_RX_HWORD_SWAP (1 << 7)
#endif /* __ASSEMBLY__ */
#endif
......@@ -61,6 +61,9 @@
/* GPMC */
#define OMAP54XX_GPMC_BASE 0x50000000
/* QSPI */
#define QSPI_BASE 0x4B300000
/*
* Hardware Register Details
*/
......
......@@ -15,6 +15,7 @@
#define BOOT_DEVICE_MMC1 5
#define BOOT_DEVICE_MMC2 6
#define BOOT_DEVICE_MMC2_2 7
#define BOOT_DEVICE_SPI 10
#define MMC_BOOT_DEVICES_START BOOT_DEVICE_MMC1
#define MMC_BOOT_DEVICES_END BOOT_DEVICE_MMC2_2
......
......@@ -266,6 +266,7 @@ struct prcm_regs {
u32 cm_l4per_mmcsd4_clkctrl;
u32 cm_l4per_msprohg_clkctrl;
u32 cm_l4per_slimbus2_clkctrl;
u32 cm_l4per_qspi_clkctrl;
u32 cm_l4per_uart1_clkctrl;
u32 cm_l4per_uart2_clkctrl;
u32 cm_l4per_uart3_clkctrl;
......
......@@ -51,5 +51,15 @@ const struct pad_conf_entry core_padconf_array_essential[] = {
{RGMII0_RXD2, (IEN | M0) },
{RGMII0_RXD1, (IEN | M0) },
{RGMII0_RXD0, (IEN | M0) },
{GPMC_A13, (IEN | PDIS | M1)}, /* QSPI1_RTCLK */
{GPMC_A14, (IEN | PDIS | M1)}, /* QSPI1_D[3] */
{GPMC_A15, (IEN | PDIS | M1)}, /* QSPI1_D[2] */
{GPMC_A16, (IEN | PDIS | M1)}, /* QSPI1_D[1] */
{GPMC_A17, (IEN | PDIS | M1)}, /* QSPI1_D[0] */
{GPMC_A18, (M1)}, /* QSPI1_SCLK */
{GPMC_A3, (IEN | PDIS | M1)}, /* QSPI1_CS2 */
{GPMC_A4, (IEN | PDIS | M1)}, /* QSPI1_CS3 */
{GPMC_CS2, (IEN | PTU | PDIS | M1)}, /* QSPI1_CS0 */
{GPMC_CS3, (IEN | PTU | PDIS | M1)}, /* QSPI1_CS1*/
};
#endif /* _MUX_DATA_DRA7XX_H_ */
-------------------------------------------------
Simple steps used to test the QSPI at U-Boot
-------------------------------------------------
For #1, build the patched U-Boot and load MLO/u-boot.img
----------------------------------
Boot from another medium like MMC
----------------------------------
U-Boot# mmc dev 0
mmc0 is current device
U-Boot# fatload mmc 0 0x82000000 MLO
reading MLO
55872 bytes read in 8 ms (6.7 MiB/s)
U-Boot# fatload mmc 0 0x83000000 u-boot.img
reading u-boot.img
248600 bytes read in 19 ms (12.5 MiB/s)
--------------------------------------------------
Commands to erase/write u-boot/mlo to flash device
--------------------------------------------------
U-Boot# sf probe 0
SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB, mapped at 5c000000
SF: Warning - Only lower 16MiB accessible, Full access #define CONFIG_SPI_FLASH_BAR
U-Boot# sf erase 0 0x10000
SF: 65536 bytes @ 0x0 Erased: OK
U-Boot# sf erase 0x20000 0x10000
SF: 65536 bytes @ 0x20000 Erased: OK
U-Boot# sf erase 0x30000 0x10000
SF: 65536 bytes @ 0x30000 Erased: OK
U-Boot# sf erase 0x40000 0x10000
SF: 65536 bytes @ 0x40000 Erased: OK
U-Boot# sf erase 0x50000 0x10000
SF: 65536 bytes @ 0x50000 Erased: OK
U-Boot# sf erase 0x60000 0x10000
SF: 65536 bytes @ 0x60000 Erased: OK
U-Boot# sf write 82000000 0 0x10000
SF: 65536 bytes @ 0x0 Written: OK
U-Boot# sf write 83000000 0x20000 0x60000
SF: 393216 bytes @ 0x20000 Written: OK
For #2, set sysboot to QSPI-1 boot mode(SYSBOOT[5:0] = 100110) and power
on. ROM should find the GP header at offset 0 and load/execute SPL. SPL
then detects that ROM was in QSPI-1 mode (boot code 10) and attempts to
find a U-Boot image header at offset 0x20000 (set in the config file)
and proceeds to load that image using the U-Boot image payload offset/size
from the header. It will then start U-Boot.
QSPI U-boot support
------------------
Host processor is connected to serial flash device via qpsi
interface. QSPI is a kind of spi module that allows single,
dual and quad read access to external spi devices. The module
has a memory mapped interface which provide direct interface
for accessing data form external spi devices.
The one QSPI in the device is primarily intended for fast booting
from Quad SPI flash devices.
Usecase
-------
MLO/u-boot.img will be flashed from SD/MMC to the flash device
using serial flash erase and write commands. Then, switch settings
will be changed to qspi boot. Then, the ROM code will read MLO
from the predefined location in the flash, where it was flashed and
execute it after storing it in SDRAM. Then, the MLO will read
u-boot.img from flash and execute it from SDRAM.
SPI mode
-------
SPI mode uses mtd spi framework for transfer and reception of data.
Can be used in:
1. Normal mode: use single pin for transfers
2. Dual Mode: use two pins for transfers.
3. Quad mode: use four pin for transfer
Memory mapped read mode
-----------------------
In this, SPI controller is configured using configuration port and then
controler is switched to memory mapped port for data read.
Driver
------
drivers/qspi/ti_qspi.c
- Newly created file which is responsible for configuring the
qspi controller and also for providing the low level api which
is responsible for transferring the datas from host controller
to flash device and vice versa.
Testing
-------
A seperated file named README.dra_qspi_test has been created which gives all the
details about the commands required to test qspi at u-boot level.
Status on SPI subsystem:
=======================
SPI COMMAND (common/cmd_sf, cmd_spi):
-
SPI FLASH (drivers/mtd/spi):
- sf_probe.c: SPI flash probing code.
- sf_ops.c: SPI flash operations code.
- sf.c: SPI flash interface, which interacts controller driver.
- Bank Address Register (Accessing flashes > 16Mbytes in 3-byte addressing)
- Added memory_mapped support for read operations.
- Common probe support for all supported flash vendors except, ramtron.
SPI DRIVERS (drivers/spi):
-
TODO:
- Runtime detection of spi_flash params, SFDP(if possible)
- Add support for multibus build/accessing.
- Extended read commands support(dual read, dual IO read)
- Quad Page Program support.
- Quad Read support(quad fast read, quad IO read)
- Dual flash connection topology support(accessing two spi flash memories with single cs)
- Banking support on dual flash connection topology.
- Need proper cleanups on spi_flash and drivers.
--
Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
18-09-2013.
07-10-2013.
......@@ -14,16 +14,11 @@ COBJS-$(CONFIG_SPL_SPI_LOAD) += spi_spl_load.o
COBJS-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o
endif
COBJS-$(CONFIG_SPI_FLASH) += spi_flash.o
COBJS-$(CONFIG_SPI_FLASH_ATMEL) += atmel.o
COBJS-$(CONFIG_SPI_FLASH_EON) += eon.o
COBJS-$(CONFIG_SPI_FLASH_GIGADEVICE) += gigadevice.o
COBJS-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.o
COBJS-$(CONFIG_SPI_FLASH_SPANSION) += spansion.o
COBJS-$(CONFIG_SPI_FLASH_SST) += sst.o
COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o
COBJS-$(CONFIG_SPI_FLASH_WINBOND) += winbond.o
COBJS-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.o
ifdef CONFIG_CMD_SF
COBJS-y += sf.o
endif
COBJS-$(CONFIG_SPI_FLASH) += sf_probe.o sf_ops.o
COBJS-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.o
COBJS-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o
COBJS := $(COBJS-y)
......
This diff is collapsed.
/*
* (C) Copyright 2010, ucRobotics Inc.
* Author: Chong Huang <chuang@ucrobotics.com>
* Licensed under the GPL-2 or later.
*/
#include <common.h>
#include <malloc.h>
#include <spi_flash.h>
#include "spi_flash_internal.h"
struct eon_spi_flash_params {
u8 idcode1;
u16 nr_sectors;
const char *name;
};
static const struct eon_spi_flash_params eon_spi_flash_table[] = {
{
.idcode1 = 0x16,
.nr_sectors = 1024,
.name = "EN25Q32B",
},
{
.idcode1 = 0x18,
.nr_sectors = 4096,
.name = "EN25Q128",
},
};
struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
{
const struct eon_spi_flash_params *params;
struct spi_flash *flash;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(eon_spi_flash_table); ++i) {
params = &eon_spi_flash_table[i];
if (params->idcode1 == idcode[2])
break;
}
if (i == ARRAY_SIZE(eon_spi_flash_table)) {
debug("SF: Unsupported EON ID %02x\n", idcode[1]);
return NULL;
}
flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
flash->page_size = 256;
flash->sector_size = 256 * 16 * 16;
flash->size = 256 * 16 * params->nr_sectors;
return flash;
}
/*
* Gigadevice SPI flash driver
* Copyright 2013, Samsung Electronics Co., Ltd.
* Author: Banajit Goswami <banajit.g@samsung.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <malloc.h>
#include <spi_flash.h>
#include "spi_flash_internal.h"
struct gigadevice_spi_flash_params {
uint16_t id;
uint16_t nr_blocks;
const char *name;
};
static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = {
{
.id = 0x6016,
.nr_blocks = 64,
.name = "GD25LQ",
},
{
.id = 0x4017,
.nr_blocks = 128,
.name = "GD25Q64B",
},
};
struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
{
const struct gigadevice_spi_flash_params *params;
struct spi_flash *flash;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(gigadevice_spi_flash_table); i++) {
params = &gigadevice_spi_flash_table[i];
if (params->id == ((idcode[1] << 8) | idcode[2]))
break;
}
if (i == ARRAY_SIZE(gigadevice_spi_flash_table)) {
debug("SF: Unsupported Gigadevice ID %02x%02x\n",
idcode[1], idcode[2]);
return NULL;
}
flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
/* page_size */
flash->page_size = 256;
/* sector_size = page_size * pages_per_sector */
flash->sector_size = flash->page_size * 16;
/* size = sector_size * sector_per_block * number of blocks */
flash->size = flash->sector_size * 16 * params->nr_blocks;
return flash;
}
/*
* Copyright 2009(C) Marvell International Ltd. and its affiliates
* Prafulla Wadaskar <prafulla@marvell.com>
*
* Based on drivers/mtd/spi/stmicro.c
*
* Copyright 2008, Network Appliance Inc.
* Jason McMullan <mcmullan@netapp.com>
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <malloc.h>
#include <spi_flash.h>
#include "spi_flash_internal.h"
struct macronix_spi_flash_params {
u16 idcode;
u16 nr_blocks;
const char *name;
};
static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
{
.idcode = 0x2013,
.nr_blocks = 8,
.name = "MX25L4005",
},
{
.idcode = 0x2014,
.nr_blocks = 16,
.name = "MX25L8005",
},
{
.idcode = 0x2015,
.nr_blocks = 32,
.name = "MX25L1605D",
},
{
.idcode = 0x2016,
.nr_blocks = 64,
.name = "MX25L3205D",
},
{
.idcode = 0x2017,
.nr_blocks = 128,
.name = "MX25L6405D",
},
{
.idcode = 0x2018,
.nr_blocks = 256,
.name = "MX25L12805D",
},
{
.idcode = 0x2618,
.nr_blocks = 256,
.name = "MX25L12855E",
},
};
struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
{
const struct macronix_spi_flash_params *params;
struct spi_flash *flash;
unsigned int i;
u16 id = idcode[2] | idcode[1] << 8;
for (i = 0; i < ARRAY_SIZE(macronix_spi_flash_table); i++) {
params = &macronix_spi_flash_table[i];
if (params->idcode == id)
break;
}
if (i == ARRAY_SIZE(macronix_spi_flash_table)) {
debug("SF: Unsupported Macronix ID %04x\n", id);
return NULL;
}
flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
flash->page_size = 256;
flash->sector_size = 256 * 16 * 16;
flash->size = flash->sector_size * params->nr_blocks;
/* Clear BP# bits for read-only flash */
spi_flash_cmd_write_status(flash, 0);
return flash;
}
......@@ -36,7 +36,7 @@
#include <common.h>
#include <malloc.h>
#include <spi_flash.h>
#include "spi_flash_internal.h"
#include "sf_internal.h"
/*
* Properties of supported FRAMs
......@@ -214,7 +214,8 @@ static int ramtron_erase(struct spi_flash *flash, u32 offset, size_t len)
* nore: we are called here with idcode pointing to the first non-0x7f byte
* already!
*/
struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode)
static struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi,
u8 *idcode)
{
const struct ramtron_spi_fram_params *params;
struct ramtron_spi_fram *sn;
......@@ -270,7 +271,7 @@ struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode)
return NULL;
found:
sn = spi_flash_alloc(struct ramtron_spi_fram, spi, params->name);
sn = malloc(sizeof(*sn));
if (!sn) {
debug("SF: Failed to allocate memory\n");
return NULL;
......@@ -285,3 +286,118 @@ found:
return &sn->flash;
}
/*
* The following table holds all device probe functions
* (All flashes are removed and implemented a common probe at
* spi_flash_probe.c)
*
* shift: number of continuation bytes before the ID
* idcode: the expected IDCODE or 0xff for non JEDEC devices
* probe: the function to call
*
* Non JEDEC devices should be ordered in the table such that
* the probe functions with best detection algorithms come first.
*
* Several matching entries are permitted, they will be tried
* in sequence until a probe function returns non NULL.
*
* IDCODE_CONT_LEN may be redefined if a device needs to declare a
* larger "shift" value. IDCODE_PART_LEN generally shouldn't be
* changed. This is the max number of bytes probe functions may
* examine when looking up part-specific identification info.
*
* Probe functions will be given the idcode buffer starting at their
* manu id byte (the "idcode" in the table below). In other words,
* all of the continuation bytes will be skipped (the "shift" below).
*/
#define IDCODE_CONT_LEN 0
#define IDCODE_PART_LEN 5
static const struct {
const u8 shift;
const u8 idcode;
struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
} flashes[] = {
/* Keep it sorted by define name */
#ifdef CONFIG_SPI_FRAM_RAMTRON
{ 6, 0xc2, spi_fram_probe_ramtron, },
# undef IDCODE_CONT_LEN
# define IDCODE_CONT_LEN 6
#endif
#ifdef CONFIG_SPI_FRAM_RAMTRON_NON_JEDEC
{ 0, 0xff, spi_fram_probe_ramtron, },
#endif
};
#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int spi_mode)
{
struct spi_slave *spi;
struct spi_flash *flash = NULL;
int ret, i, shift;
u8 idcode[IDCODE_LEN], *idp;
spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
if (!spi) {
printf("SF: Failed to set up slave\n");
return NULL;
}
ret = spi_claim_bus(spi);
if (ret) {
debug("SF: Failed to claim SPI bus: %d\n", ret);
goto err_claim_bus;
}
/* Read the ID codes */
ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
if (ret)
goto err_read_id;
#ifdef DEBUG
printf("SF: Got idcodes\n");
print_buffer(0, idcode, 1, sizeof(idcode), 0);
#endif
/* count the number of continuation bytes */
for (shift = 0, idp = idcode;
shift < IDCODE_CONT_LEN && *idp == 0x7f;
++shift, ++idp)
continue;
/* search the table for matches in shift and id */
for (i = 0; i < ARRAY_SIZE(flashes); ++i)
if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
/* we have a match, call probe */
flash = flashes[i].probe(spi, idp);
if (flash)
break;
}
if (!flash) {
printf("SF: Unsupported manufacturer %02x\n", *idp);
goto err_manufacturer_probe;
}
printf("SF: Detected %s with total size ", flash->name);
print_size(flash->size, "");
puts("\n");
spi_release_bus(spi);
return flash;
err_manufacturer_probe:
err_read_id:
spi_release_bus(spi);
err_claim_bus:
spi_free_slave(spi);
return NULL;
}
void spi_flash_free(struct spi_flash *flash)
{
spi_free_slave(flash->spi);
free(flash);
}
/*
* SPI flash interface
*
* Copyright (C) 2008 Atmel Corporation
* Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
*
* Licensed under the GPL-2 or later.
*/
#include <common.h>
#include <spi.h>
static int spi_flash_read_write(struct spi_slave *spi,
const u8 *cmd, size_t cmd_len,
const u8 *data_out, u8 *data_in,
size_t data_len)
{
unsigned long flags = SPI_XFER_BEGIN;
int ret;
if (data_len == 0)
flags |= SPI_XFER_END;
ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
if (ret) {
debug("SF: Failed to send command (%zu bytes): %d\n",
cmd_len, ret);
} else if (data_len != 0) {
ret = spi_xfer(spi, data_len * 8, data_out, data_in,
SPI_XFER_END);
if (ret)
debug("SF: Failed to transfer %zu bytes of data: %d\n",
data_len, ret);
}
return ret;
}
int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
size_t cmd_len, void *data, size_t data_len)
{
return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len);
}
int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
{
return spi_flash_cmd_read(spi, &cmd, 1, response, len);
}
int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
const void *data, size_t data_len)
{
return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
}
......@@ -2,42 +2,43 @@
* SPI flash internal definitions
*
* Copyright (C) 2008 Atmel Corporation
* Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
*
* Licensed under the GPL-2 or later.
*/
/* Common parameters -- kind of high, but they should only occur when there
* is a problem (and well your system already is broken), so err on the side
* of caution in case we're dealing with slower SPI buses and/or processors.
*/
#define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ)
#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ)
#define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ)
#ifndef _SPI_FLASH_INTERNAL_H_
#define _SPI_FLASH_INTERNAL_H_
/* Common commands */
#define CMD_READ_ID 0x9f
#define SPI_FLASH_16MB_BOUN 0x1000000
#define CMD_READ_ARRAY_SLOW 0x03
#define CMD_READ_ARRAY_FAST 0x0b
/* SECT flags */
#define SECT_4K (1 << 1)
#define SECT_32K (1 << 2)
#define E_FSR (1 << 3)
/* Erase commands */
#define CMD_ERASE_4K 0x20
#define CMD_ERASE_32K 0x52
#define CMD_ERASE_CHIP 0xc7
#define CMD_ERASE_64K 0xd8
/* Write commands */
#define CMD_WRITE_STATUS 0x01
#define CMD_PAGE_PROGRAM 0x02
#define CMD_WRITE_DISABLE 0x04
#define CMD_READ_STATUS 0x05
#define CMD_FLAG_STATUS 0x70
#define CMD_WRITE_ENABLE 0x06
#define CMD_ERASE_4K 0x20
#define CMD_ERASE_32K 0x52
#define CMD_ERASE_64K 0xd8
#define CMD_ERASE_CHIP 0xc7
#define SPI_FLASH_16MB_BOUN 0x1000000
#define CMD_READ_CONFIG 0x35