@@ -476,6 +476,44 @@ static const uint8_t sd_csd_rw_mask[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe,
};
+static void emmc_set_csd(SDState *sd, uint64_t size)
+{
+ int hwblock_shift = HWBLOCK_SHIFT;
+ uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1;
+ uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1;
+
+ sd->csd[0] = (2 << 6) | (4 << 2);
+ sd->csd[1] = 0x07;
+ sd->csd[2] = 0x00;
+ sd->csd[3] = 0x32;
+ sd->csd[4] = 0x0f;
+ if (size <= 2 * GiB) {
+ /* use 1k blocks */
+ uint32_t csize1k = (size >> (CMULT_SHIFT + 10)) - 1;
+ sd->csd[5] = 0x5a;
+ sd->csd[6] = 0x80 | ((csize1k >> 10) & 0xf);
+ sd->csd[7] = (csize1k >> 2) & 0xff;
+ } else { /* >= 2GB : size stored in ext CSD, block addressing */
+ sd->csd[5] = 0x59;
+ sd->csd[6] = 0x8f;
+ sd->csd[7] = 0xff;
+ sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1);
+ }
+ sd->csd[8] = 0xff;
+ sd->csd[9] = 0xfc | /* Max. write current */
+ ((CMULT_SHIFT - 2) >> 1);
+ sd->csd[10] = 0x40 | /* Erase sector size */
+ (((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1);
+ sd->csd[11] = 0x00 | /* Write protect group size */
+ ((sectsize << 7) & 0x80) | wpsize;
+ sd->csd[12] = 0x90 | /* Write speed factor */
+ (hwblock_shift >> 2);
+ sd->csd[13] = 0x20 | /* Max. write data block length */
+ ((hwblock_shift << 6) & 0xc0);
+ sd->csd[14] = 0x00;
+ sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
+}
+
static void sd_set_csd(SDState *sd, uint64_t size)
{
int hwblock_shift = HWBLOCK_SHIFT;
@@ -2600,6 +2638,7 @@ static void emmc_class_init(ObjectClass *klass, void *data)
sc->proto = &sd_proto_emmc;
sc->set_cid = emmc_set_cid;
+ sc->set_csd = emmc_set_csd;
}
static const TypeInfo sd_types[] = {
eMMC CSD register is very similar to SD one. Most notable change: the version announced is v4.3. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> --- TODO: comment magic values? --- hw/sd/sd.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)