ping
On Wed, Mar 2, 2022 at 8:30 PM Alex White <alex.wh...@oarcorp.com> wrote: > > This driver has been tested with Micron NOR Flash via AXI Quad SPI. > --- > .../microblaze_fpga/fs/jffs2_qspi.c | 319 ++++++++++++++++++ > .../microblaze_fpga/include/bsp/jffs2_qspi.h | 56 +++ > .../bsps/microblaze/microblaze_fpga/grp.yml | 6 + > .../bsps/microblaze/microblaze_fpga/obj.yml | 2 + > .../microblaze_fpga/optspibaseaddress.yml | 18 + > .../microblaze/microblaze_fpga/optspiirq.yml | 17 + > 6 files changed, 418 insertions(+) > create mode 100644 bsps/microblaze/microblaze_fpga/fs/jffs2_qspi.c > create mode 100644 bsps/microblaze/microblaze_fpga/include/bsp/jffs2_qspi.h > create mode 100644 > spec/build/bsps/microblaze/microblaze_fpga/optspibaseaddress.yml > create mode 100644 spec/build/bsps/microblaze/microblaze_fpga/optspiirq.yml > > diff --git a/bsps/microblaze/microblaze_fpga/fs/jffs2_qspi.c > b/bsps/microblaze/microblaze_fpga/fs/jffs2_qspi.c > new file mode 100644 > index 0000000000..39328b6b7c > --- /dev/null > +++ b/bsps/microblaze/microblaze_fpga/fs/jffs2_qspi.c > @@ -0,0 +1,319 @@ > +/* SPDX-License-Identifier: BSD-2-Clause */ > + > +/** > + * @file > + * > + * @ingroup RTEMSBSPsMicroblaze > + * > + * @brief MicroBlaze AXI QSPI JFFS2 flash driver implementation > + */ > + > +/* > + * Copyright (C) 2022 On-Line Applications Research Corporation (OAR) > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS > IS" > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > + * POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include <assert.h> > +#include <errno.h> > +#include <string.h> > +#include <fcntl.h> > +#include <sys/types.h> > +#include <sys/stat.h> > + > +#include <bspopts.h> > +#include <dev/spi/xilinx-axi-spi.h> > +#include <linux/spi/spidev.h> > +#include <rtems/jffs2.h> > +#include <rtems/libio.h> > + > +#include <bsp/jffs2_qspi.h> > + > +#define BLOCK_SIZE (64UL * 1024UL) > +#define FLASH_SIZE (32UL * BLOCK_SIZE) > +#define FLASH_PAGE_SIZE 256 > +#define FLASH_NUM_CS 2 > +#define FLASH_DEVICE_ID 0xbb19 /* Type: 0xbb, Capacity: 0x19 */ > +#define BUS_PATH "/dev/spi-0" > +#define FLASH_MOUNT_POINT "/mnt" > + > +#define READ_WRITE_EXTRA_BYTES 4 > +#define WRITE_ENABLE_BYTES 1 > +#define SECTOR_ERASE_BYTES 4 > + > +#define COMMAND_QUAD_WRITE 0x32 > +#define COMMAND_SECTOR_ERASE 0xD8 > +#define COMMAND_QUAD_READ 0x6B > +#define COMMAND_STATUSREG_READ 0x05 > +#define COMMAND_WRITE_ENABLE 0x06 > +#define FLASH_SR_IS_READY_MASK 0x01 > + > +typedef struct { > + rtems_jffs2_flash_control super; > + int fd; > +} flash_control; > + > +static uint8_t ReadBuffer[FLASH_PAGE_SIZE + READ_WRITE_EXTRA_BYTES + 4]; > +static uint8_t WriteBuffer[FLASH_PAGE_SIZE + READ_WRITE_EXTRA_BYTES + 4]; > + > +static flash_control *get_flash_control( rtems_jffs2_flash_control *super ) > +{ > + return (flash_control *) super; > +} > + > +static int flash_wait_for_ready( flash_control *self ) > +{ > + uint8_t rv = 0; > + uint8_t status = 0; > + > + WriteBuffer[0] = COMMAND_STATUSREG_READ; > + > + struct spi_ioc_transfer mesg = { > + .tx_buf = WriteBuffer, > + .rx_buf = ReadBuffer, > + .len = 2, > + .bits_per_word = 8, > + .cs = 0 > + }; > + > + do { > + rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg ); > + if ( rv != 0 ) { > + return -EIO; > + } > + > + status = ReadBuffer[1]; > + } while ( (status & FLASH_SR_IS_READY_MASK) != 0 ); > + > + return 0; > +} > + > +static int flash_write_enable( flash_control *self ) > +{ > + uint8_t rv = 0; > + > + rv = flash_wait_for_ready( self ); > + if ( rv != 0 ) { > + return rv; > + } > + > + WriteBuffer[0] = COMMAND_WRITE_ENABLE; > + > + struct spi_ioc_transfer mesg = { > + .tx_buf = WriteBuffer, > + .len = WRITE_ENABLE_BYTES, > + .bits_per_word = 8, > + .cs = 0 > + }; > + > + rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg ); > + if ( rv != 0 ) { > + return -EIO; > + } > + > + return 0; > +} > + > +static int flash_read( > + rtems_jffs2_flash_control *super, > + uint32_t offset, > + unsigned char *buffer, > + size_t size_of_buffer > +) > +{ > + int rv = 0; > + uint32_t current_offset = offset; > + uint32_t bytes_left = size_of_buffer; > + > + flash_control *self = get_flash_control( super ); > + > + rv = flash_wait_for_ready( self ); > + if ( rv != 0 ) { > + return rv; > + } > + > + WriteBuffer[0] = COMMAND_QUAD_READ; > + > + /* Read in 256-byte chunks */ > + do { > + uint32_t chunk_size = bytes_left > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE : > bytes_left; > + > + struct spi_ioc_transfer mesg = { > + .tx_buf = WriteBuffer, > + .rx_buf = ReadBuffer, > + .len = chunk_size + 8, > + .bits_per_word = 8, > + .cs = 0 > + }; > + > + WriteBuffer[1] = (uint8_t) (current_offset >> 16); > + WriteBuffer[2] = (uint8_t) (current_offset >> 8); > + WriteBuffer[3] = (uint8_t) current_offset; > + > + rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg ); > + if ( rv != 0 ) { > + return -EIO; > + } > + > + memcpy( &buffer[current_offset - offset], &ReadBuffer[8], chunk_size ); > + > + current_offset += chunk_size; > + bytes_left -= chunk_size; > + } while ( bytes_left > 0 ); > + > + return 0; > +} > + > +static int flash_write( > + rtems_jffs2_flash_control *super, > + uint32_t offset, > + const unsigned char *buffer, > + size_t size_of_buffer > +) > +{ > + int rv = 0; > + > + flash_control *self = get_flash_control( super ); > + > + rv = flash_write_enable( self ); > + if ( rv != 0 ) { > + return rv; > + } > + > + rv = flash_wait_for_ready( self ); > + if ( rv != 0 ) { > + return rv; > + } > + > + WriteBuffer[0] = COMMAND_QUAD_WRITE; > + WriteBuffer[1] = (uint8_t) (offset >> 16); > + WriteBuffer[2] = (uint8_t) (offset >> 8); > + WriteBuffer[3] = (uint8_t) offset; > + > + memcpy( &WriteBuffer[4], buffer, size_of_buffer ); > + > + struct spi_ioc_transfer mesg = { > + .tx_buf = WriteBuffer, > + .len = size_of_buffer + 4, > + .bits_per_word = 8, > + .cs = 0 > + }; > + > + rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg ); > + if ( rv != 0 ) { > + return -EIO; > + } > + > + return 0; > +} > + > +static int flash_erase( > + rtems_jffs2_flash_control *super, > + uint32_t offset > +) > +{ > + int rv = 0; > + > + flash_control *self = get_flash_control( super ); > + > + rv = flash_write_enable( self ); > + if ( rv != 0 ) { > + return rv; > + } > + > + rv = flash_wait_for_ready( self ); > + if ( rv != 0 ) { > + return rv; > + } > + > + WriteBuffer[0] = COMMAND_SECTOR_ERASE; > + WriteBuffer[1] = (uint8_t) (offset >> 16); > + WriteBuffer[2] = (uint8_t) (offset >> 8); > + WriteBuffer[3] = (uint8_t) offset; > + > + struct spi_ioc_transfer mesg = { > + .tx_buf = WriteBuffer, > + .len = SECTOR_ERASE_BYTES, > + .bits_per_word = 8, > + .cs = 0 > + }; > + > + rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg ); > + if ( rv != 0 ) { > + return -EIO; > + } > + > + return 0; > +} > + > +static flash_control flash_instance = { > + .super = { > + .block_size = BLOCK_SIZE, > + .flash_size = FLASH_SIZE, > + .read = flash_read, > + .write = flash_write, > + .erase = flash_erase, > + .device_identifier = FLASH_DEVICE_ID > + } > +}; > + > +static rtems_jffs2_mount_data mount_data = { > + .flash_control = &flash_instance.super, > + .compressor_control = NULL > +}; > + > +int microblaze_jffs2_initialize( const char* mount_dir ) > +{ > + int rv = 0; > + int fd = -1; > + > + rv = spi_bus_register_xilinx_axi( > + BUS_PATH, > + BSP_MICROBLAZE_FPGA_SPI_BASE, > + FLASH_PAGE_SIZE, > + FLASH_NUM_CS, > + BSP_MICROBLAZE_FPGA_SPI_IRQ_NUM > + ); > + if ( rv != 0 ) { > + return rv; > + } > + > + fd = open( BUS_PATH, O_RDWR ); > + if ( fd < 0 ) { > + return -1; > + } > + > + flash_instance.fd = fd; > + > + rv = mount_and_make_target_path( > + NULL, > + mount_dir, > + RTEMS_FILESYSTEM_TYPE_JFFS2, > + RTEMS_FILESYSTEM_READ_WRITE, > + &mount_data > + ); > + if ( rv != 0 ) { > + return rv; > + } > + > + return 0; > +} > diff --git a/bsps/microblaze/microblaze_fpga/include/bsp/jffs2_qspi.h > b/bsps/microblaze/microblaze_fpga/include/bsp/jffs2_qspi.h > new file mode 100644 > index 0000000000..9c071c4977 > --- /dev/null > +++ b/bsps/microblaze/microblaze_fpga/include/bsp/jffs2_qspi.h > @@ -0,0 +1,56 @@ > +/* SPDX-License-Identifier: BSD-2-Clause */ > + > +/** > + * @file > + * > + * @ingroup RTEMSBSPsMicroblaze > + * > + * @brief MicroBlaze AXI QSPI JFFS2 flash driver definitions > + */ > + > +/* > + * Copyright (C) 2022 On-Line Applications Research Corporation (OAR) > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS > IS" > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > + * POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifndef LIBBSP_MICROBLAZE_FPGA_JFFS2_QSPI_H > +#define LIBBSP_MICROBLAZE_FPGA_JFFS2_QSPI_H > + > +#ifdef __cplusplus > +extern "C" { > +#endif /* __cplusplus */ > + > +/** > + * @brief Mount jffs2 filesystem. > + * > + * @param[in] mount_dir The directory to mount the filesystem at. > + * > + * @retval 0 Successful operation. Negative number otherwise. > + */ > +int microblaze_jffs2_initialize( const char* mount_dir ); > + > +#ifdef __cplusplus > +} > +#endif /* __cplusplus */ > + > +#endif /* LIBBSP_MICROBLAZE_FPGA_JFFS2_QSPI_H */ > diff --git a/spec/build/bsps/microblaze/microblaze_fpga/grp.yml > b/spec/build/bsps/microblaze/microblaze_fpga/grp.yml > index 11df1802f1..bb9b82c250 100644 > --- a/spec/build/bsps/microblaze/microblaze_fpga/grp.yml > +++ b/spec/build/bsps/microblaze/microblaze_fpga/grp.yml > @@ -35,6 +35,10 @@ links: > uid: optintcbaseaddress > - role: build-dependency > uid: optramlen > +- role: build-dependency > + uid: optspibaseaddress > +- role: build-dependency > + uid: optspiirq > - role: build-dependency > uid: opttimerbaseaddress > - role: build-dependency > @@ -43,6 +47,8 @@ links: > uid: optuartlitebaseaddress > - role: build-dependency > uid: ../../obj > +- role: build-dependency > + uid: ../../objdevspixil > - role: build-dependency > uid: ../../objirq > - role: build-dependency > diff --git a/spec/build/bsps/microblaze/microblaze_fpga/obj.yml > b/spec/build/bsps/microblaze/microblaze_fpga/obj.yml > index 37096cdc84..993ba04004 100644 > --- a/spec/build/bsps/microblaze/microblaze_fpga/obj.yml > +++ b/spec/build/bsps/microblaze/microblaze_fpga/obj.yml > @@ -15,6 +15,7 @@ install: > - destination: ${BSP_INCLUDEDIR}/bsp > source: > - bsps/microblaze/microblaze_fpga/include/bsp/irq.h > + - bsps/microblaze/microblaze_fpga/include/bsp/jffs2_qspi.h > - bsps/microblaze/include/common/xil_types.h > - bsps/microblaze/include/dev/serial/uartlite.h > - bsps/microblaze/include/dev/serial/uartlite_l.h > @@ -24,6 +25,7 @@ source: > - bsps/microblaze/microblaze_fpga/console/console-io.c > - bsps/microblaze/microblaze_fpga/console/debug-io.c > - bsps/microblaze/microblaze_fpga/fdt/bsp_fdt.c > +- bsps/microblaze/microblaze_fpga/fs/jffs2_qspi.c > - bsps/microblaze/microblaze_fpga/irq/irq.c > - bsps/microblaze/microblaze_fpga/start/_debug_sw_break_handler.S > - bsps/microblaze/microblaze_fpga/start/_exception_handler.S > diff --git a/spec/build/bsps/microblaze/microblaze_fpga/optspibaseaddress.yml > b/spec/build/bsps/microblaze/microblaze_fpga/optspibaseaddress.yml > new file mode 100644 > index 0000000000..86907b70ab > --- /dev/null > +++ b/spec/build/bsps/microblaze/microblaze_fpga/optspibaseaddress.yml > @@ -0,0 +1,18 @@ > +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause > +actions: > +- get-integer: null > +- assert-uint32: null > +- env-assign: null > +- format-and-define: null > +build-type: option > +copyrights: > +- Copyright (C) 2022 On-Line Applications Research Corporation (OAR) > +default: 0x44a00000 > +default-by-variant: [] > +description: | > + base address of the AXI Quad SPI > +enabled-by: true > +format: '{:#010x}' > +links: [] > +name: BSP_MICROBLAZE_FPGA_SPI_BASE > +type: build > diff --git a/spec/build/bsps/microblaze/microblaze_fpga/optspiirq.yml > b/spec/build/bsps/microblaze/microblaze_fpga/optspiirq.yml > new file mode 100644 > index 0000000000..7186c6b8e1 > --- /dev/null > +++ b/spec/build/bsps/microblaze/microblaze_fpga/optspiirq.yml > @@ -0,0 +1,17 @@ > +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause > +actions: > +- get-integer: null > +- assert-uint32: null > +- define: null > +build-type: option > +copyrights: > +- Copyright (C) 2022 On-Line Applications Research Corporation (OAR) > +default: 3 > +default-by-variant: [] > +description: | > + IRQ number of the AXI SPI > +enabled-by: true > +format: '{}' > +links: [] > +name: BSP_MICROBLAZE_FPGA_SPI_IRQ_NUM > +type: build > -- > 2.32.0 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel