summaryrefslogtreecommitdiff
path: root/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/Zynq/xsdps_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/Zynq/xsdps_info.c')
-rw-r--r--FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/Zynq/xsdps_info.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/Zynq/xsdps_info.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/Zynq/xsdps_info.c
new file mode 100644
index 000000000..4ea13be80
--- /dev/null
+++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/Zynq/xsdps_info.c
@@ -0,0 +1,300 @@
+/******************************************************************************
+ *
+ * mmc_decode_cid() and sd_decode_csd()
+ *
+ * analyse the meta data of an SD-card to read its capacity and some other properties.
+ *
+ * CID and CSD Analysis borrowed from the Linux kernel.
+ *
+ ******************************************************************************/
+
+#include "xsdps.h"
+
+#include "xparameters.h"
+#include "xil_cache.h"
+
+#include "ff_headers.h"
+
+#include "xsdps_info.h"
+
+struct mmc_cid myCID;
+struct mmc_csd myCSD;
+
+u32 UNSTUFF_BITS( u32 *ulResponse, int iFirst, int iSize )
+{
+const u32 ulMask = ( iSize < 32 ? ( 1 << iSize ) : 0 ) - 1;
+const int iOffset = 3 - ( iFirst / 32);
+const int iShiftCount = iFirst & 31;
+u32 ulResult;
+
+ ulResult = ulResponse[ iOffset ] >> iShiftCount;
+ if( iSize + iShiftCount > 32 )
+ {
+ ulResult |= ulResponse[ iOffset - 1 ] << ( ( 32 - iShiftCount ) % 32 );
+ }
+ return ulResult & ulMask; \
+}
+
+int mmc_decode_cid( const struct mmc_csd *pxCSD, struct mmc_cid *pxCID, u32 *ulResponse )
+{
+int iResult = 0;
+
+ /*
+ * The selection of the format here is based upon published
+ * specs from sandisk and from what people have reported.
+ */
+
+ switch( pxCSD->mmca_vsn )
+ {
+ case 0: /* MMC v1.0 - v1.2 */
+ case 1: /* MMC v1.4 */
+ pxCID->manfid = UNSTUFF_BITS( ulResponse, 104, 24 );
+ pxCID->prod_name[ 0 ] = UNSTUFF_BITS( ulResponse, 96, 8 );
+ pxCID->prod_name[ 1 ] = UNSTUFF_BITS( ulResponse, 88, 8 );
+ pxCID->prod_name[ 2 ] = UNSTUFF_BITS( ulResponse, 80, 8 );
+ pxCID->prod_name[ 3 ] = UNSTUFF_BITS( ulResponse, 72, 8 );
+ pxCID->prod_name[ 4 ] = UNSTUFF_BITS( ulResponse, 64, 8 );
+ pxCID->prod_name[ 5 ] = UNSTUFF_BITS( ulResponse, 56, 8 );
+ pxCID->prod_name[ 6 ] = UNSTUFF_BITS( ulResponse, 48, 8 );
+ pxCID->hwrev = UNSTUFF_BITS( ulResponse, 44, 4 );
+ pxCID->fwrev = UNSTUFF_BITS( ulResponse, 40, 4 );
+ pxCID->serial = UNSTUFF_BITS( ulResponse, 16, 24 );
+ pxCID->month = UNSTUFF_BITS( ulResponse, 12, 4 );
+ pxCID->year = UNSTUFF_BITS( ulResponse, 8, 4 ) + 1997;
+ break;
+
+ case 2: /* MMC v2.0 - v2.2 */
+ case 3: /* MMC v3.1 - v3.3 */
+ case 4: /* MMC v4 */
+ pxCID->manfid = UNSTUFF_BITS( ulResponse, 120, 8 );
+ pxCID->oemid = UNSTUFF_BITS( ulResponse, 104, 16 );
+ pxCID->prod_name[ 0 ] = UNSTUFF_BITS( ulResponse, 96, 8 );
+ pxCID->prod_name[ 1 ] = UNSTUFF_BITS( ulResponse, 88, 8 );
+ pxCID->prod_name[ 2 ] = UNSTUFF_BITS( ulResponse, 80, 8 );
+ pxCID->prod_name[ 3 ] = UNSTUFF_BITS( ulResponse, 72, 8 );
+ pxCID->prod_name[ 4 ] = UNSTUFF_BITS( ulResponse, 64, 8 );
+ pxCID->prod_name[ 5 ] = UNSTUFF_BITS( ulResponse, 56, 8 );
+ pxCID->serial = UNSTUFF_BITS( ulResponse, 16, 32 );
+ pxCID->month = UNSTUFF_BITS( ulResponse, 12, 4 );
+ pxCID->year = UNSTUFF_BITS( ulResponse, 8, 4 ) + 1997;
+ break;
+
+ default:
+ FF_PRINTF ("mmc_decode_cid: card has unknown MMCA version %d\n",
+ pxCSD->mmca_vsn);
+ iResult = -1;
+ break;
+ }
+ if( iResult >= 0 )
+ {
+ FF_PRINTF ("CID: Manfid %lu (%-8.8s) serial %lu oem %u mon/year %u/%u rev %u fw %u\n",
+ pxCID->manfid,
+ pxCID->prod_name,
+ pxCID->serial,
+ pxCID->oemid,
+ pxCID->month,
+ pxCID->year,
+ pxCID->hwrev,
+ pxCID->fwrev);
+ }
+
+ return iResult;
+}
+
+static const unsigned int tran_exp[] =
+{
+ 10000, 100000, 1000000, 10000000,
+ 0, 0, 0, 0
+};
+
+static const unsigned char tran_mant[] =
+{
+ 0, 10, 12, 13, 15, 20, 25, 30,
+ 35, 40, 45, 50, 55, 60, 70, 80,
+};
+
+static const unsigned int tacc_exp[] =
+{
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] =
+{
+ 0, 10, 12, 13, 15, 20, 25, 30,
+ 35, 40, 45, 50, 55, 60, 70, 80,
+};
+
+char mmc_is_block_addressed;
+
+/* Given a 128-bit response, decode to our card CSD structure. */
+
+static __inline unsigned tobe32( unsigned value )
+{
+ return
+ ( value >> 24 ) |
+ ( ( value >> 8 ) & 0x0000ff00 ) |
+ ( ( value << 8 ) & 0x00ff0000 ) |
+ ( value << 24 );
+
+}
+
+int sd_decode_csd( struct mmc_csd *pxCSD, u32 *ulResponse )
+{
+unsigned int e, m, csd_struct;
+int iResult = 0;
+
+ csd_struct = UNSTUFF_BITS( ulResponse, 126, 2 );
+
+ pxCSD->mmca_vsn = UNSTUFF_BITS( ulResponse, 122, 4 );
+
+ FF_PRINTF("CSD data: %08x %08x %08x %08x mmca_vsn = %u\n",
+ ( unsigned )ulResponse[0],
+ ( unsigned )ulResponse[1],
+ ( unsigned )ulResponse[2],
+ ( unsigned )ulResponse[3],
+ pxCSD->mmca_vsn);
+// pxCSD->mmca_vsn = 2;
+
+ // CSD data: 005e0032 5f5a83cb 2db7ffbf 9680000f
+ // sd_decode_csd: capacity 1989120 (byte addressed)
+ switch (csd_struct) {
+ case 0:
+ m = UNSTUFF_BITS( ulResponse, 115, 4 );
+ e = UNSTUFF_BITS( ulResponse, 112, 3 );
+ pxCSD->tacc_ns = ( tacc_exp[ e ] * tacc_mant[ m ] + 9 ) / 10;
+ pxCSD->tacc_clks = UNSTUFF_BITS( ulResponse, 104, 8 ) * 100;
+
+ m = UNSTUFF_BITS( ulResponse, 99, 4 );
+ e = UNSTUFF_BITS( ulResponse, 96, 3 );
+ pxCSD->max_dtr = tran_exp[ e ] * tran_mant[ m ];
+ pxCSD->cmdclass = UNSTUFF_BITS( ulResponse, 84, 12 );
+
+ e = UNSTUFF_BITS( ulResponse, 47, 3 );
+ m = UNSTUFF_BITS( ulResponse, 62, 12 );
+ pxCSD->capacity = ( 1 + m ) << ( e + 2 );
+ /*
+ * The CSD capacity field is in units of read_blkbits.
+ * set_capacity takes units of 512 bytes.
+ */
+
+ pxCSD->read_blkbits = UNSTUFF_BITS( ulResponse, 80, 4 );
+ pxCSD->read_partial = UNSTUFF_BITS( ulResponse, 79, 1 );
+ pxCSD->write_misalign = UNSTUFF_BITS( ulResponse, 78, 1 );
+ pxCSD->read_misalign = UNSTUFF_BITS( ulResponse, 77, 1 );
+ pxCSD->r2w_factor = UNSTUFF_BITS( ulResponse, 26, 3 );
+ pxCSD->write_blkbits = UNSTUFF_BITS( ulResponse, 22, 4 );
+ pxCSD->write_partial = UNSTUFF_BITS( ulResponse, 21, 1 );
+
+ pxCSD->capacity <<= ( pxCSD->read_blkbits - 9 );
+ FF_PRINTF ("Capacity: (%u + 1) << (%u + 2) = %u Rd/Wr bits %u/%u\n",
+ m, e,
+ ( unsigned )pxCSD->capacity,
+ ( unsigned )pxCSD->read_blkbits,
+ ( unsigned )pxCSD->write_blkbits);
+
+ if( UNSTUFF_BITS( ulResponse, 46, 1 ) )
+ {
+ pxCSD->erase_size = 1;
+ }
+ else if( pxCSD->write_blkbits >= 9 )
+ {
+ pxCSD->erase_size = UNSTUFF_BITS( ulResponse, 39, 7 ) + 1;
+ pxCSD->erase_size <<= pxCSD->write_blkbits - 9;
+ }
+ else
+ {
+ pxCSD->erase_size = 0; // Card is not eraseble
+ }
+ break;
+
+ case 1:
+ /*
+ * This is a block-addressed SDHC card. Most
+ * interesting fields are unused and have fixed
+ * values. To avoid getting tripped by buggy cards,
+ * we assume those fixed values ourselves.
+ */
+ mmc_is_block_addressed = 1;
+
+ pxCSD->tacc_ns = 0; /* Unused */
+ pxCSD->tacc_clks = 0; /* Unused */
+
+ m = UNSTUFF_BITS( ulResponse, 99, 4 );
+ e = UNSTUFF_BITS( ulResponse, 96, 3 );
+ // max_dtr gives 25,000,000
+ pxCSD->max_dtr = tran_exp[ e ] * tran_mant[ m ];
+ // cmdClass gives: 10110110101 (0x5B5)
+ pxCSD->cmdclass = UNSTUFF_BITS( ulResponse, 84, 12 );
+
+ m = UNSTUFF_BITS( ulResponse, 48, 22 );
+ pxCSD->capacity = ( 1 + m ) << 10;
+
+ FF_PRINTF( "capacity: (1 + %u) << 10 DTR %u Mhz\n", m, pxCSD->max_dtr / 1000000);
+
+ pxCSD->read_blkbits = 9;
+ pxCSD->read_partial = 0;
+ pxCSD->write_misalign = 0;
+ pxCSD->read_misalign = 0;
+ pxCSD->r2w_factor = 4; /* Unused */
+ pxCSD->write_blkbits = 9;
+ pxCSD->write_partial = 0;
+ pxCSD->erase_size = 1;
+ break;
+ default:
+ FF_PRINTF ("sd_decode_csd: unrecognised CSD structure version %d\n", csd_struct);
+ iResult = -1;
+ break;
+ }
+ if( iResult >= 0 )
+ {
+ unsigned int sz;
+
+ FF_PRINTF ("sd_decode_csd: capacity %lu (%s addressed)\n",
+ pxCSD->capacity, mmc_is_block_addressed ? "block" : "byte");
+
+ sz = (pxCSD->capacity << (pxCSD->read_blkbits - 9)) >> 11;
+ if (sz < 128)
+ {
+ pxCSD->pref_erase = 512 * 1024 / 512;
+ }
+ else if (sz < 512)
+ {
+ pxCSD->pref_erase = 1024 * 1024 / 512;
+ }
+ else if (sz < 1024)
+ {
+ pxCSD->pref_erase = 2 * 1024 * 1024 / 512;
+ }
+ else
+ {
+ pxCSD->pref_erase = 4 * 1024 * 1024 / 512;
+ }
+
+ if (pxCSD->pref_erase < pxCSD->erase_size)
+ {
+ pxCSD->pref_erase = pxCSD->erase_size;
+ }
+ else
+ {
+ sz = ( pxCSD->pref_erase % pxCSD->erase_size );
+ if( sz != 0 )
+ {
+ pxCSD->pref_erase += ( pxCSD->erase_size - sz );
+ }
+ }
+
+ // compute last block addr
+
+ pxCSD->sd_last_block_address = pxCSD->capacity - 1;
+
+ // compute card capacity in bytes
+ pxCSD->capacity_bytes = ( ( uint64_t )XSDPS_BLK_SIZE_512_MASK ) * pxCSD->capacity;
+
+ FF_PRINTF( "sd_mmc_spi_get_capacity: Capacity %lu MB Erase %u Pref %lu\n",
+ ( uint32_t ) ( pxCSD->capacity_bytes / ( 1024LLU * 1024LLU ) ),
+ pxCSD->erase_size,
+ pxCSD->pref_erase );
+ }
+
+ return iResult;
+}