File indexing completed on 2025-05-11 08:22:42
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
0037
0038 #include <sys/stat.h>
0039 #include <sys/types.h>
0040 #include <string.h>
0041 #include <assert.h>
0042 #include <errno.h>
0043 #include <stdlib.h>
0044
0045 #include <bsp/jffs2_xnandpsu.h>
0046 #include <rtems/libio.h>
0047 #include <rtems/libcsupport.h>
0048 #include <rtems/malloc.h>
0049 #include <rtems/thread.h>
0050 #include <dev/nand/xnandpsu_bbm.h>
0051
0052 typedef struct {
0053 rtems_jffs2_flash_control super;
0054 XNandPsu *nandpsu;
0055 rtems_mutex access_lock;
0056 } flash_control;
0057
0058 static flash_control *get_flash_control(rtems_jffs2_flash_control *super)
0059 {
0060 return (flash_control *) super;
0061 }
0062
0063 static int flash_read(
0064 rtems_jffs2_flash_control *super,
0065 uint32_t offset,
0066 unsigned char *buffer,
0067 size_t size_of_buffer
0068 )
0069 {
0070 XNandPsu *nandpsu = get_flash_control(super)->nandpsu;
0071 rtems_status_code sc;
0072
0073 rtems_mutex_lock(&(get_flash_control(super)->access_lock));
0074 sc = XNandPsu_Read(nandpsu, offset, size_of_buffer, buffer);
0075 rtems_mutex_unlock(&(get_flash_control(super)->access_lock));
0076 if (sc) {
0077 return -EIO;
0078 }
0079 return 0;
0080 }
0081
0082 static int flash_write(
0083 rtems_jffs2_flash_control *super,
0084 uint32_t offset,
0085 const unsigned char *buffer,
0086 size_t size_of_buffer
0087 )
0088 {
0089 XNandPsu *nandpsu = get_flash_control(super)->nandpsu;
0090 rtems_status_code sc;
0091
0092 rtems_mutex_lock(&(get_flash_control(super)->access_lock));
0093 sc = XNandPsu_Write(nandpsu, offset, size_of_buffer, (void *)buffer);
0094 rtems_mutex_unlock(&(get_flash_control(super)->access_lock));
0095 if (sc) {
0096 return -EIO;
0097 }
0098 return 0;
0099 }
0100
0101 static int flash_erase(
0102 rtems_jffs2_flash_control *super,
0103 uint32_t offset
0104 )
0105 {
0106 XNandPsu *nandpsu = get_flash_control(super)->nandpsu;
0107 rtems_status_code sc;
0108 uint64_t BlockSize = nandpsu->Geometry.BlockSize;
0109
0110 if (offset > nandpsu->Geometry.DeviceSize) {
0111 return -EIO;
0112 }
0113
0114
0115 rtems_mutex_lock(&(get_flash_control(super)->access_lock));
0116 sc = XNandPsu_Erase(nandpsu, RTEMS_ALIGN_DOWN(offset, BlockSize), BlockSize);
0117 rtems_mutex_unlock(&(get_flash_control(super)->access_lock));
0118 if (sc ) {
0119 return -EIO;
0120 }
0121
0122 return 0;
0123 }
0124
0125 static int flash_block_is_bad(
0126 rtems_jffs2_flash_control *super,
0127 uint32_t offset,
0128 bool *bad
0129 )
0130 {
0131 XNandPsu *nandpsu = get_flash_control(super)->nandpsu;
0132 uint32_t BlockIndex;
0133 uint8_t BlockData;
0134 uint8_t BlockShift;
0135 uint8_t BlockType;
0136 uint32_t BlockOffset;
0137
0138 assert(bad);
0139
0140 if (offset > nandpsu->Geometry.DeviceSize) {
0141 return -EIO;
0142 }
0143
0144 *bad = true;
0145
0146 BlockIndex = offset / nandpsu->Geometry.BlockSize;
0147
0148 rtems_mutex_lock(&(get_flash_control(super)->access_lock));
0149
0150
0151 BlockOffset = BlockIndex >> XNANDPSU_BBT_BLOCK_SHIFT;
0152 BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
0153 BlockData = nandpsu->Bbt[BlockOffset];
0154 BlockType = (BlockData >> BlockShift) & XNANDPSU_BLOCK_TYPE_MASK;
0155
0156 if (BlockType == XNANDPSU_BLOCK_GOOD) {
0157 *bad = false;
0158 }
0159
0160 int TargetBlockIndex = BlockIndex % nandpsu->Geometry.NumTargetBlocks;
0161
0162 if (nandpsu->Geometry.NumTargetBlocks - TargetBlockIndex <= 4) {
0163 *bad = true;
0164 }
0165
0166 rtems_mutex_unlock(&(get_flash_control(super)->access_lock));
0167 return 0;
0168 }
0169
0170 static int flash_block_mark_bad(
0171 rtems_jffs2_flash_control *super,
0172 uint32_t offset
0173 )
0174 {
0175 rtems_status_code sc;
0176 XNandPsu *nandpsu = get_flash_control(super)->nandpsu;
0177 uint32_t BlockIndex;
0178
0179 if (offset > nandpsu->Geometry.DeviceSize) {
0180 return -EIO;
0181 }
0182
0183 BlockIndex = offset / nandpsu->Geometry.BlockSize;
0184
0185 rtems_mutex_lock(&(get_flash_control(super)->access_lock));
0186 sc = XNandPsu_MarkBlockBad(nandpsu, BlockIndex);
0187 rtems_mutex_unlock(&(get_flash_control(super)->access_lock));
0188 if ( sc != XST_SUCCESS ) {
0189 return -EIO;
0190 }
0191 return RTEMS_SUCCESSFUL;
0192 }
0193
0194 static int flash_read_oob_locked(
0195 rtems_jffs2_flash_control *super,
0196 uint32_t offset,
0197 uint8_t *oobbuf,
0198 uint32_t ooblen
0199 )
0200 {
0201 uint8_t *spare_bytes;
0202 XNandPsu *nandpsu = get_flash_control(super)->nandpsu;
0203 uint32_t SpareBytesPerPage = nandpsu->Geometry.SpareBytesPerPage;
0204
0205 if (offset > nandpsu->Geometry.DeviceSize) {
0206 return -EIO;
0207 }
0208
0209
0210 if (ooblen > SpareBytesPerPage * nandpsu->Geometry.PagesPerBlock) {
0211 return -EIO;
0212 }
0213
0214
0215 uint32_t PageIndex = offset / nandpsu->Geometry.BytesPerPage;
0216
0217 spare_bytes = rtems_malloc(SpareBytesPerPage);
0218 if (spare_bytes == NULL) {
0219 return -ENOMEM;
0220 }
0221
0222 while (ooblen) {
0223 int rv = XNandPsu_ReadSpareBytes(nandpsu, PageIndex, spare_bytes);
0224
0225 uint32_t readlen = SpareBytesPerPage;
0226 if (ooblen < readlen) {
0227 readlen = ooblen;
0228 }
0229
0230 if (rv) {
0231 free(spare_bytes);
0232 return -EIO;
0233 }
0234
0235 memcpy(oobbuf, spare_bytes, readlen);
0236
0237 PageIndex++;
0238 ooblen -= readlen;
0239 oobbuf += readlen;
0240 }
0241 free(spare_bytes);
0242 return RTEMS_SUCCESSFUL;
0243 }
0244
0245 static int flash_read_oob(
0246 rtems_jffs2_flash_control *super,
0247 uint32_t offset,
0248 uint8_t *oobbuf,
0249 uint32_t ooblen
0250 )
0251 {
0252 rtems_mutex_lock(&(get_flash_control(super)->access_lock));
0253 int ret = flash_read_oob_locked(super, offset, oobbuf, ooblen);
0254 rtems_mutex_unlock(&(get_flash_control(super)->access_lock));
0255 return ret;
0256 }
0257
0258 static int flash_write_oob(
0259 rtems_jffs2_flash_control *super,
0260 uint32_t offset,
0261 uint8_t *oobbuf,
0262 uint32_t ooblen
0263 )
0264 {
0265 rtems_status_code sc;
0266 uint8_t *spare_bytes;
0267 uint8_t *buffer = oobbuf;
0268 XNandPsu *nandpsu = get_flash_control(super)->nandpsu;
0269 uint32_t SpareBytesPerPage = nandpsu->Geometry.SpareBytesPerPage;
0270
0271 if (offset > nandpsu->Geometry.DeviceSize) {
0272 return -EIO;
0273 }
0274
0275
0276 if (ooblen > SpareBytesPerPage) {
0277 return -EIO;
0278 }
0279
0280 spare_bytes = rtems_malloc(SpareBytesPerPage);
0281 if (spare_bytes == NULL) {
0282 return -ENOMEM;
0283 }
0284
0285
0286 rtems_mutex_lock(&(get_flash_control(super)->access_lock));
0287 if (ooblen < SpareBytesPerPage) {
0288 int rv = flash_read_oob_locked(super, offset, spare_bytes, SpareBytesPerPage);
0289 if (rv) {
0290 free(spare_bytes);
0291 rtems_mutex_unlock(&(get_flash_control(super)->access_lock));
0292 return rv;
0293 }
0294 buffer = spare_bytes;
0295 memcpy(buffer, oobbuf, ooblen);
0296 }
0297
0298
0299 uint32_t PageIndex = offset / nandpsu->Geometry.BytesPerPage;
0300
0301 sc = XNandPsu_WriteSpareBytes(nandpsu, PageIndex, buffer);
0302 rtems_mutex_unlock(&(get_flash_control(super)->access_lock));
0303 free(spare_bytes);
0304
0305 if ( sc != XST_SUCCESS ) {
0306 return -EIO;
0307 }
0308 return RTEMS_SUCCESSFUL;
0309 }
0310
0311 static uint32_t flash_get_oob_size(
0312 rtems_jffs2_flash_control *super
0313 )
0314 {
0315 flash_control *self = get_flash_control(super);
0316
0317 return self->nandpsu->Geometry.SpareBytesPerPage;
0318 }
0319
0320 static flash_control flash_instance = {
0321 .super = {
0322 .read = flash_read,
0323 .write = flash_write,
0324 .erase = flash_erase,
0325 .block_is_bad = flash_block_is_bad,
0326 .block_mark_bad = flash_block_mark_bad,
0327 .oob_read = flash_read_oob,
0328 .oob_write = flash_write_oob,
0329 .get_oob_size = flash_get_oob_size,
0330 }
0331 };
0332
0333 static rtems_jffs2_compressor_control compressor_instance = {
0334 .compress = rtems_jffs2_compressor_rtime_compress,
0335 .decompress = rtems_jffs2_compressor_rtime_decompress
0336 };
0337
0338 static rtems_jffs2_mount_data mount_data;
0339
0340 int xilinx_zynqmp_nand_jffs2_initialize(
0341 const char *mount_dir,
0342 XNandPsu *NandInstPtr
0343 )
0344 {
0345 flash_instance.super.block_size = NandInstPtr->Geometry.BlockSize;
0346
0347 uint64_t max_size = 0x100000000LU - flash_instance.super.block_size;
0348
0349
0350 if (NandInstPtr->Geometry.DeviceSize > max_size) {
0351 flash_instance.super.flash_size = max_size;
0352 } else {
0353 flash_instance.super.flash_size = NandInstPtr->Geometry.DeviceSize;
0354 }
0355
0356 flash_instance.super.write_size = NandInstPtr->Geometry.BytesPerPage;
0357 flash_instance.nandpsu = NandInstPtr;
0358 rtems_mutex_init(&flash_instance.access_lock, "XNandPsu JFFS2 adapter lock");
0359 mount_data.flash_control = &flash_instance.super;
0360 mount_data.compressor_control = &compressor_instance;
0361
0362 int rv = 0;
0363 rv = mount(
0364 NULL,
0365 mount_dir,
0366 RTEMS_FILESYSTEM_TYPE_JFFS2,
0367 RTEMS_FILESYSTEM_READ_WRITE,
0368 &mount_data
0369 );
0370 if ( rv != 0 ) {
0371 return rv;
0372 }
0373
0374 return 0;
0375 }