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 <yjd...@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;