diff --git a/boards/arm/samv7/samv71-xult/configs/mtd/defconfig b/boards/arm/samv7/samv71-xult/configs/mtd/defconfig new file mode 100644 index 0000000000000..b720b0375ef1c --- /dev/null +++ b/boards/arm/samv7/samv71-xult/configs/mtd/defconfig @@ -0,0 +1,93 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_RAMFUNCS is not set +# CONFIG_MMCSD_MMCSUPPORT is not set +# CONFIG_MMCSD_SPI is not set +# CONFIG_SAMV7_SDRAMHEAP is not set +# CONFIG_SAMV7_UART0 is not set +# CONFIG_SAMV7_UART2 is not set +# CONFIG_SAMV7_UART4 is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="samv71-xult" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_SAMV71_XULT=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="samv7" +CONFIG_ARCH_CHIP_SAMV71=y +CONFIG_ARCH_CHIP_SAMV71Q21=y +CONFIG_ARCH_CHIP_SAMV71Q=y +CONFIG_ARCH_CHIP_SAMV7=y +CONFIG_ARCH_CHIP_SAMV7_MEM_FLASH=0x200000 +CONFIG_ARCH_CHIP_SAMV7_MEM_RAM=0x60000 +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_IRQBUTTONS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_AT24XX_ADDR=0x57 +CONFIG_AT24XX_EXTENDED=y +CONFIG_AT24XX_EXTSIZE=160 +CONFIG_AT24XX_SIZE=2 +CONFIG_BOARD_LOOPSPERMSEC=51262 +CONFIG_BUILTIN=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FS_FAT=y +CONFIG_FS_NXFFS=y +CONFIG_FS_PROCFS=y +CONFIG_FS_SMARTFS=y +CONFIG_I2CTOOL_MAXBUS=0 +CONFIG_I2C_RESET=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LINE_MAX=64 +CONFIG_MMCSD_MULTIBLOCK_LIMIT=1 +CONFIG_MMCSD_SDIO=y +CONFIG_MTD=y +CONFIG_MTD_AT24XX=y +CONFIG_MTD_AT25=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_CONFIG=y +CONFIG_MTD_PARTITION=y +CONFIG_MTD_PARTITION_REGISTER=y +CONFIG_MTD_PROGMEM=y +CONFIG_MTD_S25FL1=y +CONFIG_MTD_SMART=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_LOSMART=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=393216 +CONFIG_RAM_START=0x20400000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SAMV7_GPIOA_IRQ=y +CONFIG_SAMV7_GPIOB_IRQ=y +CONFIG_SAMV7_GPIOD_IRQ=y +CONFIG_SAMV7_GPIO_IRQ=y +CONFIG_SAMV7_HSMCI0=y +CONFIG_SAMV7_JTAG_FULL_SW_ENABLE=y +CONFIG_SAMV7_QSPI=y +CONFIG_SAMV7_QSPI_DMA=y +CONFIG_SAMV7_SDRAMC=y +CONFIG_SAMV7_SDRAMSIZE=2097152 +CONFIG_SAMV7_TWIHS0=y +CONFIG_SAMV7_TWIHS0_GLITCH_FILTER=0 +CONFIG_SAMV7_USART1=y +CONFIG_SAMV7_XDMAC=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDIO_BLOCKSETUP=y +CONFIG_START_DAY=10 +CONFIG_START_MONTH=3 +CONFIG_START_YEAR=2014 +CONFIG_SYSTEM_I2CTOOL=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_RAMTEST=y +CONFIG_USART1_SERIAL_CONSOLE=y diff --git a/boards/arm/samv7/samv71-xult/src/Make.defs b/boards/arm/samv7/samv71-xult/src/Make.defs index 15df7aea06883..6d638847f02e9 100644 --- a/boards/arm/samv7/samv71-xult/src/Make.defs +++ b/boards/arm/samv7/samv71-xult/src/Make.defs @@ -105,6 +105,10 @@ ifeq ($(CONFIG_LCD_ST7789),y) CSRCS += sam_st7789.c endif +ifeq ($(CONFIG_MTD_S25FL1),y) +CSRCS += sam_s25fl1.c +endif + .PHONY = context distclean $(SCRIPTOUT): $(LDSCRIPT_TEMPLATE) $(CONFIGFILE) diff --git a/boards/arm/samv7/samv71-xult/src/sam_bringup.c b/boards/arm/samv7/samv71-xult/src/sam_bringup.c index 06e32bc08895b..e9b210236ba41 100644 --- a/boards/arm/samv7/samv71-xult/src/sam_bringup.c +++ b/boards/arm/samv7/samv71-xult/src/sam_bringup.c @@ -50,15 +50,6 @@ #include "sam_twihs.h" #include "samv71-xult.h" -#if defined(HAVE_S25FL1) || defined(HAVE_PROGMEM_CHARDEV) -# include -#endif - -#ifdef HAVE_S25FL1 -# include -# include "sam_qspi.h" -#endif - #ifdef HAVE_LED_DRIVER # include #endif @@ -208,20 +199,8 @@ static void sam_i2ctool(void) int sam_bringup(void) { -#ifdef HAVE_S25FL1 - struct qspi_dev_s *qspi; -#endif -#if defined(HAVE_S25FL1) - struct mtd_dev_s *mtd; -#endif #if defined(HAVE_RTC_DSXXXX) || defined(HAVE_RTC_PCF85263) struct i2c_master_s *i2c; -#endif -#if defined(HAVE_S25FL1_CHARDEV) -#if defined(CONFIG_BCH) - char blockdev[18]; - char chardev[12]; -#endif /* defined(CONFIG_BCH) */ #endif int ret; @@ -409,82 +388,11 @@ int sam_bringup(void) #endif #ifdef HAVE_S25FL1 - /* Create an instance of the SAMV71 QSPI device driver */ - - qspi = sam_qspi_initialize(0); - if (!qspi) - { - syslog(LOG_ERR, "ERROR: sam_qspi_initialize failed\n"); - } - else + ret = sam_s25fl1_init(); + if (ret < 0) { - /* Use the QSPI device instance to initialize the - * S25FL1 device. - */ - - mtd = s25fl1_initialize(qspi, true); - if (!mtd) - { - syslog(LOG_ERR, "ERROR: s25fl1_initialize failed\n"); - } - -#ifdef HAVE_S25FL1_SMARTFS - /* Configure the device with no partition support */ - - ret = smart_initialize(S25FL1_SMART_MINOR, mtd, NULL); - if (ret != OK) - { - syslog(LOG_ERR, "ERROR: Failed to initialize SmartFS: %d\n", ret); - } - -#elif defined(HAVE_S25FL1_NXFFS) - /* Initialize to provide NXFFS on the S25FL1 MTD interface */ - - ret = nxffs_initialize(mtd); - if (ret < 0) - { - syslog(LOG_ERR, "ERROR: NXFFS initialization failed: %d\n", ret); - } - - /* Mount the file system at /mnt/s25fl1 */ - - ret = nx_mount(NULL, "/mnt/s25fl1", "nxffs", 0, NULL); - if (ret < 0) - { - syslog(LOG_ERR, "ERROR: Failed to mount the NXFFS volume: %d\n", - ret); - return ret; - } - -#else /* if defined(HAVE_S25FL1_CHARDEV) */ - /* Use the FTL layer to wrap the MTD driver as a block driver */ - - ret = ftl_initialize(S25FL1_MTD_MINOR, mtd); - if (ret < 0) - { - syslog(LOG_ERR, "ERROR: Failed to initialize the FTL layer: %d\n", - ret); - return ret; - } - -#if defined(CONFIG_BCH) - /* Use the minor number to create device paths */ - - snprintf(blockdev, sizeof(blockdev), "/dev/mtdblock%d", - S25FL1_MTD_MINOR); - snprintf(chardev, sizeof(chardev), "/dev/mtd%d", S25FL1_MTD_MINOR); - - /* Now create a character device on the block device */ - - ret = bchdev_register(blockdev, chardev, false); - if (ret < 0) - { - syslog(LOG_ERR, "ERROR: bchdev_register %s failed: %d\n", - chardev, ret); - return ret; - } -#endif /* defined(CONFIG_BCH) */ -#endif + syslog(LOG_ERR, "ERROR: Failed to initialize s25fl flash: %d\n", + ret); } #endif diff --git a/boards/arm/samv7/samv71-xult/src/sam_s25fl1.c b/boards/arm/samv7/samv71-xult/src/sam_s25fl1.c new file mode 100644 index 0000000000000..b3294324515c9 --- /dev/null +++ b/boards/arm/samv7/samv71-xult/src/sam_s25fl1.c @@ -0,0 +1,454 @@ +/**************************************************************************** + * boards/arm/samv7/samv71-xult/src/sam_s25fl1.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sam_qspi.h" +#include "samv71-xult.h" +#include "board_progmem.h" /* For struct mtd_partition_s definition */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define QSPI_PORTNO 0 + +typedef enum + { + MTD_TYPE_BCH, + MTD_TYPE_SMARTFS, + MTD_TYPE_NXFFS, + MTD_TYPE_MTD, + } mtd_types; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct mtd_partition_s g_mtd_partition_table[] = +{ + { + .size = 0x4000, /* 16 KiB */ + .devpath = "/nxffs", + .type = MTD_TYPE_NXFFS, + }, + { + .size = 0x8000, /* 32 KiB */ + .devpath = "/dev/bch", + .type = MTD_TYPE_BCH, + }, + { + .size = 0x8000, /* 32 KiB */ + .devpath = "/dev/mtd", + .type = MTD_TYPE_MTD, + }, +}; + +static const size_t g_mtd_partition_table_size = + nitems(g_mtd_partition_table); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: issmartfs + * + * Description: + * Check a SMART (Sector Mapped Allocation for Really Tiny) Flash file + * system image on the specified block device (must be a SMART device). + * + * Inputs: + * pathname - the full path to a registered block driver + * + * Return: + * Zero (OK) on success; -1 (ERROR) on failure with errno set: + * + * EINVAL - NULL block driver string + * ENOENT - 'pathname' does not refer to anything in the filesystem. + * ENOTBLK - 'pathname' does not refer to a block driver + * EFTYPE - the block driver hasn't been formatted yet + * + ****************************************************************************/ + +#ifdef CONFIG_FS_SMARTFS +static int issmartfs(FAR const char *pathname) +{ + struct smart_format_s fmt; + int fd; + int ret; + + /* Find the inode of the block driver identified by 'source' */ + + fd = open(pathname, O_RDONLY); + if (fd < 0) + { + return ERROR; + } + + /* Get the format information so we know the block have been formatted */ + + ret = ioctl(fd, BIOC_GETFORMAT, (unsigned long)&fmt); + if (ret < 0) + { + close(fd); + return ret; + } + + if (!(fmt.flags & SMART_FMT_ISFORMATTED)) + { + errno = EFTYPE; + ret = ERROR; + } + + close(fd); + return ret; +} + +/**************************************************************************** + * Name: mksmartfs + * + * Description: + * Make a SMART Flash file system image on the specified block device + * + * Inputs: + * pathname - the full path to a registered block driver + * sectorsize - the size of logical sectors on the device from 256-16384. + * Setting this to zero will cause the device to be formatted + * using the default CONFIG_MTD_SMART_SECTOR_SIZE value. + * nrootdirs - Number of root directory entries to create. + * + * Return: + * Zero (OK) on success; -1 (ERROR) on failure with errno set. + * + * Assumptions: + * - The caller must assure that the block driver is not mounted and not in + * use when this function is called. The result of formatting a mounted + * device is indeterminate (but likely not good). + * + ****************************************************************************/ + +static int mksmartfs(FAR const char *pathname, uint16_t sectorsize) +{ + struct smart_format_s fmt; + struct smart_read_write_s request; + uint8_t type; + int fd; + int ret; + + /* Find the inode of the block driver identified by 'pathname' */ + + fd = open(pathname, O_RDWR); + if (fd < 0) + { + ret = -ENOENT; + goto errout; + } + + /* Perform a low-level SMART format */ + + ret = ioctl(fd, BIOC_LLFORMAT, sectorsize << 16); + if (ret != OK) + { + ret = -errno; + goto errout_with_driver; + } + + /* Get the format information so we know how big the sectors are */ + + ret = ioctl(fd, BIOC_GETFORMAT, (unsigned long) &fmt); + if (ret != OK) + { + ret = -errno; + goto errout_with_driver; + } + + /* Now write the filesystem to media. */ + + ret = ioctl(fd, BIOC_ALLOCSECT, SMARTFS_ROOT_DIR_SECTOR); + if (ret != SMARTFS_ROOT_DIR_SECTOR) + { + ret = -EIO; + goto errout_with_driver; + } + + /* Mark this block as a directory entry */ + + type = SMARTFS_SECTOR_TYPE_DIR; + request.offset = 0; + request.count = 1; + request.buffer = &type; + request.logsector = SMARTFS_ROOT_DIR_SECTOR; + + /* Issue a write to the sector, single byte */ + + ret = ioctl(fd, BIOC_WRITESECT, (unsigned long) &request); + if (ret != OK) + { + ret = -EIO; + goto errout_with_driver; + } + +errout_with_driver: + + /* Close the driver */ + + close(fd); + +errout: + + /* Return any reported errors */ + + if (ret < 0) + { + errno = -ret; + return ERROR; + } + + return OK; +} +#endif /* CONFIG_FS_SMARTFS */ + +/**************************************************************************** + * Name: sam_s25fl1_alloc_mtdpart + * + * Description: + * Allocate an MTD partition from FLASH. + * + * Input Parameters: + * mtd - The MTD device to be partitioned + * mtd_offset - MTD Partition offset from the base address in FLASH. + * mtd_size - Size for the MTD partition. + * + * Returned Value: + * MTD partition data pointer on success, NULL on failure. + * + ****************************************************************************/ + +static struct mtd_dev_s +*sam_s25fl1_alloc_mtdpart(struct mtd_dev_s *mtd, + struct mtd_geometry_s *geo, + struct mtd_partition_s + *part) +{ + ASSERT((part->offset + part->size) <= geo->neraseblocks * geo->erasesize); + ASSERT((part->offset % geo->erasesize) == 0); + ASSERT((part->size % geo->erasesize) == 0); + + size_t startblock = part->offset / geo->blocksize; + size_t blocks = part->size / geo->blocksize; + + return mtd_partition(mtd, startblock, blocks); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_s25fl1_init + * + * Description: + * Initialize s25fl1. + * + ****************************************************************************/ + +int sam_s25fl1_init(void) +{ + int ret = OK; +#ifdef CONFIG_FS_SMARTFS + char partref[4]; + char smartfs_path[30]; +#endif + + struct qspi_dev_s *qspi = sam_qspi_initialize(QSPI_PORTNO); + if (!qspi) + { + syslog(LOG_ERR, "ERROR: sam_qspi_initialize failed\n"); + return ERROR; + } + + /* Use the QSPI device instance to initialize the s25fl1 device. */ + + struct mtd_dev_s *mtd = s25fl1_initialize(qspi, true); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: s25fl1_initialize failed\n"); + return ERROR; + } + + /* Get geometry of s25fl1 */ + + struct mtd_geometry_s geometry; + ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)&geometry); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: s25fl1 ioctl failed: %s\n", + strerror(errno)); + return ret; + } + + size_t i; + size_t offset = 0; + for (i = 0; i < g_mtd_partition_table_size; i++) + { + struct mtd_partition_s *part = &g_mtd_partition_table[i]; + part->offset = offset; + if (part->size == 0) + { + part->size = (geometry.neraseblocks * geometry.erasesize) - offset; + } + + part->mtd = sam_s25fl1_alloc_mtdpart(mtd, &geometry, part); + if (!part->mtd) + { + syslog(LOG_ERR, "ERROR: sam_s25fl1_alloc_mtdpart failed\n"); + return ERROR; + } + + /* Use the FTL layer to wrap the MTD driver as a block driver */ + + if (part->type == MTD_TYPE_BCH) + { + ret = ftl_initialize(S25FL1_MTD_MINOR + i, part->mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize FTL layer: %d\n", + ret); + return ret; + } + + /* Now create a character device on the block device */ + +#if defined(CONFIG_BCH) + char blockdev[18]; + snprintf(blockdev, sizeof(blockdev), "/dev/mtdblock%d", + S25FL1_MTD_MINOR + i); + ret = bchdev_register(blockdev, part->devpath, false); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: bchdev_register %s failed: %d\n", + part->devpath, ret); + return ret; + } +#endif /* defined(CONFIG_BCH) */ + } + else if (part->type == MTD_TYPE_SMARTFS) + { +#if defined (CONFIG_FS_SMARTFS) + sprintf(partref, "p%d", i); + ret = smart_initialize(0, part->mtd, partref); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: smart_initialize %s failed: %d\n", + part->devpath, ret); + return ret; + } + + sprintf(smartfs_path, "/dev/smart0%s", partref); + if (issmartfs(smartfs_path) != OK) + { + mksmartfs(smartfs_path, 0); + } + + ret = nx_mount(smartfs_path, part->devpath, "smartfs", 0, + NULL); + if (ret < 0) + { + /* Mount failed. */ + + syslog(LOG_ERR, "ERROR: mount %s failed: %d\n", smartfs_path, + ret); + return ret; + } +#endif + } + else if (part->type == MTD_TYPE_NXFFS) + { +#if defined (HAVE_S25FL1_NXFFS) + /* Initialize to provide NXFFS on the S25FL1 MTD interface */ + + ret = nxffs_initialize(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: NXFFS initialization failed: %d\n", + ret); + } + + /* Mount the file system at /mnt/s25fl1 */ + + ret = nx_mount(NULL, part->devpath, "nxffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount NXFFS volume: %d\n", + ret); + return ret; + } +#endif + } + else if (part->type == MTD_TYPE_MTD) + { +#if defined (HAVE_S25FL1_MTDDEV) + ret = mtd_partition_register(part->mtd, part->devpath, false); + if (ret < 0) + { + syslog(LOG_ERR, "failed to register %d %d\n", ret, errno); + } +#endif + } + else + { + syslog(LOG_ERR, "ERROR: Incorrect device type %d for %s.\n", + part->type, part->devpath); + } + + offset += part->size; + } + + return ret; +} diff --git a/boards/arm/samv7/samv71-xult/src/samv71-xult.h b/boards/arm/samv7/samv71-xult/src/samv71-xult.h index e806afbb1a813..1dce5c4d73a46 100644 --- a/boards/arm/samv7/samv71-xult/src/samv71-xult.h +++ b/boards/arm/samv7/samv71-xult/src/samv71-xult.h @@ -53,6 +53,7 @@ #define HAVE_S25FL1_NXFFS 1 #define HAVE_S25FL1_SMARTFS 1 #define HAVE_S25FL1_CHARDEV 1 +#define HAVE_S25FL1_MTDDEV 1 #define HAVE_PROGMEM_CHARDEV 1 #define HAVE_WM8904 1 #define HAVE_AUDIO_NULL 1 @@ -180,6 +181,7 @@ # undef HAVE_S25FL1_NXFFS # undef HAVE_S25FL1_SMARTFS # undef HAVE_S25FL1_CHARDEV +# undef HAVE_S25FL1_MTDDEV #endif #ifndef CONFIG_SAMV7_QSPI @@ -187,6 +189,7 @@ # undef HAVE_S25FL1_NXFFS # undef HAVE_S25FL1_SMARTFS # undef HAVE_S25FL1_CHARDEV +# undef HAVE_S25FL1_MTDDEV #endif #ifndef CONFIG_FS_NXFFS @@ -197,12 +200,8 @@ # undef HAVE_S25FL1_SMARTFS #endif -#if defined(HAVE_S25FL1_NXFFS) && defined(HAVE_S25FL1_SMARTFS) -# undef HAVE_S25FL1_NXFFS -#endif - -#if defined(HAVE_S25FL1_NXFFS) || defined(HAVE_S25FL1_SMARTFS) -# undef HAVE_S25FL1_CHARDEV +#ifndef CONFIG_MTD_PARTITON_REGISTER +# undef HAVE_S25FL1_MTDDEV #endif /* On-chip Programming Memory */ @@ -733,6 +732,18 @@ int sam_emac0_setmac(void); int sam_at24config(void); #endif +/**************************************************************************** + * Name: sam_s25fl1_init + * + * Description: + * Create an S25F1 NOR flash based MTD configuration device. + * + ****************************************************************************/ + +#ifdef CONFIG_MTD_S25FL1 +int sam_s25fl1_init(void); +#endif + /**************************************************************************** * Name: sam_tsc_setup *