1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright © 2009 - Maxim Levitsky 4*4882a593Smuzhiyun * Common routines & support for SmartMedia/xD format 5*4882a593Smuzhiyun */ 6*4882a593Smuzhiyun #include <linux/bitops.h> 7*4882a593Smuzhiyun #include <linux/mtd/mtd.h> 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun /* Full oob structure as written on the flash */ 10*4882a593Smuzhiyun struct sm_oob { 11*4882a593Smuzhiyun uint32_t reserved; 12*4882a593Smuzhiyun uint8_t data_status; 13*4882a593Smuzhiyun uint8_t block_status; 14*4882a593Smuzhiyun uint8_t lba_copy1[2]; 15*4882a593Smuzhiyun uint8_t ecc2[3]; 16*4882a593Smuzhiyun uint8_t lba_copy2[2]; 17*4882a593Smuzhiyun uint8_t ecc1[3]; 18*4882a593Smuzhiyun } __packed; 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun /* one sector is always 512 bytes, but it can consist of two nand pages */ 22*4882a593Smuzhiyun #define SM_SECTOR_SIZE 512 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun /* oob area is also 16 bytes, but might be from two pages */ 25*4882a593Smuzhiyun #define SM_OOB_SIZE 16 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun /* This is maximum zone size, and all devices that have more that one zone 28*4882a593Smuzhiyun have this size */ 29*4882a593Smuzhiyun #define SM_MAX_ZONE_SIZE 1024 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun /* support for small page nand */ 32*4882a593Smuzhiyun #define SM_SMALL_PAGE 256 33*4882a593Smuzhiyun #define SM_SMALL_OOB_SIZE 8 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun int sm_register_device(struct mtd_info *mtd, int smartmedia); 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun sm_sector_valid(struct sm_oob * oob)39*4882a593Smuzhiyunstatic inline int sm_sector_valid(struct sm_oob *oob) 40*4882a593Smuzhiyun { 41*4882a593Smuzhiyun return hweight16(oob->data_status) >= 5; 42*4882a593Smuzhiyun } 43*4882a593Smuzhiyun sm_block_valid(struct sm_oob * oob)44*4882a593Smuzhiyunstatic inline int sm_block_valid(struct sm_oob *oob) 45*4882a593Smuzhiyun { 46*4882a593Smuzhiyun return hweight16(oob->block_status) >= 7; 47*4882a593Smuzhiyun } 48*4882a593Smuzhiyun sm_block_erased(struct sm_oob * oob)49*4882a593Smuzhiyunstatic inline int sm_block_erased(struct sm_oob *oob) 50*4882a593Smuzhiyun { 51*4882a593Smuzhiyun static const uint32_t erased_pattern[4] = { 52*4882a593Smuzhiyun 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun /* First test for erased block */ 55*4882a593Smuzhiyun if (!memcmp(oob, erased_pattern, sizeof(*oob))) 56*4882a593Smuzhiyun return 1; 57*4882a593Smuzhiyun return 0; 58*4882a593Smuzhiyun } 59