* POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
-
/******************************************************************************
* Included Files
*****************************************************************************/
#include <tinyara/kmalloc.h>
#include <tinyara/spi/spi.h>
#include <arpa/inet.h>
+#include <tinyara/fs/mtd.h>
#include "up_arch.h"
#include "cache.h"
* Pre-processor Definitions
*****************************************************************************/
#define S5J_SFLASH_MAPPED_ADDR (CONFIG_S5J_FLASH_BASE)
-#undef S5J_SFLASH_USE_DIRECT_RW
+#define S5J_SFLASH_USE_DIRECT_RW
-#define SFLASH_SECTOR_SIZE (CONFIG_S5J_FLASH_SECTOR_SIZE)
+#define SFLASH_SECTOR_SIZE (4096)
#define SECTOR_ALIGN_SIZE(x) (((x)/SFLASH_SECTOR_SIZE)*SFLASH_SECTOR_SIZE)
-#define MIN(a, b) (a > b) ? b : a
-
-#if defined(CONFIG_BOARD_COREDUMP_FLASH) || defined(CONFIG_BOARD_RAMDUMP_FLASH)
-volatile bool g_sflash_nonsleep_mode = false;
-
-#define usleep(x) \
- do { \
- if (g_sflash_nonsleep_mode) { \
- up_udelay(x); \
- } else { \
- usleep(x); \
- } \
- } while (0)
-#endif
+#define MIN(a, b) ( a > b ) ? b : a
/******************************************************************************
* Private Types
*****************************************************************************/
/* Command definitions */
-
enum s5j_sflash_command_e {
- SFLASH_WRITE_STATUS_REGISTER = 0x01,/* WRSR */
+ SFLASH_WRITE_STATUS_REGISTER = 0x01, /* WRSR */
SFLASH_WRITE = 0x02,
SFLASH_READ = 0x03,
SFLASH_WRITE_DISABLE = 0x04, /* WRDI */
SFLASH_READ_STATUS_REGISTER = 0x05, /* RDSR */
- SFLASH_WRITE_ENABLE = 0x06, /* WREN */
- SFLASH_SECTOR_ERASE = 0x20, /* SE */
- SFLASH_READ_STATUS_REGISTER2 = 0x35,/* RDSR-2 - Winbond only */
+ SFLASH_WRITE_ENABLE = 0x06, /* WREN */
+ SFLASH_SECTOR_ERASE = 0x20, /* SE */
+ SFLASH_READ_STATUS_REGISTER2 = 0x35, /* RDSR-2 - Winbond only */
SFLASH_BLOCK_ERASE_MID = 0x52, /* SE */
SFLASH_BLOCK_ERASE_LARGE = 0xD8, /* SE */
- SFLASH_READ_ID1 = 0x90, /* data size varies */
- SFLASH_READ_ID2 = 0xAB, /* data size varies */
+ SFLASH_READ_ID1 = 0x90, /* data size varies */
+ SFLASH_READ_ID2 = 0xAB, /* data size varies */
SFLASH_READ_JEDEC_ID = 0x9F, /* RDID */
- SFLASH_CHIP_ERASE1 = 0x60, /* CE */
- SFLASH_CHIP_ERASE2 = 0xC7, /* CE */
- SFLASH_DUMMY = 0xA5, /* Dummy */
+ SFLASH_CHIP_ERASE1 = 0x60, /* CE */
+ SFLASH_CHIP_ERASE2 = 0xC7, /* CE */
+ SFLASH_DUMMY = 0xA5, /* Dummy */
};
struct s5j_sflash_priv_s {
uint32_t addr;
sem_t sem_excl; /* mutex */
+ void *priv;
};
struct s5j_sflash_dev_s {
/* this ptr can be used in nsh_cmd */
-FAR struct s5j_sflash_dev_s *sflashdev;
+FAR struct s5j_sflash_dev_s *sflashdev = NULL;
/******************************************************************************
* Private Function Prototypes
* Private Functions
*****************************************************************************/
-static void QSPI_Set_GPIOPort(void)
-{
- s32 gpio_sf_clk;
- s32 gpio_sf_cs;
- s32 gpio_sf_si;
- s32 gpio_sf_so;
- s32 gpio_sf_wp;
- s32 gpio_sf_hld;
-
- gpio_sf_clk = s5j_gpio(GPP1, 0);
- gpio_sf_cs = s5j_gpio(GPP1, 1);
- gpio_sf_si = s5j_gpio(GPP1, 2);
- gpio_sf_so = s5j_gpio(GPP1, 3);
- gpio_sf_wp = s5j_gpio(GPP1, 4);
- gpio_sf_hld = s5j_gpio(GPP1, 5);
-
- gpio_cfg_pin(gpio_sf_clk, GPIO_FUNC(2));
- gpio_cfg_pin(gpio_sf_cs, GPIO_FUNC(2));
- gpio_cfg_pin(gpio_sf_si, GPIO_FUNC(2));
- gpio_cfg_pin(gpio_sf_so, GPIO_FUNC(2));
- gpio_cfg_pin(gpio_sf_wp, GPIO_FUNC(2));
- gpio_cfg_pin(gpio_sf_hld, GPIO_FUNC(2));
-
- gpio_set_pull(gpio_sf_clk, GPIO_PULL_UP);
- gpio_set_pull(gpio_sf_cs, GPIO_PULL_UP);
- gpio_set_pull(gpio_sf_si, GPIO_PULL_UP);
- gpio_set_pull(gpio_sf_so, GPIO_PULL_UP);
- gpio_set_pull(gpio_sf_wp, GPIO_PULL_UP);
- gpio_set_pull(gpio_sf_hld, GPIO_PULL_UP);
-
- return;
-}
-
/******************************************************************************
* Name: s5j_sflash_sem_post
*
* Description:
* Release the mutual exclusion semaphore
*
+ * Input Parameters:
+ * dev - pointer to spi dev structure
+ *
+ * Returned Value:
+ * OK
*****************************************************************************/
static inline void s5j_sflash_sem_post(struct s5j_sflash_dev_s *dev)
* Description:
* Initialize semaphores
*
+ * Input Parameters:
+ * dev - pointer to spi dev structure
+ *
+ * Returned Value:
+ * OK
*****************************************************************************/
static inline void s5j_sflash_sem_init(struct s5j_sflash_dev_s *dev)
* Description:
* Take the exclusive access, waiting as necessary
*
+ * Input Parameters:
+ * dev - pointer to spi dev structure
+ *
+ * Returned Value:
+ * OK
*****************************************************************************/
static inline void s5j_sflash_sem_wait(struct s5j_sflash_dev_s *dev)
* Name: s5j_sflash_erase
*
* Description:
- * erase flash
+ * Flash Erase
+ *
+ * Input Parameters:
+ * dev - pointer to spi dev structure
+ * cmd - erase command
+ * addr - erase start address
*
+ * Returned Value:
+ * OK
*****************************************************************************/
-int s5j_sflash_erase(struct s5j_sflash_dev_s *dev, uint8_t cmd, uint32_t addr)
+static int s5j_sflash_erase(struct s5j_sflash_dev_s *dev, uint8_t cmd, uint32_t addr)
{
int ret;
+#ifdef CONFIG_S5J_FLASH_ONLY_ALLOW_SUBSECTOR
+ uint32_t i;
+#endif
uint32_t val;
int size = 0;
}
#endif
+ s5j_qspi_disable_wp();
+
do {
ret = s5j_sflash_write_enable(dev);
if (OK != ret) {
case SFLASH_SECTOR_ERASE:
Outp32(rERASE_ADDRESS, addr);
Outp8(rSE, QSPI_DUMMY_DATA);
- size = 4096; /* Sub-sector size */
+ size = 4096; /* Sub-sector size */
break;
case SFLASH_BLOCK_ERASE_LARGE:
- size = 65536; /* block size */
+ size = 65536; /* block size */
+#ifdef CONFIG_S5J_FLASH_ONLY_ALLOW_SUBSECTOR
+ for (i = 0; i < 16; i++) {
+ Outp32(rERASE_ADDRESS, addr + i * 4096);
+ Outp8(rSE, QSPI_DUMMY_DATA);
+
+ while (getreg8(rRDSR) & 0x1) ;
+ pthread_yield();
+ }
+#else
SetBits(rCOMMAND2, 16, 0xFF, COMMAND_ERASE_64KB);
/* SetBits(rCOMMAND2, 16, 0xFF, COMMAND_ERASE_32KB); */
Outp32(rERASE_ADDRESS, addr);
Outp8(rBE, QSPI_DUMMY_DATA);
-
+#endif
break;
default:
break;
while (getreg8(rRDSR) & 0x1) ;
+ s5j_qspi_enable_wp();
+
if (cmd != SFLASH_CHIP_ERASE1) {
arch_invalidate_dcache(addr + S5J_SFLASH_MAPPED_ADDR, (addr + S5J_SFLASH_MAPPED_ADDR + size));
}
return OK;
}
-int s5j_sflash_write_enable(struct s5j_sflash_dev_s *dev)
+/******************************************************************************
+ * Name: s5j_sflash_write_enable
+ *
+ * Description:
+ * Enable flash write operation
+ *
+ * Input Parameters:
+ * dev - pointer to spi dev structure
+ *
+ * Returned Value:
+ * OK
+ *****************************************************************************/
+static int s5j_sflash_write_enable(struct s5j_sflash_dev_s *dev)
{
SetBits(rCOMMAND4, 8, 0xFF, 0x06);
}
/******************************************************************************
+ * Name: s5j_sflash_write_disable
+ *
+ * Description:
+ * Disable flash write operation
+ *
+ * Input Parameters:
+ * dev - pointer to spi dev structure
+ *
+ * Returned Value:
+ * OK
+ *****************************************************************************/
+static int s5j_sflash_write_disable(struct s5j_sflash_dev_s *dev)
+{
+ SetBits(rCOMMAND4, 8, 0xFF, 0x04);
+
+ return OK;
+}
+
+/******************************************************************************
* Name: s5j_sflash_read
*
* Description:
* Read data from flash.
*
+ * Input Parameters:
+ * dev - pointer to spi dev structure
+ * addr - Start address
+ * buf - pointer to buffer for data to read
+ * size - number of bytes to read
+ *
+ * Returned Value:
+ * OK
*****************************************************************************/
-int s5j_sflash_read(struct s5j_sflash_dev_s *dev, uint32_t addr, uint8_t *buf, uint32_t size)
+static int s5j_sflash_read(struct s5j_sflash_dev_s *dev, uint32_t addr, uint8_t *buf, uint32_t size)
{
int32_t i;
int32_t readsize;
}
#endif
+ /* it avoid to conflict smartfs read and SSS f/w write */
+ s5j_qspi_take_sem();
+
fvdbg("addr 0x%x, size %d\n", addr, size);
while (size != 0) {
/* first align */
size -= readsize;
}
+ s5j_qspi_release_sem();
+
fvdbg("buf[%d]\n", *buf);
return OK;
}
* Description:
* Write data.
*
+ * Input Parameters:
+ * dev - pointer to spi dev structure
+ * addr - Start address
+ * buf - pointer to buffer for data to write
+ * size - number of bytes to write
+ *
+ * Returned Value:
+ * OK
*****************************************************************************/
-int s5j_sflash_write(struct s5j_sflash_dev_s *dev, uint32_t addr, uint8_t *buf, uint32_t size)
+static int s5j_sflash_write(struct s5j_sflash_dev_s *dev, uint32_t addr, uint8_t *buf, uint32_t size)
{
int32_t i;
int32_t readsize;
offset = addr % SFLASH_SECTOR_SIZE;
readsize = MIN(SFLASH_SECTOR_SIZE - offset, size);
-
+ s5j_qspi_disable_wp();
memcpy((void *)(addr + S5J_SFLASH_MAPPED_ADDR), (void *)(buf + i), readsize);
arch_flush_dcache(addr + S5J_SFLASH_MAPPED_ADDR, (addr + S5J_SFLASH_MAPPED_ADDR + readsize));
+ s5j_qspi_enable_wp();
addr += readsize;
i += readsize;
size -= readsize;
/* check write in progress */
while (getreg8(rRDSR) & 0x1) ;
+ pthread_yield();
}
return OK;
* Description:
* initialize sflash controller.
*
+ * Input Parameters:
+ * spidev - pointer to spi dev structure
+ *
+ * Returned Value:
+ * OK
*****************************************************************************/
static int s5j_sflash_init(struct s5j_sflash_dev_s *dev)
{
/* initialize mutex */
-
s5j_sflash_sem_init(dev);
- QSPI_Set_GPIOPort();
- HW_REG32(0x80310000, 0x04) = 0x8010001A; /* disable WP */
- HW_REG32(0x80310000, 0x78) = 0x8; //FLASH_IO_MODE
- HW_REG32(0x80310000, 0x74) = 0x4; //QUAD_FAST_READ
-
- /* COMMNAD1 will be asserted by default value */
- cal_clk_setrate(d1_serialflash, 80000000);
-
return OK;
}
* Description:
* Support Lock/Unlock. This function s a part of spi_ops.
*
+ * Input Parameters:
+ * spidev - pointer to spi dev structure
+ * lock - true, locks access; false, release access
+ *
+ * Returned Value:
+ * OK
*****************************************************************************/
static int s5j_sflash_lock(FAR struct spi_dev_s *spidev, bool lock)
*
* Description:
* Support SPI CS. But, the S5J only 1 sflash. We don't necessary.
- * This function is a part of spi_ops.
+ * This function is a part of spi_ops. Dummy Function
*
*****************************************************************************/
* Name: s5j_sflash_setfrequency
*
* Description:
- * Support changing frequency.
+ * Support changing frequency. Dummy function.
*
*****************************************************************************/
* Name: s5j_sflash_setmode
*
* Description:
- * Support changing mode(CPHA/CPOL).
+ * Support changing mode(CPHA/CPOL). Dummy function.
*
*****************************************************************************/
* Name: s5j_sflash_setbits
*
* Description:
- * Support changing 1/4Bit. But we can't change bit.
- * If you need to change bit, please ask the broadcom.
- * This function is a part of spi_ops.
+ * Support changing 1/4Bit. Dummy function.
*
*****************************************************************************/
* Name: s5j_sflash_setbits
*
* Description:
- * This function is a part of spi_ops
+ * This function is a part of spi_ops. Dummy function.
*
*****************************************************************************/
* Send a slave address from upper-level driver to device.
* This function is a part of spi_ops.
*
+ * Input Parameters:
+ * spidev - pointer to spi dev structure
+ * wd - write data. Data is a command or erase addr.
+ *
+ * Returned Value:
+ * OK, or 0.
*****************************************************************************/
static uint16_t s5j_sflash_send(FAR struct spi_dev_s *spidev, uint16_t wd)
* Send data from upper-level driver to device.
* This function is a part of spi_ops.
*
+ * Input Parameters:
+ * spidev - pointer to spi dev structure
+ * txbuffer - pointer to buffer with data to send
+ * rxbuffer - pointer to buffer for read data
+ * nwords - number of words (actually bytes)
+ *
+ * Returned Value:
+ * None
*****************************************************************************/
static void s5j_sflash_exchange(FAR struct spi_dev_s *spidev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords)
* Send data from upper-level driver to device.
* This function is a part of spi_ops.
*
+ * Input Parameters:
+ * spidev - pointer to spi dev structure
+ * buffer - pointer to buffer with data to send
+ * nwords - number of words (actually bytes)
+ *
+ * Returned Value:
+ * None
+ *
*****************************************************************************/
static void s5j_sflash_sndblock(FAR struct spi_dev_s *spidev, FAR const void *buffer, size_t nwords)
/* it's not word, it's byte */
- s5j_sflash_write(dev, dev->priv.addr, (uint8_t *)buffer, nwords);
+ s5j_sflash_write(dev, dev->priv.addr, (uint8_t *) buffer, nwords);
return;
}
* Recv data from device to upper-level driver
* This function is a part of spi_ops.
*
+ * Input Parameters:
+ * spidev - pointer to spi dev structure
+ * buffer - pointer to buffer for read data
+ * nwords - number of words (actually bytes)
+ *
+ * Returned Value:
+ * None
+ *
*****************************************************************************/
static void s5j_sflash_recvblock(FAR struct spi_dev_s *spidev, FAR void *buffer, size_t nwords)
* Name: up_spiflashinitialize
*
* Description:
- * Initialize the selected SPI port
+ * Initialize SPI port
+ *
+ * Input Parameters:
+ * None
*
* Returned Value:
* Valid SPI device structure reference on success; a NULL on failure
FAR struct spi_dev_s *up_spiflashinitialize(void)
{
- static bool sflashdev_initialized = 0;
- /* Lets have single instance */
- if (sflashdev_initialized == 0) {
+ if (sflashdev == NULL) {
if (!(sflashdev = kmm_malloc(sizeof(struct s5j_sflash_dev_s)))) {
return NULL;
}
+
sflashdev->ops = (FAR const struct spi_ops_s *)&s5j_spi_ops;
+
s5j_sflash_init(sflashdev);
- sflashdev_initialized = 1;
+ sflashdev->priv.priv = NULL;
}
+
return (FAR struct spi_dev_s *)sflashdev;
}
+
+
+/****************************************************************************
+ * Name: up_spiflashinitialized
+ *
+ * Description:
+ * Check is spi slash device is initialized.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * == 1, Initialized
+ * == 0, not initialized
+ *
+ ****************************************************************************/
+
+int up_spiflashinitialized(void)
+{
+ if (sflashdev->priv.priv) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * Name: update_spiflashmtd
+ *
+ * Description:
+ * Updates spiflash private field with mtd pointer value
+ *
+ * Input Parameters:
+ * mtd - pointer to mtd dev structure
+ *
+ * Returned Value:
+ * none
+ *
+ ****************************************************************************/
+
+void update_spiflashmtd(struct mtd_dev_s *mtd)
+{
+ sflashdev->priv.priv = mtd;
+ return;
+}
+
+/****************************************************************************
+ * Name: getspiflashmtd
+ *
+ * Description:
+ * Returns spi flash mtd structure pointer
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * mtd dev structure pointer
+ *
+ ****************************************************************************/
+
+struct mtd_dev_s *getspiflashmtd(void)
+{
+ return (struct mtd_dev_s *)sflashdev->priv.priv;
+}
\ No newline at end of file