You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by bt...@apache.org on 2020/12/05 06:41:56 UTC
[incubator-nuttx] branch master updated: Added: MT29F2G Nand Flash
block driver for sam4s-xplained-pro. Fixed: SDIO Interface hanging after
inserted SD Card.
This is an automated email from the ASF dual-hosted git repository.
btashton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 6aba444 Added: MT29F2G Nand Flash block driver for sam4s-xplained-pro. Fixed: SDIO Interface hanging after inserted SD Card.
6aba444 is described below
commit 6aba444359bd0624263d6eae74941f1f6161a10e
Author: yjdwbj <yj...@gmail.com>
AuthorDate: Wed Dec 2 23:03:31 2020 +0800
Added: MT29F2G Nand Flash block driver for sam4s-xplained-pro.
Fixed: SDIO Interface hanging after inserted SD Card.
Disabled the CONFIG_SYSTEMTICK_EXTCLK, using nxsig_usleep instead of usleep
---
arch/arm/src/sam34/Kconfig | 11 +
arch/arm/src/sam34/Make.defs | 4 +
arch/arm/src/sam34/hardware/sam_matrix.h | 8 +-
arch/arm/src/sam34/sam4s_nand.c | 593 +++++++++++++++++++++
arch/arm/src/sam34/sam4s_nand.h | 179 +++++++
boards/arm/sam34/sam4s-xplained-pro/Kconfig | 39 ++
.../configs/{nsh => fs}/defconfig | 24 +-
.../sam34/sam4s-xplained-pro/configs/nsh/defconfig | 8 +-
.../arm/sam34/sam4s-xplained-pro/include/board.h | 16 +
boards/arm/sam34/sam4s-xplained-pro/src/Makefile | 10 +
.../sam4s-xplained-pro/src/sam4s-xplained-pro.h | 42 +-
.../arm/sam34/sam4s-xplained-pro/src/sam_appinit.c | 23 +
.../sam34/sam4s-xplained-pro/src/sam_nandflash.c | 245 +++++++++
boards/arm/sam34/sam4s-xplained-pro/src/sam_spi.c | 195 +++++++
drivers/mmcsd/mmcsd_sdio.c | 5 +-
drivers/mtd/mtd_nand.c | 35 +-
drivers/mtd/mtd_onfi.c | 12 +-
17 files changed, 1399 insertions(+), 50 deletions(-)
diff --git a/arch/arm/src/sam34/Kconfig b/arch/arm/src/sam34/Kconfig
index 8ea5bb9..62144d3 100644
--- a/arch/arm/src/sam34/Kconfig
+++ b/arch/arm/src/sam34/Kconfig
@@ -814,6 +814,17 @@ config SAM34_EXTNANDSIZE
default 0
---help---
Size of the external NAND in bytes.
+ config SAM34_HAVE_NAND
+ bool
+ default n
+
+config SAM34_NAND_DUMP
+ bool "NAND data dump"
+ default n
+ depends on DEBUG_FEATURES && DEBUG_FS
+ ---help---
+ Dump the contents of all data read and written to FLASH. Depends on
+ CONFIG_DEBUG_FEATURES and DEBUG_FS.
endif # SAM34_EXTNAND
diff --git a/arch/arm/src/sam34/Make.defs b/arch/arm/src/sam34/Make.defs
index c131183..c53866a 100644
--- a/arch/arm/src/sam34/Make.defs
+++ b/arch/arm/src/sam34/Make.defs
@@ -149,6 +149,10 @@ ifeq ($(CONFIG_SAM34_HSMCI),y)
CHIP_CSRCS += sam_hsmci.c
endif
+ifeq ($(CONFIG_SAM34_EXTNAND),y)
+CHIP_CSRCS += sam4s_nand.c
+endif
+
ifeq ($(CONFIG_SAM34_SPI0),y)
CHIP_CSRCS += sam_spi.c
else
diff --git a/arch/arm/src/sam34/hardware/sam_matrix.h b/arch/arm/src/sam34/hardware/sam_matrix.h
index 975803b..3ac4e4d 100644
--- a/arch/arm/src/sam34/hardware/sam_matrix.h
+++ b/arch/arm/src/sam34/hardware/sam_matrix.h
@@ -128,7 +128,7 @@
/* MATRIX register addresses ************************************************************/
-#define SAM_MATRIX_MCFG(n)) (SAM_MATRIX_BASE+SAM_MATRIX_MCFG_OFFSET(n))
+#define SAM_MATRIX_MCFG(n) (SAM_MATRIX_BASE+SAM_MATRIX_MCFG_OFFSET(n))
#define SAM_MATRIX_MCFG0 (SAM_MATRIX_BASE+SAM_MATRIX_MCFG0_OFFSET)
#define SAM_MATRIX_MCFG1 (SAM_MATRIX_BASE+SAM_MATRIX_MCFG1_OFFSET)
#define SAM_MATRIX_MCFG2 (SAM_MATRIX_BASE+SAM_MATRIX_MCFG2_OFFSET)
@@ -200,6 +200,7 @@
#define SAM_MATRIX_WPSR (SAM_MATRIX_BASE+SAM_MATRIX_WPSR_OFFSET)
/* MATRIX register bit definitions ******************************************************/
+
/* Master Configuration Registers */
#define MATRIX_MCFG_ULBT_SHIFT (0) /* Bits 0-2: Undefined Length Burst Type */
@@ -309,6 +310,7 @@
/* SMC Chip Select NAND Flash Assignment Register */
#if defined(CONFIG_ARCH_CHIP_SAM4S) || defined(CONFIG_ARCH_CHIP_SAM4E)
+#define MATRIX_CCFG_SMCNFCS_SMC_NFCS(n) (1<<(n)) /* Bit n: SMC NAND Flash Chip Select n Assignment */
# define MATRIX_CCFG_SMCNFCS_SMC_NFCS0 (1 << 0) /* Bit 0: SMC NAND Flash Chip Select 0 Assignment */
# define MATRIX_CCFG_SMCNFCS_SMC_NFCS1 (1 << 1) /* Bit 1: SMC NAND Flash Chip Select 2 Assignment */
# define MATRIX_CCFG_SMCNFCS_SMC_NFCS2 (1 << 2) /* Bit 2: SMC NAND Flash Chip Select 2 Assignment */
@@ -364,8 +366,4 @@
* Public Data
****************************************************************************************/
-/****************************************************************************************
- * Public Functions
- ****************************************************************************************/
-
#endif /* __ARCH_ARM_SRC_SAM34_HARDWARE_SAM_MATRIX_H */
diff --git a/arch/arm/src/sam34/sam4s_nand.c b/arch/arm/src/sam34/sam4s_nand.c
new file mode 100644
index 0000000..6a49f64
--- /dev/null
+++ b/arch/arm/src/sam34/sam4s_nand.c
@@ -0,0 +1,593 @@
+/****************************************************************************
+ * arch/arm/src/sam34/sam4s_nand.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/mtd/nand_config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mtd/nand.h>
+#include <nuttx/mtd/nand_raw.h>
+#include <nuttx/mtd/nand_model.h>
+
+#include <nuttx/irq.h>
+#include <arch/board/board.h>
+#include "hardware/sam4s_pinmap.h"
+#include "arm_arch.h"
+#include "sam4s_nand.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Nand flash chip status codes */
+
+#define STATUS_ERROR (1 << 0)
+#define STATUS_READY (1 << 6)
+
+/* Number of tries for erasing or writing block */
+
+#define NAND_ERASE_NRETRIES 2
+#define NAND_WRITE_NRETRIES 2
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Low-level HSMC Helpers */
+
+#ifdef CONFIG_SAM34_NAND_DUMP
+# define nand_dump(m,b,s) lib_dumpbuffer(m,b,s)
+#else
+# define nand_dump(m,b,s)
+#endif
+
+/* Raw Data Transfer Helpers */
+
+static int nand_write(struct sam_nandcs_s *priv, uint32_t rowaddr,
+ uint32_t coladdr, uint8_t *buffer, uint16_t buflen,
+ uint16_t offset);
+static int nand_read(struct sam_nandcs_s *priv, uint32_t rowaddr,
+ uint32_t coladdr, uint8_t *buffer, uint16_t buflen,
+ uint16_t offset);
+
+/* MTD driver methods */
+
+static int nand_eraseblock(struct nand_raw_s *raw, off_t block);
+static int nand_rawread(struct nand_raw_s *raw, off_t block,
+ unsigned int page, void *data, void *spare);
+static int nand_rawwrite(struct nand_raw_s *raw, off_t block,
+ unsigned int page, const void *data, const void *spare);
+
+/* Initialization */
+
+static void nand_reset(struct sam_nandcs_s *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* These pre-allocated structures hold the state of the MTD driver for NAND
+ * on CS0..3 as configured.
+ */
+
+#ifdef CONFIG_SAM34_NCS0_NAND
+static struct sam_nandcs_s g_cs0nand;
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void nand_reset(struct sam_nandcs_s *priv)
+{
+ WRITE_COMMAND8(&priv->raw, COMMAND_RESET);
+
+ /* The device will be busy for a maximum of 1ms. */
+
+ up_mdelay(1);
+}
+
+/****************************************************************************
+ * Name: nand_wait_ready
+ *
+ * Description:
+ * Waiting for the completion of a page program, erase and random read
+ * completion.
+ *
+ * Input Parameters:
+ * priv Pointer to a sam_nandcs_s instance.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static int nand_wait_ready(struct sam_nandcs_s *priv)
+{
+ uint32_t timeout;
+ uint8_t status;
+ up_udelay(10);
+
+ /* The ready/busy (R/nB) signal of the NAND Flash */
+
+ while (!sam_gpioread(priv->rb));
+ WRITE_COMMAND8(&priv->raw, COMMAND_STATUS);
+
+ /* Issue command */
+
+ timeout = 0;
+ while (timeout < MAX_READ_STATUS_COUNT)
+ {
+ /* Read status byte */
+
+ status = READ_DATA8(&priv->raw);
+
+ /* Check status. If status bit 6 = 1 device is ready */
+
+ if ((status & STATUS_READY) == STATUS_READY)
+ {
+ /* If status bit 0 = 0 the last operation was successful */
+
+ if ((status & STATUS_ERROR) == 0)
+ {
+ return OK;
+ }
+ else
+ {
+ return -EIO;
+ }
+ }
+
+ timeout++;
+ }
+
+ return -ETIMEDOUT;
+}
+
+/****************************************************************************
+ * Name: nand_eraseblock
+ *
+ * Description:
+ * Erases the specified block of the device.
+ *
+ * Input Parameters:
+ * raw - Lower-half, raw NAND FLASH interface
+ * block - Number of the physical block to erase.
+ *
+ * Returned Value:
+ * OK is returned in success; a negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static inline int nand_tryeraseblock(struct sam_nandcs_s *priv, off_t block)
+{
+ uint32_t rowaddr;
+ int ret = OK;
+
+ /* Calculate address used for erase */
+
+ rowaddr = block * nandmodel_pagesperblock(&priv->raw.model);
+
+ WRITE_COMMAND8(&priv->raw, COMMAND_ERASE_1);
+ WRITE_ADDRESS8(&priv->raw, rowaddr); /* 3rd cycle row addr */
+ WRITE_ADDRESS8(&priv->raw, rowaddr >> 8); /* 4th cycle row addr */
+ WRITE_ADDRESS8(&priv->raw, rowaddr >> 16); /* 5st cycle row addr */
+ WRITE_COMMAND8(&priv->raw, COMMAND_ERASE_2);
+
+ ret = nand_wait_ready(priv);
+ if (ret < 0)
+ {
+ ferr("ERROR: Block %d Could not erase: %d\n", block, ret);
+ }
+
+ return ret;
+}
+
+static int nand_eraseblock(struct nand_raw_s *raw, off_t block)
+{
+ struct sam_nandcs_s *priv = (struct sam_nandcs_s *)raw;
+ int retries = NAND_ERASE_NRETRIES;
+ int ret = OK;
+
+ DEBUGASSERT(priv);
+
+ finfo("block=%d\n", (int)block);
+
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Try up to NAND_ERASE_NRETRIES times to erase the FLASH */
+
+ while (retries > 0)
+ {
+ ret = nand_tryeraseblock(priv, block);
+ if (ret == OK)
+ {
+ return OK;
+ }
+
+ retries--;
+ }
+
+ ferr("ERROR: Block %d Failed to erase after %d tries\n",
+ (int)block, NAND_ERASE_NRETRIES);
+
+ return -EAGAIN;
+}
+
+/****************************************************************************
+ * Name: nand_write
+ *
+ * Description:
+ * Write data to NAND using the NAND data address.
+ *
+ * Input Parameters:
+ * priv - Lower-half, private NAND FLASH device state
+ * buffer - Buffer that provides the data for the write
+ * offset - Data offset in bytes
+ *
+ * Returned Value:
+ * OK on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int nand_write(struct sam_nandcs_s *priv, uint32_t rowaddr,
+ uint32_t coladdr, uint8_t *buffer,
+ uint16_t buflen, uint16_t offset)
+{
+ uintptr_t dest;
+ int ret = OK;
+
+ nand_dump("NAND Write", buffer, buflen);
+
+ dest = priv->raw.dataaddr + offset;
+
+ /* Apply the offset to the destination address */
+
+ WRITE_COMMAND8(&priv->raw, COMMAND_WRITE_1);
+ WRITE_ADDRESS8(&priv->raw, coladdr); /* 1st cycle column addr */
+ WRITE_ADDRESS8(&priv->raw, coladdr >> 8); /* 2nt cycle column addr */
+ WRITE_ADDRESS8(&priv->raw, rowaddr); /* 3rd cycle row addr */
+ WRITE_ADDRESS8(&priv->raw, rowaddr >> 8); /* 4th cycle row addr */
+ WRITE_ADDRESS8(&priv->raw, rowaddr >> 16); /* 5st cycle row addr */
+
+ volatile uint8_t *dest8 = (volatile uint8_t *)dest;
+ for (; buflen > 0; buflen--)
+ {
+ *dest8 = *buffer++;
+ }
+
+ WRITE_COMMAND8(&priv->raw, COMMAND_WRITE_2);
+
+ ret = nand_wait_ready(priv);
+
+ return ret;
+}
+
+static int nand_read(struct sam_nandcs_s *priv, uint32_t rowaddr,
+ uint32_t coladdr, uint8_t *buffer,
+ uint16_t buflen, uint16_t offset)
+{
+ volatile uint8_t *src8 = (volatile uint8_t *)priv->raw.dataaddr + offset;
+ uint8_t *dest8 = (uint8_t *)buffer;
+ int remaining;
+ int ret = OK;
+
+ WRITE_COMMAND8(&priv->raw, COMMAND_READ_1);
+ WRITE_ADDRESS8(&priv->raw, coladdr); /* 1st cycle column addr */
+ WRITE_ADDRESS8(&priv->raw, coladdr >> 8); /* 2nt cycle column addr */
+ WRITE_ADDRESS8(&priv->raw, rowaddr); /* 3rd cycle row addr */
+ WRITE_ADDRESS8(&priv->raw, rowaddr >> 8); /* 4th cycle row addr */
+ WRITE_ADDRESS8(&priv->raw, rowaddr >> 16); /* 5st cycle row addr */
+ WRITE_COMMAND8(&priv->raw, COMMAND_READ_2);
+ up_udelay(10);
+ while (!sam_gpioread(priv->rb));
+
+ remaining = buflen;
+ for (; remaining > 0; remaining--)
+ {
+ *dest8++ = *src8;
+ }
+
+ nand_dump("NAND Read", buffer, buflen);
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_rawread
+ *
+ * Description:
+ * Reads the data and/or the spare areas of a page of a NAND FLASH into the
+ * provided buffers. This is a raw read of the flash contents.
+ *
+ * Input Parameters:
+ * raw - Lower-half, raw NAND FLASH interface
+ * block - Number of the block where the page to read resides.
+ * page - Number of the page to read inside the given block.
+ * data - Buffer where the data area will be stored.
+ * spare - Buffer where the spare area will be stored.
+ *
+ * Returned Value:
+ * OK is returned in success; a negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int nand_rawread(struct nand_raw_s *raw, off_t block,
+ unsigned int page, void *data, void *spare)
+{
+ struct sam_nandcs_s *priv = (struct sam_nandcs_s *)raw;
+ uint16_t pagesize;
+ uint16_t sparesize;
+ off_t rowaddr;
+ off_t coladdr;
+ int ret = OK;
+
+ DEBUGASSERT(priv && (data || spare));
+
+ /* Get page and spare sizes */
+
+ pagesize = nandmodel_getpagesize(&priv->raw.model);
+ sparesize = nandmodel_getsparesize(&priv->raw.model);
+
+ /* Calculate actual address of the page */
+
+ rowaddr = block * nandmodel_pagesperblock(&priv->raw.model) + page;
+ coladdr = data ? 0 : pagesize;
+ fwarn("block=%d page=%d rowaddr=%d coladdr %d data=%p spare=%p\n",
+ (int)block, page, rowaddr, coladdr , data, spare);
+ coladdr = (coladdr >> 8) & 0x4 ? coladdr & 0x83f : coladdr;
+ if (data)
+ {
+ ret = nand_read(priv, rowaddr, coladdr, (uint8_t *)data, pagesize, 0);
+ if (ret < 0)
+ {
+ ferr("ERROR: nand_nfcsram_read for data region failed: %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (spare)
+ {
+ uint16_t offset = data ? pagesize : 0;
+ ret = nand_read(priv, rowaddr, coladdr, (uint8_t *)spare, sparesize,
+ offset);
+ if (ret < 0)
+ {
+ ferr("ERROR: nand_nfcsram_read for spare region failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_rawwrite
+ *
+ * Description:
+ * Writes the data and/or the spare area of a page on a NAND FLASH chip.
+ * This is a raw write of the flash contents.
+ *
+ * Input Parameters:
+ * raw - Lower-half, raw NAND FLASH interface
+ * block - Number of the block where the page to write resides.
+ * page - Number of the page to write inside the given block.
+ * data - Buffer containing the data to be writing
+ * spare - Buffer containing the spare data to be written.
+ *
+ * Returned Value:
+ * OK is returned in success; a negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int nand_rawwrite(struct nand_raw_s *raw, off_t block,
+ unsigned int page, const void *data,
+ const void *spare)
+{
+ struct sam_nandcs_s *priv = (struct sam_nandcs_s *)raw;
+ uint16_t pagesize;
+ uint16_t sparesize;
+ off_t rowaddr;
+ int ret = OK;
+
+ DEBUGASSERT(raw);
+ finfo("block=%d page=%d data=%p spare=%p\n",
+ (int)block, page, data, spare);
+
+ /* Get page and spare sizes */
+
+ pagesize = nandmodel_getpagesize(&priv->raw.model);
+ sparesize = nandmodel_getsparesize(&priv->raw.model);
+
+ rowaddr = block * nandmodel_pagesperblock(&priv->raw.model) + page;
+
+ if (data)
+ {
+ ret = nand_write(priv, rowaddr, 0, (uint8_t *)data, pagesize, 0);
+ if (ret < 0)
+ {
+ ferr("ERROR: Failed writing data area: %d\n", ret);
+ }
+ }
+
+ if (spare)
+ {
+ ret = nand_write(priv, rowaddr, 0, (uint8_t *)spare, sparesize,
+ pagesize);
+ if (ret < 0)
+ {
+ ferr("ERROR: Failed writing data spare: %d\n", ret);
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sam_nand_initialize
+ *
+ * Description:
+ * Create and initialize an raw NAND device instance. This driver
+ * implements the RAW NAND interface: No software ECC or sparing is
+ * performed here. Those necessary NAND features are provided by common,
+ * higher level NAND MTD layers found in drivers/mtd.
+ *
+ * Input Parameters:
+ * cs - Chip select number (in the event that multiple NAND devices
+ * are connected on-board).
+ *
+ * Returned Value:
+ * On success a non-NULL pointer to an MTD device structure is returned;
+ * NULL is returned on a failure.
+ *
+ ****************************************************************************/
+
+struct mtd_dev_s *sam_nand_initialize(int cs)
+{
+ struct sam_nandcs_s *priv;
+ struct mtd_dev_s *mtd;
+ uintptr_t cmdaddr;
+ uintptr_t addraddr;
+ uintptr_t dataaddr;
+ uint8_t ecctype;
+ int ret;
+
+ finfo("CS%d\n", cs);
+
+ if (SAM_SMCCS_BASE(cs) == SAM_SMC_CS0_BASE)
+ {
+ /* Refer to the pre-allocated NAND device structure */
+
+ priv = &g_cs0nand;
+
+ /* Set up the NAND addresses. These must be provided in the board.h
+ * header file.
+ */
+
+ cmdaddr = BOARD_NCS0_NAND_CMDADDR;
+ addraddr = BOARD_NCS0_NAND_ADDRADDR;
+ dataaddr = BOARD_NCS0_NAND_DATAADDR;
+
+ /* Pass on the configured ECC type */
+
+ ecctype = SAM34_NCS0_ECCTYPE;
+ }
+ else
+ {
+ ferr("ERROR: CS%d unsupported or invalid\n", cs);
+ return NULL;
+ }
+
+ /* Initialize the device structure */
+
+ memset(priv, 0, sizeof(struct sam_nandcs_s));
+ priv->raw.cmdaddr = cmdaddr;
+ priv->raw.addraddr = addraddr;
+ priv->raw.dataaddr = dataaddr;
+ priv->raw.ecctype = ecctype;
+ priv->raw.eraseblock = nand_eraseblock;
+ priv->raw.rawread = nand_rawread;
+ priv->raw.rawwrite = nand_rawwrite;
+
+ priv->cs = cs;
+ priv->rb = GPIO_SMC_RB;
+
+ /* Initialize the NAND hardware for this CS */
+
+ /**
+ * Note: The initialization is shown for the reference purpose only, and
+ * for other MCUs, refer to the Package and Pinout chapter of the
+ * respective data sheet.
+ *
+ * The I/O pin initialization for the 8-bit NAND is connected to the NCS0:
+ *
+ * To initialize the 8-bit D0-D7 data bus, configure the Port C, PC0 to
+ * PC7 in Peripheral-A mode
+ *
+ * To initialize the NANDOE,configure the Port C,PC9 in Peripheral-A mode
+ *
+ * To initialize the NANDWE,configure the Port C,PC10 in Peripheral-A mode
+ *
+ * To initialize the NANDCLE,configure the Port C,PC17 in Peripheral-A mode
+ *
+ * To initialize the NANDALE,configure the Port C,PC16 in Peripheral-A mode
+ *
+ * To initialize the R/nB, configure any PIO as an input pin with pull-up
+ * enabled
+ *
+ * To initialize the nCE, configure any PIO as an output pin (refer to Tips
+ * and Tricks for the supported nCE connection types)
+ **/
+
+ ret = board_nandflash_config(cs);
+ if (ret < 0)
+ {
+ ferr("ERROR: board_nandflash_config failed for CS%d: %d\n",
+ cs, ret);
+ return NULL;
+ }
+
+ /* Reset the NAND FLASH part */
+
+ nand_reset(priv);
+
+ /* Probe the NAND part. On success, an MTD interface that wraps
+ * our raw NAND interface is returned.
+ **/
+
+ mtd = nand_initialize(&priv->raw);
+ if (!mtd)
+ {
+ ferr("ERROR: CS%d nand_initialize failed %d\n", cs);
+ return NULL;
+ }
+
+ /* Return the MTD wrapper interface as the MTD device */
+
+ return mtd;
+}
diff --git a/arch/arm/src/sam34/sam4s_nand.h b/arch/arm/src/sam34/sam4s_nand.h
new file mode 100644
index 0000000..253a664
--- /dev/null
+++ b/arch/arm/src/sam34/sam4s_nand.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+ * arch/arm/src/sam34/sam4s_nand.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_SAM4S_SAM_NAND_H
+#define __ARCH_ARM_SRC_SAM4S_SAM_NAND_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/mtd/nand_config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <debug.h>
+
+#include <nuttx/mtd/nand_raw.h>
+#include <nuttx/semaphore.h>
+
+#include "arm_arch.h"
+#include "chip.h"
+#include "sam_gpio.h"
+#include "hardware/sam_smc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Only NCS0 can support NAND. The rest is a fantasy */
+
+#if defined(CONFIG_SAM34_EXTNAND)
+ # define CONFIG_SAM34_NCS0_NAND 1
+#else
+ # undef CONFIG_SAM34_NCS0_NAND
+#endif
+
+/* On-Die ECC, Requires Micron Flash to support on-die */
+
+#define SAM34_NCS0_ECCTYPE NANDECC_NONE
+
+#if defined(CONFIG_SAM34_NCS0_NAND)
+# if defined(CONFIG_SAM34_NCS0_ECCNONE) ||\
+ defined(CONFIG_MTD_NAND_EMBEDDEDECC)
+# define SAM34_NCS0_ECCTYPE NANDECC_NONE
+# elif defined(CONFIG_MTD_NAND_SWECC)
+# define SAM34_NCS0_ECCTYPE NANDECC_SWECC
+# endif
+#endif /* CONFIG_SAM34_NCS0_NAND */
+
+/* Count the number of banks that configured for NAND with PMECC support
+ * enabled.
+ */
+
+#ifdef CONFIG_SAM34_NCS0_NAND
+# define CONFIG_SAM34_HAVE_NAND 1
+# define NAND_HAVE_NCS0 1
+#else
+# define NAND_HAVE_NCS0 0
+#endif
+
+#define MAX_READ_STATUS_COUNT 100000 /* Read status timeout */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* This type represents the state of a raw NAND MTD device on a single chip
+ * select. The struct nand_raw_s must appear at the beginning of the
+ * definition so that you can freely cast between pointers to struct
+ * nand_raw_s and struct sam_nandcs_s.
+ *
+ * NOTE: Currently, only SAM4S CS0 can support NAND. The logic here would
+ * support NAND on any CS, but that capability is not needed.
+ */
+
+struct sam_nandcs_s
+{
+ struct nand_raw_s raw; /* Externally visible part of the driver */
+
+ /* Static configuration */
+
+ uint8_t cs; /* Chip select number (0..3) */
+ gpio_pinset_t rb; /* NAND Ready/Busy detect GPIO pin */
+#endif
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/* NAND global state */
+
+EXTERN struct sam_nand_s g_nand;
+
+/****************************************************************************
+ * Name: sam_nand_initialize
+ *
+ * Description:
+ * Create and initialize an raw NAND device instance. This driver
+ * implements the RAW NAND interface: No software ECC or sparing is
+ * performed here. Those necessary NAND features are provided by common,
+ * higher level NAND MTD layers found in drivers/mtd.
+ *
+ * Input Parameters:
+ * cs - Chip select number (in the event that multiple NAND devices
+ * are connected on-board).
+ *
+ * Returned Value:
+ * On success a non-NULL pointer to an MTD device structure is returned;
+ * NULL is returned on a failure.
+ *
+ ****************************************************************************/
+
+struct mtd_dev_s;
+struct mtd_dev_s *sam_nand_initialize(int cs);
+
+/****************************************************************************
+ * Name: board_nandflash_config
+ *
+ * Description:
+ * If CONFIG_SAM34_BOOT_CS3FLASH is defined, then NAND FLASH support is
+ * enabled. This function provides the board-specific implementation of
+ * the logic to reprogram the SMC to support NAND FLASH on the specified
+ * CS. As a minimum, this board-specific initialization should do the
+ * following:
+ *
+ * 1. Enable clocking to the HSMC
+ * 2. Configure timing for the HSMC CS
+ * 3. Configure NAND PIO pins
+ *
+ * Input Parameters:
+ * cs - Chip select number (in the event that multiple NAND devices
+ * are connected on-board).
+ *
+ * Returned Value:
+ * OK if the HSMC was successfully configured for this CS. A negated
+ * errno value is returned on a failure. This would fail with -ENODEV,
+ * for example, if the board does not support NAND FLASH on the requested
+ * CS.
+ *
+ ****************************************************************************/
+
+int board_nandflash_config(int cs);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
diff --git a/boards/arm/sam34/sam4s-xplained-pro/Kconfig b/boards/arm/sam34/sam4s-xplained-pro/Kconfig
index 86a649d..f8150d2 100644
--- a/boards/arm/sam34/sam4s-xplained-pro/Kconfig
+++ b/boards/arm/sam34/sam4s-xplained-pro/Kconfig
@@ -20,4 +20,43 @@ config SAM4S_XPLAINED_PRO_CPULOAD_TIMER_DEVPATH
default "/dev/tc0"
depends on TIMER && SCHED_CPULOAD && SCHED_CPULOAD_EXTCLK
+config SAM34_NAND_BLOCKMOUNT
+ bool "NAND FLASH auto-mount"
+ default n
+ depends on NSH_ARCHINIT && SAM34_EXTNAND
+ ---help---
+ Automatically initialize the NAND FLASH driver when NSH starts.
+
+choice
+ prompt "NAND FLASH configuration"
+ default SAM34_NAND_NXFFS
+ depends on SAM34_NAND_BLOCKMOUNT
+
+config SAM34_NAND_FTL
+ bool "Create NAND FLASH block driver"
+ depends on MTD && MTD_NAND
+ ---help---
+ Create the MTD driver for the NAND and "wrap" the NAND as a standard
+ block driver that could then, for example, be mounted using FAT or
+ any other file system. Any file system may be used, but there will
+ be no wear-leveling.
+
+ NOTE: This options is not currently recommended. There is not now
+ NuttX file system that can handle the NAND back blocks or performs
+ wear-leveling other than NXFFS and NXFFS does not use a block driver
+ but, rather, operates directly upon the NAND MTD device.
+
+config SAM34_NAND_NXFFS
+ bool "Create NAND FLASH NXFFS file system"
+ depends on MTD && MTD_NAND && FS_NXFFS && NXFFS_NAND
+ ---help---
+ Create the MTD driver for the NAND and mount the NAND device as
+ a wear-leveling, NuttX FLASH file system (NXFFS). The downside of
+ NXFFS is that it can be very slow.
+
+ NOTE: NXFFS is recommended because (1) it can handle the NAND back
+ blocks and (1) performs wear-leveling.
+
+endchoice # NAND FLASH configuration
+
endif
diff --git a/boards/arm/sam34/sam4s-xplained-pro/configs/nsh/defconfig b/boards/arm/sam34/sam4s-xplained-pro/configs/fs/defconfig
similarity index 85%
copy from boards/arm/sam34/sam4s-xplained-pro/configs/nsh/defconfig
copy to boards/arm/sam34/sam4s-xplained-pro/configs/fs/defconfig
index 35c2b36..c997be0 100644
--- a/boards/arm/sam34/sam4s-xplained-pro/configs/nsh/defconfig
+++ b/boards/arm/sam34/sam4s-xplained-pro/configs/fs/defconfig
@@ -6,6 +6,8 @@
# modifications.
#
# CONFIG_ARCH_RAMFUNCS is not set
+# CONFIG_MTD_NAND_BLOCKCHECK is not set
+# CONFIG_MTD_NAND_SWECC is not set
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="sam4s-xplained-pro"
CONFIG_ARCH_BOARD_SAM4S_XPLAINED_PRO=y
@@ -15,12 +17,11 @@ CONFIG_ARCH_CHIP_SAM34=y
CONFIG_ARCH_CHIP_SAM4S=y
CONFIG_ARCH_INTERRUPTSTACK=1024
CONFIG_ARCH_STACKDUMP=y
-CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT=y
CONFIG_ARMV7M_USEBASEPRI=y
CONFIG_ARM_MPU=y
CONFIG_BOARDCTL_USBDEVCTRL=y
CONFIG_BOARD_LATE_INITIALIZE=y
-CONFIG_BOARD_LOOPSPERMSEC=9186
+CONFIG_BOARD_LOOPSPERMSEC=11401
CONFIG_BUILTIN=y
CONFIG_CDCACM=y
CONFIG_CDCACM_BULKIN_REQLEN=250
@@ -29,12 +30,6 @@ CONFIG_CDCACM_TXBUFSIZE=1024
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEV_ZERO=y
-CONFIG_DISABLE_ENVIRON=y
-CONFIG_EXAMPLES_CPUHOG=y
-CONFIG_EXAMPLES_SERIALBLASTER=y
-CONFIG_EXAMPLES_SERIALRX=y
-CONFIG_EXAMPLES_SERIALRX_BUFSIZE=4096
-CONFIG_EXAMPLES_SERIALRX_PRINTHEX=y
CONFIG_FS_FAT=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
@@ -46,6 +41,14 @@ CONFIG_LIBC_STRERROR=y
CONFIG_LIBC_STRERROR_SHORT=y
CONFIG_MAX_TASKS=16
CONFIG_MMCSD_SDIO=y
+CONFIG_MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_EMBEDDEDECC=y
+CONFIG_MTD_NAND_MAXNUMBLOCKS=2048
+CONFIG_MTD_NAND_MAXNUMPAGESPERBLOCK=64
+CONFIG_MTD_NAND_MAXPAGEDATASIZE=2048
+CONFIG_MTD_NAND_MAXPAGESPARESIZE=64
+CONFIG_MTD_NAND_MAXSPAREECCBYTES=64
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_DISABLE_IFCONFIG=y
@@ -71,6 +74,7 @@ CONFIG_SAM34_EXTNANDSIZE=268435456
CONFIG_SAM34_GPIOC_IRQ=y
CONFIG_SAM34_GPIO_IRQ=y
CONFIG_SAM34_HSMCI=y
+CONFIG_SAM34_NAND_BLOCKMOUNT=y
CONFIG_SAM34_PDCA=y
CONFIG_SAM34_RTC=y
CONFIG_SAM34_RTT=y
@@ -81,15 +85,11 @@ CONFIG_SAM34_UART1=y
CONFIG_SAM34_UDP=y
CONFIG_SAM34_USART1=y
CONFIG_SAM34_WDT=y
-CONFIG_SCHED_CPULOAD=y
-CONFIG_SCHED_CPULOAD_EXTCLK=y
-CONFIG_SCHED_CPULOAD_TICKSPERSEC=222
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SDCLONE_DISABLE=y
CONFIG_SDIO_BLOCKSETUP=y
CONFIG_STDIO_BUFFER_SIZE=256
-CONFIG_SYSTEMTICK_EXTCLK=y
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=15
CONFIG_UART1_SERIAL_CONSOLE=y
diff --git a/boards/arm/sam34/sam4s-xplained-pro/configs/nsh/defconfig b/boards/arm/sam34/sam4s-xplained-pro/configs/nsh/defconfig
index 35c2b36..4e15807 100644
--- a/boards/arm/sam34/sam4s-xplained-pro/configs/nsh/defconfig
+++ b/boards/arm/sam34/sam4s-xplained-pro/configs/nsh/defconfig
@@ -15,12 +15,11 @@ CONFIG_ARCH_CHIP_SAM34=y
CONFIG_ARCH_CHIP_SAM4S=y
CONFIG_ARCH_INTERRUPTSTACK=1024
CONFIG_ARCH_STACKDUMP=y
-CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT=y
CONFIG_ARMV7M_USEBASEPRI=y
CONFIG_ARM_MPU=y
CONFIG_BOARDCTL_USBDEVCTRL=y
CONFIG_BOARD_LATE_INITIALIZE=y
-CONFIG_BOARD_LOOPSPERMSEC=9186
+CONFIG_BOARD_LOOPSPERMSEC=11401
CONFIG_BUILTIN=y
CONFIG_CDCACM=y
CONFIG_CDCACM_BULKIN_REQLEN=250
@@ -29,7 +28,6 @@ CONFIG_CDCACM_TXBUFSIZE=1024
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEV_ZERO=y
-CONFIG_DISABLE_ENVIRON=y
CONFIG_EXAMPLES_CPUHOG=y
CONFIG_EXAMPLES_SERIALBLASTER=y
CONFIG_EXAMPLES_SERIALRX=y
@@ -81,15 +79,11 @@ CONFIG_SAM34_UART1=y
CONFIG_SAM34_UDP=y
CONFIG_SAM34_USART1=y
CONFIG_SAM34_WDT=y
-CONFIG_SCHED_CPULOAD=y
-CONFIG_SCHED_CPULOAD_EXTCLK=y
-CONFIG_SCHED_CPULOAD_TICKSPERSEC=222
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SDCLONE_DISABLE=y
CONFIG_SDIO_BLOCKSETUP=y
CONFIG_STDIO_BUFFER_SIZE=256
-CONFIG_SYSTEMTICK_EXTCLK=y
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=15
CONFIG_UART1_SERIAL_CONSOLE=y
diff --git a/boards/arm/sam34/sam4s-xplained-pro/include/board.h b/boards/arm/sam34/sam4s-xplained-pro/include/board.h
index d98c2e5..cf873e6 100644
--- a/boards/arm/sam34/sam4s-xplained-pro/include/board.h
+++ b/boards/arm/sam34/sam4s-xplained-pro/include/board.h
@@ -261,4 +261,20 @@
#define BUTTON_SW0_BIT (1 << BUTTON_SW0)
+/* NAND *********************************************************************/
+
+#define GPIO_SMC_RB (GPIO_INPUT | GPIO_SMC_NWAIT)
+
+/* Address for transferring command bytes to the nandflash, CLE A22 */
+
+#define BOARD_NCS0_NAND_CMDADDR 0x60400000
+
+/* Address for transferring address bytes to the nandflash, ALE A21 */
+
+#define BOARD_NCS0_NAND_ADDRADDR 0x60200000
+
+/* Address for transferring data bytes to the nandflash. */
+
+#define BOARD_NCS0_NAND_DATAADDR 0x60000000
+
#endif /* __BOARDS_ARM_SAM34_SAM4S_XPLAINED_PRO_INCLUDE_BOARD_H */
diff --git a/boards/arm/sam34/sam4s-xplained-pro/src/Makefile b/boards/arm/sam34/sam4s-xplained-pro/src/Makefile
index f2830ee..c31353c 100644
--- a/boards/arm/sam34/sam4s-xplained-pro/src/Makefile
+++ b/boards/arm/sam34/sam4s-xplained-pro/src/Makefile
@@ -37,10 +37,20 @@ include $(TOPDIR)/Make.defs
CSRCS = sam_boot.c
+ifeq ($(CONFIG_MMCSD_SPI),y)
+CSRCS += sam_spi.c
+endif
+
ifeq ($(CONFIG_LIB_BOARDCTL),y)
CSRCS += sam_appinit.c
endif
+ifeq ($(CONFIG_SAM34_EXTNAND),y)
+ifeq ($(CONFIG_MTD_NAND),y)
+CSRCS += sam_nandflash.c
+endif
+endif
+
ifeq ($(CONFIG_SAM34_HSMCI),y)
CSRCS += sam_hsmci.c
endif
diff --git a/boards/arm/sam34/sam4s-xplained-pro/src/sam4s-xplained-pro.h b/boards/arm/sam34/sam4s-xplained-pro/src/sam4s-xplained-pro.h
index a4895d1..0437d54 100644
--- a/boards/arm/sam34/sam4s-xplained-pro/src/sam4s-xplained-pro.h
+++ b/boards/arm/sam34/sam4s-xplained-pro/src/sam4s-xplained-pro.h
@@ -60,8 +60,16 @@
#define HAVE_HSMCI 1
#define HAVE_PROC 1
#define HAVE_USBDEV 1
+
+#if defined(CONFIG_MTD_NAND) && defined(CONFIG_SAM34_EXTNAND)
+#define HAVE_NAND 1
+#endif
#undef HAVE_USBMONITOR
+#if defined(CONFIG_MMCSD_SPI)
+# define HAVE_MMCSD_SPI 1
+#endif
+
/* HSMCI */
/* Can't support MMC/SD if the card interface is not enabled */
@@ -93,6 +101,16 @@
# undef HAVE_HSMCI
#endif
+/* MMC/SD minor numbers */
+
+#ifndef CONFIG_NSH_MMCSDMINOR
+# define CONFIG_NSH_MMCSDMINOR 0
+#endif
+
+#ifndef CONFIG_NSH_MMCSDSLOTNO
+# define CONFIG_NSH_MMCSDSLOTNO 0
+#endif
+
/* USB Device */
/* CONFIG_SAM34_UDP and CONFIG_USBDEV must be defined, or there is no USB
@@ -173,11 +191,24 @@
* Public data
****************************************************************************/
-#ifndef __ASSEMBLY__
+/* SPI0 */
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
+#ifdef HAVE_MMCSD_SPI
+#define GPIO_SPISD_NPCS0 (GPIO_OUTPUT | GPIO_CFG_PULLUP | GPIO_OUTPUT_SET | \
+ GPIO_PORT_PIOA | GPIO_PIN11)
+#define SPISD_PORT SPI0_CS0
+
+#define GPIO_SPI_CD (GPIO_INPUT | GPIO_CFG_PULLUP | GPIO_PORT_PIOC | GPIO_PIN19)
+#define SD_SPI_IRQ SAM_IRQ_PC19
+#endif /* HAVE_MMCSD_SPI */
+
+/* NAND */
+
+#ifdef HAVE_NAND
+# define NAND_MINOR 0
+# define SAM_SMC_CS0 0 /* GPIO_SMC_NCS0 connect SAM_SMC_CS0_BASE */
+int sam_nand_automount(int minor);
+#endif /* HAVE_NAND */
/****************************************************************************
* Name: sam_hsmci_initialize
@@ -193,6 +224,8 @@ int sam_hsmci_initialize(void);
# define sam_hsmci_initialize()
#endif
+int sam_sdinitialize(int port, int minor);
+
/****************************************************************************
* Name: sam_cardinserted
*
@@ -235,5 +268,4 @@ bool sam_writeprotected(int slotno);
int sam_watchdog_initialize(void);
-#endif /* __ASSEMBLY__ */
#endif /* __BOARDS_ARM_SAM34_SAM4S_XPLAINED_SRC_SAM4S_XPLAINED_H */
diff --git a/boards/arm/sam34/sam4s-xplained-pro/src/sam_appinit.c b/boards/arm/sam34/sam4s-xplained-pro/src/sam_appinit.c
index 6253472..031590c 100644
--- a/boards/arm/sam34/sam4s-xplained-pro/src/sam_appinit.c
+++ b/boards/arm/sam34/sam4s-xplained-pro/src/sam_appinit.c
@@ -114,6 +114,17 @@ int board_app_initialize(uintptr_t arg)
}
#endif
+#ifdef HAVE_NAND
+ ret = sam_nand_automount(SAM_SMC_CS0);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR,
+ "ERROR: Failed to initialize the NAND: %d (%d)\n",
+ ret, errno);
+ return ret;
+ }
+#endif
+
#ifdef HAVE_HSMCI
/* Initialize the HSMCI driver */
@@ -157,6 +168,18 @@ int board_app_initialize(uintptr_t arg)
}
#endif
+ /* SPI */
+
+#ifdef HAVE_MMCSD_SPI
+ ret = sam_sdinitialize(0, 0);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: Failed to initialize MMC/SD slot: %d\n",
+ ret);
+ return ret;
+ }
+#endif
+
#ifdef HAVE_USBMONITOR
/* Start the USB Monitor */
diff --git a/boards/arm/sam34/sam4s-xplained-pro/src/sam_nandflash.c b/boards/arm/sam34/sam4s-xplained-pro/src/sam_nandflash.c
new file mode 100644
index 0000000..0374369
--- /dev/null
+++ b/boards/arm/sam34/sam4s-xplained-pro/src/sam_nandflash.c
@@ -0,0 +1,245 @@
+/****************************************************************************
+ * boards/arm/sam34/sam4s-xplained-pro/src/sam_nandflash.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/mount.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/fs/nxffs.h>
+#include <arch/board/board.h>
+
+#include "arm_arch.h"
+#include "sam_periphclks.h"
+#include "sam4s_nand.h"
+#include "hardware/sam_smc.h"
+#include "hardware/sam4s_pinmap.h"
+#include "hardware/sam_matrix.h"
+
+#include "sam4s-xplained-pro.h"
+
+#ifdef HAVE_NAND
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+static const gpio_pinset_t g_nandpins[] =
+{
+ GPIO_SMC_NCS0, GPIO_SMC_NANDALE, GPIO_SMC_NANDCLE,
+ GPIO_SMC_NANDOE, GPIO_SMC_NANDWE, GPIO_SMC_RB,
+
+ GPIO_SMC_D0, GPIO_SMC_D1, GPIO_SMC_D2, GPIO_SMC_D3,
+ GPIO_SMC_D4, GPIO_SMC_D5, GPIO_SMC_D6, GPIO_SMC_D7
+};
+
+#define NAND_NPINS (sizeof(g_nandpins) / sizeof(gpio_pinset_t))
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_nandflash_config
+ *
+ * Description:
+ * If CONFIG_SAM34_EXTNAND is defined, then NAND FLASH support is
+ * enabled. This function provides the board-specific implementation of
+ * the logic to reprogram the SMC to support NAND FLASH on the specified
+ * CS.
+ *
+ * Input Parameters:
+ * cs - Chip select number (in the event that multiple NAND devices
+ * are connected on-board).
+ *
+ * Returned Value:
+ * OK if the HSMC was successfully configured for this CS. A negated
+ * errno value is returned on a failure. This would fail with -ENODEV,
+ * for example, if the board does not support NAND FLASH on the requested
+ * CS.
+ *
+ ****************************************************************************/
+
+int board_nandflash_config(int cs)
+{
+ /* The Embest and Ronetix CM boards and one Hynix NAND HY27UF(08/16)2G2B
+ * Series NAND (MT29F2G08ABAEAWP).
+ * This part has a capacity of 256Mx8bit () with spare 8Mx8 bit capacity.
+ * The device contains 2048 blocks, composed by 64 x 2112 byte pages.
+ * The effective size is approximately 256MiB.
+ *
+ * NAND is available on NCS0.
+ */
+
+ int i;
+
+ /* Configure GPIO pins (leaving SRAM in the disabled state) */
+
+ for (i = 0; i < NAND_NPINS; i++)
+ {
+ sam_configgpio(g_nandpins[i]);
+ }
+
+ /* SMC NAND Flash Chip Select Configuration Register */
+
+ putreg32(MATRIX_CCFG_SMCNFCS_SMC_NFCS(cs), SAM_MATRIX_CCFG_SMCNFCS);
+
+ /* below from sam4s-xplained */
+
+ sam_smc_enableclk();
+
+ /* Configure SMC setup timing */
+
+ putreg32(SMCCS_SETUP_NWESETUP(3) | SMCCS_SETUP_NCSWRSETUP(1) |
+ SMCCS_SETUP_NRDSETUP(2) | SMCCS_SETUP_NCSRDSETUP(1),
+ SAM_SMCCS_SETUP(cs));
+
+ /* Configure the SMC pulse timing */
+
+ putreg32(SMCCS_PULSE_NWEPULSE(5) | SMCCS_PULSE_NCSWRPULSE(5) |
+ SMCCS_PULSE_NRDPULSE(5) | SMCCS_PULSE_NCSRDPULSE(5),
+ SAM_SMCCS_PULSE(cs));
+
+ /* Configure the SMC cycle timing */
+
+ /**
+ * Select 0. Chip Select 0 has been programmed with:
+ * NRD_HOLD = 4; READ_MODE = 1 (NRD controlled)
+ * NWE_SETUP = 3; WRITE_MODE = 1 (NWE controlled)
+ * TDF_CYCLES = 6; TDF_MODE = 1 (optimization enabled).
+ */
+
+ putreg32(SMCCS_CYCLE_NWECYCLE(12) | SMCCS_CYCLE_NRDCYCLE(11),
+ SAM_SMCCS_CYCLE(cs));
+
+ /* Configure the SMC mode */
+
+ /**
+ *
+ * READ_MODE:
+ * 0: The read operation is controlled by the NCS signal.
+ * 1: The read operation is controlled by the NRD signal.
+ *
+ **/
+
+ putreg32(SMCCS_MODE_TDFCYCLES(6) | SMCCS_MODE_TDFMODE |
+ SMCCS_MODE_WRITEMODE | SMCCS_MODE_READMODE,
+ SAM_SMCCS_MODE(cs));
+
+ /* Configure NAND PIO pins
+ *
+ * NAND Interface NAND DESC
+ *
+ * NCS0 CE - Dedicated pin; no configuration needed
+ * NANDCLE CLE - Dedicated pin; no configuration needed
+ * NANDALE ALE - Dedicated pin; no configuration needed
+ * NANDOE RE - Dedicated pin; no configuration needed
+ * NANDWE WE - Dedicated pin; no configuration needed
+ * NAND_RB RB - PC13
+ * IO_D0-7 IO0-7 - Dedicated pins; no configuration needed
+ */
+
+ sam_configgpio(GPIO_SMC_NANDALE);
+ sam_configgpio(GPIO_SMC_NANDCLE);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: sam_nand_automount
+ *
+ * Description:
+ * Initialize and configure the NAND on CS3
+ *
+ ****************************************************************************/
+
+int sam_nand_automount(int minor)
+{
+ FAR struct mtd_dev_s *mtd;
+ static bool initialized = false;
+
+ /* Have we already initialized? */
+
+ if (!initialized)
+ {
+ /* Create and initialize an NAND MATD device */
+
+ mtd = sam_nand_initialize(SAM_SMC_CS0);
+
+ if (!mtd)
+ {
+ ferr("ERROR: Failed to create the NAND driver on CS%d\n",
+ SAM_SMC_CS0);
+ return -ENODEV;
+ }
+
+#if defined(CONFIG_SAM34_NAND_FTL)
+ /* Use the FTL layer to wrap the MTD driver as a block driver */
+
+ int ret = OK;
+ ret = ftl_initialize(NAND_MINOR, mtd);
+ if (ret < 0)
+ {
+ ferr("ERROR: Failed to initialize the FTL layer: %d\n", ret);
+ return ret;
+ }
+
+#elif defined(CONFIG_SAM34_NAND_NXFFS)
+ /* Initialize to provide NXFFS on the MTD interface */
+
+ int ret = OK;
+ ret = nxffs_initialize(mtd);
+ if (ret < 0)
+ {
+ ferr("ERROR: NXFFS initialization failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Mount the file system at /mnt/nand */
+
+ ret = mount(NULL, "/mnt/nand", "nxffs", 0, NULL);
+ if (ret < 0)
+ {
+ ferr("ERROR: Failed to mount the NXFFS volume: %d\n", errno);
+ return ret;
+ }
+#endif
+
+ /* Now we are initialized */
+
+ initialized = true;
+ }
+
+ return OK;
+}
+
+#endif /* HAVE_NAND */
diff --git a/boards/arm/sam34/sam4s-xplained-pro/src/sam_spi.c b/boards/arm/sam34/sam4s-xplained-pro/src/sam_spi.c
new file mode 100644
index 0000000..73f44c5
--- /dev/null
+++ b/boards/arm/sam34/sam4s-xplained-pro/src/sam_spi.c
@@ -0,0 +1,195 @@
+/****************************************************************************
+ * boards/arm/sam34/sam4s-xplained-pro/src/sam_spi.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/spi/spi.h>
+#include <arch/board/board.h>
+
+#include "arm_arch.h"
+#include "chip.h"
+#include "sam_gpio.h"
+#include "sam_spi.h"
+#include "sam4s-xplained-pro.h"
+
+#if defined(CONFIG_SAM34_SPI0)
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sam_spidev_initialize
+ *
+ * Description:
+ * Called to configure SPI chip select PIO pins for the SAM4S-Xplained-Pro
+ * board.
+ *
+ ****************************************************************************/
+
+void weak_function sam_spidev_initialize(void)
+{
+#ifdef CONFIG_SAM34_SPI0
+ sam_configgpio(GPIO_SPI0_NPCS0);
+#endif
+}
+
+/****************************************************************************
+ * Name: sam_spi[0|1]select, sam_spi[0|1]status, and sam_spi[0|1]cmddata
+ *
+ * Description:
+ * These external functions must be provided by board-specific logic.
+ * They include:
+ *
+ * o sam_spi[0|1]select is a functions tomanage the board-specific chip
+ * selects
+ * o sam_spi[0|1]status and sam_spi[0|1]cmddata:
+ * Implementations of the status and cmddata methods of the SPI interface
+ * defined by struct spi_ops_(see include/nuttx/spi/spi.h).
+ * All other methods including sam_spibus_initialize()) are provided by
+ * common SAM3/4 logic.
+ *
+ * To use this common SPI logic on your board:
+ *
+ * 1. Provide logic in sam_boardinitialize() to configure SPI chip select
+ * pins.
+ * 2. Provide sam_spi[0|1]select() and sam_spi[0|1]status() functions in
+ * your board-specific logic.
+ * These functions will perform chip selection and status operations
+ * using PIOs in the way your board is configured.
+ * 2. If CONFIG_SPI_CMDDATA is defined in the NuttX configuration, provide
+ * sam_spi[0|1]cmddata() functions in your board-specific logic. This
+ * function will perform cmd/data selection operations using PIOs in
+ * the way your board is configured.
+ * 3. Add a call to sam_spibus_initialize() in your low level application
+ * initialization logic
+ * 4. The handle returned by sam_spibus_initialize() may then be used to
+ * bind the SPI driver to higher level logic (e.g., calling
+ * mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ * the SPI MMC/SD driver).
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sam_spi[0|1]select
+ *
+ * Description:
+ * PIO chip select pins may be programmed by the board specific logic in
+ * one of two different ways. First, the pins may be programmed as SPI
+ * peripherals. In that case, the pins are completely controlled by the
+ * SPI driver. This method still needs to be provided, but it may be only
+ * a stub.
+ *
+ * An alternative way to program the PIO chip select pins is as a normal
+ * PIO output. In that case, the automatic control of the CS pins is
+ * bypassed and this function must provide control of the chip select.
+ * NOTE: In this case, the PIO output pin does *not* have to be the
+ * same as the NPCS pin normal associated with the chip select number.
+ *
+ * Input Parameters:
+ * devid - Identifies the (logical) device
+ * selected - TRUE:Select the device, FALSE:De-select the device
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAM34_SPI0
+void sam_spi0select(uint32_t devid, bool selected)
+{
+#ifdef CONFIG_MMCSD_SPI
+ /* The AT25 serial FLASH connects using NPCS0 */
+
+ if (devid == SPIDEV_MMCSD(0))
+ {
+ sam_gpiowrite(GPIO_SPI0_NPCS0, !selected);
+ }
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_spi[0|1]status
+ *
+ * Description:
+ * Return status information associated with the SPI device.
+ *
+ * Input Parameters:
+ * devid - Identifies the (logical) device
+ *
+ * Returned Value:
+ * Bit-encoded SPI status (see include/nuttx/spi/spi.h.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAM34_SPI0
+uint8_t sam_spi0status(FAR struct spi_dev_s *dev, uint32_t devid)
+{
+ return SPI_STATUS_PRESENT;
+}
+#endif
+
+int sam_sdinitialize(int port, int minor)
+{
+ FAR struct spi_dev_s *spi;
+ int ret;
+
+ /* Get the SPI driver instance for the SD chip select */
+
+ finfo("Initializing SERCOM SPI%d\n", port);
+
+ spi = sam_spibus_initialize(port);
+ if (!spi)
+ {
+ ferr("ERROR: Failed to initialize SPI%d\n", port);
+ return -ENODEV;
+ }
+
+ finfo("Successfully initialized SPI%d\n", port);
+
+ /* Bind the SPI device for the chip select to the slot */
+
+ finfo("Binding SPI%d to MMC/SD slot %d\n", port, 0);
+
+ ret = mmcsd_spislotinitialize(minor, 0, spi);
+ if (ret < 0)
+ {
+ ferr("ERROR: Failed to bind SPI%d to MMC/SD slot %d: %d\n",
+ port, 0, ret);
+ return ret;
+ }
+
+ finfo("Successfully bound SPI%d to MMC/SD slot %d\n",
+ port, 0);
+
+ return OK;
+}
+
+#endif /* CONFIG_SAM34_SPI0 */
diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c
index 600144c..dce104b 100644
--- a/drivers/mmcsd/mmcsd_sdio.c
+++ b/drivers/mmcsd/mmcsd_sdio.c
@@ -42,6 +42,7 @@
#include <errno.h>
#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/clock.h>
@@ -2645,7 +2646,7 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv)
priv->widebus = true;
SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_4BIT);
- usleep(MMCSD_CLK_DELAY);
+ nxsig_usleep(MMCSD_CLK_DELAY);
return OK;
}
@@ -2777,7 +2778,7 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
/* Select high speed MMC clocking (which may depend on the DSR setting) */
SDIO_CLOCK(priv->dev, CLOCK_MMC_TRANSFER);
- usleep(MMCSD_CLK_DELAY);
+ nxsig_usleep(MMCSD_CLK_DELAY);
return OK;
}
diff --git a/drivers/mtd/mtd_nand.c b/drivers/mtd/mtd_nand.c
index 01d87b1..008420d 100644
--- a/drivers/mtd/mtd_nand.c
+++ b/drivers/mtd/mtd_nand.c
@@ -66,6 +66,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+
/* Success Values returned by the nand_checkblock function */
#define GOODBLOCK 254
@@ -82,6 +83,7 @@
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
+
/* NAND locking */
static int nand_lock(FAR struct nand_dev_s *nand);
@@ -94,7 +96,6 @@ static int nand_checkblock(FAR struct nand_dev_s *nand, off_t block);
static int nand_devscan(FAR struct nand_dev_s *nand);
#else
# define nand_checkblock(n,b) (GOODBLOCK)
-# define nand_devscan(n) (0)
#endif
/* Misc. NAND helpers */
@@ -282,6 +283,7 @@ static int nand_devscan(FAR struct nand_dev_s *nand)
finfo("Good blocks: %u - %u\n", good, good + ngood);
ngood = 0;
}
+
#endif
if (ret == BADBLOCK)
{
@@ -296,12 +298,12 @@ static int nand_devscan(FAR struct nand_dev_s *nand)
#if defined(CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS)
else
{
- if (ngood == 0)
- {
- good = block;
- }
+ if (ngood == 0)
+ {
+ good = block;
+ }
- ngood++;
+ ngood++;
}
#endif
}
@@ -381,6 +383,7 @@ static int nand_eraseblock(FAR struct nand_dev_s *nand, off_t block,
int ret;
/* finfo("Block %d\n", block); */
+
DEBUGASSERT(nand && nand->raw);
#ifdef CONFIG_MTD_NAND_BLOCKCHECK
@@ -455,7 +458,7 @@ static int nand_readpage(FAR struct nand_dev_s *nand, off_t block,
{
ferr("ERROR: Block is BAD\n");
return -EAGAIN;
- }
+ }
#endif
#ifdef CONFIG_MTD_NAND_SWECC
@@ -787,8 +790,8 @@ static int nand_ioctl(struct mtd_dev_s *dev, int cmd, unsigned long arg)
struct mtd_geometry_s *geo = (struct mtd_geometry_s *)arg;
if (geo)
{
- /* Populate the geometry structure with information needed to know
- * the capacity and how to access the device. Returns:
+ /* Populate the geometry structure with information needed to
+ * know the capacity and how to access the device. Returns:
*
* blocksize Size of one read/write block in bytes
* erasesize Size of one erase block in bytes
@@ -880,7 +883,7 @@ FAR struct mtd_dev_s *nand_initialize(FAR struct nand_raw_s *raw)
chipid = nand_chipid(raw);
if (nandmodel_find(g_nandmodels, NAND_NMODELS, chipid,
&raw->model))
- {
+ {
ferr("ERROR: Could not determine NAND model\n");
return NULL;
}
@@ -895,7 +898,8 @@ FAR struct mtd_dev_s *nand_initialize(FAR struct nand_raw_s *raw)
/* Construct the NAND model structure */
model->devid = onfi.manufacturer;
- model->options = onfi.buswidth ? NANDMODEL_DATAWIDTH16 : NANDMODEL_DATAWIDTH8;
+ model->options = onfi.buswidth ? NANDMODEL_DATAWIDTH16 :
+ NANDMODEL_DATAWIDTH8;
model->pagesize = onfi.pagesize;
model->sparesize = onfi.sparesize;
@@ -933,7 +937,8 @@ FAR struct mtd_dev_s *nand_initialize(FAR struct nand_raw_s *raw)
/* Disable any internal, embedded ECC function */
- onfi_embeddedecc(&onfi, cmdaddr, addraddr, dataaddr, false);
+ onfi_embeddedecc(&onfi, raw->cmdaddr, raw->addraddr, raw->dataaddr,
+ true);
}
/* Allocate an NAND MTD device structure */
@@ -955,9 +960,13 @@ FAR struct mtd_dev_s *nand_initialize(FAR struct nand_raw_s *raw)
nxsem_init(&nand->exclsem, 0, 1);
- /* Scan the device for bad blocks */
+#if defined(CONFIG_MTD_NAND_BLOCKCHECK) && defined(CONFIG_DEBUG_INFO) && \
+ defined(CONFIG_DEBUG_FS)
+
+ /* Scan the device for bad blocks */
nand_devscan(nand);
+#endif
/* Return the implementation-specific state structure as the MTD device */
diff --git a/drivers/mtd/mtd_onfi.c b/drivers/mtd/mtd_onfi.c
index 29efdf4..14bc282 100644
--- a/drivers/mtd/mtd_onfi.c
+++ b/drivers/mtd/mtd_onfi.c
@@ -189,7 +189,7 @@ static int onfi_readstatus(uintptr_t cmdaddr, uintptr_t dataaddr)
****************************************************************************/
#ifdef CONFIG_MTD_NAND_EMBEDDEDECC
-bool onfi_have_embeddedecc(FAR struct onfi_pgparam_s *onfi)
+bool onfi_have_embeddedecc(FAR const struct onfi_pgparam_s *onfi)
{
/* Check if the Nandflash has an embedded ECC controller. Known memories
* with this feature:
@@ -243,8 +243,8 @@ bool onfi_compatible(uintptr_t cmdaddr, uintptr_t addraddr,
parmtab[3] = READ_NAND(dataaddr);
return
- (parmtab[0] == 'O' && parmtab[1] == 'N' &&
- parmtab[2] == 'F' && parmtab[3] == 'I');
+ (parmtab[0] == 'O' && parmtab[1] == 'N' &&
+ parmtab[2] == 'F' && parmtab[3] == 'I');
}
/****************************************************************************
@@ -318,7 +318,7 @@ int onfi_read(uintptr_t cmdaddr, uintptr_t addraddr, uintptr_t dataaddr,
{
ferr("ERROR: Failed to read ONFI parameter table\n");
return -EIO;
- }
+ }
/* JEDEC manufacturer ID */
@@ -398,6 +398,7 @@ bool onfi_embeddedecc(FAR const struct onfi_pgparam_s *onfi,
if (onfi_have_embeddedecc(onfi))
{
/* Yes... enable or disable it */
+
/* Perform common setup */
WRITE_NAND_COMMAND(NAND_CMD_SET_FEATURE, cmdaddr);
@@ -411,7 +412,6 @@ bool onfi_embeddedecc(FAR const struct onfi_pgparam_s *onfi,
WRITE_NAND(0x00, dataaddr);
WRITE_NAND(0x00, dataaddr);
WRITE_NAND(0x00, dataaddr);
- setSmcOpEccType(SMC_ECC_INTERNAL);
}
else
{
@@ -499,7 +499,7 @@ bool onfi_ebidetect(uintptr_t cmdaddr, uintptr_t addraddr,
*/
found = true;
- }
+ }
}
return found;