File indexing completed on 2025-05-11 08:23:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <assert.h>
0037 #include <errno.h>
0038 #include <string.h>
0039 #include <fcntl.h>
0040 #include <sys/types.h>
0041 #include <sys/stat.h>
0042
0043 #include <bspopts.h>
0044 #include <dev/spi/xilinx-axi-spi.h>
0045 #include <linux/spi/spidev.h>
0046 #include <rtems/jffs2.h>
0047 #include <rtems/libio.h>
0048
0049 #include <bsp.h>
0050 #include <bsp/jffs2_qspi.h>
0051
0052 #define BLOCK_SIZE (64UL * 1024UL)
0053 #define FLASH_SIZE (32UL * BLOCK_SIZE)
0054 #define FLASH_PAGE_SIZE 256
0055 #define FLASH_NUM_CS 2
0056 #define FLASH_DEVICE_ID 0xbb19
0057 #define BUS_PATH "/dev/spi-0"
0058 #define FLASH_MOUNT_POINT "/mnt"
0059
0060 #define READ_WRITE_EXTRA_BYTES 4
0061 #define WRITE_ENABLE_BYTES 1
0062 #define SECTOR_ERASE_BYTES 4
0063
0064 #define COMMAND_QUAD_WRITE 0x32
0065 #define COMMAND_SECTOR_ERASE 0xD8
0066 #define COMMAND_QUAD_READ 0x6B
0067 #define COMMAND_STATUSREG_READ 0x05
0068 #define COMMAND_WRITE_ENABLE 0x06
0069 #define FLASH_SR_IS_READY_MASK 0x01
0070
0071 typedef struct {
0072 rtems_jffs2_flash_control super;
0073 int fd;
0074 } flash_control;
0075
0076 static uint8_t ReadBuffer[FLASH_PAGE_SIZE + READ_WRITE_EXTRA_BYTES + 4];
0077 static uint8_t WriteBuffer[FLASH_PAGE_SIZE + READ_WRITE_EXTRA_BYTES + 4];
0078
0079 static flash_control *get_flash_control( rtems_jffs2_flash_control *super )
0080 {
0081 return (flash_control *) super;
0082 }
0083
0084 static int flash_wait_for_ready( flash_control *self )
0085 {
0086 uint8_t rv = 0;
0087 uint8_t status = 0;
0088
0089 WriteBuffer[0] = COMMAND_STATUSREG_READ;
0090
0091 struct spi_ioc_transfer mesg = {
0092 .tx_buf = WriteBuffer,
0093 .rx_buf = ReadBuffer,
0094 .len = 2,
0095 .bits_per_word = 8,
0096 .cs = 0
0097 };
0098
0099 do {
0100 rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg );
0101 if ( rv != 0 ) {
0102 return -EIO;
0103 }
0104
0105 status = ReadBuffer[1];
0106 } while ( (status & FLASH_SR_IS_READY_MASK) != 0 );
0107
0108 return 0;
0109 }
0110
0111 static int flash_write_enable( flash_control *self )
0112 {
0113 uint8_t rv = 0;
0114
0115 rv = flash_wait_for_ready( self );
0116 if ( rv != 0 ) {
0117 return rv;
0118 }
0119
0120 WriteBuffer[0] = COMMAND_WRITE_ENABLE;
0121
0122 struct spi_ioc_transfer mesg = {
0123 .tx_buf = WriteBuffer,
0124 .len = WRITE_ENABLE_BYTES,
0125 .bits_per_word = 8,
0126 .cs = 0
0127 };
0128
0129 rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg );
0130 if ( rv != 0 ) {
0131 return -EIO;
0132 }
0133
0134 return 0;
0135 }
0136
0137 static int flash_read(
0138 rtems_jffs2_flash_control *super,
0139 uint32_t offset,
0140 unsigned char *buffer,
0141 size_t size_of_buffer
0142 )
0143 {
0144 int rv = 0;
0145 uint32_t current_offset = offset;
0146 uint32_t bytes_left = size_of_buffer;
0147
0148 flash_control *self = get_flash_control( super );
0149
0150 rv = flash_wait_for_ready( self );
0151 if ( rv != 0 ) {
0152 return rv;
0153 }
0154
0155 WriteBuffer[0] = COMMAND_QUAD_READ;
0156
0157
0158 do {
0159 uint32_t chunk_size = bytes_left > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE : bytes_left;
0160
0161 struct spi_ioc_transfer mesg = {
0162 .tx_buf = WriteBuffer,
0163 .rx_buf = ReadBuffer,
0164 .len = chunk_size + 8,
0165 .bits_per_word = 8,
0166 .cs = 0
0167 };
0168
0169 WriteBuffer[1] = (uint8_t) (current_offset >> 16);
0170 WriteBuffer[2] = (uint8_t) (current_offset >> 8);
0171 WriteBuffer[3] = (uint8_t) current_offset;
0172
0173 rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg );
0174 if ( rv != 0 ) {
0175 return -EIO;
0176 }
0177
0178 memcpy( &buffer[current_offset - offset], &ReadBuffer[8], chunk_size );
0179
0180 current_offset += chunk_size;
0181 bytes_left -= chunk_size;
0182 } while ( bytes_left > 0 );
0183
0184 return 0;
0185 }
0186
0187 static int flash_write(
0188 rtems_jffs2_flash_control *super,
0189 uint32_t offset,
0190 const unsigned char *buffer,
0191 size_t size_of_buffer
0192 )
0193 {
0194 int rv = 0;
0195
0196 flash_control *self = get_flash_control( super );
0197
0198 rv = flash_write_enable( self );
0199 if ( rv != 0 ) {
0200 return rv;
0201 }
0202
0203 rv = flash_wait_for_ready( self );
0204 if ( rv != 0 ) {
0205 return rv;
0206 }
0207
0208 WriteBuffer[0] = COMMAND_QUAD_WRITE;
0209 WriteBuffer[1] = (uint8_t) (offset >> 16);
0210 WriteBuffer[2] = (uint8_t) (offset >> 8);
0211 WriteBuffer[3] = (uint8_t) offset;
0212
0213 memcpy( &WriteBuffer[4], buffer, size_of_buffer );
0214
0215 struct spi_ioc_transfer mesg = {
0216 .tx_buf = WriteBuffer,
0217 .len = size_of_buffer + 4,
0218 .bits_per_word = 8,
0219 .cs = 0
0220 };
0221
0222 rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg );
0223 if ( rv != 0 ) {
0224 return -EIO;
0225 }
0226
0227 return 0;
0228 }
0229
0230 static int flash_erase(
0231 rtems_jffs2_flash_control *super,
0232 uint32_t offset
0233 )
0234 {
0235 int rv = 0;
0236
0237 flash_control *self = get_flash_control( super );
0238
0239 rv = flash_write_enable( self );
0240 if ( rv != 0 ) {
0241 return rv;
0242 }
0243
0244 rv = flash_wait_for_ready( self );
0245 if ( rv != 0 ) {
0246 return rv;
0247 }
0248
0249 WriteBuffer[0] = COMMAND_SECTOR_ERASE;
0250 WriteBuffer[1] = (uint8_t) (offset >> 16);
0251 WriteBuffer[2] = (uint8_t) (offset >> 8);
0252 WriteBuffer[3] = (uint8_t) offset;
0253
0254 struct spi_ioc_transfer mesg = {
0255 .tx_buf = WriteBuffer,
0256 .len = SECTOR_ERASE_BYTES,
0257 .bits_per_word = 8,
0258 .cs = 0
0259 };
0260
0261 rv = ioctl( self->fd, SPI_IOC_MESSAGE( 1 ), &mesg );
0262 if ( rv != 0 ) {
0263 return -EIO;
0264 }
0265
0266 return 0;
0267 }
0268
0269 static flash_control flash_instance = {
0270 .super = {
0271 .block_size = BLOCK_SIZE,
0272 .flash_size = FLASH_SIZE,
0273 .read = flash_read,
0274 .write = flash_write,
0275 .erase = flash_erase,
0276 .device_identifier = FLASH_DEVICE_ID
0277 }
0278 };
0279
0280 static rtems_jffs2_mount_data mount_data = {
0281 .flash_control = &flash_instance.super,
0282 .compressor_control = NULL
0283 };
0284
0285 int microblaze_jffs2_initialize( const char* mount_dir )
0286 {
0287 int rv = 0;
0288 int fd = -1;
0289
0290 uintptr_t mblaze_spi_base = try_get_prop_from_device_tree(
0291 "xlnx,xps-spi-2.00.a",
0292 "reg",
0293 BSP_MICROBLAZE_FPGA_SPI_BASE
0294 );
0295
0296 rtems_vector_number mblaze_spi_irq_num = try_get_prop_from_device_tree(
0297 "xlnx,xps-spi-2.00.a",
0298 "interrupts",
0299 BSP_MICROBLAZE_FPGA_SPI_IRQ_NUM
0300 );
0301
0302 rv = spi_bus_register_xilinx_axi(
0303 BUS_PATH,
0304 mblaze_spi_base,
0305 FLASH_PAGE_SIZE,
0306 FLASH_NUM_CS,
0307 mblaze_spi_irq_num
0308 );
0309 if ( rv != 0 ) {
0310 return rv;
0311 }
0312
0313 fd = open( BUS_PATH, O_RDWR );
0314 if ( fd < 0 ) {
0315 return -1;
0316 }
0317
0318 flash_instance.fd = fd;
0319
0320 rv = mount_and_make_target_path(
0321 NULL,
0322 mount_dir,
0323 RTEMS_FILESYSTEM_TYPE_JFFS2,
0324 RTEMS_FILESYSTEM_READ_WRITE,
0325 &mount_data
0326 );
0327 if ( rv != 0 ) {
0328 return rv;
0329 }
0330
0331 return 0;
0332 }