]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/Zynq/xsdps_info.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-FAT / portable / Zynq / xsdps_info.c
1 /******************************************************************************\r
2  *\r
3  * mmc_decode_cid() and sd_decode_csd()\r
4  *\r
5  * analyse the meta data of an SD-card to read its capacity and some other properties.\r
6  *\r
7  * CID and CSD Analysis borrowed from the Linux kernel.\r
8  *\r
9  ******************************************************************************/\r
10 \r
11 #include "xsdps.h"\r
12 \r
13 #include "xparameters.h"\r
14 #include "xil_cache.h"\r
15 \r
16 #include "ff_headers.h"\r
17 \r
18 #include "xsdps_info.h"\r
19 \r
20 struct mmc_cid myCID;\r
21 struct mmc_csd myCSD;\r
22 \r
23 u32 UNSTUFF_BITS( u32 *ulResponse, int iFirst, int iSize )\r
24 {\r
25 const u32 ulMask = ( iSize < 32 ? ( 1 << iSize ) : 0 ) - 1;\r
26 const int iOffset = 3 - ( iFirst / 32);\r
27 const int iShiftCount = iFirst & 31;\r
28 u32 ulResult;\r
29 \r
30         ulResult = ulResponse[ iOffset ] >> iShiftCount;\r
31         if( iSize + iShiftCount > 32 )\r
32         {\r
33                 ulResult |= ulResponse[ iOffset - 1 ] << ( ( 32 - iShiftCount ) % 32 );\r
34         }\r
35         return ulResult & ulMask;                                               \\r
36 }\r
37 \r
38 int mmc_decode_cid( const struct mmc_csd *pxCSD, struct mmc_cid *pxCID, u32 *ulResponse )\r
39 {\r
40 int iResult = 0;\r
41 \r
42         /*\r
43          * The selection of the format here is based upon published\r
44          * specs from sandisk and from what people have reported.\r
45          */\r
46 \r
47         switch( pxCSD->mmca_vsn )\r
48         {\r
49         case 0: /* MMC v1.0 - v1.2 */\r
50         case 1: /* MMC v1.4 */\r
51                 pxCID->manfid         = UNSTUFF_BITS( ulResponse, 104, 24 );\r
52                 pxCID->prod_name[ 0 ] = UNSTUFF_BITS( ulResponse, 96, 8 );\r
53                 pxCID->prod_name[ 1 ] = UNSTUFF_BITS( ulResponse, 88, 8 );\r
54                 pxCID->prod_name[ 2 ] = UNSTUFF_BITS( ulResponse, 80, 8 );\r
55                 pxCID->prod_name[ 3 ] = UNSTUFF_BITS( ulResponse, 72, 8 );\r
56                 pxCID->prod_name[ 4 ] = UNSTUFF_BITS( ulResponse, 64, 8 );\r
57                 pxCID->prod_name[ 5 ] = UNSTUFF_BITS( ulResponse, 56, 8 );\r
58                 pxCID->prod_name[ 6 ] = UNSTUFF_BITS( ulResponse, 48, 8 );\r
59                 pxCID->hwrev          = UNSTUFF_BITS( ulResponse, 44, 4 );\r
60                 pxCID->fwrev          = UNSTUFF_BITS( ulResponse, 40, 4 );\r
61                 pxCID->serial         = UNSTUFF_BITS( ulResponse, 16, 24 );\r
62                 pxCID->month          = UNSTUFF_BITS( ulResponse, 12, 4 );\r
63                 pxCID->year           = UNSTUFF_BITS( ulResponse, 8, 4 ) + 1997;\r
64                 break;\r
65 \r
66         case 2: /* MMC v2.0 - v2.2 */\r
67         case 3: /* MMC v3.1 - v3.3 */\r
68         case 4: /* MMC v4 */\r
69                 pxCID->manfid         = UNSTUFF_BITS( ulResponse, 120, 8 );\r
70                 pxCID->oemid          = UNSTUFF_BITS( ulResponse, 104, 16 );\r
71                 pxCID->prod_name[ 0 ] = UNSTUFF_BITS( ulResponse, 96, 8 );\r
72                 pxCID->prod_name[ 1 ] = UNSTUFF_BITS( ulResponse, 88, 8 );\r
73                 pxCID->prod_name[ 2 ] = UNSTUFF_BITS( ulResponse, 80, 8 );\r
74                 pxCID->prod_name[ 3 ] = UNSTUFF_BITS( ulResponse, 72, 8 );\r
75                 pxCID->prod_name[ 4 ] = UNSTUFF_BITS( ulResponse, 64, 8 );\r
76                 pxCID->prod_name[ 5 ] = UNSTUFF_BITS( ulResponse, 56, 8 );\r
77                 pxCID->serial         = UNSTUFF_BITS( ulResponse, 16, 32 );\r
78                 pxCID->month          = UNSTUFF_BITS( ulResponse, 12, 4 );\r
79                 pxCID->year           = UNSTUFF_BITS( ulResponse, 8, 4 ) + 1997;\r
80                 break;\r
81 \r
82         default:\r
83                 FF_PRINTF ("mmc_decode_cid: card has unknown MMCA version %d\n",\r
84                         pxCSD->mmca_vsn);\r
85                 iResult = -1;\r
86                 break;\r
87         }\r
88         if( iResult >= 0 )\r
89         {\r
90                 FF_PRINTF ("CID: Manfid %lu (%-8.8s) serial %lu oem %u mon/year %u/%u rev %u fw %u\n",\r
91                         pxCID->manfid,\r
92                         pxCID->prod_name,\r
93                         pxCID->serial,\r
94                         pxCID->oemid,\r
95                         pxCID->month,\r
96                         pxCID->year,\r
97                         pxCID->hwrev,\r
98                         pxCID->fwrev);\r
99         }\r
100 \r
101         return iResult;\r
102 }\r
103 \r
104 static const unsigned int tran_exp[] =\r
105 {\r
106         10000,          100000,         1000000,        10000000,\r
107         0,              0,              0,              0\r
108 };\r
109 \r
110 static const unsigned char tran_mant[] =\r
111 {\r
112         0,      10,     12,     13,     15,     20,     25,     30,\r
113         35,     40,     45,     50,     55,     60,     70,     80,\r
114 };\r
115 \r
116 static const unsigned int tacc_exp[] =\r
117 {\r
118         1,      10,     100,    1000,   10000,  100000, 1000000, 10000000,\r
119 };\r
120 \r
121 static const unsigned int tacc_mant[] =\r
122 {\r
123         0,      10,     12,     13,     15,     20,     25,     30,\r
124         35,     40,     45,     50,     55,     60,     70,     80,\r
125 };\r
126 \r
127 char mmc_is_block_addressed;\r
128 \r
129 /* Given a 128-bit response, decode to our card CSD structure. */\r
130 \r
131 static __inline unsigned tobe32( unsigned value )\r
132 {\r
133         return\r
134                 ( value >> 24 ) |\r
135                 ( ( value >>  8 ) & 0x0000ff00 ) |\r
136                 ( ( value <<  8 ) & 0x00ff0000 ) |\r
137                 ( value << 24 );\r
138         \r
139 }\r
140 \r
141 int sd_decode_csd( struct mmc_csd *pxCSD, u32 *ulResponse )\r
142 {\r
143 unsigned int e, m, csd_struct;\r
144 int iResult = 0;\r
145 \r
146         csd_struct = UNSTUFF_BITS( ulResponse, 126, 2 );\r
147 \r
148         pxCSD->mmca_vsn = UNSTUFF_BITS( ulResponse, 122, 4 );\r
149 \r
150         FF_PRINTF("CSD data: %08x %08x %08x %08x mmca_vsn = %u\n",\r
151                 ( unsigned )ulResponse[0],\r
152                 ( unsigned )ulResponse[1],\r
153                 ( unsigned )ulResponse[2],\r
154                 ( unsigned )ulResponse[3],\r
155                 pxCSD->mmca_vsn);\r
156 //      pxCSD->mmca_vsn = 2;\r
157 \r
158         // CSD data: 005e0032 5f5a83cb 2db7ffbf 9680000f\r
159         // sd_decode_csd: capacity 1989120 (byte addressed)\r
160         switch (csd_struct) {\r
161         case 0:\r
162                 m = UNSTUFF_BITS( ulResponse, 115, 4 );\r
163                 e = UNSTUFF_BITS( ulResponse, 112, 3 );\r
164                 pxCSD->tacc_ns = ( tacc_exp[ e ] * tacc_mant[ m ] + 9 ) / 10;\r
165                 pxCSD->tacc_clks = UNSTUFF_BITS( ulResponse, 104, 8 ) * 100;\r
166 \r
167                 m = UNSTUFF_BITS( ulResponse, 99, 4 );\r
168                 e = UNSTUFF_BITS( ulResponse, 96, 3 );\r
169                 pxCSD->max_dtr = tran_exp[ e ] * tran_mant[ m ];\r
170                 pxCSD->cmdclass = UNSTUFF_BITS( ulResponse, 84, 12 );\r
171 \r
172                 e = UNSTUFF_BITS( ulResponse, 47, 3 );\r
173                 m = UNSTUFF_BITS( ulResponse, 62, 12 );\r
174                 pxCSD->capacity = ( 1 + m ) << ( e + 2 );\r
175                 /*\r
176                  * The CSD capacity field is in units of read_blkbits.\r
177                  * set_capacity takes units of 512 bytes.\r
178                  */\r
179 \r
180                 pxCSD->read_blkbits = UNSTUFF_BITS( ulResponse, 80, 4 );\r
181                 pxCSD->read_partial = UNSTUFF_BITS( ulResponse, 79, 1 );\r
182                 pxCSD->write_misalign = UNSTUFF_BITS( ulResponse, 78, 1 );\r
183                 pxCSD->read_misalign = UNSTUFF_BITS( ulResponse, 77, 1 );\r
184                 pxCSD->r2w_factor = UNSTUFF_BITS( ulResponse, 26, 3 );\r
185                 pxCSD->write_blkbits = UNSTUFF_BITS( ulResponse, 22, 4 );\r
186                 pxCSD->write_partial = UNSTUFF_BITS( ulResponse, 21, 1 );\r
187 \r
188                 pxCSD->capacity <<= ( pxCSD->read_blkbits - 9 );\r
189                 FF_PRINTF ("Capacity: (%u + 1) << (%u + 2) = %u Rd/Wr bits %u/%u\n",\r
190                         m, e,\r
191                         ( unsigned )pxCSD->capacity,\r
192                         ( unsigned )pxCSD->read_blkbits,\r
193                         ( unsigned )pxCSD->write_blkbits);\r
194 \r
195                 if( UNSTUFF_BITS( ulResponse, 46, 1 ) )\r
196                 {\r
197                         pxCSD->erase_size = 1;\r
198                 }\r
199                 else if( pxCSD->write_blkbits >= 9 )\r
200                 {\r
201                         pxCSD->erase_size = UNSTUFF_BITS( ulResponse, 39, 7 ) + 1;\r
202                         pxCSD->erase_size <<= pxCSD->write_blkbits - 9;\r
203                 }\r
204                 else\r
205                 {\r
206                         pxCSD->erase_size = 0; // Card is not eraseble\r
207                 }\r
208                 break;\r
209 \r
210         case 1:\r
211                 /*\r
212                  * This is a block-addressed SDHC card. Most\r
213                  * interesting fields are unused and have fixed\r
214                  * values. To avoid getting tripped by buggy cards,\r
215                  * we assume those fixed values ourselves.\r
216                  */\r
217                 mmc_is_block_addressed = 1;\r
218 \r
219                 pxCSD->tacc_ns = 0; /* Unused */\r
220                 pxCSD->tacc_clks = 0; /* Unused */\r
221 \r
222                 m = UNSTUFF_BITS( ulResponse, 99, 4 );\r
223                 e = UNSTUFF_BITS( ulResponse, 96, 3 );\r
224                 // max_dtr gives 25,000,000\r
225                 pxCSD->max_dtr = tran_exp[ e ] * tran_mant[ m ];\r
226                 // cmdClass gives: 10110110101 (0x5B5)\r
227                 pxCSD->cmdclass = UNSTUFF_BITS( ulResponse, 84, 12 );\r
228 \r
229                 m = UNSTUFF_BITS( ulResponse, 48, 22 );\r
230                 pxCSD->capacity = ( 1 + m ) << 10;\r
231 \r
232                 FF_PRINTF( "capacity: (1 + %u) << 10  DTR %u Mhz\n", m, pxCSD->max_dtr / 1000000);\r
233 \r
234                 pxCSD->read_blkbits = 9;\r
235                 pxCSD->read_partial = 0;\r
236                 pxCSD->write_misalign = 0;\r
237                 pxCSD->read_misalign = 0;\r
238                 pxCSD->r2w_factor = 4; /* Unused */\r
239                 pxCSD->write_blkbits = 9;\r
240                 pxCSD->write_partial = 0;\r
241                 pxCSD->erase_size = 1;\r
242                 break;\r
243         default:\r
244                 FF_PRINTF ("sd_decode_csd: unrecognised CSD structure version %d\n", csd_struct);\r
245                 iResult = -1;\r
246                 break;\r
247         }\r
248         if( iResult >= 0 )\r
249         {\r
250         unsigned int sz;\r
251 \r
252                 FF_PRINTF ("sd_decode_csd: capacity %lu (%s addressed)\n",\r
253                         pxCSD->capacity, mmc_is_block_addressed ? "block" : "byte");\r
254 \r
255                 sz = (pxCSD->capacity << (pxCSD->read_blkbits - 9)) >> 11;\r
256                 if (sz < 128)\r
257                 {\r
258                         pxCSD->pref_erase = 512 * 1024 / 512;\r
259                 }\r
260                 else if (sz < 512)\r
261                 {\r
262                         pxCSD->pref_erase = 1024 * 1024 / 512;\r
263                 }\r
264                 else if (sz < 1024)\r
265                 {\r
266                         pxCSD->pref_erase = 2 * 1024 * 1024 / 512;\r
267                 }\r
268                 else\r
269                 {\r
270                         pxCSD->pref_erase = 4 * 1024 * 1024 / 512;\r
271                 }\r
272 \r
273                 if (pxCSD->pref_erase < pxCSD->erase_size)\r
274                 {\r
275                         pxCSD->pref_erase = pxCSD->erase_size;\r
276                 }\r
277                 else\r
278                 {\r
279                         sz = ( pxCSD->pref_erase % pxCSD->erase_size );\r
280                         if( sz != 0 )\r
281                         {\r
282                                 pxCSD->pref_erase += ( pxCSD->erase_size - sz );\r
283                         }\r
284                 }\r
285 \r
286                 // compute last block addr\r
287 \r
288                 pxCSD->sd_last_block_address = pxCSD->capacity - 1;\r
289 \r
290                 // compute card capacity in bytes\r
291                 pxCSD->capacity_bytes = ( ( uint64_t )XSDPS_BLK_SIZE_512_MASK ) * pxCSD->capacity;\r
292 \r
293                 FF_PRINTF( "sd_mmc_spi_get_capacity: Capacity %lu MB Erase %u Pref %lu\n",\r
294                         ( uint32_t ) ( pxCSD->capacity_bytes / ( 1024LLU * 1024LLU ) ),\r
295                         pxCSD->erase_size,\r
296                         pxCSD->pref_erase );\r
297         }\r
298 \r
299         return iResult;\r
300 }\r