99#include <linux/kernel.h>
1010#include <linux/mtd/spinand.h>
1111
12+ #define FM25S01BI3_STATUS_ECC_MASK (7 << 4)
13+ #define FM25S01BI3_STATUS_ECC_NO_BITFLIPS (0 << 4)
14+ #define FM25S01BI3_STATUS_ECC_1_3_BITFLIPS (1 << 4)
15+ #define FM25S01BI3_STATUS_ECC_UNCOR_ERROR (2 << 4)
16+ #define FM25S01BI3_STATUS_ECC_4_6_BITFLIPS (3 << 4)
17+ #define FM25S01BI3_STATUS_ECC_7_8_BITFLIPS (5 << 4)
18+
1219#define SPINAND_MFR_FMSH 0xA1
1320
1421static SPINAND_OP_VARIANTS (read_cache_variants ,
@@ -45,11 +52,66 @@ static int fm25s01a_ooblayout_free(struct mtd_info *mtd, int section,
4552 return 0 ;
4653}
4754
55+ static int fm25s01bi3_ecc_get_status (struct spinand_device * spinand ,
56+ u8 status )
57+ {
58+ switch (status & FM25S01BI3_STATUS_ECC_MASK ) {
59+ case FM25S01BI3_STATUS_ECC_NO_BITFLIPS :
60+ return 0 ;
61+
62+ case FM25S01BI3_STATUS_ECC_UNCOR_ERROR :
63+ return - EBADMSG ;
64+
65+ case FM25S01BI3_STATUS_ECC_1_3_BITFLIPS :
66+ return 3 ;
67+
68+ case FM25S01BI3_STATUS_ECC_4_6_BITFLIPS :
69+ return 6 ;
70+
71+ case FM25S01BI3_STATUS_ECC_7_8_BITFLIPS :
72+ return 8 ;
73+
74+ default :
75+ break ;
76+ }
77+
78+ return - EINVAL ;
79+ }
80+
81+ static int fm25s01bi3_ooblayout_ecc (struct mtd_info * mtd , int section ,
82+ struct mtd_oob_region * region )
83+ {
84+ if (section )
85+ return - ERANGE ;
86+
87+ region -> offset = 64 ;
88+ region -> length = 64 ;
89+
90+ return 0 ;
91+ }
92+
93+ static int fm25s01bi3_ooblayout_free (struct mtd_info * mtd , int section ,
94+ struct mtd_oob_region * region )
95+ {
96+ if (section > 3 )
97+ return - ERANGE ;
98+
99+ region -> offset = (16 * section ) + 4 ;
100+ region -> length = 12 ;
101+
102+ return 0 ;
103+ }
104+
48105static const struct mtd_ooblayout_ops fm25s01a_ooblayout = {
49106 .ecc = fm25s01a_ooblayout_ecc ,
50107 .free = fm25s01a_ooblayout_free ,
51108};
52109
110+ static const struct mtd_ooblayout_ops fm25s01bi3_ooblayout = {
111+ .ecc = fm25s01bi3_ooblayout_ecc ,
112+ .free = fm25s01bi3_ooblayout_free ,
113+ };
114+
53115static const struct spinand_info fmsh_spinand_table [] = {
54116 SPINAND_INFO ("FM25S01A ",
55117 SPINAND_ID (SPINAND_READID_METHOD_OPCODE_DUMMY , 0xE4 ),
@@ -60,6 +122,16 @@ static const struct spinand_info fmsh_spinand_table[] = {
60122 & update_cache_variants ),
61123 SPINAND_HAS_QE_BIT ,
62124 SPINAND_ECCINFO (& fm25s01a_ooblayout , NULL )),
125+ SPINAND_INFO ("FM25S01BI3 ",
126+ SPINAND_ID (SPINAND_READID_METHOD_OPCODE_DUMMY , 0xd4 ),
127+ NAND_MEMORG (1 , 2048 , 128 , 64 , 1024 , 20 , 1 , 1 , 1 ),
128+ NAND_ECCREQ (8 , 512 ),
129+ SPINAND_INFO_OP_VARIANTS (& read_cache_variants ,
130+ & write_cache_variants ,
131+ & update_cache_variants ),
132+ SPINAND_HAS_QE_BIT ,
133+ SPINAND_ECCINFO (& fm25s01bi3_ooblayout ,
134+ fm25s01bi3_ecc_get_status )),
63135};
64136
65137static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = {
0 commit comments