[PATCH v2 1/2] block: m25p80: Add support of mt35xu02gbba
Add Micro 2Gb OSPI flash part with sfdp data. Signed-off-by: Sai Pavan Boddu Reviewed-by: Francisco Iglesias --- hw/block/m25p80_sfdp.h | 1 + hw/block/m25p80.c | 3 +++ hw/block/m25p80_sfdp.c | 36 3 files changed, 40 insertions(+) diff --git a/hw/block/m25p80_sfdp.h b/hw/block/m25p80_sfdp.h index 011a880f66..1733b56950 100644 --- a/hw/block/m25p80_sfdp.h +++ b/hw/block/m25p80_sfdp.h @@ -16,6 +16,7 @@ #define M25P80_SFDP_MAX_SIZE (1 << 24) uint8_t m25p80_sfdp_n25q256a(uint32_t addr); +uint8_t m25p80_sfdp_mt35xu02g(uint32_t addr); uint8_t m25p80_sfdp_mx25l25635e(uint32_t addr); uint8_t m25p80_sfdp_mx25l25635f(uint32_t addr); diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 0a12030a3a..08a00a6d9b 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -267,6 +267,9 @@ static const FlashPartInfo known_devices[] = { { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) }, { INFO_STACKED("mt35xu01g", 0x2c5b1b, 0x104100, 128 << 10, 1024, ER_4K | ER_32K, 2) }, +{ INFO_STACKED("mt35xu02gbba", 0x2c5b1c, 0x104100, 128 << 10, 2048, + ER_4K | ER_32K, 4), + .sfdp_read = m25p80_sfdp_mt35xu02g }, { INFO_STACKED("n25q00",0x20ba21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, { INFO_STACKED("n25q00a", 0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, { INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, diff --git a/hw/block/m25p80_sfdp.c b/hw/block/m25p80_sfdp.c index b33811a4f5..6ee2cfaf11 100644 --- a/hw/block/m25p80_sfdp.c +++ b/hw/block/m25p80_sfdp.c @@ -57,6 +57,42 @@ static const uint8_t sfdp_n25q256a[] = { }; define_sfdp_read(n25q256a); +static const uint8_t sfdp_mt35xu02g[] = { +0x53, 0x46, 0x44, 0x50, 0x06, 0x01, 0x01, 0xff, +0x00, 0x06, 0x01, 0x10, 0x30, 0x00, 0x00, 0xff, +0x84, 0x00, 0x01, 0x02, 0x80, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xe5, 0x20, 0x8a, 0xff, 0xff, 0xff, 0xff, 0x7f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, +0xff, 0xff, 0x00, 0x00, 0x0c, 0x20, 0x11, 0xd8, +0x0f, 0x52, 0x00, 0x00, 0x24, 0x5a, 0x99, 0x00, +0x8b, 0x8e, 0x03, 0xe1, 0xac, 0x01, 0x27, 0x38, +0x7a, 0x75, 0x7a, 0x75, 0xfb, 0xbd, 0xd5, 0x5c, +0x00, 0x00, 0x70, 0xff, 0x81, 0xb0, 0x38, 0x36, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x43, 0x0e, 0xff, 0xff, 0x21, 0xdc, 0x5c, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +define_sfdp_read(mt35xu02g); /* * Matronix -- 2.25.1
[PATCH v2 0/2] OSPI updates
Add a new 2Gib octal flash mt35xu02gbba. Add an interface for versal virt board to swap the default flash. Changes for V2: Added type checks for provided flash part name. Sai Pavan Boddu (2): block: m25p80: Add support of mt35xu02gbba arm: xlnx-versal-virt: Add machine property ospi-flash hw/block/m25p80_sfdp.h| 1 + hw/arm/xlnx-versal-virt.c | 44 ++- hw/block/m25p80.c | 3 +++ hw/block/m25p80_sfdp.c| 36 4 files changed, 83 insertions(+), 1 deletion(-) -- 2.25.1
[PATCH v2 2/2] arm: xlnx-versal-virt: Add machine property ospi-flash
This property allows users to change flash model on command line as below. ex: "-M xlnx-versal-virt,ospi-flash=mt35xu02gbba" Signed-off-by: Sai Pavan Boddu --- hw/arm/xlnx-versal-virt.c | 44 ++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 94942c55df..bfaed1aebf 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -49,6 +49,7 @@ struct VersalVirt { struct { bool secure; } cfg; +char *ospi_model; }; static void fdt_create(VersalVirt *s) @@ -638,6 +639,22 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) _fatal); } +static char *versal_get_ospi_model(Object *obj, Error **errp) +{ +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj); + +return g_strdup(s->ospi_model); +} + +static void versal_set_ospi_model(Object *obj, const char *value, Error **errp) +{ +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj); + +g_free(s->ospi_model); +s->ospi_model = g_strdup(value); +} + + static void versal_virt_init(MachineState *machine) { VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine); @@ -732,12 +749,25 @@ static void versal_virt_init(MachineState *machine) for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) { BusState *spi_bus; DeviceState *flash_dev; +ObjectClass *flash_klass; qemu_irq cs_line; DriveInfo *dinfo = drive_get(IF_MTD, 0, i); spi_bus = qdev_get_child_bus(DEVICE(>soc.pmc.iou.ospi), "spi0"); -flash_dev = qdev_new("mt35xu01g"); +if (s->ospi_model) { +flash_klass = object_class_by_name(s->ospi_model); +if (!flash_klass || +object_class_is_abstract(flash_klass) || +!object_class_dynamic_cast(flash_klass, "m25p80-generic")) { +error_setg(_fatal, "'%s' is either abstract or" + " not a subtype of m25p80", s->ospi_model); +return; +} +} + +flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g"); + if (dinfo) { qdev_prop_set_drive_err(flash_dev, "drive", blk_by_legacy_dinfo(dinfo), _fatal); @@ -770,6 +800,13 @@ static void versal_virt_machine_instance_init(Object *obj) 0); } +static void versal_virt_machine_finalize(Object *obj) +{ +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj); + +g_free(s->ospi_model); +} + static void versal_virt_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -781,6 +818,10 @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data) mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; mc->no_cdrom = true; mc->default_ram_id = "ddr"; +object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model, + versal_set_ospi_model); +object_class_property_set_description(oc, "ospi-flash", + "Change the OSPI Flash model"); } static const TypeInfo versal_virt_machine_init_typeinfo = { @@ -789,6 +830,7 @@ static const TypeInfo versal_virt_machine_init_typeinfo = { .class_init = versal_virt_machine_class_init, .instance_init = versal_virt_machine_instance_init, .instance_size = sizeof(VersalVirt), +.instance_finalize = versal_virt_machine_finalize, }; static void versal_virt_machine_init_register_types(void) -- 2.25.1
[PATCH v2] xlnx-versal-ospi: disable reentrancy detection for iomem_dac
The OSPI DMA reads flash data through the OSPI linear address space (the iomem_dac region), because of this the reentrancy guard introduced in commit a2e1753b ("memory: prevent dma-reentracy issues") is disabled for the memory region. Signed-off-by: Sai Pavan Boddu --- Changes for V2: Added code comments. hw/ssi/xlnx-versal-ospi.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/hw/ssi/xlnx-versal-ospi.c b/hw/ssi/xlnx-versal-ospi.c index c7b95b1f37..c479138ec1 100644 --- a/hw/ssi/xlnx-versal-ospi.c +++ b/hw/ssi/xlnx-versal-ospi.c @@ -1772,6 +1772,12 @@ static void xlnx_versal_ospi_init(Object *obj) memory_region_init_io(>iomem_dac, obj, _dac_ops, s, TYPE_XILINX_VERSAL_OSPI "-dac", 0x2000); sysbus_init_mmio(sbd, >iomem_dac); +/* + * The OSPI DMA reads flash data through the OSPI linear address space (the + * iomem_dac region), because of this the reentrancy guard needs to be + * disabled. + */ +s->iomem_dac.disable_reentrancy_guard = true; sysbus_init_irq(sbd, >irq); -- 2.25.1
[PATCH 1/1] xlnx-versal-ospi: disable reentrancy detection for iomem_dac
The OSPI DMA reads flash data through the OSPI linear address space (the iomem_dac region), because of this the reentrancy guard introduced in commit a2e1753b ("memory: prevent dma-reentracy issues") is disabled for the memory region. Signed-off-by: Sai Pavan Boddu --- hw/ssi/xlnx-versal-ospi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ssi/xlnx-versal-ospi.c b/hw/ssi/xlnx-versal-ospi.c index 1a61679c2f..5123e7dde7 100644 --- a/hw/ssi/xlnx-versal-ospi.c +++ b/hw/ssi/xlnx-versal-ospi.c @@ -1772,6 +1772,7 @@ static void xlnx_versal_ospi_init(Object *obj) memory_region_init_io(>iomem_dac, obj, _dac_ops, s, TYPE_XILINX_VERSAL_OSPI "-dac", 0x2000); sysbus_init_mmio(sbd, >iomem_dac); +s->iomem_dac.disable_reentrancy_guard = true; sysbus_init_irq(sbd, >irq); -- 2.25.1
[PATCH 0/1] versal-ospi fix
Disable reentrancy on iomem_dac memory-region. Sai Pavan Boddu (1): xlnx-versal-ospi: disable reentrancy detection for iomem_dac hw/ssi/xlnx-versal-ospi.c | 1 + 1 file changed, 1 insertion(+) -- 2.25.1
[PATCH 0/2] OSPI updates
Add a new 2Gib octal flash mt35xu02gbba. Add an interface for versal virt board to swap the default flash. Sai Pavan Boddu (2): block: m25p80: Add support of mt35xu02gbba arm: xlnx-versal-virt: Add machine property ospi-flash hw/block/m25p80_sfdp.h| 1 + hw/arm/xlnx-versal-virt.c | 31 ++- hw/block/m25p80.c | 3 +++ hw/block/m25p80_sfdp.c| 36 4 files changed, 70 insertions(+), 1 deletion(-) -- 2.25.1
[PATCH 1/2] block: m25p80: Add support of mt35xu02gbba
Add Micro 2Gb OSPI flash part with sfdp data. Signed-off-by: Sai Pavan Boddu --- hw/block/m25p80_sfdp.h | 1 + hw/block/m25p80.c | 3 +++ hw/block/m25p80_sfdp.c | 36 3 files changed, 40 insertions(+) diff --git a/hw/block/m25p80_sfdp.h b/hw/block/m25p80_sfdp.h index 011a880f66..1733b56950 100644 --- a/hw/block/m25p80_sfdp.h +++ b/hw/block/m25p80_sfdp.h @@ -16,6 +16,7 @@ #define M25P80_SFDP_MAX_SIZE (1 << 24) uint8_t m25p80_sfdp_n25q256a(uint32_t addr); +uint8_t m25p80_sfdp_mt35xu02g(uint32_t addr); uint8_t m25p80_sfdp_mx25l25635e(uint32_t addr); uint8_t m25p80_sfdp_mx25l25635f(uint32_t addr); diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index afc3fdf4d6..c8c7f6c1c3 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -267,6 +267,9 @@ static const FlashPartInfo known_devices[] = { { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) }, { INFO_STACKED("mt35xu01g", 0x2c5b1b, 0x104100, 128 << 10, 1024, ER_4K | ER_32K, 2) }, +{ INFO_STACKED("mt35xu02gbba", 0x2c5b1c, 0x104100, 128 << 10, 2048, + ER_4K | ER_32K, 4), + .sfdp_read = m25p80_sfdp_mt35xu02g }, { INFO_STACKED("n25q00",0x20ba21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, { INFO_STACKED("n25q00a", 0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, { INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, diff --git a/hw/block/m25p80_sfdp.c b/hw/block/m25p80_sfdp.c index b33811a4f5..6ee2cfaf11 100644 --- a/hw/block/m25p80_sfdp.c +++ b/hw/block/m25p80_sfdp.c @@ -57,6 +57,42 @@ static const uint8_t sfdp_n25q256a[] = { }; define_sfdp_read(n25q256a); +static const uint8_t sfdp_mt35xu02g[] = { +0x53, 0x46, 0x44, 0x50, 0x06, 0x01, 0x01, 0xff, +0x00, 0x06, 0x01, 0x10, 0x30, 0x00, 0x00, 0xff, +0x84, 0x00, 0x01, 0x02, 0x80, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xe5, 0x20, 0x8a, 0xff, 0xff, 0xff, 0xff, 0x7f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, +0xff, 0xff, 0x00, 0x00, 0x0c, 0x20, 0x11, 0xd8, +0x0f, 0x52, 0x00, 0x00, 0x24, 0x5a, 0x99, 0x00, +0x8b, 0x8e, 0x03, 0xe1, 0xac, 0x01, 0x27, 0x38, +0x7a, 0x75, 0x7a, 0x75, 0xfb, 0xbd, 0xd5, 0x5c, +0x00, 0x00, 0x70, 0xff, 0x81, 0xb0, 0x38, 0x36, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x43, 0x0e, 0xff, 0xff, 0x21, 0xdc, 0x5c, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +define_sfdp_read(mt35xu02g); /* * Matronix -- 2.25.1
[PATCH 1/1] xlnx-versal-ospi: disable reentrancy detection for iomem_dac
The OSPI DMA reads flash data through the OSPI linear address space (the iomem_dac region), because of this the reentrancy guard introduced in commit a2e1753b ("memory: prevent dma-reentracy issues") is disabled for the memory region. Signed-off-by: Sai Pavan Boddu --- hw/ssi/xlnx-versal-ospi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ssi/xlnx-versal-ospi.c b/hw/ssi/xlnx-versal-ospi.c index 1a61679c2f..5123e7dde7 100644 --- a/hw/ssi/xlnx-versal-ospi.c +++ b/hw/ssi/xlnx-versal-ospi.c @@ -1772,6 +1772,7 @@ static void xlnx_versal_ospi_init(Object *obj) memory_region_init_io(>iomem_dac, obj, _dac_ops, s, TYPE_XILINX_VERSAL_OSPI "-dac", 0x2000); sysbus_init_mmio(sbd, >iomem_dac); +s->iomem_dac.disable_reentrancy_guard = true; sysbus_init_irq(sbd, >irq); -- 2.25.1
[PATCH 0/1] versal-ospi fix
Disable reentrancy on iomem_dac memory-region. Sai Pavan Boddu (1): xlnx-versal-ospi: disable reentrancy detection for iomem_dac hw/ssi/xlnx-versal-ospi.c | 1 + 1 file changed, 1 insertion(+) -- 2.25.1
[PATCH 2/2] arm: xlnx-versal-virt: Add machine property ospi-flash
This property allows users to change flash model on command line as below. ex: "-M xlnx-versal-virt,ospi-flash=mt35xu02gbba" Signed-off-by: Sai Pavan Boddu --- hw/arm/xlnx-versal-virt.c | 31 ++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 537118224f..c57cff74d8 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -49,6 +49,7 @@ struct VersalVirt { struct { bool secure; } cfg; +char *ospi_model; }; static void fdt_create(VersalVirt *s) @@ -637,6 +638,22 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) _fatal); } +static char *versal_get_ospi_model(Object *obj, Error **errp) +{ +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj); + +return g_strdup(s->ospi_model); +} + +static void versal_set_ospi_model(Object *obj, const char *value, Error **errp) +{ +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj); + +g_free(s->ospi_model); +s->ospi_model = g_strdup(value); +} + + static void versal_virt_init(MachineState *machine) { VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine); @@ -736,7 +753,7 @@ static void versal_virt_init(MachineState *machine) spi_bus = qdev_get_child_bus(DEVICE(>soc.pmc.iou.ospi), "spi0"); -flash_dev = qdev_new("mt35xu01g"); +flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g"); if (dinfo) { qdev_prop_set_drive_err(flash_dev, "drive", blk_by_legacy_dinfo(dinfo), _fatal); @@ -769,6 +786,13 @@ static void versal_virt_machine_instance_init(Object *obj) 0); } +static void versal_virt_machine_finalize(Object *obj) +{ +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj); + +g_free(s->ospi_model); +} + static void versal_virt_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -780,6 +804,10 @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data) mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; mc->no_cdrom = true; mc->default_ram_id = "ddr"; +object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model, + versal_set_ospi_model); +object_class_property_set_description(oc, "ospi-flash", + "Change the OSPI Flash model"); } static const TypeInfo versal_virt_machine_init_typeinfo = { @@ -788,6 +816,7 @@ static const TypeInfo versal_virt_machine_init_typeinfo = { .class_init = versal_virt_machine_class_init, .instance_init = versal_virt_machine_instance_init, .instance_size = sizeof(VersalVirt), +.instance_finalize = versal_virt_machine_finalize, }; static void versal_virt_machine_init_register_types(void) -- 2.25.1
RE: [PATCH v3 02/21] sd: emmc: Add support for eMMC cards
Hi Cedric, > -Original Message- > From: Cédric Le Goater > Sent: Monday, March 1, 2021 4:32 PM > To: Sai Pavan Boddu ; Markus Armbruster > ; Kevin Wolf ; Max Reitz > ; Vladimir Sementsov-Ogievskiy > ; Eric Blake ; Joel Stanley > ; Vincent Palatin ; Dr. David Alan > Gilbert ; Thomas Huth ; Stefan > Hajnoczi ; Peter Maydell ; > Alistair Francis ; Edgar Iglesias > ; > Luc Michel ; Paolo Bonzini > > Cc: qemu-block@nongnu.org; qemu-de...@nongnu.org; Sai Pavan Boddu > > Subject: Re: [PATCH v3 02/21] sd: emmc: Add support for eMMC cards > > On 2/28/21 8:33 PM, Sai Pavan Boddu wrote: > > Add eMMC device built on top of SD card. > > > > Signed-off-by: Sai Pavan Boddu > > --- > > include/hw/sd/sd.h | 2 ++ > > hw/sd/sd.c | 20 > > 2 files changed, 22 insertions(+) > > > > diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index > > 05ef9b7..b402dad 100644 > > --- a/include/hw/sd/sd.h > > +++ b/include/hw/sd/sd.h > > @@ -90,6 +90,8 @@ typedef struct { > > } SDRequest; > > > > > > +#define TYPE_EMMC "emmc" > > +OBJECT_DECLARE_SIMPLE_TYPE(EMMCState, EMMC) > > #define TYPE_SD_CARD "sd-card" > > OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD) > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > index 74b9162..a23af6d 100644 > > --- a/hw/sd/sd.c > > +++ b/hw/sd/sd.c > > @@ -108,6 +108,7 @@ struct SDState { > > uint8_t spec_version; > > BlockBackend *blk; > > bool spi; > > +bool emmc; > > > > /* Runtime changeables */ > > > > @@ -143,6 +144,10 @@ struct SDState { > > bool cmd_line; > > }; > > > > +struct EMMCState { > > +SDState parent; > > +}; > > + > > static void sd_realize(DeviceState *dev, Error **errp); > > > > static const char *sd_state_name(enum SDCardStates state) @@ -2105,6 > > +2110,13 @@ static void sd_instance_init(Object *obj) > > sd->ocr_power_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, > > sd_ocr_powerup, sd); } > > > > +static void emmc_instance_init(Object *obj) { > > +SDState *sd = SD_CARD(obj); > > + > > +sd->emmc = true; > > +} > I think field 'emmc' would fit better in SDCardClass since it is a device > constant. > You should not need 'struct EMMCState'. So something like below. > Then you can add handlers for specific emmc commands. > > Thanks, > > C. > > > diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index > 47360ba4ee98..80e7cd526a57 100644 > --- a/include/hw/sd/sd.h > +++ b/include/hw/sd/sd.h > @@ -93,6 +93,8 @@ typedef struct { > #define TYPE_SD_CARD "sd-card" > OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD) > > +#define TYPE_EMMC "emmc" > + > struct SDCardClass { > /*< private >*/ > DeviceClass parent_class; > @@ -124,6 +126,8 @@ struct SDCardClass { > void (*enable)(SDState *sd, bool enable); > bool (*get_inserted)(SDState *sd); > bool (*get_readonly)(SDState *sd); > + > +bool emmc; > }; > > #define TYPE_SD_BUS "sd-bus" > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > index 660026f2a667..95608f11b36e 100644 > --- a/hw/sd/sd.c > +++ b/hw/sd/sd.c > @@ -2447,9 +2447,24 @@ static const TypeInfo sd_info = { > .instance_finalize = sd_instance_finalize, }; > > +static void emmc_class_init(ObjectClass *klass, void *data) { > +SDCardClass *sc = SD_CARD_CLASS(klass); > + > +sc->emmc = true; > +} > + > +static const TypeInfo emmc_info = { > +.name = TYPE_EMMC, > +.parent = TYPE_SD_CARD, > +.instance_size = sizeof(SDState), > +.class_init = emmc_class_init, > +}; > + [Sai Pavan Boddu] Yes, I see your point. Let me try, I was preferring a simpler approach just to not disturb the code much but lets see how this workout. Thanks, Sai Pavan > static void sd_register_types(void) > { > type_register_static(_info); > +type_register_static(_info); > } > > type_init(sd_register_types)
RE: [PATCH v3 12/21] sd: emmc: add CMD21 tuning sequence
Hi David, > -Original Message- > From: Dr. David Alan Gilbert > Sent: Monday, March 1, 2021 4:12 PM > To: Sai Pavan Boddu > Cc: Markus Armbruster ; Kevin Wolf > ; Max Reitz ; Vladimir Sementsov- > Ogievskiy ; Eric Blake ; > Joel Stanley ; Cédric Le Goater ; Vincent > Palatin ; Thomas Huth ; Stefan > Hajnoczi ; Peter Maydell ; > Alistair Francis ; Edgar Iglesias > ; > Luc Michel ; Paolo Bonzini > ; qemu-block@nongnu.org; qemu-de...@nongnu.org; > Sai Pavan Boddu > Subject: Re: [PATCH v3 12/21] sd: emmc: add CMD21 tuning sequence > > * Sai Pavan Boddu (sai.pavan.bo...@xilinx.com) wrote: > > eMMC cards support tuning sequence for entering HS200 mode. > > > > Signed-off-by: Sai Pavan Boddu > > Signed-off-by: Edgar E. Iglesias > > --- > > hw/sd/sd.c | 47 +++ > > 1 file changed, 47 insertions(+) > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > index bf963ec..174c28e 100644 > > --- a/hw/sd/sd.c > > +++ b/hw/sd/sd.c > > @@ -1386,6 +1386,14 @@ static sd_rsp_type_t > sd_normal_command(SDState *sd, SDRequest req) > > } > > break; > > > > +case 21:/* CMD21: mmc SEND TUNING_BLOCK */ > > +if (sd->emmc && (sd->state == sd_transfer_state)) { > > +sd->state = sd_sendingdata_state; > > +sd->data_offset = 0; > > +return sd_r1; > > +} > > +break; > > + > > case 23:/* CMD23: SET_BLOCK_COUNT */ > > if (sd->spec_version < SD_PHY_SPECv3_01_VERS) { > > break; > > @@ -2120,6 +2128,30 @@ static const uint8_t > sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { > > 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, > > }; > > > > +#define EXCSD_BUS_WIDTH_OFFSET 183 > > +#define BUS_WIDTH_8_MASK0x4 > > +#define BUS_WIDTH_4_MASK0x2 > > +#define MMC_TUNING_BLOCK_SIZE 128 > > + > > +static const uint8_t mmc_tunning_block_pattern[128] = { > > + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, > > + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, > > + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, > > + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, > > + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, > > + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, > > + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, > > + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, > > + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, > > + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, > > + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, > > + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, > > + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, > > + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, > > + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, > > + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, > > Where does this magic pattern come from? Is it part of some spec? [Sai Pavan Boddu] Yes its part of JEDEC eMMC spec. It's the tuning sequence for HS200 mode. Regards, Sai Pavan > > Dave > > > +}; > > + > > uint8_t sd_read_byte(SDState *sd) > > { > > /* TODO: Append CRCs */ > > @@ -2213,6 +2245,21 @@ uint8_t sd_read_byte(SDState *sd) > > ret = sd_tuning_block_pattern[sd->data_offset++]; > > break; > > > > +case 21:/* CMD21: SEND_TUNNING_BLOCK (MMC) */ > > +if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { > > +sd->state = sd_transfer_state; > > +} > > +if (sd->ext_csd[EXCSD_BUS_WIDTH_OFFSET] & BUS_WIDTH_8_MASK) { > > +ret = mmc_tunning_block_pattern[sd->data_offset++]; > > +} else { > > +/* Return LSB Nibbles of two byte from the 8bit tuning block > > + * for 4bit mode > > + */ > > +ret = mmc_tunning_block_pattern[sd->data_offset++] & 0x0F; > > +ret |= (mmc_tunning_block_pattern[sd->data_offset++] & 0x0F) > > << 4; > > +} > > +break; > > + > > case 22:/* ACMD22: SEND_NUM_WR_BLOCKS */ > > ret = sd->data[sd->data_offset ++]; > > > > -- > > 2.7.4 > > > -- > Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK
[PATCH v3 14/21] sd: emmc: Add support for emmc erase
Add CMD35 and CMD36 which sets the erase start and end. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 09c1222..bba0446 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1552,6 +1552,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) /* Erase commands (Class 5) */ case 32:/* CMD32: ERASE_WR_BLK_START */ +case 35:/* CMD35: ERASE_GROUP_START */ switch (sd->state) { case sd_transfer_state: sd->erase_start = req.arg; @@ -1563,6 +1564,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) break; case 33:/* CMD33: ERASE_WR_BLK_END */ +case 36:/* CMD36: ERASE_GROUP_END */ switch (sd->state) { case sd_transfer_state: sd->erase_end = req.arg; -- 2.7.4
[PATCH v3 19/21] arm: xlnx-versal: Add emmc to versal
Configuring SDHCI-0 to act as eMMC controller. Signed-off-by: Sai Pavan Boddu --- include/hw/arm/xlnx-versal.h | 1 + hw/arm/xlnx-versal-virt.c| 29 + hw/arm/xlnx-versal.c | 14 -- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 2b76885..440f3b4 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -76,6 +76,7 @@ struct Versal { struct { MemoryRegion *mr_ddr; uint32_t psci_conduit; +bool has_emmc; } cfg; }; diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 8482cd6..053a322 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -46,6 +46,7 @@ struct VersalVirt { struct { bool secure; +bool has_emmc; } cfg; }; @@ -333,6 +334,13 @@ static void fdt_add_sd_nodes(VersalVirt *s) qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", 2, addr, 2, MM_PMC_SD0_SIZE); qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +/* + * eMMC specific properties + */ +if (s->cfg.has_emmc && i == 0) { +qemu_fdt_setprop(s->fdt, name, "non-removable", NULL, 0); +qemu_fdt_setprop_sized_cells(s->fdt, name, "bus-width", 1, 8); +} g_free(name); } } @@ -524,11 +532,17 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) _fatal); } +static void versal_virt_set_emmc(Object *obj, bool value, Error **errp) +{ +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj); + +s->cfg.has_emmc = value; +} + static void versal_virt_init(MachineState *machine) { VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine); int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; -int i; /* * If the user provides an Operating System to be loaded, we expect them @@ -560,6 +574,8 @@ static void versal_virt_init(MachineState *machine) _abort); object_property_set_int(OBJECT(>soc), "psci-conduit", psci_conduit, _abort); +object_property_set_bool(OBJECT(>soc), "has-emmc", s->cfg.has_emmc, + _abort); sysbus_realize(SYS_BUS_DEVICE(>soc), _fatal); fdt_create(s); @@ -581,10 +597,12 @@ static void versal_virt_init(MachineState *machine) memory_region_add_subregion_overlap(get_system_memory(), 0, >soc.fpd.apu.mr, 0); -/* Plugin SD cards. */ -for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) { -sd_plugin_card(>soc.pmc.iou.sd[i], drive_get_next(IF_SD)); +if (!s->cfg.has_emmc) { +sd_plugin_card(>soc.pmc.iou.sd[0], +drive_get_next(IF_SD)); } +/* Plugin SD cards. */ +sd_plugin_card(>soc.pmc.iou.sd[1], drive_get_next(IF_SD)); s->binfo.ram_size = machine->ram_size; s->binfo.loader_start = 0x0; @@ -621,6 +639,9 @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data) mc->default_cpus = XLNX_VERSAL_NR_ACPUS; mc->no_cdrom = true; mc->default_ram_id = "ddr"; +object_class_property_add_bool(oc, "emmc", +NULL, versal_virt_set_emmc); + } static const TypeInfo versal_virt_machine_init_typeinfo = { diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 628e77e..6ca2c8f 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -230,6 +230,9 @@ static void versal_create_admas(Versal *s, qemu_irq *pic) } #define SDHCI_CAPABILITIES 0x280737ec6481 /* Same as on ZynqMP. */ +#define SDHCI_EMMC_CAPS ((SDHCI_CAPABILITIES & ~(3 << 30)) | \ + (1 << 30)) + static void versal_create_sds(Versal *s, qemu_irq *pic) { int i; @@ -242,11 +245,17 @@ static void versal_create_sds(Versal *s, qemu_irq *pic) TYPE_SYSBUS_SDHCI); dev = DEVICE(>pmc.iou.sd[i]); +dev->id = g_strdup_printf("sdhci%d", i); object_property_set_uint(OBJECT(dev), "sd-spec-version", 3, _fatal); -object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES, +object_property_set_uint(OBJECT(dev), "capareg", SDHCI_EMMC_CAPS, _fatal); -object_property_set_uint(OBJECT(dev), "uhs", UHS_I, _fatal); +/* + * UHS is not applicable for eMMC + */ +if (!s->cfg.has_emmc || i == 1) { +object_property_set_uint(OBJECT(dev), "uhs", UHS_I, _fatal); +} sysbus_realize(SYS_BUS_DEVICE(dev), _fatal); mr = sys
[PATCH v3 16/21] sd: emmc: Support boot area in emmc image
From: Joel Stanley This assumes a specially constructued image: dd if=/dev/zero of=mmc-bootarea.img count=2 bs=1M dd if=u-boot-spl.bin of=mmc-bootarea.img conv=notrunc dd if=u-boot.bin of=mmc-bootarea.img conv=notrunc count=64 bs=1K cat mmc-bootarea.img obmc-phosphor-image.wic > mmc.img truncate --size 16GB mmc.img truncate --size 128MB mmc-bootarea.img Signed-off-by: Joel Stanley [clg: - changes on the definition names ] Signed-off-by: Cédric Le Goater [spb: use data_start property to access right emmc partition, Clean up PARTITION_ENABLE support as incomplete, Fix commit message to be generic.] Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 40 1 file changed, 40 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 08b77ad..d311477 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1044,6 +1044,34 @@ static void sd_lock_command(SDState *sd) sd->card_status &= ~CARD_IS_LOCKED; } +/* + * This requires a disk image that has two boot partitions inserted at the + * beginning of it. The size of the boot partitions are configured in the + * ext_csd structure, which is hardcoded in qemu. They are currently set to + * 1MB each. + */ +static uint32_t sd_bootpart_offset(SDState *sd) +{ +unsigned int access = sd->ext_csd[EXT_CSD_PART_CONFIG] & +EXT_CSD_PART_CONFIG_ACC_MASK; +unsigned int boot_capacity = sd->ext_csd[EXT_CSD_BOOT_MULT] << 17; + +if (!sd->emmc) { +return 0; +} + +switch (access) { +case EXT_CSD_PART_CONFIG_ACC_DEFAULT: +return boot_capacity * 2; +case EXT_CSD_PART_CONFIG_ACC_BOOT0: +return 0; +case EXT_CSD_PART_CONFIG_ACC_BOOT0 + 1: +return boot_capacity * 1; +default: + g_assert_not_reached(); +} +} + static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) { uint32_t rca = 0x; @@ -1359,6 +1387,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1378,6 +1409,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1434,6 +1468,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1464,6 +1501,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; -- 2.7.4
[PATCH v3 01/21] sd: sd: Remove usage of tabs in the file
Set tabstop as 4 and used expandtabs Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 190 ++--- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 8517dbc..74b9162 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -332,39 +332,39 @@ static void sd_set_scr(SDState *sd) sd->scr[7] = 0x00; } -#define MID0xaa -#define OID"XY" -#define PNM"QEMU!" -#define PRV0x01 -#define MDT_YR 2006 -#define MDT_MON2 +#define MID 0xaa +#define OID "XY" +#define PNM "QEMU!" +#define PRV 0x01 +#define MDT_YR 2006 +#define MDT_MON 2 static void sd_set_cid(SDState *sd) { -sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ -sd->cid[1] = OID[0]; /* OEM/Application ID (OID) */ +sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ +sd->cid[1] = OID[0];/* OEM/Application ID (OID) */ sd->cid[2] = OID[1]; -sd->cid[3] = PNM[0]; /* Fake product name (PNM) */ +sd->cid[3] = PNM[0];/* Fake product name (PNM) */ sd->cid[4] = PNM[1]; sd->cid[5] = PNM[2]; sd->cid[6] = PNM[3]; sd->cid[7] = PNM[4]; -sd->cid[8] = PRV; /* Fake product revision (PRV) */ -sd->cid[9] = 0xde; /* Fake serial number (PSN) */ +sd->cid[8] = PRV; /* Fake product revision (PRV) */ +sd->cid[9] = 0xde; /* Fake serial number (PSN) */ sd->cid[10] = 0xad; sd->cid[11] = 0xbe; sd->cid[12] = 0xef; -sd->cid[13] = 0x00 | /* Manufacture date (MDT) */ +sd->cid[13] = 0x00 |/* Manufacture date (MDT) */ ((MDT_YR - 2000) / 10); sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; } -#define HWBLOCK_SHIFT 9 /* 512 bytes */ -#define SECTOR_SHIFT 5 /* 16 kilobytes */ -#define WPGROUP_SHIFT 7 /* 2 megs */ -#define CMULT_SHIFT9 /* 512 times HWBLOCK_SIZE */ -#define WPGROUP_SIZE (1 << (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) +#define HWBLOCK_SHIFT 9 /* 512 bytes */ +#define SECTOR_SHIFT5 /* 16 kilobytes */ +#define WPGROUP_SHIFT 7 /* 2 megs */ +#define CMULT_SHIFT 9 /* 512 times HWBLOCK_SIZE */ +#define WPGROUP_SIZE(1 << (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) static const uint8_t sd_csd_rw_mask[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -385,31 +385,31 @@ static void sd_set_csd(SDState *sd, uint64_t size) csize = (size >> (CMULT_SHIFT + hwblock_shift)) - 1; if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */ -sd->csd[0] = 0x00; /* CSD structure */ -sd->csd[1] = 0x26; /* Data read access-time-1 */ -sd->csd[2] = 0x00; /* Data read access-time-2 */ +sd->csd[0] = 0x00; /* CSD structure */ +sd->csd[1] = 0x26; /* Data read access-time-1 */ +sd->csd[2] = 0x00; /* Data read access-time-2 */ sd->csd[3] = 0x32; /* Max. data transfer rate: 25 MHz */ -sd->csd[4] = 0x5f; /* Card Command Classes */ -sd->csd[5] = 0x50 |/* Max. read data block length */ +sd->csd[4] = 0x5f; /* Card Command Classes */ +sd->csd[5] = 0x50 | /* Max. read data block length */ hwblock_shift; -sd->csd[6] = 0xe0 |/* Partial block for read allowed */ +sd->csd[6] = 0xe0 | /* Partial block for read allowed */ ((csize >> 10) & 0x03); -sd->csd[7] = 0x00 |/* Device size */ +sd->csd[7] = 0x00 | /* Device size */ ((csize >> 2) & 0xff); -sd->csd[8] = 0x3f |/* Max. read current */ +sd->csd[8] = 0x3f | /* Max. read current */ ((csize << 6) & 0xc0); -sd->csd[9] = 0xfc |/* Max. write current */ +sd->csd[9] = 0xfc | /* Max. write current */ ((CMULT_SHIFT - 2) >> 1); -sd->csd[10] = 0x40 | /* Erase sector size */ +sd->csd[10] = 0x40 |/* Erase sector size */ (((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1); -sd->csd[11] = 0x00 | /* Write protect group size */ +sd->csd[11] = 0x00 |/* Write protect group size */ ((sectsize << 7) & 0x80) | wpsize; -sd->csd[12] = 0x90 | /* Write speed factor */ +sd->csd[12] = 0x90 |/* Write speed factor */ (hwblock_shift >> 2); -sd->csd[13] = 0x20 | /* Max. write data block length */ +sd->csd[13] = 0x20 |/* Max. write data block length */ ((hwblock_shift << 6) &am
[PATCH v3 18/21] sd: sdhci: Support eMMC devices
Embedded device slots should be allowed as support of eMMC is available. Signed-off-by: Sai Pavan Boddu --- hw/sd/sdhci.c | 4 1 file changed, 4 deletions(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 8ffa539..771212a 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -99,10 +99,6 @@ static void sdhci_check_capareg(SDHCIState *s, Error **errp) msk = FIELD_DP64(msk, SDHC_CAPAB, ASYNC_INT, 0); val = FIELD_EX64(s->capareg, SDHC_CAPAB, SLOT_TYPE); -if (val) { -error_setg(errp, "slot-type not supported"); -return; -} trace_sdhci_capareg("slot type", val); msk = FIELD_DP64(msk, SDHC_CAPAB, SLOT_TYPE, 0); -- 2.7.4
[PATCH v3 04/21] sd: emmc: update OCR fields for eMMC
From: Vincent Palatin eMMC OCR register doesn't has UHS-II field and voltage fields are different. Signed-off-by: Vincent Palatin Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 27 --- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 6de414b..bc9d913 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -287,6 +287,15 @@ FIELD(OCR, UHS_II_CARD,29, 1) /* Only UHS-II */ FIELD(OCR, CARD_CAPACITY, 30, 1) /* 0:SDSC, 1:SDHC/SDXC */ FIELD(OCR, CARD_POWER_UP, 31, 1) +/* + * eMMC OCR register + */ +FIELD(EMMC_OCR, VDD_WINDOW_0, 7, 1) +FIELD(EMMC_OCR, VDD_WINDOW_1, 8, 7) +FIELD(EMMC_OCR, VDD_WINDOW_2, 15, 9) +FIELD(EMMC_OCR, ACCESS_MODE, 29, 2) +FIELD(EMMC_OCR, POWER_UP, 31, 1) + #define ACMD41_ENQUIRY_MASK 0x00ff #define ACMD41_R3_MASK (R_OCR_VDD_VOLTAGE_WIN_HI_MASK \ | R_OCR_ACCEPT_SWITCH_1V8_MASK \ @@ -296,8 +305,16 @@ FIELD(OCR, CARD_POWER_UP, 31, 1) static void sd_set_ocr(SDState *sd) { -/* All voltages OK */ -sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; +if (sd->emmc) { +/* + * Dual Voltage eMMC card + */ +sd->ocr = R_EMMC_OCR_VDD_WINDOW_0_MASK | + R_EMMC_OCR_VDD_WINDOW_2_MASK; +} else { +/* All voltages OK */ +sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; +} } static void sd_ocr_powerup(void *opaque) @@ -525,7 +542,11 @@ static void sd_response_r1_make(SDState *sd, uint8_t *response) static void sd_response_r3_make(SDState *sd, uint8_t *response) { -stl_be_p(response, sd->ocr & ACMD41_R3_MASK); +if (sd->emmc) { +stl_be_p(response, sd->ocr); +} else { +stl_be_p(response, sd->ocr & ACMD41_R3_MASK); +} } static void sd_response_r6_make(SDState *sd, uint8_t *response) -- 2.7.4
[PATCH v3 11/21] sd: emmc: Add mmc switch function support
switch operation in eMMC card updates the ext_csd register to request changes in card operations. Here we implement similar sequence but requests are mostly dummy and make no change. Implement SWITCH_ERROR if the write operation extends goes beyond length of ext_csd. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 56 ++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 8a7d0de..bf963ec 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -523,6 +523,7 @@ static void sd_set_rca(SDState *sd, uint16_t value) FIELD(CSR, AKE_SEQ_ERROR, 3, 1) FIELD(CSR, APP_CMD, 5, 1) FIELD(CSR, FX_EVENT,6, 1) +FIELD(CSR, SWITCH_ERROR,7, 1) FIELD(CSR, READY_FOR_DATA, 8, 1) FIELD(CSR, CURRENT_STATE, 9, 4) FIELD(CSR, ERASE_RESET,13, 1) @@ -886,6 +887,43 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) return ret; } +enum { +MMC_CMD6_ACCESS_COMMAND_SET = 0, +MMC_CMD6_ACCESS_SET_BITS, +MMC_CMD6_ACCESS_CLEAR_BITS, +MMC_CMD6_ACCESS_WRITE_BYTE, +}; + +static void mmc_function_switch(SDState *sd, uint32_t arg) +{ +uint32_t access = extract32(arg, 24, 2); +uint32_t index = extract32(arg, 16, 8); +uint32_t value = extract32(arg, 8, 8); +uint8_t b = sd->ext_csd[index]; + +switch (access) { +case MMC_CMD6_ACCESS_COMMAND_SET: +qemu_log_mask(LOG_UNIMP, "MMC Command set switching not supported\n"); +return; +case MMC_CMD6_ACCESS_SET_BITS: +b |= value; +break; +case MMC_CMD6_ACCESS_CLEAR_BITS: +b &= ~value; +break; +case MMC_CMD6_ACCESS_WRITE_BYTE: +b = value; +break; +} + +if (index >= 192) { +sd->card_status |= R_CSR_SWITCH_ERROR_MASK; +return; +} + +sd->ext_csd[index] = b; +} + static void sd_function_switch(SDState *sd, uint32_t arg) { int i, mode, new_func; @@ -1105,12 +1143,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) case 6: /* CMD6: SWITCH_FUNCTION */ switch (sd->mode) { case sd_data_transfer_mode: -sd_function_switch(sd, req.arg); -sd->state = sd_sendingdata_state; -sd->data_start = 0; -sd->data_offset = 0; -return sd_r1; - +if (sd->emmc) { +sd->state = sd_programming_state; +mmc_function_switch(sd, req.arg); +sd->state = sd_transfer_state; +return sd_r1b; +} else { +sd_function_switch(sd, req.arg); +sd->state = sd_sendingdata_state; +sd->data_start = 0; +sd->data_offset = 0; +return sd_r1; +} default: break; } -- 2.7.4
[PATCH v3 17/21] sd: emmc: Subtract bootarea size from blk
From: Joel Stanley The userdata size is derived from the file the user passes on the command line, but we must take into account the boot areas. Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater --- hw/sd/sd.c | 5 + 1 file changed, 5 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index d311477..5135a64 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -657,6 +657,11 @@ static void sd_reset(DeviceState *dev) } size = sect << 9; +if (sd->emmc) { +unsigned int boot_capacity = sd->ext_csd[EXT_CSD_BOOT_MULT] << 17; +size -= boot_capacity * 2; +} + sect = sd_addr_to_wpnum(size) + 1; sd->state = sd_idle_state; -- 2.7.4
[PATCH v3 20/21] docs: devel: emmc: Add a doc for emmc card emulation
Add few simple steps to create emmc card with boot and user data partitions. Signed-off-by: Sai Pavan Boddu --- docs/devel/emmc.txt | 16 1 file changed, 16 insertions(+) create mode 100644 docs/devel/emmc.txt diff --git a/docs/devel/emmc.txt b/docs/devel/emmc.txt new file mode 100644 index 000..2d098fe --- /dev/null +++ b/docs/devel/emmc.txt @@ -0,0 +1,16 @@ + +eMMC block emulation + + +Any eMMC devices has 3 kinds of partitions Boot, RPMB and User data. We +are supporting Boot and User data partitions. Boot area partitions are +expected to be 1MB size as hard coded in EXT_CSD register. + +Below is the example of combining two 1MB bootarea partition and +user data partitions. + + cat mmc-bootarea0.bin mmc-bootarea1.bin image.wic > mmc.img + qemu-img resize mmc.img 4G + +Note: mmc-bootarea0/1 are just raw paritions. User data can have +partition tables. -- 2.7.4
[PATCH v3 10/21] sd: emmc: support idle state in CMD2
eMMC is expected to be in idle-state post CMD1. Ready state is an intermediate stage which we don't come across in Device identification mode. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Reviewed-by: Alistair Francis --- hw/sd/sd.c | 4 1 file changed, 4 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 054ad1e..8a7d0de 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1059,6 +1059,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) if (sd->spi) goto bad_cmd; switch (sd->state) { +case sd_idle_state: +if (!sd->emmc) { +break; +} case sd_ready_state: sd->state = sd_identification_state; return sd_r2_i; -- 2.7.4
[PATCH v3 00/21] eMMC support
Hi, This patch series add support for eMMC cards. This work was previosly submitted by Vincent, rebased few changes on top. Cedric & Joel has helped to added boot partition access support. I expect them to make a follow-up series to use it with aspeed machines. Present series adds eMMC support to Versal SOC. Initial patch series version is RFC Changes for V2: Split Patch 1 Add comments for eMMC Erase commands Added documentation about eMMC and Versal-virt board. Make eMMC optional for xlnx-versal-virt machines Changes for V3: Revome addition of EMMC drive flag Add TYPE_EMMC device Add id strings for shci instances Update versal doc with eMMC example Fix signed-off-by lines for few patches Cédric Le Goater (1): sd: sdmmc-internal: Add command string for SEND_OP_CMD Joel Stanley (2): sd: emmc: Support boot area in emmc image sd: emmc: Subtract bootarea size from blk Sai Pavan Boddu (14): sd: sd: Remove usage of tabs in the file sd: emmc: Add support for eMMC cards sd: emmc: Dont not update CARD_CAPACITY for eMMC cards sd: emmc: Update CMD1 definition for eMMC sd: emmc: support idle state in CMD2 sd: emmc: Add mmc switch function support sd: emmc: add CMD21 tuning sequence sd: emmc: Make ACMD41 illegal for mmc sd: emmc: Add support for emmc erase sd: emmc: Update CID structure for eMMC sd: sdhci: Support eMMC devices arm: xlnx-versal: Add emmc to versal docs: devel: emmc: Add a doc for emmc card emulation docs: arm: xlnx-versal-virt: Add eMMC support documentation Vincent Palatin (4): sd: emmc: Update SET_RELATIVE_ADDR command sd: emmc: update OCR fields for eMMC sd: emmc: Add support for EXT_CSD & CSD for eMMC sd: emmc: Update CMD8 to send EXT_CSD register docs/devel/emmc.txt | 16 + docs/system/arm/xlnx-versal-virt.rst | 14 + hw/sd/sdmmc-internal.h | 97 ++ include/hw/arm/xlnx-versal.h | 1 + include/hw/sd/sd.h | 2 + hw/arm/xlnx-versal-virt.c| 29 +- hw/arm/xlnx-versal.c | 14 +- hw/sd/sd.c | 563 ++- hw/sd/sdhci.c| 4 - hw/sd/sdmmc-internal.c | 2 +- 10 files changed, 594 insertions(+), 148 deletions(-) create mode 100644 docs/devel/emmc.txt -- 2.7.4
[PATCH v3 03/21] sd: emmc: Update SET_RELATIVE_ADDR command
From: Vincent Palatin Change SET_RELATIVE_ADDR command to assign relative address as requested by user. Signed-off-by: Vincent Palatin Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater [spb: Split original patch series] Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index a23af6d..6de414b 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -436,9 +436,13 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1; } -static void sd_set_rca(SDState *sd) +static void sd_set_rca(SDState *sd, uint16_t value) { -sd->rca += 0x4567; +if (sd->emmc) { +sd->rca = value; +} else { +sd->rca += 0x4567; +} } FIELD(CSR, AKE_SEQ_ERROR, 3, 1) @@ -984,8 +988,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) case sd_identification_state: case sd_standby_state: sd->state = sd_standby_state; -sd_set_rca(sd); -return sd_r6; +sd_set_rca(sd, req.arg >> 16); +return sd->emmc ? sd_r1 : sd_r6; default: break; -- 2.7.4
[PATCH v3 15/21] sd: emmc: Update CID structure for eMMC
CID structure is little different for eMMC, w.r.t to product name and manufacturing date. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 47 ++- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index bba0446..08b77ad 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -365,23 +365,36 @@ static void sd_set_scr(SDState *sd) static void sd_set_cid(SDState *sd) { -sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ -sd->cid[1] = OID[0];/* OEM/Application ID (OID) */ -sd->cid[2] = OID[1]; -sd->cid[3] = PNM[0];/* Fake product name (PNM) */ -sd->cid[4] = PNM[1]; -sd->cid[5] = PNM[2]; -sd->cid[6] = PNM[3]; -sd->cid[7] = PNM[4]; -sd->cid[8] = PRV; /* Fake product revision (PRV) */ -sd->cid[9] = 0xde; /* Fake serial number (PSN) */ -sd->cid[10] = 0xad; -sd->cid[11] = 0xbe; -sd->cid[12] = 0xef; -sd->cid[13] = 0x00 |/* Manufacture date (MDT) */ -((MDT_YR - 2000) / 10); -sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; -sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; +if (sd->emmc) { +sd->cid[0] = MID; +sd->cid[1] = 0x1; /* CBX */ +sd->cid[2] = OID[0];/* OEM/Application ID (OID) */ +sd->cid[8] = 0x0; +sd->cid[9] = PRV;/* Fake product revision (PRV) */ +sd->cid[10] = 0xde; /* Fake serial number (PSN) */ +sd->cid[11] = 0xad; +sd->cid[12] = 0xbe; +sd->cid[13] = 0xef; +sd->cid[14] = ((MDT_YR - 1997) % 0x10); /* MDT */ +} else { +sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ +sd->cid[1] = OID[0];/* OEM/Application ID (OID) */ +sd->cid[2] = OID[1]; +sd->cid[8] = PRV; /* Fake product revision (PRV) */ +sd->cid[9] = 0xde; /* Fake serial number (PSN) */ +sd->cid[10] = 0xad; +sd->cid[11] = 0xbe; +sd->cid[12] = 0xef; +sd->cid[13] = 0x00 |/* Manufacture date (MDT) */ +((MDT_YR - 2000) / 10); +sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; + } + sd->cid[3] = PNM[0];/* Fake product name (PNM) 48bit */ + sd->cid[4] = PNM[1]; + sd->cid[5] = PNM[2]; + sd->cid[6] = PNM[3]; + sd->cid[7] = PNM[4]; + sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; } #define HWBLOCK_SHIFT 9 /* 512 bytes */ -- 2.7.4
[PATCH v3 12/21] sd: emmc: add CMD21 tuning sequence
eMMC cards support tuning sequence for entering HS200 mode. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 47 +++ 1 file changed, 47 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index bf963ec..174c28e 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1386,6 +1386,14 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } break; +case 21:/* CMD21: mmc SEND TUNING_BLOCK */ +if (sd->emmc && (sd->state == sd_transfer_state)) { +sd->state = sd_sendingdata_state; +sd->data_offset = 0; +return sd_r1; +} +break; + case 23:/* CMD23: SET_BLOCK_COUNT */ if (sd->spec_version < SD_PHY_SPECv3_01_VERS) { break; @@ -2120,6 +2128,30 @@ static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, }; +#define EXCSD_BUS_WIDTH_OFFSET 183 +#define BUS_WIDTH_8_MASK0x4 +#define BUS_WIDTH_4_MASK0x2 +#define MMC_TUNING_BLOCK_SIZE 128 + +static const uint8_t mmc_tunning_block_pattern[128] = { + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, +}; + uint8_t sd_read_byte(SDState *sd) { /* TODO: Append CRCs */ @@ -2213,6 +2245,21 @@ uint8_t sd_read_byte(SDState *sd) ret = sd_tuning_block_pattern[sd->data_offset++]; break; +case 21:/* CMD21: SEND_TUNNING_BLOCK (MMC) */ +if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { +sd->state = sd_transfer_state; +} +if (sd->ext_csd[EXCSD_BUS_WIDTH_OFFSET] & BUS_WIDTH_8_MASK) { +ret = mmc_tunning_block_pattern[sd->data_offset++]; +} else { +/* Return LSB Nibbles of two byte from the 8bit tuning block + * for 4bit mode + */ +ret = mmc_tunning_block_pattern[sd->data_offset++] & 0x0F; +ret |= (mmc_tunning_block_pattern[sd->data_offset++] & 0x0F) << 4; +} +break; + case 22:/* ACMD22: SEND_NUM_WR_BLOCKS */ ret = sd->data[sd->data_offset ++]; -- 2.7.4
[PATCH v3 05/21] sd: emmc: Add support for EXT_CSD & CSD for eMMC
From: Vincent Palatin eMMC CSD is similar to SD with an option to refer EXT_CSD for larger devices. Signed-off-by: Vincent Palatin [clg: Add user friendly macros for EXT_CSD register] Signed-off-by: Cédric Le Goater [spb: updated commit message] Signed-off-by: Sai Pavan Boddu --- hw/sd/sdmmc-internal.h | 97 ++ hw/sd/sd.c | 61 +-- 2 files changed, 156 insertions(+), 2 deletions(-) diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h index d8bf17d..7ab7b4d 100644 --- a/hw/sd/sdmmc-internal.h +++ b/hw/sd/sdmmc-internal.h @@ -37,4 +37,101 @@ const char *sd_cmd_name(uint8_t cmd); */ const char *sd_acmd_name(uint8_t cmd); +/* + * EXT_CSD fields + */ + +#define EXT_CSD_CMDQ_MODE_EN15 /* R/W */ +#define EXT_CSD_FLUSH_CACHE 32 /* W */ +#define EXT_CSD_CACHE_CTRL33 /* R/W */ +#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ +#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */ +#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */ +#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */ +#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */ +#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ +#define EXT_CSD_GP_SIZE_MULT143 /* R/W */ +#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ +#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ +#define EXT_CSD_HPI_MGMT161 /* R/W */ +#define EXT_CSD_RST_N_FUNCTION162 /* R/W */ +#define EXT_CSD_BKOPS_EN163 /* R/W */ +#define EXT_CSD_BKOPS_START 164 /* W */ +#define EXT_CSD_SANITIZE_START165 /* W */ +#define EXT_CSD_WR_REL_PARAM166 /* RO */ +#define EXT_CSD_RPMB_MULT 168 /* RO */ +#define EXT_CSD_FW_CONFIG 169 /* R/W */ +#define EXT_CSD_BOOT_WP 173 /* R/W */ +#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ +#define EXT_CSD_PART_CONFIG 179 /* R/W */ +#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ +#define EXT_CSD_BUS_WIDTH 183 /* R/W */ +#define EXT_CSD_STROBE_SUPPORT184 /* RO */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_POWER_CLASS 187 /* R/W */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_STRUCTURE 194 /* RO */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */ +#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */ +#define EXT_CSD_PART_SWITCH_TIME199 /* RO */ +#define EXT_CSD_PWR_CL_52_195 200 /* RO */ +#define EXT_CSD_PWR_CL_26_195 201 /* RO */ +#define EXT_CSD_PWR_CL_52_360 202 /* RO */ +#define EXT_CSD_PWR_CL_26_360 203 /* RO */ +#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ +#define EXT_CSD_S_A_TIMEOUT 217 /* RO */ +#define EXT_CSD_S_C_VCCQ 219 /* RO */ +#define EXT_CSD_S_C_VCC 220 /* RO */ +#define EXT_CSD_REL_WR_SEC_C222 /* RO */ +#define EXT_CSD_HC_WP_GRP_SIZE221 /* RO */ +#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ +#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ +#define EXT_CSD_ACC_SIZE225 /* RO */ +#define EXT_CSD_BOOT_MULT 226 /* RO */ +#define EXT_CSD_BOOT_INFO 228 /* RO */ +#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ +#define EXT_CSD_SEC_ERASE_MULT230 /* RO */ +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ +#define EXT_CSD_TRIM_MULT 232 /* RO */ +#define EXT_CSD_PWR_CL_200_195236 /* RO */ +#define EXT_CSD_PWR_CL_200_360237 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ +#define EXT_CSD_BKOPS_STATUS246 /* RO */ +#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ +#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ +#define EXT_CSD_CACHE_SIZE249 /* RO, 4 bytes */ +#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ +#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */ +#define EXT_CSD_PRE_EOL_INFO267 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */ +#define EXT_CSD_CMDQ_DEPTH307 /* RO */ +#define EXT_CSD_CMDQ_SUPPORT308 /* RO */ +#define EXT_CSD_SUPPORTED_MODE493 /* RO */ +#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ +#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ +#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ +#define EXT_CSD_MAX_PACKED_READS 501 /* RO */ +#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ +#define EXT_CSD_HPI_FEATURES503 /* RO */ +#define EXT_CSD_S_CMD_SET 504 /* RO */ + +/* + * EXT_CSD field definitions + */ + +#define EXT_CSD_WR_REL_PARAM_EN (1 << 2) +#define EXT_CSD_WR_REL_PARAM_EN_RPMB_REL_WR (1 << 4) + +#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) +#define EXT_CSD_PART_CONFIG_ACC_DEFAULT (0x0) +#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) + +#define EXT_CSD_PART_CONFIG_EN_MASK (0x7 << 3) +#define EXT_CSD_PART_CONFIG_EN_BOOT0 (0x1 << 3) +#define EXT_CSD_PART_CONFIG_EN_USER (0x7 << 3) + #endif diff --git a/hw/sd/sd.c b/hw/sd/sd.c index bc9d913..a26695b 100644 --- a/hw/sd/s
[PATCH v3 06/21] sd: emmc: Update CMD8 to send EXT_CSD register
From: Vincent Palatin Sends the EXT_CSD register as response to CMD8. Signed-off-by: Vincent Palatin Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 52 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index a26695b..181e7e2 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1141,24 +1141,37 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } break; -case 8: /* CMD8: SEND_IF_COND */ -if (sd->spec_version < SD_PHY_SPECv2_00_VERS) { -break; -} -if (sd->state != sd_idle_state) { -break; -} -sd->vhs = 0; - -/* No response if not exactly one VHS bit is set. */ -if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) { -return sd->spi ? sd_r7 : sd_r0; -} +case 8:/* CMD8: SEND_IF_COND / SEND_EXT_CSD */ +if (sd->emmc) { +switch (sd->state) { +case sd_transfer_state: +/* MMC : Sends the EXT_CSD register as a Block of data */ +sd->state = sd_sendingdata_state; +memcpy(sd->data, sd->ext_csd, sizeof(sd->ext_csd)); +sd->data_start = addr; +sd->data_offset = 0; +return sd_r1; +default: +break; +} +} else { +if (sd->spec_version < SD_PHY_SPECv2_00_VERS) { +break; +} +if (sd->state != sd_idle_state) { +break; +} +sd->vhs = 0; -/* Accept. */ -sd->vhs = req.arg; -return sd_r7; +/* No response if not exactly one VHS bit is set. */ +if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) { +return sd->spi ? sd_r7 : sd_r0; +} +/* Accept. */ +sd->vhs = req.arg; +return sd_r7; +} case 9: /* CMD9: SEND_CSD */ switch (sd->state) { case sd_standby_state: @@ -2081,6 +2094,13 @@ uint8_t sd_read_byte(SDState *sd) sd->state = sd_transfer_state; break; +case 8: /* CMD8: SEND_EXT_CSD on MMC */ +ret = sd->data[sd->data_offset++]; +if (sd->data_offset >= sizeof(sd->ext_csd)) { +sd->state = sd_transfer_state; +} +break; + case 9: /* CMD9: SEND_CSD */ case 10:/* CMD10: SEND_CID */ ret = sd->data[sd->data_offset ++]; -- 2.7.4
[PATCH v3 07/21] sd: sdmmc-internal: Add command string for SEND_OP_CMD
From: Cédric Le Goater This adds extra info to trace log. Signed-off-by: Sai Pavan Boddu --- hw/sd/sdmmc-internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd/sdmmc-internal.c b/hw/sd/sdmmc-internal.c index 2053def..8648a78 100644 --- a/hw/sd/sdmmc-internal.c +++ b/hw/sd/sdmmc-internal.c @@ -14,7 +14,7 @@ const char *sd_cmd_name(uint8_t cmd) { static const char *cmd_abbrev[SDMMC_CMD_MAX] = { - [0]= "GO_IDLE_STATE", + [0]= "GO_IDLE_STATE", [1]= "SEND_OP_CMD", [2]= "ALL_SEND_CID",[3]= "SEND_RELATIVE_ADDR", [4]= "SET_DSR", [5]= "IO_SEND_OP_COND", [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD", -- 2.7.4
[PATCH v3 21/21] docs: arm: xlnx-versal-virt: Add eMMC support documentation
Add details of eMMC specific machine property and example for passing eMMC device. Signed-off-by: Sai Pavan Boddu --- docs/system/arm/xlnx-versal-virt.rst | 14 ++ 1 file changed, 14 insertions(+) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst index 2602d0f..d1099fa 100644 --- a/docs/system/arm/xlnx-versal-virt.rst +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -29,6 +29,7 @@ Implemented devices: - 2 GEMs (Cadence MACB Ethernet MACs) - 8 ADMA (Xilinx zDMA) channels - 2 SD Controllers +* SDHCI0 can be configured as eMMC - OCM (256KB of On Chip Memory) - DDR memory @@ -43,6 +44,19 @@ Other differences between the hardware and the QEMU model: - QEMU provides 8 virtio-mmio virtio transports; these start at address ``0xa000`` and have IRQs from 111 and upwards. +Enabling eMMC +""""""""""""" +In order to enable eMMC pass the following machine property "emmc=on". +ex: +"-M xlnx-versal-virt,emmc=on" + +Above switch would configure SDHCI0 to accept eMMC. More details on eMMC +emulation can be found in docs/devel/emmc.txt. + +Below is the command to pass eMMC device. +"-drive file=emmc.img,if=none,id=emmc,format=raw + -device emmc,drive=emmc,id=emmc0,bus=/sdhci0/sd-bus" + Running """"""" If the user provides an Operating System to be loaded, we expect users -- 2.7.4
[PATCH v3 13/21] sd: emmc: Make ACMD41 illegal for mmc
ACMD41 is not applicable for eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 174c28e..09c1222 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1737,6 +1737,9 @@ static sd_rsp_type_t sd_app_command(SDState *sd, break; case 41:/* ACMD41: SD_APP_OP_COND */ +if (sd->emmc) { +break; +} if (sd->spi) { /* SEND_OP_CMD */ sd->state = sd_transfer_state; -- 2.7.4
[PATCH v3 08/21] sd: emmc: Dont not update CARD_CAPACITY for eMMC cards
OCR.CARD_CAPACITY field is only valid for sd cards, So skip it for eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Reviewed-by: Alistair Francis --- hw/sd/sd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 181e7e2..2612135 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -328,7 +328,8 @@ static void sd_ocr_powerup(void *opaque) /* card power-up OK */ sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1); -if (sd->size > SDSC_MAX_CAPACITY) { +/* eMMC supports only Byte mode */ +if (!sd->emmc && sd->size > SDSC_MAX_CAPACITY) { sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1); } } -- 2.7.4
[PATCH v3 09/21] sd: emmc: Update CMD1 definition for eMMC
Add support to Power up the card and send response r3 in case of eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Reviewed-by: Alistair Francis --- hw/sd/sd.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 2612135..054ad1e 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1041,8 +1041,16 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) break; case 1: /* CMD1: SEND_OP_CMD */ -if (!sd->spi) +/* MMC: Powerup & send r3 + * SD: send r1 in spi mode + */ +if (sd->emmc) { +sd_ocr_powerup(sd); +return sd->state == sd_idle_state ? + sd_r3 : sd_r0; +} else if (!sd->spi) { goto bad_cmd; +} sd->state = sd_transfer_state; return sd_r1; -- 2.7.4
[PATCH v3 02/21] sd: emmc: Add support for eMMC cards
Add eMMC device built on top of SD card. Signed-off-by: Sai Pavan Boddu --- include/hw/sd/sd.h | 2 ++ hw/sd/sd.c | 20 2 files changed, 22 insertions(+) diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index 05ef9b7..b402dad 100644 --- a/include/hw/sd/sd.h +++ b/include/hw/sd/sd.h @@ -90,6 +90,8 @@ typedef struct { } SDRequest; +#define TYPE_EMMC "emmc" +OBJECT_DECLARE_SIMPLE_TYPE(EMMCState, EMMC) #define TYPE_SD_CARD "sd-card" OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 74b9162..a23af6d 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -108,6 +108,7 @@ struct SDState { uint8_t spec_version; BlockBackend *blk; bool spi; +bool emmc; /* Runtime changeables */ @@ -143,6 +144,10 @@ struct SDState { bool cmd_line; }; +struct EMMCState { +SDState parent; +}; + static void sd_realize(DeviceState *dev, Error **errp); static const char *sd_state_name(enum SDCardStates state) @@ -2105,6 +2110,13 @@ static void sd_instance_init(Object *obj) sd->ocr_power_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sd_ocr_powerup, sd); } +static void emmc_instance_init(Object *obj) +{ +SDState *sd = SD_CARD(obj); + +sd->emmc = true; +} + static void sd_instance_finalize(Object *obj) { SDState *sd = SD_CARD(obj); @@ -2213,9 +2225,17 @@ static const TypeInfo sd_info = { .instance_finalize = sd_instance_finalize, }; +static const TypeInfo emmc_info = { +.name = TYPE_EMMC, +.parent = TYPE_SD_CARD, +.instance_size = sizeof(EMMCState), +.instance_init = emmc_instance_init, +}; + static void sd_register_types(void) { type_register_static(_info); +type_register_static(_info); } type_init(sd_register_types) -- 2.7.4
RE: [PATCH v2 01/22] block: add eMMC block device type
Hi Cedric, > -Original Message- > From: Cédric Le Goater > Sent: Wednesday, February 24, 2021 7:25 PM > To: Stefan Hajnoczi ; Sai Pavan Boddu > > Cc: Philippe Mathieu-Daudé ; Markus Armbruster > ; Kevin Wolf ; Max Reitz > ; Vladimir Sementsov-Ogievskiy > ; Eric Blake ; Joel Stanley > ; Vincent Palatin ; Dr. David Alan > Gilbert ; Thomas Huth ; Peter > Maydell ; Alistair Francis > ; Edgar Iglesias ; Luc Michel > ; Paolo Bonzini ; qemu- > de...@nongnu.org; qemu-block@nongnu.org > Subject: Re: [PATCH v2 01/22] block: add eMMC block device type > > On 2/24/21 12:40 PM, Stefan Hajnoczi wrote: > > On Tue, Feb 23, 2021 at 05:35:20PM +, Sai Pavan Boddu wrote: > >> Hi Philippe, > >> > >>> -Original Message- > >>> From: Philippe Mathieu-Daudé > >>> Sent: Monday, February 22, 2021 5:34 PM > >>> To: Sai Pavan Boddu ; Markus Armbruster > >>> ; Kevin Wolf ; Max Reitz > >>> ; Vladimir Sementsov-Ogievskiy > >>> ; Eric Blake ; Joel > >>> Stanley ; Cédric Le Goater ; Vincent > >>> Palatin ; Dr. David Alan Gilbert > >>> ; Thomas Huth ; Stefan > >>> Hajnoczi ; Peter Maydell > >>> ; Alistair Francis > >>> ; Edgar Iglesias ; Luc > >>> Michel ; Paolo Bonzini > >>> > >>> Cc: Sai Pavan Boddu ; qemu-de...@nongnu.org; > >>> qemu- bl...@nongnu.org > >>> Subject: Re: [PATCH v2 01/22] block: add eMMC block device type > >>> > >>> On 2/22/21 9:20 AM, Sai Pavan Boddu wrote: > >>>> From: Vincent Palatin > >>>> > >>>> Add new block device type. > >>>> > >>>> Signed-off-by: Vincent Palatin > >>>> [SPB: Rebased over 5.1 version] > >>>> Signed-off-by: Sai Pavan Boddu > >>>> Signed-off-by: Joel Stanley > >>>> Signed-off-by: Cédric Le Goater > >>>> Reviewed-by: Alistair Francis > >>>> --- > >>>> include/sysemu/blockdev.h | 1 + > >>>> blockdev.c| 1 + > >>>> 2 files changed, 2 insertions(+) > >>>> > >>>> diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h > >>>> index 3b5fcda..eefae9f 100644 > >>>> --- a/include/sysemu/blockdev.h > >>>> +++ b/include/sysemu/blockdev.h > >>>> @@ -24,6 +24,7 @@ typedef enum { > >>>> */ > >>>> IF_NONE = 0, > >>>> IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, > >>>> IF_VIRTIO, IF_XEN, > >>>> +IF_EMMC, > >>>> IF_COUNT > >>>> } BlockInterfaceType; > >>>> > >>>> diff --git a/blockdev.c b/blockdev.c index cd438e6..390d43c 100644 > >>>> --- a/blockdev.c > >>>> +++ b/blockdev.c > >>>> @@ -83,6 +83,7 @@ static const char *const if_name[IF_COUNT] = { > >>>> [IF_SD] = "sd", > >>>> [IF_VIRTIO] = "virtio", > >>>> [IF_XEN] = "xen", > >>>> +[IF_EMMC] = "emmc", > >>>> }; > >>> > >>> We don't need to introduce support for the legacy -drive magic. > >>> > >>> -device should be enough for this device, right? > >> [Sai Pavan Boddu] I was seeing to use -device for emmc. But I see we > anyway need blockdev support for this, which would require us the use -drive. > >> > >> Can you give some pointers, how to approach this ? > > > > It is probably not necessary to add a new IF_ constant. Would this work: > > > > -drive if=none,id=emmc0,file=test.img,format=raw > > -device emmc,...,drive=emmc0 > > > > Or the more modern: > > > > -blockdev node-name=emmc0,driver=file,filename=test.img > > -device emmc,...,drive=emmc0 > > > > ? > > > > (The syntax might need small tweaks but is shows the general idea.) > > Yes. This is better. > > We could have an "emmc" device inheriting from "sd-card". The "emmc" > property would not be necessary anymore and may be, we could cleanup up > some parts doing : > > if (sd->emmc) { /* eMMC */ > ... > } else { > > } > > with SDCardClass handlers. the SWITCH_FUNCTION command is a good > candidate, CMD8 also. [Sai Pavan Boddu] Nice, this approach looks clean. But we still may be depending on emmc property. Not sure! I would get back with v3, your review on those patches would be great. Thanks & Regards, Sai Pavan > > C.
RE: [PATCH v2 01/22] block: add eMMC block device type
Hi Stefan > -Original Message- > From: Stefan Hajnoczi > Sent: Wednesday, February 24, 2021 5:10 PM > To: Sai Pavan Boddu > Cc: Philippe Mathieu-Daudé ; Markus Armbruster > ; Kevin Wolf ; Max Reitz > ; Vladimir Sementsov-Ogievskiy > ; Eric Blake ; Joel Stanley > ; Cédric Le Goater ; Vincent Palatin > ; Dr. David Alan Gilbert ; > Thomas Huth ; Peter Maydell > ; Alistair Francis ; Edgar > Iglesias ; Luc Michel ; Paolo > Bonzini ; qemu-de...@nongnu.org; qemu- > bl...@nongnu.org > Subject: Re: [PATCH v2 01/22] block: add eMMC block device type > > On Tue, Feb 23, 2021 at 05:35:20PM +, Sai Pavan Boddu wrote: > > Hi Philippe, > > > > > -Original Message- > > > From: Philippe Mathieu-Daudé > > > Sent: Monday, February 22, 2021 5:34 PM > > > To: Sai Pavan Boddu ; Markus Armbruster > > > ; Kevin Wolf ; Max Reitz > > > ; Vladimir Sementsov-Ogievskiy > > > ; Eric Blake ; Joel > > > Stanley ; Cédric Le Goater ; Vincent > > > Palatin ; Dr. David Alan Gilbert > > > ; Thomas Huth ; Stefan > > > Hajnoczi ; Peter Maydell > > > ; Alistair Francis > > > ; Edgar Iglesias ; Luc > > > Michel ; Paolo Bonzini > > > > > > Cc: Sai Pavan Boddu ; qemu-de...@nongnu.org; > > > qemu- bl...@nongnu.org > > > Subject: Re: [PATCH v2 01/22] block: add eMMC block device type > > > > > > On 2/22/21 9:20 AM, Sai Pavan Boddu wrote: > > > > From: Vincent Palatin > > > > > > > > Add new block device type. > > > > > > > > Signed-off-by: Vincent Palatin > > > > [SPB: Rebased over 5.1 version] > > > > Signed-off-by: Sai Pavan Boddu > > > > Signed-off-by: Joel Stanley > > > > Signed-off-by: Cédric Le Goater > > > > Reviewed-by: Alistair Francis > > > > --- > > > > include/sysemu/blockdev.h | 1 + > > > > blockdev.c| 1 + > > > > 2 files changed, 2 insertions(+) > > > > > > > > diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h > > > > index 3b5fcda..eefae9f 100644 > > > > --- a/include/sysemu/blockdev.h > > > > +++ b/include/sysemu/blockdev.h > > > > @@ -24,6 +24,7 @@ typedef enum { > > > > */ > > > > IF_NONE = 0, > > > > IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, > > > > IF_VIRTIO, IF_XEN, > > > > +IF_EMMC, > > > > IF_COUNT > > > > } BlockInterfaceType; > > > > > > > > diff --git a/blockdev.c b/blockdev.c index cd438e6..390d43c 100644 > > > > --- a/blockdev.c > > > > +++ b/blockdev.c > > > > @@ -83,6 +83,7 @@ static const char *const if_name[IF_COUNT] = { > > > > [IF_SD] = "sd", > > > > [IF_VIRTIO] = "virtio", > > > > [IF_XEN] = "xen", > > > > +[IF_EMMC] = "emmc", > > > > }; > > > > > > We don't need to introduce support for the legacy -drive magic. > > > > > > -device should be enough for this device, right? > > [Sai Pavan Boddu] I was seeing to use -device for emmc. But I see we anyway > need blockdev support for this, which would require us the use -drive. > > > > Can you give some pointers, how to approach this ? > > It is probably not necessary to add a new IF_ constant. Would this work: > > -drive if=none,id=emmc0,file=test.img,format=raw > -device emmc,...,drive=emmc0 [Sai Pavan Boddu] Great, this works for me. > > Or the more modern: > > -blockdev node-name=emmc0,driver=file,filename=test.img > -device emmc,...,drive=emmc0 [Sai Pavan Boddu] Thanks, I would try to follow the modern approach then! Regards, Sai Pavan > > ? > > (The syntax might need small tweaks but is shows the general idea.) > > Stefan
RE: [PATCH v2 01/22] block: add eMMC block device type
Hi Philippe, > -Original Message- > From: Philippe Mathieu-Daudé > Sent: Monday, February 22, 2021 5:34 PM > To: Sai Pavan Boddu ; Markus Armbruster > ; Kevin Wolf ; Max Reitz > ; Vladimir Sementsov-Ogievskiy > ; Eric Blake ; Joel Stanley > ; Cédric Le Goater ; Vincent Palatin > ; Dr. David Alan Gilbert ; > Thomas Huth ; Stefan Hajnoczi ; > Peter Maydell ; Alistair Francis > ; Edgar Iglesias ; Luc Michel > ; Paolo Bonzini > Cc: Sai Pavan Boddu ; qemu-de...@nongnu.org; qemu- > bl...@nongnu.org > Subject: Re: [PATCH v2 01/22] block: add eMMC block device type > > On 2/22/21 9:20 AM, Sai Pavan Boddu wrote: > > From: Vincent Palatin > > > > Add new block device type. > > > > Signed-off-by: Vincent Palatin > > [SPB: Rebased over 5.1 version] > > Signed-off-by: Sai Pavan Boddu > > Signed-off-by: Joel Stanley > > Signed-off-by: Cédric Le Goater > > Reviewed-by: Alistair Francis > > --- > > include/sysemu/blockdev.h | 1 + > > blockdev.c| 1 + > > 2 files changed, 2 insertions(+) > > > > diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h > > index 3b5fcda..eefae9f 100644 > > --- a/include/sysemu/blockdev.h > > +++ b/include/sysemu/blockdev.h > > @@ -24,6 +24,7 @@ typedef enum { > > */ > > IF_NONE = 0, > > IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, > > IF_XEN, > > +IF_EMMC, > > IF_COUNT > > } BlockInterfaceType; > > > > diff --git a/blockdev.c b/blockdev.c > > index cd438e6..390d43c 100644 > > --- a/blockdev.c > > +++ b/blockdev.c > > @@ -83,6 +83,7 @@ static const char *const if_name[IF_COUNT] = { > > [IF_SD] = "sd", > > [IF_VIRTIO] = "virtio", > > [IF_XEN] = "xen", > > +[IF_EMMC] = "emmc", > > }; > > We don't need to introduce support for the legacy -drive magic. > > -device should be enough for this device, right? [Sai Pavan Boddu] I was seeing to use -device for emmc. But I see we anyway need blockdev support for this, which would require us the use -drive. Can you give some pointers, how to approach this ? Regards, Sai Pavan
RE: [PATCH v2 01/22] block: add eMMC block device type
Hi Philippe, > -Original Message- > From: Philippe Mathieu-Daudé > Sent: Monday, February 22, 2021 6:54 PM > To: Dr. David Alan Gilbert ; Markus Armbruster > > Cc: Sai Pavan Boddu ; Kevin Wolf ; > Max Reitz ; Vladimir Sementsov-Ogievskiy > ; Eric Blake ; Joel Stanley > ; Cédric Le Goater ; Vincent Palatin > ; Thomas Huth ; Stefan > Hajnoczi ; Peter Maydell ; > Alistair Francis ; Edgar Iglesias > ; > Luc Michel ; Paolo Bonzini > ; Sai Pavan Boddu ; qemu- > de...@nongnu.org; qemu-block@nongnu.org > Subject: Re: [PATCH v2 01/22] block: add eMMC block device type > > On 2/22/21 2:16 PM, Dr. David Alan Gilbert wrote: > > * Markus Armbruster (arm...@redhat.com) wrote: > >> Philippe Mathieu-Daudé writes: > >> > >>> On 2/22/21 9:20 AM, Sai Pavan Boddu wrote: > >>>> From: Vincent Palatin > >>>> > >>>> Add new block device type. > >>>> > >>>> Signed-off-by: Vincent Palatin > >>>> [SPB: Rebased over 5.1 version] > >>>> Signed-off-by: Sai Pavan Boddu > >>>> Signed-off-by: Joel Stanley > >>>> Signed-off-by: Cédric Le Goater > >>>> Reviewed-by: Alistair Francis > >>>> --- > >>>> include/sysemu/blockdev.h | 1 + > >>>> blockdev.c| 1 + > >>>> 2 files changed, 2 insertions(+) > >>>> > >>>> diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h > >>>> index 3b5fcda..eefae9f 100644 > >>>> --- a/include/sysemu/blockdev.h > >>>> +++ b/include/sysemu/blockdev.h > >>>> @@ -24,6 +24,7 @@ typedef enum { > >>>> */ > >>>> IF_NONE = 0, > >>>> IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, > >>>> IF_VIRTIO, IF_XEN, > >>>> +IF_EMMC, > >>>> IF_COUNT > >>>> } BlockInterfaceType; > >>>> > >>>> diff --git a/blockdev.c b/blockdev.c index cd438e6..390d43c 100644 > >>>> --- a/blockdev.c > >>>> +++ b/blockdev.c > >>>> @@ -83,6 +83,7 @@ static const char *const if_name[IF_COUNT] = { > >>>> [IF_SD] = "sd", > >>>> [IF_VIRTIO] = "virtio", > >>>> [IF_XEN] = "xen", > >>>> +[IF_EMMC] = "emmc", > >>>> }; > >>> > >>> We don't need to introduce support for the legacy -drive magic. > >>> > >>> -device should be enough for this device, right? > >> > >> External interface extensions need rationale: why do we want / need it? > >> The commit message neglects to provide one. > >> > >> Even more so when the interface in question is in a state like -drive > >> is. > > > > I wouldn't be too nasty about -drive; for me I still find it the > > easiest way to start a VM. > > But eMMC isn't a bus where you can plug drives, it is soldered on-board and is > mmio mapped to a fixed address. I don't see the point of having a drive > interface for it... [Sai Pavan Boddu] Yeah, this makes sense but having a drive would be a simple implementation without disturbing much in the sd card emulation code. And its just easy to use, just as how sd cards are inserted. I need to see, how easy it would be with -device. Thanks, Sai Pavan
RE: [PATCH v2 04/22] sd: emmc: update OCR fields for eMMC
Hi Cedric > -Original Message- > From: Cédric Le Goater > Sent: Monday, February 22, 2021 3:22 PM > To: Sai Pavan Boddu ; Markus Armbruster > ; Kevin Wolf ; Max Reitz > ; Vladimir Sementsov-Ogievskiy > ; Eric Blake ; Joel Stanley > ; Vincent Palatin ; Dr. David Alan > Gilbert ; Thomas Huth ; Stefan > Hajnoczi ; Peter Maydell ; > Alistair Francis ; Edgar Iglesias > ; > Luc Michel ; Paolo Bonzini > > Cc: qemu-block@nongnu.org; qemu-de...@nongnu.org; Sai Pavan Boddu > > Subject: Re: [PATCH v2 04/22] sd: emmc: update OCR fields for eMMC > > On 2/22/21 9:20 AM, Sai Pavan Boddu wrote: > > From: Vincent Palatin > > > > eMMC OCR register doesn't has UHS-II field and voltage fields are > > different. > > Can a patch be "From" a person without a "Signed-off-by" of the same person ? [Sai Pavan Boddu] No I should not be like this. My mistake, I would respin the series with corrections. Few other patches may have this after the split I did. Regards, Sai Pavan > > C. > > > Signed-off-by: Sai Pavan Boddu > > > > --- > > hw/sd/sd.c | 27 --- > > 1 file changed, 24 insertions(+), 3 deletions(-) > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > index 42ee49c..430bea5 100644 > > --- a/hw/sd/sd.c > > +++ b/hw/sd/sd.c > > @@ -283,6 +283,15 @@ FIELD(OCR, UHS_II_CARD,29, 1) /* Only > UHS-II */ > > FIELD(OCR, CARD_CAPACITY, 30, 1) /* 0:SDSC, 1:SDHC/SDXC */ > > FIELD(OCR, CARD_POWER_UP, 31, 1) > > > > +/* > > + * eMMC OCR register > > + */ > > +FIELD(EMMC_OCR, VDD_WINDOW_0, 7, 1) > > +FIELD(EMMC_OCR, VDD_WINDOW_1, 8, 7) > > +FIELD(EMMC_OCR, VDD_WINDOW_2, 15, 9) > > +FIELD(EMMC_OCR, ACCESS_MODE, 29, 2) > > +FIELD(EMMC_OCR, POWER_UP, 31, 1) > > + > > #define ACMD41_ENQUIRY_MASK 0x00ff > > #define ACMD41_R3_MASK (R_OCR_VDD_VOLTAGE_WIN_HI_MASK \ > > | R_OCR_ACCEPT_SWITCH_1V8_MASK \ > > @@ -292,8 +301,16 @@ FIELD(OCR, CARD_POWER_UP, 31, 1) > > > > static void sd_set_ocr(SDState *sd) > > { > > -/* All voltages OK */ > > -sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; > > +if (sd->emmc) { > > +/* > > + * Dual Voltage eMMC card > > + */ > > +sd->ocr = R_EMMC_OCR_VDD_WINDOW_0_MASK | > > + R_EMMC_OCR_VDD_WINDOW_2_MASK; > > +} else { > > +/* All voltages OK */ > > +sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; > > +} > > } > > > > static void sd_ocr_powerup(void *opaque) @@ -521,7 +538,11 @@ static > > void sd_response_r1_make(SDState *sd, uint8_t *response) > > > > static void sd_response_r3_make(SDState *sd, uint8_t *response) { > > -stl_be_p(response, sd->ocr & ACMD41_R3_MASK); > > +if (sd->emmc) { > > +stl_be_p(response, sd->ocr); > > +} else { > > +stl_be_p(response, sd->ocr & ACMD41_R3_MASK); > > +} > > } > > > > static void sd_response_r6_make(SDState *sd, uint8_t *response) > >
[PATCH v2 14/22] sd: emmc: Add support for emmc erase
Add CMD35 and CMD36 which sets the erase start and end. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index df82b61..6d2ef2b 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1544,6 +1544,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) /* Erase commands (Class 5) */ case 32:/* CMD32: ERASE_WR_BLK_START */ +case 35:/* CMD35: ERASE_GROUP_START */ switch (sd->state) { case sd_transfer_state: sd->erase_start = req.arg; @@ -1555,6 +1556,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) break; case 33:/* CMD33: ERASE_WR_BLK_END */ +case 36:/* CMD36: ERASE_GROUP_END */ switch (sd->state) { case sd_transfer_state: sd->erase_end = req.arg; -- 2.7.4
[PATCH v2 06/22] sd: emmc: Update CMD8 to send EXT_CSD register
From: Vincent Palatin Sends the EXT_CSD register as response to CMD8. Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 52 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 4c211ba..a4f93b5 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1133,24 +1133,37 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } break; -case 8: /* CMD8: SEND_IF_COND */ -if (sd->spec_version < SD_PHY_SPECv2_00_VERS) { -break; -} -if (sd->state != sd_idle_state) { -break; -} -sd->vhs = 0; - -/* No response if not exactly one VHS bit is set. */ -if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) { -return sd->spi ? sd_r7 : sd_r0; -} +case 8:/* CMD8: SEND_IF_COND / SEND_EXT_CSD */ +if (sd->emmc) { +switch (sd->state) { +case sd_transfer_state: +/* MMC : Sends the EXT_CSD register as a Block of data */ +sd->state = sd_sendingdata_state; +memcpy(sd->data, sd->ext_csd, sizeof(sd->ext_csd)); +sd->data_start = addr; +sd->data_offset = 0; +return sd_r1; +default: +break; +} +} else { +if (sd->spec_version < SD_PHY_SPECv2_00_VERS) { +break; +} +if (sd->state != sd_idle_state) { +break; +} +sd->vhs = 0; -/* Accept. */ -sd->vhs = req.arg; -return sd_r7; +/* No response if not exactly one VHS bit is set. */ +if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) { +return sd->spi ? sd_r7 : sd_r0; +} +/* Accept. */ +sd->vhs = req.arg; +return sd_r7; +} case 9: /* CMD9: SEND_CSD */ switch (sd->state) { case sd_standby_state: @@ -2073,6 +2086,13 @@ uint8_t sd_read_byte(SDState *sd) sd->state = sd_transfer_state; break; +case 8: /* CMD8: SEND_EXT_CSD on MMC */ +ret = sd->data[sd->data_offset++]; +if (sd->data_offset >= sizeof(sd->ext_csd)) { +sd->state = sd_transfer_state; +} +break; + case 9: /* CMD9: SEND_CSD */ case 10:/* CMD10: SEND_CID */ ret = sd->data[sd->data_offset ++]; -- 2.7.4
[PATCH v2 21/22] docs: devel: emmc: Add a doc for emmc card emulation
Add few simple steps to create emmc card with boot and user data partitions. Signed-off-by: Sai Pavan Boddu --- docs/devel/emmc.txt | 16 1 file changed, 16 insertions(+) create mode 100644 docs/devel/emmc.txt diff --git a/docs/devel/emmc.txt b/docs/devel/emmc.txt new file mode 100644 index 000..2d098fe --- /dev/null +++ b/docs/devel/emmc.txt @@ -0,0 +1,16 @@ + +eMMC block emulation + + +Any eMMC devices has 3 kinds of partitions Boot, RPMB and User data. We +are supporting Boot and User data partitions. Boot area partitions are +expected to be 1MB size as hard coded in EXT_CSD register. + +Below is the example of combining two 1MB bootarea partition and +user data partitions. + + cat mmc-bootarea0.bin mmc-bootarea1.bin image.wic > mmc.img + qemu-img resize mmc.img 4G + +Note: mmc-bootarea0/1 are just raw paritions. User data can have +partition tables. -- 2.7.4
[PATCH v2 10/22] sd: emmc: support idle state in CMD2
eMMC is expected to be in idle-state post CMD1. Ready state is an intermediate stage which we don't come across in Device identification mode. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Reviewed-by: Alistair Francis --- hw/sd/sd.c | 4 1 file changed, 4 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 8bc8d5d..ae5c5e8 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1051,6 +1051,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) if (sd->spi) goto bad_cmd; switch (sd->state) { +case sd_idle_state: +if (!sd->emmc) { +break; +} case sd_ready_state: sd->state = sd_identification_state; return sd_r2_i; -- 2.7.4
[PATCH v2 02/22] sd: sd: Remove usage of tabs in the file
Set tabstop as 4 and used expandtabs Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 190 ++--- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 8517dbc..74b9162 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -332,39 +332,39 @@ static void sd_set_scr(SDState *sd) sd->scr[7] = 0x00; } -#define MID0xaa -#define OID"XY" -#define PNM"QEMU!" -#define PRV0x01 -#define MDT_YR 2006 -#define MDT_MON2 +#define MID 0xaa +#define OID "XY" +#define PNM "QEMU!" +#define PRV 0x01 +#define MDT_YR 2006 +#define MDT_MON 2 static void sd_set_cid(SDState *sd) { -sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ -sd->cid[1] = OID[0]; /* OEM/Application ID (OID) */ +sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ +sd->cid[1] = OID[0];/* OEM/Application ID (OID) */ sd->cid[2] = OID[1]; -sd->cid[3] = PNM[0]; /* Fake product name (PNM) */ +sd->cid[3] = PNM[0];/* Fake product name (PNM) */ sd->cid[4] = PNM[1]; sd->cid[5] = PNM[2]; sd->cid[6] = PNM[3]; sd->cid[7] = PNM[4]; -sd->cid[8] = PRV; /* Fake product revision (PRV) */ -sd->cid[9] = 0xde; /* Fake serial number (PSN) */ +sd->cid[8] = PRV; /* Fake product revision (PRV) */ +sd->cid[9] = 0xde; /* Fake serial number (PSN) */ sd->cid[10] = 0xad; sd->cid[11] = 0xbe; sd->cid[12] = 0xef; -sd->cid[13] = 0x00 | /* Manufacture date (MDT) */ +sd->cid[13] = 0x00 |/* Manufacture date (MDT) */ ((MDT_YR - 2000) / 10); sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; } -#define HWBLOCK_SHIFT 9 /* 512 bytes */ -#define SECTOR_SHIFT 5 /* 16 kilobytes */ -#define WPGROUP_SHIFT 7 /* 2 megs */ -#define CMULT_SHIFT9 /* 512 times HWBLOCK_SIZE */ -#define WPGROUP_SIZE (1 << (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) +#define HWBLOCK_SHIFT 9 /* 512 bytes */ +#define SECTOR_SHIFT5 /* 16 kilobytes */ +#define WPGROUP_SHIFT 7 /* 2 megs */ +#define CMULT_SHIFT 9 /* 512 times HWBLOCK_SIZE */ +#define WPGROUP_SIZE(1 << (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) static const uint8_t sd_csd_rw_mask[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -385,31 +385,31 @@ static void sd_set_csd(SDState *sd, uint64_t size) csize = (size >> (CMULT_SHIFT + hwblock_shift)) - 1; if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */ -sd->csd[0] = 0x00; /* CSD structure */ -sd->csd[1] = 0x26; /* Data read access-time-1 */ -sd->csd[2] = 0x00; /* Data read access-time-2 */ +sd->csd[0] = 0x00; /* CSD structure */ +sd->csd[1] = 0x26; /* Data read access-time-1 */ +sd->csd[2] = 0x00; /* Data read access-time-2 */ sd->csd[3] = 0x32; /* Max. data transfer rate: 25 MHz */ -sd->csd[4] = 0x5f; /* Card Command Classes */ -sd->csd[5] = 0x50 |/* Max. read data block length */ +sd->csd[4] = 0x5f; /* Card Command Classes */ +sd->csd[5] = 0x50 | /* Max. read data block length */ hwblock_shift; -sd->csd[6] = 0xe0 |/* Partial block for read allowed */ +sd->csd[6] = 0xe0 | /* Partial block for read allowed */ ((csize >> 10) & 0x03); -sd->csd[7] = 0x00 |/* Device size */ +sd->csd[7] = 0x00 | /* Device size */ ((csize >> 2) & 0xff); -sd->csd[8] = 0x3f |/* Max. read current */ +sd->csd[8] = 0x3f | /* Max. read current */ ((csize << 6) & 0xc0); -sd->csd[9] = 0xfc |/* Max. write current */ +sd->csd[9] = 0xfc | /* Max. write current */ ((CMULT_SHIFT - 2) >> 1); -sd->csd[10] = 0x40 | /* Erase sector size */ +sd->csd[10] = 0x40 |/* Erase sector size */ (((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1); -sd->csd[11] = 0x00 | /* Write protect group size */ +sd->csd[11] = 0x00 |/* Write protect group size */ ((sectsize << 7) & 0x80) | wpsize; -sd->csd[12] = 0x90 | /* Write speed factor */ +sd->csd[12] = 0x90 |/* Write speed factor */ (hwblock_shift >> 2); -sd->csd[13] = 0x20 | /* Max. write data block length */ +sd->csd[13] = 0x20 |/* Max. write data block length */ ((hwblock_shift << 6) &am
[PATCH v2 17/22] sd: emmc: Support boot area in emmc image
From: Joel Stanley This assumes a specially constructued image: dd if=/dev/zero of=mmc-bootarea.img count=2 bs=1M dd if=u-boot-spl.bin of=mmc-bootarea.img conv=notrunc dd if=u-boot.bin of=mmc-bootarea.img conv=notrunc count=64 bs=1K cat mmc-bootarea.img obmc-phosphor-image.wic > mmc.img truncate --size 16GB mmc.img truncate --size 128MB mmc-bootarea.img Signed-off-by: Joel Stanley [clg: - changes on the definition names ] Signed-off-by: Cédric Le Goater [spb: use data_start property to access right emmc partition, Clean up PARTITION_ENABLE support as incomplete, Fix commit message to be generic.] Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 40 1 file changed, 40 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 60799aa..ab29e54 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1040,6 +1040,34 @@ static void sd_lock_command(SDState *sd) sd->card_status &= ~CARD_IS_LOCKED; } +/* + * This requires a disk image that has two boot partitions inserted at the + * beginning of it. The size of the boot partitions are configured in the + * ext_csd structure, which is hardcoded in qemu. They are currently set to + * 1MB each. + */ +static uint32_t sd_bootpart_offset(SDState *sd) +{ +unsigned int access = sd->ext_csd[EXT_CSD_PART_CONFIG] & +EXT_CSD_PART_CONFIG_ACC_MASK; +unsigned int boot_capacity = sd->ext_csd[EXT_CSD_BOOT_MULT] << 17; + +if (!sd->emmc) { +return 0; +} + +switch (access) { +case EXT_CSD_PART_CONFIG_ACC_DEFAULT: +return boot_capacity * 2; +case EXT_CSD_PART_CONFIG_ACC_BOOT0: +return 0; +case EXT_CSD_PART_CONFIG_ACC_BOOT0 + 1: +return boot_capacity * 1; +default: + g_assert_not_reached(); +} +} + static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) { uint32_t rca = 0x; @@ -1355,6 +1383,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1374,6 +1405,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1430,6 +1464,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1460,6 +1497,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; -- 2.7.4
[PATCH v2 19/22] sd: sdhci: Support eMMC devices
Embedded device slots should be allowed as support of eMMC is available. Signed-off-by: Sai Pavan Boddu --- hw/sd/sdhci.c | 4 1 file changed, 4 deletions(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 8ffa539..771212a 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -99,10 +99,6 @@ static void sdhci_check_capareg(SDHCIState *s, Error **errp) msk = FIELD_DP64(msk, SDHC_CAPAB, ASYNC_INT, 0); val = FIELD_EX64(s->capareg, SDHC_CAPAB, SLOT_TYPE); -if (val) { -error_setg(errp, "slot-type not supported"); -return; -} trace_sdhci_capareg("slot type", val); msk = FIELD_DP64(msk, SDHC_CAPAB, SLOT_TYPE, 0); -- 2.7.4
[PATCH v2 22/22] docs: arm: xlnx-versal-virt: Add eMMC support documentation
Add details of eMMC specific machine property. Signed-off-by: Sai Pavan Boddu --- docs/system/arm/xlnx-versal-virt.rst | 10 ++ 1 file changed, 10 insertions(+) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst index 2602d0f..a48a88d 100644 --- a/docs/system/arm/xlnx-versal-virt.rst +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -29,6 +29,7 @@ Implemented devices: - 2 GEMs (Cadence MACB Ethernet MACs) - 8 ADMA (Xilinx zDMA) channels - 2 SD Controllers +* SDHCI0 can be configured as eMMC - OCM (256KB of On Chip Memory) - DDR memory @@ -43,6 +44,15 @@ Other differences between the hardware and the QEMU model: - QEMU provides 8 virtio-mmio virtio transports; these start at address ``0xa000`` and have IRQs from 111 and upwards. +Enabling eMMC +""""""""""""" +In order to enable eMMC pass the following machine property "emmc=on". +ex: +"-M xlnx-versal-virt,emmc=on" + +Above switch would configure SDHCI0 to accept eMMC card. More details on eMMC +emulation can be found in docs/devel/emmc.txt. + Running """"""" If the user provides an Operating System to be loaded, we expect users -- 2.7.4
[PATCH v2 05/22] sd: emmc: Add support for EXT_CSD & CSD for eMMC
From: Vincent Palatin eMMC CSD is similar to SD with an option to refer EXT_CSD for larger devices. Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 57 +++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 430bea5..4c211ba 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -135,6 +135,7 @@ struct SDState { uint64_t data_start; uint32_t data_offset; uint8_t data[512]; +uint8_t ext_csd[512]; qemu_irq readonly_cb; qemu_irq inserted_cb; QEMUTimer *ocr_power_timer; @@ -389,6 +390,51 @@ static const uint8_t sd_csd_rw_mask[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, }; +static void mmc_set_ext_csd(SDState *sd, uint64_t size) +{ +uint32_t sectcount = size >> HWBLOCK_SHIFT; + +memset(sd->ext_csd, 0, sizeof(sd->ext_csd)); +sd->ext_csd[504] = 0x1; /* supported command sets */ +sd->ext_csd[503] = 0x1; /* HPI features */ +sd->ext_csd[502] = 0x1; /* Background operations support */ +sd->ext_csd[241] = 0xA; /* 1st initialization time after partitioning */ +sd->ext_csd[232] = 0x1; /* Trim multiplier */ +sd->ext_csd[231] = 0x15; /* Secure feature support */ +sd->ext_csd[230] = 0x96; /* Secure erase support */ +sd->ext_csd[229] = 0x96; /* Secure TRIM multiplier */ +sd->ext_csd[228] = 0x7; /* Boot information */ +sd->ext_csd[226] = 0x8; /* Boot partition size */ +sd->ext_csd[225] = 0x6; /* Access size */ +sd->ext_csd[224] = 0x4; /* HC Erase unit size */ +sd->ext_csd[223] = 0x1; /* HC erase timeout */ +sd->ext_csd[222] = 0x1; /* Reliable write sector count */ +sd->ext_csd[221] = 0x4; /* HC write protect group size */ +sd->ext_csd[220] = 0x8; /* Sleep current VCC */ +sd->ext_csd[219] = 0x7; /* Sleep current VCCQ */ +sd->ext_csd[217] = 0x11; /* Sleep/Awake timeout */ +sd->ext_csd[215] = (sectcount >> 24) & 0xff; /* Sector count */ +sd->ext_csd[214] = (sectcount >> 16) & 0xff; /* ... */ +sd->ext_csd[213] = (sectcount >> 8) & 0xff; /* ... */ +sd->ext_csd[212] = (sectcount & 0xff); /* ... */ +sd->ext_csd[210] = 0xa; /* Min write perf for 8bit@52Mhz */ +sd->ext_csd[209] = 0xa; /* Min read perf for 8bit@52Mhz */ +sd->ext_csd[208] = 0xa; /* Min write perf for 4bit@52Mhz */ +sd->ext_csd[207] = 0xa; /* Min read perf for 4bit@52Mhz */ +sd->ext_csd[206] = 0xa; /* Min write perf for 4bit@26Mhz */ +sd->ext_csd[205] = 0xa; /* Min read perf for 4bit@26Mhz */ +sd->ext_csd[199] = 0x1; /* Partition switching timing */ +sd->ext_csd[198] = 0x1; /* Out-of-interrupt busy timing */ +sd->ext_csd[196] = 0xFF; /* Card type */ +sd->ext_csd[194] = 0x2; /* CSD Structure version */ +sd->ext_csd[192] = 0x5; /* Extended CSD revision */ +sd->ext_csd[168] = 0x1; /* RPMB size */ +sd->ext_csd[160] = 0x3; /* Partinioning support */ +sd->ext_csd[159] = 0x00; /* Max enhanced area size */ +sd->ext_csd[158] = 0x00; /* ... */ +sd->ext_csd[157] = 0xEC; /* ... */ +} + static void sd_set_csd(SDState *sd, uint64_t size) { int hwblock_shift = HWBLOCK_SHIFT; @@ -402,8 +448,11 @@ static void sd_set_csd(SDState *sd, uint64_t size) } csize = (size >> (CMULT_SHIFT + hwblock_shift)) - 1; -if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */ -sd->csd[0] = 0x00; /* CSD structure */ +if (size <= SDSC_MAX_CAPACITY || sd->emmc) { /* Standard Capacity SD */ +if (sd->emmc && size >= SDSC_MAX_CAPACITY) { +csize = 0xfff; +} +sd->csd[0] = sd->emmc ? 0xd0 : 0x00; /* CSD structure */ sd->csd[1] = 0x26; /* Data read access-time-1 */ sd->csd[2] = 0x00; /* Data read access-time-2 */ sd->csd[3] = 0x32; /* Max. data transfer rate: 25 MHz */ @@ -447,6 +496,10 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[14] = 0x00; } sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1; + +if (sd->emmc) { +mmc_set_ext_csd(sd, size); +} } static void sd_set_rca(SDState *sd, uint16_t value) -- 2.7.4
[PATCH v2 12/22] sd: emmc: add CMD21 tuning sequence
eMMC cards support tuning sequence for entering HS200 mode. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 47 +++ 1 file changed, 47 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index e50d40b..d702027 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1378,6 +1378,14 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } break; +case 21:/* CMD21: mmc SEND TUNING_BLOCK */ +if (sd->emmc && (sd->state == sd_transfer_state)) { +sd->state = sd_sendingdata_state; +sd->data_offset = 0; +return sd_r1; +} +break; + case 23:/* CMD23: SET_BLOCK_COUNT */ if (sd->spec_version < SD_PHY_SPECv3_01_VERS) { break; @@ -2112,6 +2120,30 @@ static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, }; +#define EXCSD_BUS_WIDTH_OFFSET 183 +#define BUS_WIDTH_8_MASK0x4 +#define BUS_WIDTH_4_MASK0x2 +#define MMC_TUNING_BLOCK_SIZE 128 + +static const uint8_t mmc_tunning_block_pattern[128] = { + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, +}; + uint8_t sd_read_byte(SDState *sd) { /* TODO: Append CRCs */ @@ -2205,6 +2237,21 @@ uint8_t sd_read_byte(SDState *sd) ret = sd_tuning_block_pattern[sd->data_offset++]; break; +case 21:/* CMD21: SEND_TUNNING_BLOCK (MMC) */ +if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { +sd->state = sd_transfer_state; +} +if (sd->ext_csd[EXCSD_BUS_WIDTH_OFFSET] & BUS_WIDTH_8_MASK) { +ret = mmc_tunning_block_pattern[sd->data_offset++]; +} else { +/* Return LSB Nibbles of two byte from the 8bit tuning block + * for 4bit mode + */ +ret = mmc_tunning_block_pattern[sd->data_offset++] & 0x0F; +ret |= (mmc_tunning_block_pattern[sd->data_offset++] & 0x0F) << 4; +} +break; + case 22:/* ACMD22: SEND_NUM_WR_BLOCKS */ ret = sd->data[sd->data_offset ++]; -- 2.7.4
[PATCH v2 08/22] sd: emmc: Dont not update CARD_CAPACITY for eMMC cards
OCR.CARD_CAPACITY field is only valid for sd cards, So skip it for eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Reviewed-by: Alistair Francis --- hw/sd/sd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index a4f93b5..9835f52 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -324,7 +324,8 @@ static void sd_ocr_powerup(void *opaque) /* card power-up OK */ sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1); -if (sd->size > SDSC_MAX_CAPACITY) { +/* eMMC supports only Byte mode */ +if (!sd->emmc && sd->size > SDSC_MAX_CAPACITY) { sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1); } } -- 2.7.4
[PATCH v2 20/22] arm: xlnx-versal: Add emmc to versal
Configuring SDHCI-0 to act as eMMC controller. Signed-off-by: Sai Pavan Boddu --- include/hw/arm/xlnx-versal.h | 1 + hw/arm/xlnx-versal-virt.c| 30 +- hw/arm/xlnx-versal.c | 13 +++-- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 2b76885..440f3b4 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -76,6 +76,7 @@ struct Versal { struct { MemoryRegion *mr_ddr; uint32_t psci_conduit; +bool has_emmc; } cfg; }; diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 8482cd6..273e0c7 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -46,6 +46,7 @@ struct VersalVirt { struct { bool secure; +bool has_emmc; } cfg; }; @@ -333,6 +334,13 @@ static void fdt_add_sd_nodes(VersalVirt *s) qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", 2, addr, 2, MM_PMC_SD0_SIZE); qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +/* + * eMMC specific properties + */ +if (s->cfg.has_emmc && i == 0) { +qemu_fdt_setprop(s->fdt, name, "non-removable", NULL, 0); +qemu_fdt_setprop_sized_cells(s->fdt, name, "bus-width", 1, 8); +} g_free(name); } } @@ -512,7 +520,7 @@ static void create_virtio_regions(VersalVirt *s) } } -static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) +static void sd_plugin_card(SDHCIState *sd, DriveInfo *di, bool emmc) { BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; DeviceState *card; @@ -520,15 +528,22 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) card = qdev_new(TYPE_SD_CARD); object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card)); qdev_prop_set_drive_err(card, "drive", blk, _fatal); +object_property_set_bool(OBJECT(card), "emmc", emmc, _fatal); qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sd), "sd-bus"), _fatal); } +static void versal_virt_set_emmc(Object *obj, bool value, Error **errp) +{ +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj); + +s->cfg.has_emmc = value; +} + static void versal_virt_init(MachineState *machine) { VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine); int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; -int i; /* * If the user provides an Operating System to be loaded, we expect them @@ -560,6 +575,8 @@ static void versal_virt_init(MachineState *machine) _abort); object_property_set_int(OBJECT(>soc), "psci-conduit", psci_conduit, _abort); +object_property_set_bool(OBJECT(>soc), "has-emmc", s->cfg.has_emmc, + _abort); sysbus_realize(SYS_BUS_DEVICE(>soc), _fatal); fdt_create(s); @@ -581,10 +598,10 @@ static void versal_virt_init(MachineState *machine) memory_region_add_subregion_overlap(get_system_memory(), 0, >soc.fpd.apu.mr, 0); +sd_plugin_card(>soc.pmc.iou.sd[0], +drive_get_next(s->cfg.has_emmc ? IF_EMMC : IF_SD), s->cfg.has_emmc); /* Plugin SD cards. */ -for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) { -sd_plugin_card(>soc.pmc.iou.sd[i], drive_get_next(IF_SD)); -} +sd_plugin_card(>soc.pmc.iou.sd[1], drive_get_next(IF_SD), false); s->binfo.ram_size = machine->ram_size; s->binfo.loader_start = 0x0; @@ -621,6 +638,9 @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data) mc->default_cpus = XLNX_VERSAL_NR_ACPUS; mc->no_cdrom = true; mc->default_ram_id = "ddr"; +object_class_property_add_bool(oc, "emmc", +NULL, versal_virt_set_emmc); + } static const TypeInfo versal_virt_machine_init_typeinfo = { diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 628e77e..67ed1af 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -230,6 +230,9 @@ static void versal_create_admas(Versal *s, qemu_irq *pic) } #define SDHCI_CAPABILITIES 0x280737ec6481 /* Same as on ZynqMP. */ +#define SDHCI_EMMC_CAPS ((SDHCI_CAPABILITIES & ~(3 << 30)) | \ + (1 << 30)) + static void versal_create_sds(Versal *s, qemu_irq *pic) { int i; @@ -244,9 +247,14 @@ static void versal_create_sds(Versal *s, qemu_irq *pic) object_property_set_uint(OBJECT(dev), "sd-spec-version", 3, _fatal); -object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES, +
[PATCH v2 01/22] block: add eMMC block device type
From: Vincent Palatin Add new block device type. Signed-off-by: Vincent Palatin [SPB: Rebased over 5.1 version] Signed-off-by: Sai Pavan Boddu Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater Reviewed-by: Alistair Francis --- include/sysemu/blockdev.h | 1 + blockdev.c| 1 + 2 files changed, 2 insertions(+) diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 3b5fcda..eefae9f 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -24,6 +24,7 @@ typedef enum { */ IF_NONE = 0, IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, +IF_EMMC, IF_COUNT } BlockInterfaceType; diff --git a/blockdev.c b/blockdev.c index cd438e6..390d43c 100644 --- a/blockdev.c +++ b/blockdev.c @@ -83,6 +83,7 @@ static const char *const if_name[IF_COUNT] = { [IF_SD] = "sd", [IF_VIRTIO] = "virtio", [IF_XEN] = "xen", +[IF_EMMC] = "emmc", }; static int if_max_devs[IF_COUNT] = { -- 2.7.4
[PATCH v2 11/22] sd: emmc: Add mmc switch function support
switch operation in eMMC card updates the ext_csd register to request changes in card operations. Here we implement similar sequence but requests are mostly dummy and make no change. Implement SWITCH_ERROR if the write operation extends goes beyond length of ext_csd. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 56 ++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index ae5c5e8..e50d40b 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -515,6 +515,7 @@ static void sd_set_rca(SDState *sd, uint16_t value) FIELD(CSR, AKE_SEQ_ERROR, 3, 1) FIELD(CSR, APP_CMD, 5, 1) FIELD(CSR, FX_EVENT,6, 1) +FIELD(CSR, SWITCH_ERROR,7, 1) FIELD(CSR, READY_FOR_DATA, 8, 1) FIELD(CSR, CURRENT_STATE, 9, 4) FIELD(CSR, ERASE_RESET,13, 1) @@ -878,6 +879,43 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) return ret; } +enum { +MMC_CMD6_ACCESS_COMMAND_SET = 0, +MMC_CMD6_ACCESS_SET_BITS, +MMC_CMD6_ACCESS_CLEAR_BITS, +MMC_CMD6_ACCESS_WRITE_BYTE, +}; + +static void mmc_function_switch(SDState *sd, uint32_t arg) +{ +uint32_t access = extract32(arg, 24, 2); +uint32_t index = extract32(arg, 16, 8); +uint32_t value = extract32(arg, 8, 8); +uint8_t b = sd->ext_csd[index]; + +switch (access) { +case MMC_CMD6_ACCESS_COMMAND_SET: +qemu_log_mask(LOG_UNIMP, "MMC Command set switching not supported\n"); +return; +case MMC_CMD6_ACCESS_SET_BITS: +b |= value; +break; +case MMC_CMD6_ACCESS_CLEAR_BITS: +b &= ~value; +break; +case MMC_CMD6_ACCESS_WRITE_BYTE: +b = value; +break; +} + +if (index >= 192) { +sd->card_status |= R_CSR_SWITCH_ERROR_MASK; +return; +} + +sd->ext_csd[index] = b; +} + static void sd_function_switch(SDState *sd, uint32_t arg) { int i, mode, new_func; @@ -1097,12 +1135,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) case 6: /* CMD6: SWITCH_FUNCTION */ switch (sd->mode) { case sd_data_transfer_mode: -sd_function_switch(sd, req.arg); -sd->state = sd_sendingdata_state; -sd->data_start = 0; -sd->data_offset = 0; -return sd_r1; - +if (sd->emmc) { +sd->state = sd_programming_state; +mmc_function_switch(sd, req.arg); +sd->state = sd_transfer_state; +return sd_r1b; +} else { +sd_function_switch(sd, req.arg); +sd->state = sd_sendingdata_state; +sd->data_start = 0; +sd->data_offset = 0; +return sd_r1; +} default: break; } -- 2.7.4
[PATCH v2 16/22] sd: emmc: Add Extended CSD register definitions
From: Cédric Le Goater Add user friendly macros for EXT_CSD register. Signed-off-by: Cédric Le Goater [spb: Rebased over versal emmc series, updated commit message] Signed-off-by: Sai Pavan Boddu --- hw/sd/sdmmc-internal.h | 97 ++ hw/sd/sd.c | 54 +++- 2 files changed, 126 insertions(+), 25 deletions(-) diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h index d8bf17d..7ab7b4d 100644 --- a/hw/sd/sdmmc-internal.h +++ b/hw/sd/sdmmc-internal.h @@ -37,4 +37,101 @@ const char *sd_cmd_name(uint8_t cmd); */ const char *sd_acmd_name(uint8_t cmd); +/* + * EXT_CSD fields + */ + +#define EXT_CSD_CMDQ_MODE_EN15 /* R/W */ +#define EXT_CSD_FLUSH_CACHE 32 /* W */ +#define EXT_CSD_CACHE_CTRL33 /* R/W */ +#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ +#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */ +#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */ +#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */ +#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */ +#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ +#define EXT_CSD_GP_SIZE_MULT143 /* R/W */ +#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ +#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ +#define EXT_CSD_HPI_MGMT161 /* R/W */ +#define EXT_CSD_RST_N_FUNCTION162 /* R/W */ +#define EXT_CSD_BKOPS_EN163 /* R/W */ +#define EXT_CSD_BKOPS_START 164 /* W */ +#define EXT_CSD_SANITIZE_START165 /* W */ +#define EXT_CSD_WR_REL_PARAM166 /* RO */ +#define EXT_CSD_RPMB_MULT 168 /* RO */ +#define EXT_CSD_FW_CONFIG 169 /* R/W */ +#define EXT_CSD_BOOT_WP 173 /* R/W */ +#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ +#define EXT_CSD_PART_CONFIG 179 /* R/W */ +#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ +#define EXT_CSD_BUS_WIDTH 183 /* R/W */ +#define EXT_CSD_STROBE_SUPPORT184 /* RO */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_POWER_CLASS 187 /* R/W */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_STRUCTURE 194 /* RO */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */ +#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */ +#define EXT_CSD_PART_SWITCH_TIME199 /* RO */ +#define EXT_CSD_PWR_CL_52_195 200 /* RO */ +#define EXT_CSD_PWR_CL_26_195 201 /* RO */ +#define EXT_CSD_PWR_CL_52_360 202 /* RO */ +#define EXT_CSD_PWR_CL_26_360 203 /* RO */ +#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ +#define EXT_CSD_S_A_TIMEOUT 217 /* RO */ +#define EXT_CSD_S_C_VCCQ 219 /* RO */ +#define EXT_CSD_S_C_VCC 220 /* RO */ +#define EXT_CSD_REL_WR_SEC_C222 /* RO */ +#define EXT_CSD_HC_WP_GRP_SIZE221 /* RO */ +#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ +#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ +#define EXT_CSD_ACC_SIZE225 /* RO */ +#define EXT_CSD_BOOT_MULT 226 /* RO */ +#define EXT_CSD_BOOT_INFO 228 /* RO */ +#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ +#define EXT_CSD_SEC_ERASE_MULT230 /* RO */ +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ +#define EXT_CSD_TRIM_MULT 232 /* RO */ +#define EXT_CSD_PWR_CL_200_195236 /* RO */ +#define EXT_CSD_PWR_CL_200_360237 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ +#define EXT_CSD_BKOPS_STATUS246 /* RO */ +#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ +#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ +#define EXT_CSD_CACHE_SIZE249 /* RO, 4 bytes */ +#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ +#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */ +#define EXT_CSD_PRE_EOL_INFO267 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */ +#define EXT_CSD_CMDQ_DEPTH307 /* RO */ +#define EXT_CSD_CMDQ_SUPPORT308 /* RO */ +#define EXT_CSD_SUPPORTED_MODE493 /* RO */ +#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ +#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ +#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ +#define EXT_CSD_MAX_PACKED_READS 501 /* RO */ +#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ +#define EXT_CSD_HPI_FEATURES503 /* RO */ +#define EXT_CSD_S_CMD_SET 504 /* RO */ + +/* + * EXT_CSD field definitions + */ + +#define EXT_CSD_WR_REL_PARAM_EN (1 << 2) +#define EXT_CSD_WR_REL_PARAM_EN_RPMB_REL_WR (1 << 4) + +#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) +#define EXT_CSD_PART_CONFIG_ACC_DEFAULT (0x0) +#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) + +#define EXT_CSD_PART_CONFIG_EN_MASK (0x7 << 3) +#define EXT_CSD_PART_CONFIG_EN_BOOT0 (0x1 << 3) +#define EXT_CSD_PART_CONFIG_EN_USER (0x7 << 3) + #endif diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 3c24810..60799aa 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -409,41 +409,45 @@ static void mmc_set_ext_
[PATCH v2 18/22] sd: emmc: Subtract bootarea size from blk
From: Joel Stanley The userdata size is derived from the file the user passes on the command line, but we must take into account the boot areas. Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater --- hw/sd/sd.c | 5 + 1 file changed, 5 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index ab29e54..a0b4507 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -653,6 +653,11 @@ static void sd_reset(DeviceState *dev) } size = sect << 9; +if (sd->emmc) { +unsigned int boot_capacity = sd->ext_csd[EXT_CSD_BOOT_MULT] << 17; +size -= boot_capacity * 2; +} + sect = sd_addr_to_wpnum(size) + 1; sd->state = sd_idle_state; -- 2.7.4
[PATCH v2 07/22] sd: sdmmc-internal: Add command string for SEND_OP_CMD
From: Cédric Le Goater This adds extra info to trace log. Signed-off-by: Sai Pavan Boddu --- hw/sd/sdmmc-internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd/sdmmc-internal.c b/hw/sd/sdmmc-internal.c index 2053def..8648a78 100644 --- a/hw/sd/sdmmc-internal.c +++ b/hw/sd/sdmmc-internal.c @@ -14,7 +14,7 @@ const char *sd_cmd_name(uint8_t cmd) { static const char *cmd_abbrev[SDMMC_CMD_MAX] = { - [0]= "GO_IDLE_STATE", + [0]= "GO_IDLE_STATE", [1]= "SEND_OP_CMD", [2]= "ALL_SEND_CID",[3]= "SEND_RELATIVE_ADDR", [4]= "SET_DSR", [5]= "IO_SEND_OP_COND", [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD", -- 2.7.4
[PATCH v2 03/22] sd: emmc: Add support for eMMC cards
From: Vincent Palatin This patch adds support for eMMC cards, change SET_RELATIVE_ADDR command to assign relative address as requested by user. Signed-off-by: Vincent Palatin Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater [spb: Split original patch series] Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 14 ++ 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 74b9162..42ee49c 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -108,6 +108,7 @@ struct SDState { uint8_t spec_version; BlockBackend *blk; bool spi; +bool emmc; /* Runtime changeables */ @@ -431,9 +432,13 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1; } -static void sd_set_rca(SDState *sd) +static void sd_set_rca(SDState *sd, uint16_t value) { -sd->rca += 0x4567; +if (sd->emmc) { +sd->rca = value; +} else { +sd->rca += 0x4567; +} } FIELD(CSR, AKE_SEQ_ERROR, 3, 1) @@ -979,8 +984,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) case sd_identification_state: case sd_standby_state: sd->state = sd_standby_state; -sd_set_rca(sd); -return sd_r6; +sd_set_rca(sd, req.arg >> 16); +return sd->emmc ? sd_r1 : sd_r6; default: break; @@ -2176,6 +2181,7 @@ static Property sd_properties[] = { * board to ensure that ssi transfers only occur when the chip select * is asserted. */ DEFINE_PROP_BOOL("spi", SDState, spi, false), +DEFINE_PROP_BOOL("emmc", SDState, emmc, false), DEFINE_PROP_END_OF_LIST() }; -- 2.7.4
[PATCH v2 15/22] sd: emmc: Update CID structure for eMMC
CID structure is little different for eMMC, w.r.t to product name and manufacturing date. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 47 ++- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 6d2ef2b..3c24810 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -361,23 +361,36 @@ static void sd_set_scr(SDState *sd) static void sd_set_cid(SDState *sd) { -sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ -sd->cid[1] = OID[0];/* OEM/Application ID (OID) */ -sd->cid[2] = OID[1]; -sd->cid[3] = PNM[0];/* Fake product name (PNM) */ -sd->cid[4] = PNM[1]; -sd->cid[5] = PNM[2]; -sd->cid[6] = PNM[3]; -sd->cid[7] = PNM[4]; -sd->cid[8] = PRV; /* Fake product revision (PRV) */ -sd->cid[9] = 0xde; /* Fake serial number (PSN) */ -sd->cid[10] = 0xad; -sd->cid[11] = 0xbe; -sd->cid[12] = 0xef; -sd->cid[13] = 0x00 |/* Manufacture date (MDT) */ -((MDT_YR - 2000) / 10); -sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; -sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; +if (sd->emmc) { +sd->cid[0] = MID; +sd->cid[1] = 0x1; /* CBX */ +sd->cid[2] = OID[0];/* OEM/Application ID (OID) */ +sd->cid[8] = 0x0; +sd->cid[9] = PRV;/* Fake product revision (PRV) */ +sd->cid[10] = 0xde; /* Fake serial number (PSN) */ +sd->cid[11] = 0xad; +sd->cid[12] = 0xbe; +sd->cid[13] = 0xef; +sd->cid[14] = ((MDT_YR - 1997) % 0x10); /* MDT */ +} else { +sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ +sd->cid[1] = OID[0];/* OEM/Application ID (OID) */ +sd->cid[2] = OID[1]; +sd->cid[8] = PRV; /* Fake product revision (PRV) */ +sd->cid[9] = 0xde; /* Fake serial number (PSN) */ +sd->cid[10] = 0xad; +sd->cid[11] = 0xbe; +sd->cid[12] = 0xef; +sd->cid[13] = 0x00 |/* Manufacture date (MDT) */ +((MDT_YR - 2000) / 10); +sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; + } + sd->cid[3] = PNM[0];/* Fake product name (PNM) 48bit */ + sd->cid[4] = PNM[1]; + sd->cid[5] = PNM[2]; + sd->cid[6] = PNM[3]; + sd->cid[7] = PNM[4]; + sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; } #define HWBLOCK_SHIFT 9 /* 512 bytes */ -- 2.7.4
[PATCH v2 13/22] sd: emmc: Make ACMD41 illegal for mmc
ACMD41 is not applicable for eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index d702027..df82b61 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1729,6 +1729,9 @@ static sd_rsp_type_t sd_app_command(SDState *sd, break; case 41:/* ACMD41: SD_APP_OP_COND */ +if (sd->emmc) { +break; +} if (sd->spi) { /* SEND_OP_CMD */ sd->state = sd_transfer_state; -- 2.7.4
[PATCH v2 04/22] sd: emmc: update OCR fields for eMMC
From: Vincent Palatin eMMC OCR register doesn't has UHS-II field and voltage fields are different. Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 27 --- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 42ee49c..430bea5 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -283,6 +283,15 @@ FIELD(OCR, UHS_II_CARD,29, 1) /* Only UHS-II */ FIELD(OCR, CARD_CAPACITY, 30, 1) /* 0:SDSC, 1:SDHC/SDXC */ FIELD(OCR, CARD_POWER_UP, 31, 1) +/* + * eMMC OCR register + */ +FIELD(EMMC_OCR, VDD_WINDOW_0, 7, 1) +FIELD(EMMC_OCR, VDD_WINDOW_1, 8, 7) +FIELD(EMMC_OCR, VDD_WINDOW_2, 15, 9) +FIELD(EMMC_OCR, ACCESS_MODE, 29, 2) +FIELD(EMMC_OCR, POWER_UP, 31, 1) + #define ACMD41_ENQUIRY_MASK 0x00ff #define ACMD41_R3_MASK (R_OCR_VDD_VOLTAGE_WIN_HI_MASK \ | R_OCR_ACCEPT_SWITCH_1V8_MASK \ @@ -292,8 +301,16 @@ FIELD(OCR, CARD_POWER_UP, 31, 1) static void sd_set_ocr(SDState *sd) { -/* All voltages OK */ -sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; +if (sd->emmc) { +/* + * Dual Voltage eMMC card + */ +sd->ocr = R_EMMC_OCR_VDD_WINDOW_0_MASK | + R_EMMC_OCR_VDD_WINDOW_2_MASK; +} else { +/* All voltages OK */ +sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; +} } static void sd_ocr_powerup(void *opaque) @@ -521,7 +538,11 @@ static void sd_response_r1_make(SDState *sd, uint8_t *response) static void sd_response_r3_make(SDState *sd, uint8_t *response) { -stl_be_p(response, sd->ocr & ACMD41_R3_MASK); +if (sd->emmc) { +stl_be_p(response, sd->ocr); +} else { +stl_be_p(response, sd->ocr & ACMD41_R3_MASK); +} } static void sd_response_r6_make(SDState *sd, uint8_t *response) -- 2.7.4
[PATCH v2 09/22] sd: emmc: Update CMD1 definition for eMMC
Add support to Power up the card and send response r3 in case of eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Reviewed-by: Alistair Francis --- hw/sd/sd.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 9835f52..8bc8d5d 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1033,8 +1033,16 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) break; case 1: /* CMD1: SEND_OP_CMD */ -if (!sd->spi) +/* MMC: Powerup & send r3 + * SD: send r1 in spi mode + */ +if (sd->emmc) { +sd_ocr_powerup(sd); +return sd->state == sd_idle_state ? + sd_r3 : sd_r0; +} else if (!sd->spi) { goto bad_cmd; +} sd->state = sd_transfer_state; return sd_r1; -- 2.7.4
[PATCH v2 00/22] eMMC support
Hi, This patch series add support for eMMC cards. This work was previosly submitted by Vincent, rebased few changes on top. Cedric & Joel has helped to added boot partition access support. I expect them to make a follow-up series to use it with aspeed machines. Present series adds eMMC support to Versal SOC. Initial patch series version is RFC Changes for V2: Split Patch 1 Add comments for eMMC Erase commands Added documentation about eMMC and Versal-virt board. Make eMMC optional for xlnx-versal-virt machines Regards, Sai Pavan Cédric Le Goater (2): sd: sdmmc-internal: Add command string for SEND_OP_CMD sd: emmc: Add Extended CSD register definitions Joel Stanley (2): sd: emmc: Support boot area in emmc image sd: emmc: Subtract bootarea size from blk Sai Pavan Boddu (13): sd: sd: Remove usage of tabs in the file sd: emmc: Dont not update CARD_CAPACITY for eMMC cards sd: emmc: Update CMD1 definition for eMMC sd: emmc: support idle state in CMD2 sd: emmc: Add mmc switch function support sd: emmc: add CMD21 tuning sequence sd: emmc: Make ACMD41 illegal for mmc sd: emmc: Add support for emmc erase sd: emmc: Update CID structure for eMMC sd: sdhci: Support eMMC devices arm: xlnx-versal: Add emmc to versal docs: devel: emmc: Add a doc for emmc card emulation docs: arm: xlnx-versal-virt: Add eMMC support documentation Vincent Palatin (5): block: add eMMC block device type sd: emmc: Add support for eMMC cards sd: emmc: update OCR fields for eMMC sd: emmc: Add support for EXT_CSD & CSD for eMMC sd: emmc: Update CMD8 to send EXT_CSD register docs/devel/emmc.txt | 16 + docs/system/arm/xlnx-versal-virt.rst | 10 + hw/sd/sdmmc-internal.h | 97 +++ include/hw/arm/xlnx-versal.h | 1 + include/sysemu/blockdev.h| 1 + blockdev.c | 1 + hw/arm/xlnx-versal-virt.c| 30 +- hw/arm/xlnx-versal.c | 13 +- hw/sd/sd.c | 545 ++- hw/sd/sdhci.c| 4 - hw/sd/sdmmc-internal.c | 2 +- 11 files changed, 571 insertions(+), 149 deletions(-) create mode 100644 docs/devel/emmc.txt -- 2.7.4
RE: [RFC PATCH 11/15] sd: emmc: Add Extended CSD register definitions
Hi Luc, > -Original Message- > From: Luc Michel > Sent: Saturday, February 13, 2021 6:26 PM > To: Sai Pavan Boddu ; Markus Armbruster > ; Kevin Wolf ; Max Reitz > ; Vladimir Sementsov-Ogievskiy > ; Eric Blake ; Joel Stanley > ; Cédric Le Goater ; Vincent Palatin > ; Dr. David Alan Gilbert ; > Thomas Huth ; Stefan Hajnoczi ; > Peter Maydell ; Alistair Francis > ; Edgar Iglesias ; Paolo Bonzini > > Cc: qemu-block@nongnu.org; qemu-de...@nongnu.org; Sai Pavan Boddu > > Subject: Re: [RFC PATCH 11/15] sd: emmc: Add Extended CSD register > definitions > > On 2/11/21 9:17 AM, Sai Pavan Boddu wrote: > > From: Cédric Le Goater > > > > Add user friendly macros for EXT_CSD register. > > > Signed-off-by: Cédric Le Goater > > [spb: Rebased over versal emmc series, > >updated commit message] > > Signed-off-by: Sai Pavan Boddu > > Hi, > > If Cédric agrees, maybe you can squash this commit into patch 2, and add the > missing register definitions? [Sai Pavan Boddu] Yeah, that would be nice. I will leave @Cédric Le Goater comment here. > > Also, can you set diff.orderFile = script/git.orderfile in your git config > for your > QEMU repo? It makes the review process a bit easier. [Sai Pavan Boddu] Ok, I would configure this. Thanks ! Regards, Sai Pavan > > Thanks! > > -- > Luc > > > --- > > hw/sd/sd.c | 54 +++- > > hw/sd/sdmmc-internal.h | 97 > ++ > > 2 files changed, 126 insertions(+), 25 deletions(-) > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > index 45311fa..54fba7b 100644 > > --- a/hw/sd/sd.c > > +++ b/hw/sd/sd.c > > @@ -398,41 +398,45 @@ static void mmc_set_ext_csd(SDState *sd, uint64_t > size) > > uint32_t sectcount = size >> HWBLOCK_SHIFT; > > > > memset(sd->ext_csd, 0, 512); > > -sd->ext_csd[504] = 0x1; /* supported command sets */ > > -sd->ext_csd[503] = 0x1; /* HPI features */ > > -sd->ext_csd[502] = 0x1; /* Background operations support */ > > +sd->ext_csd[EXT_CSD_S_CMD_SET] = 0x1; /* supported command sets */ > > +sd->ext_csd[EXT_CSD_HPI_FEATURES] = 0x3; /* HPI features */ > > +sd->ext_csd[EXT_CSD_BKOPS_SUPPORT] = 0x1; /* Background operations > > + support */ > > sd->ext_csd[241] = 0xA; /* 1st initialization time after partitioning > > */ > > -sd->ext_csd[232] = 0x1; /* Trim multiplier */ > > -sd->ext_csd[231] = 0x15; /* Secure feature support */ > > -sd->ext_csd[230] = 0x96; /* Secure erase support */ > > -sd->ext_csd[229] = 0x96; /* Secure TRIM multiplier */ > > -sd->ext_csd[228] = 0x7; /* Boot information */ > > -sd->ext_csd[226] = 0x8; /* Boot partition size */ > > -sd->ext_csd[225] = 0x6; /* Access size */ > > -sd->ext_csd[224] = 0x4; /* HC Erase unit size */ > > -sd->ext_csd[223] = 0x1; /* HC erase timeout */ > > -sd->ext_csd[222] = 0x1; /* Reliable write sector count */ > > -sd->ext_csd[221] = 0x4; /* HC write protect group size */ > > -sd->ext_csd[220] = 0x8; /* Sleep current VCC */ > > -sd->ext_csd[219] = 0x7; /* Sleep current VCCQ */ > > -sd->ext_csd[217] = 0x11; /* Sleep/Awake timeout */ > > +sd->ext_csd[EXT_CSD_TRIM_MULT] = 0x1; /* Trim multiplier */ > > +sd->ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT] = 0x15; /* Secure feature > > +support */ > > +sd->ext_csd[EXT_CSD_SEC_ERASE_MULT] = 0x96; /* Secure erase support > */ > > +sd->ext_csd[EXT_CSD_SEC_TRIM_MULT] = 0x96; /* Secure TRIM > multiplier */ > > +sd->ext_csd[EXT_CSD_BOOT_INFO] = 0x7; /* Boot information */ > > +sd->ext_csd[EXT_CSD_BOOT_MULT] = 0x8; /* Boot partition size. 128KB > unit */ > > +sd->ext_csd[EXT_CSD_ACC_SIZE] = 0x6; /* Access size */ > > +sd->ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] = 0x4; /* HC Erase unit size > */ > > +sd->ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT] = 0x1; /* HC erase > timeout */ > > +sd->ext_csd[EXT_CSD_REL_WR_SEC_C] = 0x1; /* Reliable write sector > count */ > > +sd->ext_csd[EXT_CSD_HC_WP_GRP_SIZE] = 0x4; /* HC write protect > group size */ > > +sd->ext_csd[EXT_CSD_S_C_VCC] = 0x8; /* Sleep current VCC */ > > +sd->ext_csd[EXT_CSD_S_C_VCCQ] = 0x7; /* Sleep current VCCQ */ > > +sd->ext_csd[EXT_CSD_S_A_TIMEOUT] = 0x11; /* Sleep/Awake timeout > > + */ > >
RE: [RFC PATCH 10/15] sd: emmc: Update CID structure for eMMC
Hi Alistair > -Original Message- > From: Alistair Francis > Sent: Saturday, February 13, 2021 3:41 AM > To: Sai Pavan Boddu > Cc: Markus Armbruster ; Kevin Wolf > ; Max Reitz ; Vladimir Sementsov- > Ogievskiy ; Eric Blake ; > Joel Stanley ; Cédric Le Goater ; Vincent > Palatin ; Dr. David Alan Gilbert > ; Thomas Huth ; Stefan Hajnoczi > ; Peter Maydell ; Alistair > Francis ; Edgar Iglesias ; Luc > Michel ; Paolo Bonzini ; > Sai Pavan Boddu ; qemu-de...@nongnu.org Developers > ; Qemu-block > Subject: Re: [RFC PATCH 10/15] sd: emmc: Update CID structure for eMMC > > On Thu, Feb 11, 2021 at 12:30 AM Sai Pavan Boddu > wrote: > > > > CID structure is little different for eMMC, w.r.t to product name and > > manufacturing date. > > > > Signed-off-by: Sai Pavan Boddu > > Signed-off-by: Edgar E. Iglesias > > --- > > hw/sd/sd.c | 52 +++- > > 1 file changed, 35 insertions(+), 17 deletions(-) > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > index 7aab647..45311fa 100644 > > --- a/hw/sd/sd.c > > +++ b/hw/sd/sd.c > > @@ -345,23 +345,41 @@ static void sd_set_scr(SDState *sd) > > > > static void sd_set_cid(SDState *sd) > > { > > -sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ > > -sd->cid[1] = OID[0]; /* OEM/Application ID (OID) */ > > -sd->cid[2] = OID[1]; > > -sd->cid[3] = PNM[0]; /* Fake product name (PNM) */ > > -sd->cid[4] = PNM[1]; > > -sd->cid[5] = PNM[2]; > > -sd->cid[6] = PNM[3]; > > -sd->cid[7] = PNM[4]; > > -sd->cid[8] = PRV; /* Fake product revision (PRV) */ > > -sd->cid[9] = 0xde; /* Fake serial number (PSN) */ > > -sd->cid[10] = 0xad; > > -sd->cid[11] = 0xbe; > > -sd->cid[12] = 0xef; > > -sd->cid[13] = 0x00 | /* Manufacture date (MDT) */ > > -((MDT_YR - 2000) / 10); > > -sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; > > -sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; > > +if (sd->emmc) { > > +sd->cid[0] = MID; > > +sd->cid[1] = 0x1; /* CBX */ > > +sd->cid[2] = OID[0]; /* OEM/Application ID (OID) */ > > +sd->cid[3] = PNM[0];/* Fake product name (PNM) 48bit */ > > +sd->cid[4] = PNM[1]; > > +sd->cid[5] = PNM[2]; > > +sd->cid[6] = PNM[3]; > > +sd->cid[7] = PNM[4]; > > Aren't the majority of these the same between the two cases? It's probably > cleaner to split them out then. [Sai Pavan Boddu] Yes, I would try to re-order. If I see only the PNM fields are same, rest all fields kind of moved a byte below. Regards, Sai Pavan > > Alistair > > > +sd->cid[8] = 0x0; > > +sd->cid[9] = PRV;/* Fake product revision (PRV) */ > > +sd->cid[10] = 0xde; /* Fake serial number (PSN) */ > > +sd->cid[11] = 0xad; > > +sd->cid[12] = 0xbe; > > +sd->cid[13] = 0xef; > > +sd->cid[14] = ((MDT_YR - 1997) % 0x10); /* MDT */ > > +} else { > > +sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ > > +sd->cid[1] = OID[0];/* OEM/Application ID (OID) */ > > +sd->cid[2] = OID[1]; > > +sd->cid[3] = PNM[0];/* Fake product name (PNM) 40bit */ > > +sd->cid[4] = PNM[1]; > > +sd->cid[5] = PNM[2]; > > +sd->cid[6] = PNM[3]; > > +sd->cid[7] = PNM[4]; > > +sd->cid[8] = PRV; /* Fake product revision (PRV) */ > > +sd->cid[9] = 0xde; /* Fake serial number (PSN) */ > > +sd->cid[10] = 0xad; > > +sd->cid[11] = 0xbe; > > +sd->cid[12] = 0xef; > > +sd->cid[13] = 0x00 |/* Manufacture date (MDT) */ > > +((MDT_YR - 2000) / 10); > > +sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; > > + } > > + sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; > > } > > > > #define HWBLOCK_SHIFT 9 /* 512 bytes */ > > -- > > 2.7.4 > > > >
RE: [RFC PATCH 09/15] sd: emmc: Add support for emmc erase
Hi Alistair, > -Original Message- > From: Alistair Francis > Sent: Saturday, February 13, 2021 3:38 AM > To: Sai Pavan Boddu > Cc: Markus Armbruster ; Kevin Wolf > ; Max Reitz ; Vladimir Sementsov- > Ogievskiy ; Eric Blake ; > Joel Stanley ; Cédric Le Goater ; Vincent > Palatin ; Dr. David Alan Gilbert > ; Thomas Huth ; Stefan Hajnoczi > ; Peter Maydell ; Alistair > Francis ; Edgar Iglesias ; Luc > Michel ; Paolo Bonzini ; > Sai Pavan Boddu ; qemu-de...@nongnu.org Developers > ; Qemu-block > Subject: Re: [RFC PATCH 09/15] sd: emmc: Add support for emmc erase > > On Thu, Feb 11, 2021 at 12:19 AM Sai Pavan Boddu > wrote: > > > > Add CMD35 and CMD36 which sets the erase start and end. > > > > Signed-off-by: Sai Pavan Boddu > > Signed-off-by: Edgar E. Iglesias > > --- > > hw/sd/sd.c | 2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > index 236f2b8..7aab647 100644 > > --- a/hw/sd/sd.c > > +++ b/hw/sd/sd.c > > @@ -1544,6 +1544,7 @@ static sd_rsp_type_t sd_normal_command(SDState > > *sd, SDRequest req) > > > > /* Erase commands (Class 5) */ > > case 32: /* CMD32: ERASE_WR_BLK_START */ > > +case 35: > > Can you comment the CMD here? [Sai Pavan Boddu] Sure I will update this. Regards, Sai Pavan > > > switch (sd->state) { > > case sd_transfer_state: > > sd->erase_start = req.arg; @@ -1555,6 +1556,7 @@ static > > sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) > > break; > > > > case 33: /* CMD33: ERASE_WR_BLK_END */ > > +case 36: > > and here? > > Alistair > > > switch (sd->state) { > > case sd_transfer_state: > > sd->erase_end = req.arg; > > -- > > 2.7.4 > > > >
[RFC PATCH 15/15] arm: xlnx-versal: Add emmc to versal
Configuring SDHCI-0 to act as eMMC controller. Signed-off-by: Sai Pavan Boddu --- hw/arm/xlnx-versal-virt.c | 16 +++- hw/arm/xlnx-versal.c | 14 -- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 8482cd6..18489e4 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -333,6 +333,13 @@ static void fdt_add_sd_nodes(VersalVirt *s) qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", 2, addr, 2, MM_PMC_SD0_SIZE); qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +/* + * eMMC specific properties + */ +if (i == 0) { +qemu_fdt_setprop(s->fdt, name, "non-removable", NULL, 0); +qemu_fdt_setprop_sized_cells(s->fdt, name, "bus-width", 1, 8); +} g_free(name); } } @@ -512,7 +519,7 @@ static void create_virtio_regions(VersalVirt *s) } } -static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) +static void sd_plugin_card(SDHCIState *sd, DriveInfo *di, bool emmc) { BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; DeviceState *card; @@ -520,6 +527,7 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) card = qdev_new(TYPE_SD_CARD); object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card)); qdev_prop_set_drive_err(card, "drive", blk, _fatal); +object_property_set_bool(OBJECT(card), "emmc", emmc, _fatal); qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sd), "sd-bus"), _fatal); } @@ -528,7 +536,6 @@ static void versal_virt_init(MachineState *machine) { VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine); int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; -int i; /* * If the user provides an Operating System to be loaded, we expect them @@ -581,10 +588,9 @@ static void versal_virt_init(MachineState *machine) memory_region_add_subregion_overlap(get_system_memory(), 0, >soc.fpd.apu.mr, 0); +sd_plugin_card(>soc.pmc.iou.sd[0], drive_get_next(IF_EMMC), true); /* Plugin SD cards. */ -for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) { -sd_plugin_card(>soc.pmc.iou.sd[i], drive_get_next(IF_SD)); -} +sd_plugin_card(>soc.pmc.iou.sd[1], drive_get_next(IF_SD), false); s->binfo.ram_size = machine->ram_size; s->binfo.loader_start = 0x0; diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index b077716..3498dd9 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -230,9 +230,14 @@ static void versal_create_admas(Versal *s, qemu_irq *pic) } #define SDHCI_CAPABILITIES 0x280737ec6481 /* Same as on ZynqMP. */ +#define SDHCI0_CAPS ((SDHCI_CAPABILITIES & ~(3 << 30)) | \ + (1 << 30)) +#define SDHCI1_CAPS SDHCI_CAPABILITIES + static void versal_create_sds(Versal *s, qemu_irq *pic) { int i; +uint64_t caps[] = {SDHCI0_CAPS, SDHCI1_CAPS}; for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) { DeviceState *dev; @@ -244,9 +249,14 @@ static void versal_create_sds(Versal *s, qemu_irq *pic) object_property_set_uint(OBJECT(dev), "sd-spec-version", 3, _fatal); -object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES, +object_property_set_uint(OBJECT(dev), "capareg", caps[i], _fatal); -object_property_set_uint(OBJECT(dev), "uhs", UHS_I, _fatal); +/* + * UHS is not applicable for eMMC + */ +if (i == 1) { +object_property_set_uint(OBJECT(dev), "uhs", UHS_I, _fatal); +} sysbus_realize(SYS_BUS_DEVICE(dev), _fatal); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); -- 2.7.4
[RFC PATCH 11/15] sd: emmc: Add Extended CSD register definitions
From: Cédric Le Goater Add user friendly macros for EXT_CSD register. Signed-off-by: Cédric Le Goater [spb: Rebased over versal emmc series, updated commit message] Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 54 +++- hw/sd/sdmmc-internal.h | 97 ++ 2 files changed, 126 insertions(+), 25 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 45311fa..54fba7b 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -398,41 +398,45 @@ static void mmc_set_ext_csd(SDState *sd, uint64_t size) uint32_t sectcount = size >> HWBLOCK_SHIFT; memset(sd->ext_csd, 0, 512); -sd->ext_csd[504] = 0x1; /* supported command sets */ -sd->ext_csd[503] = 0x1; /* HPI features */ -sd->ext_csd[502] = 0x1; /* Background operations support */ +sd->ext_csd[EXT_CSD_S_CMD_SET] = 0x1; /* supported command sets */ +sd->ext_csd[EXT_CSD_HPI_FEATURES] = 0x3; /* HPI features */ +sd->ext_csd[EXT_CSD_BKOPS_SUPPORT] = 0x1; /* Background operations + support */ sd->ext_csd[241] = 0xA; /* 1st initialization time after partitioning */ -sd->ext_csd[232] = 0x1; /* Trim multiplier */ -sd->ext_csd[231] = 0x15; /* Secure feature support */ -sd->ext_csd[230] = 0x96; /* Secure erase support */ -sd->ext_csd[229] = 0x96; /* Secure TRIM multiplier */ -sd->ext_csd[228] = 0x7; /* Boot information */ -sd->ext_csd[226] = 0x8; /* Boot partition size */ -sd->ext_csd[225] = 0x6; /* Access size */ -sd->ext_csd[224] = 0x4; /* HC Erase unit size */ -sd->ext_csd[223] = 0x1; /* HC erase timeout */ -sd->ext_csd[222] = 0x1; /* Reliable write sector count */ -sd->ext_csd[221] = 0x4; /* HC write protect group size */ -sd->ext_csd[220] = 0x8; /* Sleep current VCC */ -sd->ext_csd[219] = 0x7; /* Sleep current VCCQ */ -sd->ext_csd[217] = 0x11; /* Sleep/Awake timeout */ +sd->ext_csd[EXT_CSD_TRIM_MULT] = 0x1; /* Trim multiplier */ +sd->ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT] = 0x15; /* Secure feature +support */ +sd->ext_csd[EXT_CSD_SEC_ERASE_MULT] = 0x96; /* Secure erase support */ +sd->ext_csd[EXT_CSD_SEC_TRIM_MULT] = 0x96; /* Secure TRIM multiplier */ +sd->ext_csd[EXT_CSD_BOOT_INFO] = 0x7; /* Boot information */ +sd->ext_csd[EXT_CSD_BOOT_MULT] = 0x8; /* Boot partition size. 128KB unit */ +sd->ext_csd[EXT_CSD_ACC_SIZE] = 0x6; /* Access size */ +sd->ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] = 0x4; /* HC Erase unit size */ +sd->ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT] = 0x1; /* HC erase timeout */ +sd->ext_csd[EXT_CSD_REL_WR_SEC_C] = 0x1; /* Reliable write sector count */ +sd->ext_csd[EXT_CSD_HC_WP_GRP_SIZE] = 0x4; /* HC write protect group size */ +sd->ext_csd[EXT_CSD_S_C_VCC] = 0x8; /* Sleep current VCC */ +sd->ext_csd[EXT_CSD_S_C_VCCQ] = 0x7; /* Sleep current VCCQ */ +sd->ext_csd[EXT_CSD_S_A_TIMEOUT] = 0x11; /* Sleep/Awake timeout */ sd->ext_csd[215] = (sectcount >> 24) & 0xff; /* Sector count */ sd->ext_csd[214] = (sectcount >> 16) & 0xff; /* ... */ sd->ext_csd[213] = (sectcount >> 8) & 0xff; /* ... */ -sd->ext_csd[212] = (sectcount & 0xff); /* ... */ +sd->ext_csd[EXT_CSD_SEC_CNT] = (sectcount & 0xff); /* ... */ sd->ext_csd[210] = 0xa; /* Min write perf for 8bit@52Mhz */ sd->ext_csd[209] = 0xa; /* Min read perf for 8bit@52Mhz */ sd->ext_csd[208] = 0xa; /* Min write perf for 4bit@52Mhz */ sd->ext_csd[207] = 0xa; /* Min read perf for 4bit@52Mhz */ sd->ext_csd[206] = 0xa; /* Min write perf for 4bit@26Mhz */ sd->ext_csd[205] = 0xa; /* Min read perf for 4bit@26Mhz */ -sd->ext_csd[199] = 0x1; /* Partition switching timing */ -sd->ext_csd[198] = 0x1; /* Out-of-interrupt busy timing */ -sd->ext_csd[196] = 0xFF; /* Card type */ -sd->ext_csd[194] = 0x2; /* CSD Structure version */ -sd->ext_csd[192] = 0x5; /* Extended CSD revision */ -sd->ext_csd[168] = 0x1; /* RPMB size */ -sd->ext_csd[160] = 0x3; /* Partinioning support */ +sd->ext_csd[EXT_CSD_PART_SWITCH_TIME] = 0x1; /* Partition switching +timing */ +sd->ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] = 0x1; /* Out-of-interrupt busy + timing */ +sd->ext_csd[EXT_CSD_CARD_TYPE] = 0xFF; /* Card type */ +sd->ext_csd[EXT_CSD_STRUCTURE] = 0x2; /* CSD Structure version */ +sd->ext_csd[EXT_CSD_REV] = 0x5; /* Extended CSD revision */ +sd->ext_csd[EXT_CSD_RPMB_MULT] = 0x1; /* RPMB size */ +sd->ext_csd[EXT_CSD_PARTITION_SUPPORT] = 0x3; /* Partinioning support */
[RFC PATCH 06/15] sd: emmc: Add mmc switch function support
switch operation in eMMC card updates the ext_csd register to request changes in card operations. Here we implement similar sequence but requests are mostly dummy and make no change. Implement SWITCH_ERROR if the write operation extends goes beyond length of ext_csd. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 56 ++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 69289e0..7925174 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -519,6 +519,7 @@ static void sd_set_rca(SDState *sd, uint16_t value) FIELD(CSR, AKE_SEQ_ERROR, 3, 1) FIELD(CSR, APP_CMD, 5, 1) FIELD(CSR, FX_EVENT,6, 1) +FIELD(CSR, SWITCH_ERROR,7, 1) FIELD(CSR, READY_FOR_DATA, 8, 1) FIELD(CSR, CURRENT_STATE, 9, 4) FIELD(CSR, ERASE_RESET,13, 1) @@ -878,6 +879,43 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) return ret; } +enum { +MMC_CMD6_ACCESS_COMMAND_SET = 0, +MMC_CMD6_ACCESS_SET_BITS, +MMC_CMD6_ACCESS_CLEAR_BITS, +MMC_CMD6_ACCESS_WRITE_BYTE, +}; + +static void mmc_function_switch(SDState *sd, uint32_t arg) +{ +uint32_t access = extract32(arg, 24, 2); +uint32_t index = extract32(arg, 16, 8); +uint32_t value = extract32(arg, 8, 8); +uint8_t b = sd->ext_csd[index]; + +switch (access) { +case MMC_CMD6_ACCESS_COMMAND_SET: +qemu_log_mask(LOG_UNIMP, "MMC Command set switching not supported\n"); +return; +case MMC_CMD6_ACCESS_SET_BITS: +b |= value; +break; +case MMC_CMD6_ACCESS_CLEAR_BITS: +b &= ~value; +break; +case MMC_CMD6_ACCESS_WRITE_BYTE: +b = value; +break; +} + +if (index >= 192) { +sd->card_status |= R_CSR_SWITCH_ERROR_MASK; +return; +} + +sd->ext_csd[index] = b; +} + static void sd_function_switch(SDState *sd, uint32_t arg) { int i, mode, new_func; @@ -1097,12 +1135,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) case 6:/* CMD6: SWITCH_FUNCTION */ switch (sd->mode) { case sd_data_transfer_mode: -sd_function_switch(sd, req.arg); -sd->state = sd_sendingdata_state; -sd->data_start = 0; -sd->data_offset = 0; -return sd_r1; - +if (sd->emmc) { +sd->state = sd_programming_state; +mmc_function_switch(sd, req.arg); +sd->state = sd_transfer_state; +return sd_r1b; +} else { +sd_function_switch(sd, req.arg); +sd->state = sd_sendingdata_state; +sd->data_start = 0; +sd->data_offset = 0; +return sd_r1; +} default: break; } -- 2.7.4
[RFC PATCH 13/15] sd: emmc: Subtract bootarea size from blk
From: Joel Stanley The userdata size is derived from the file the user passes on the command line, but we must take into account the boot areas. Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater --- hw/sd/sd.c | 5 + 1 file changed, 5 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 55c1104..a2f39c9 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -658,6 +658,11 @@ static void sd_reset(DeviceState *dev) } size = sect << 9; +if (sd->emmc) { +unsigned int boot_capacity = sd->ext_csd[EXT_CSD_BOOT_MULT] << 17; +size -= boot_capacity * 2; +} + sect = sd_addr_to_wpnum(size) + 1; sd->state = sd_idle_state; -- 2.7.4
[RFC PATCH 14/15] sd: sdhci: Support eMMC devices
Embedded device slots should be allowed as support of eMMC is available. Signed-off-by: Sai Pavan Boddu --- hw/sd/sdhci.c | 4 1 file changed, 4 deletions(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 8ffa539..771212a 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -99,10 +99,6 @@ static void sdhci_check_capareg(SDHCIState *s, Error **errp) msk = FIELD_DP64(msk, SDHC_CAPAB, ASYNC_INT, 0); val = FIELD_EX64(s->capareg, SDHC_CAPAB, SLOT_TYPE); -if (val) { -error_setg(errp, "slot-type not supported"); -return; -} trace_sdhci_capareg("slot type", val); msk = FIELD_DP64(msk, SDHC_CAPAB, SLOT_TYPE, 0); -- 2.7.4
[RFC PATCH 12/15] sd: emmc: Support boot area in emmc image
From: Joel Stanley This assumes a specially constructued image: dd if=/dev/zero of=mmc-bootarea.img count=2 bs=1M dd if=u-boot-spl.bin of=mmc-bootarea.img conv=notrunc dd if=u-boot.bin of=mmc-bootarea.img conv=notrunc count=64 bs=1K cat mmc-bootarea.img obmc-phosphor-image.wic > mmc.img truncate --size 16GB mmc.img truncate --size 128MB mmc-bootarea.img Signed-off-by: Joel Stanley [clg: - changes on the definition names ] Signed-off-by: Cédric Le Goater [spb: use data_start property to access right emmc partition, Clean up PARTITION_ENABLE support as incomplete, Fix commit message to be generic.] Signed-off-by: Sai Pavan Boddu --- hw/sd/sd.c | 40 1 file changed, 40 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 54fba7b..55c1104 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1045,6 +1045,34 @@ static void sd_lock_command(SDState *sd) sd->card_status &= ~CARD_IS_LOCKED; } +/* + * This requires a disk image that has two boot partitions inserted at the + * beginning of it. The size of the boot partitions are configured in the + * ext_csd structure, which is hardcoded in qemu. They are currently set to + * 1MB each. + */ +static uint32_t sd_bootpart_offset(SDState *sd) +{ +unsigned int access = sd->ext_csd[EXT_CSD_PART_CONFIG] & +EXT_CSD_PART_CONFIG_ACC_MASK; +unsigned int boot_capacity = sd->ext_csd[EXT_CSD_BOOT_MULT] << 17; + +if (!sd->emmc) { +return 0; +} + +switch (access) { +case EXT_CSD_PART_CONFIG_ACC_DEFAULT: +return boot_capacity * 2; +case EXT_CSD_PART_CONFIG_ACC_BOOT0: +return 0; +case EXT_CSD_PART_CONFIG_ACC_BOOT0 + 1: +return boot_capacity * 1; +default: + g_assert_not_reached(); +} +} + static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) { uint32_t rca = 0x; @@ -1360,6 +1388,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1379,6 +1410,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1435,6 +1469,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; @@ -1465,6 +1502,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) return sd_r1; } +if (sd->emmc) { +addr += sd_bootpart_offset(sd); +} sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; -- 2.7.4
[RFC PATCH 08/15] sd: emmc: Make ACMD41 illegal for mmc
ACMD41 is not applicable for eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 90359f6..236f2b8 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1729,6 +1729,9 @@ static sd_rsp_type_t sd_app_command(SDState *sd, break; case 41: /* ACMD41: SD_APP_OP_COND */ +if (sd->emmc) { +break; +} if (sd->spi) { /* SEND_OP_CMD */ sd->state = sd_transfer_state; -- 2.7.4
[RFC PATCH 07/15] sd: emmc: add CMD21 tuning sequence
eMMC cards support tuning sequence for entering HS200 mode. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 47 +++ 1 file changed, 47 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 7925174..90359f6 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1378,6 +1378,14 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } break; +case 21:/* CMD21: mmc SEND TUNING_BLOCK */ +if (sd->emmc && (sd->state == sd_transfer_state)) { +sd->state = sd_sendingdata_state; +sd->data_offset = 0; +return sd_r1; +} +break; + case 23:/* CMD23: SET_BLOCK_COUNT */ if (sd->spec_version < SD_PHY_SPECv3_01_VERS) { break; @@ -2112,6 +2120,30 @@ static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, }; +#define EXCSD_BUS_WIDTH_OFFSET 183 +#define BUS_WIDTH_8_MASK0x4 +#define BUS_WIDTH_4_MASK0x2 +#define MMC_TUNING_BLOCK_SIZE 128 + +static const uint8_t mmc_tunning_block_pattern[128] = { + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, +}; + uint8_t sd_read_byte(SDState *sd) { /* TODO: Append CRCs */ @@ -2204,6 +2236,21 @@ uint8_t sd_read_byte(SDState *sd) ret = sd_tuning_block_pattern[sd->data_offset++]; break; +case 21:/* CMD21: SEND_TUNNING_BLOCK (MMC) */ +if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { +sd->state = sd_transfer_state; +} +if (sd->ext_csd[EXCSD_BUS_WIDTH_OFFSET] & BUS_WIDTH_8_MASK) { +ret = mmc_tunning_block_pattern[sd->data_offset++]; +} else { +/* Return LSB Nibbles of two byte from the 8bit tuning block + * for 4bit mode + */ +ret = mmc_tunning_block_pattern[sd->data_offset++] & 0x0F; +ret |= (mmc_tunning_block_pattern[sd->data_offset++] & 0x0F) << 4; +} +break; + case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ ret = sd->data[sd->data_offset ++]; -- 2.7.4
[RFC PATCH 05/15] sd: emmc: support idle state in CMD2
eMMC is expected to be in idle-state post CMD1. Ready state is an intermediate stage which we don't come across in Device identification mode. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 4 1 file changed, 4 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index e3738b2..69289e0 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1051,6 +1051,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) if (sd->spi) goto bad_cmd; switch (sd->state) { +case sd_idle_state: +if (!sd->emmc) { +break; +} case sd_ready_state: sd->state = sd_identification_state; return sd_r2_i; -- 2.7.4
[RFC PATCH 02/15] sd: add eMMC support
From: Vincent Palatin The parameters mimick a real 4GB eMMC, but it can be set to various sizes. Signed-off-by: Vincent Palatin [SPB: Rebased the patch over qemu 5.1, Mark eMMC to support all timing modes] Signed-off-by: Sai Pavan Boddu Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater --- hw/sd/sd.c | 143 + hw/sd/sdmmc-internal.c | 2 +- 2 files changed, 122 insertions(+), 23 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 8517dbc..a75fa1c 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -108,6 +108,7 @@ struct SDState { uint8_t spec_version; BlockBackend *blk; bool spi; +bool emmc; /* Runtime changeables */ @@ -134,6 +135,7 @@ struct SDState { uint64_t data_start; uint32_t data_offset; uint8_t data[512]; +uint8_t ext_csd[512]; qemu_irq readonly_cb; qemu_irq inserted_cb; QEMUTimer *ocr_power_timer; @@ -287,7 +289,8 @@ FIELD(OCR, CARD_POWER_UP, 31, 1) | R_OCR_ACCEPT_SWITCH_1V8_MASK \ | R_OCR_UHS_II_CARD_MASK \ | R_OCR_CARD_CAPACITY_MASK \ - | R_OCR_CARD_POWER_UP_MASK) + | R_OCR_CARD_POWER_UP_MASK \ + | R_OCR_DUAL_VOLTAGE_CARD_MASK) static void sd_set_ocr(SDState *sd) { @@ -371,6 +374,51 @@ static const uint8_t sd_csd_rw_mask[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, }; +static void mmc_set_ext_csd(SDState *sd, uint64_t size) +{ +uint32_t sectcount = size >> HWBLOCK_SHIFT; + +memset(sd->ext_csd, 0, 512); +sd->ext_csd[504] = 0x1; /* supported command sets */ +sd->ext_csd[503] = 0x1; /* HPI features */ +sd->ext_csd[502] = 0x1; /* Background operations support */ +sd->ext_csd[241] = 0xA; /* 1st initialization time after partitioning */ +sd->ext_csd[232] = 0x1; /* Trim multiplier */ +sd->ext_csd[231] = 0x15; /* Secure feature support */ +sd->ext_csd[230] = 0x96; /* Secure erase support */ +sd->ext_csd[229] = 0x96; /* Secure TRIM multiplier */ +sd->ext_csd[228] = 0x7; /* Boot information */ +sd->ext_csd[226] = 0x8; /* Boot partition size */ +sd->ext_csd[225] = 0x6; /* Access size */ +sd->ext_csd[224] = 0x4; /* HC Erase unit size */ +sd->ext_csd[223] = 0x1; /* HC erase timeout */ +sd->ext_csd[222] = 0x1; /* Reliable write sector count */ +sd->ext_csd[221] = 0x4; /* HC write protect group size */ +sd->ext_csd[220] = 0x8; /* Sleep current VCC */ +sd->ext_csd[219] = 0x7; /* Sleep current VCCQ */ +sd->ext_csd[217] = 0x11; /* Sleep/Awake timeout */ +sd->ext_csd[215] = (sectcount >> 24) & 0xff; /* Sector count */ +sd->ext_csd[214] = (sectcount >> 16) & 0xff; /* ... */ +sd->ext_csd[213] = (sectcount >> 8) & 0xff; /* ... */ +sd->ext_csd[212] = (sectcount & 0xff); /* ... */ +sd->ext_csd[210] = 0xa; /* Min write perf for 8bit@52Mhz */ +sd->ext_csd[209] = 0xa; /* Min read perf for 8bit@52Mhz */ +sd->ext_csd[208] = 0xa; /* Min write perf for 4bit@52Mhz */ +sd->ext_csd[207] = 0xa; /* Min read perf for 4bit@52Mhz */ +sd->ext_csd[206] = 0xa; /* Min write perf for 4bit@26Mhz */ +sd->ext_csd[205] = 0xa; /* Min read perf for 4bit@26Mhz */ +sd->ext_csd[199] = 0x1; /* Partition switching timing */ +sd->ext_csd[198] = 0x1; /* Out-of-interrupt busy timing */ +sd->ext_csd[196] = 0xFF; /* Card type */ +sd->ext_csd[194] = 0x2; /* CSD Structure version */ +sd->ext_csd[192] = 0x5; /* Extended CSD revision */ +sd->ext_csd[168] = 0x1; /* RPMB size */ +sd->ext_csd[160] = 0x3; /* Partinioning support */ +sd->ext_csd[159] = 0x00; /* Max enhanced area size */ +sd->ext_csd[158] = 0x00; /* ... */ +sd->ext_csd[157] = 0xEC; /* ... */ +} + static void sd_set_csd(SDState *sd, uint64_t size) { int hwblock_shift = HWBLOCK_SHIFT; @@ -384,7 +432,34 @@ static void sd_set_csd(SDState *sd, uint64_t size) } csize = (size >> (CMULT_SHIFT + hwblock_shift)) - 1; -if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */ +if (sd->emmc) { /* eMMC */ +sd->csd[0] = 0xd0; +sd->csd[1] = 0x0f; +sd->csd[2] = 0x00; +sd->csd[3] = 0x32; +sd->csd[4] = 0x0f; +if (size <= 0x8000ULL) { +/* 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; +
[RFC PATCH 03/15] sd: emmc: Dont not update CARD_CAPACITY for eMMC cards
OCR.CARD_CAPACITY field is only valid for sd cards, So skip it for eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index a75fa1c..57fff89 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -308,7 +308,8 @@ static void sd_ocr_powerup(void *opaque) /* card power-up OK */ sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1); -if (sd->size > SDSC_MAX_CAPACITY) { +/* eMMC supports only Byte mode */ +if (!sd->emmc && sd->size > SDSC_MAX_CAPACITY) { sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1); } } -- 2.7.4
[RFC PATCH 04/15] sd: emmc: Update CMD1 definition for eMMC
Add support to Power up the card and send response r3 in case of eMMC. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 57fff89..e3738b2 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1033,8 +1033,16 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) break; case 1:/* CMD1: SEND_OP_CMD */ -if (!sd->spi) +/* MMC: Powerup & send r3 + * SD: send r1 in spi mode + */ +if (sd->emmc) { +sd_ocr_powerup(sd); +return sd->state == sd_idle_state ? + sd_r3 : sd_r0; +} else if (!sd->spi) { goto bad_cmd; +} sd->state = sd_transfer_state; return sd_r1; -- 2.7.4
[RFC PATCH 10/15] sd: emmc: Update CID structure for eMMC
CID structure is little different for eMMC, w.r.t to product name and manufacturing date. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 52 +++- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 7aab647..45311fa 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -345,23 +345,41 @@ static void sd_set_scr(SDState *sd) static void sd_set_cid(SDState *sd) { -sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ -sd->cid[1] = OID[0]; /* OEM/Application ID (OID) */ -sd->cid[2] = OID[1]; -sd->cid[3] = PNM[0]; /* Fake product name (PNM) */ -sd->cid[4] = PNM[1]; -sd->cid[5] = PNM[2]; -sd->cid[6] = PNM[3]; -sd->cid[7] = PNM[4]; -sd->cid[8] = PRV; /* Fake product revision (PRV) */ -sd->cid[9] = 0xde; /* Fake serial number (PSN) */ -sd->cid[10] = 0xad; -sd->cid[11] = 0xbe; -sd->cid[12] = 0xef; -sd->cid[13] = 0x00 | /* Manufacture date (MDT) */ -((MDT_YR - 2000) / 10); -sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; -sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; +if (sd->emmc) { +sd->cid[0] = MID; +sd->cid[1] = 0x1; /* CBX */ +sd->cid[2] = OID[0];/* OEM/Application ID (OID) */ +sd->cid[3] = PNM[0];/* Fake product name (PNM) 48bit */ +sd->cid[4] = PNM[1]; +sd->cid[5] = PNM[2]; +sd->cid[6] = PNM[3]; +sd->cid[7] = PNM[4]; +sd->cid[8] = 0x0; +sd->cid[9] = PRV;/* Fake product revision (PRV) */ +sd->cid[10] = 0xde; /* Fake serial number (PSN) */ +sd->cid[11] = 0xad; +sd->cid[12] = 0xbe; +sd->cid[13] = 0xef; +sd->cid[14] = ((MDT_YR - 1997) % 0x10); /* MDT */ +} else { +sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ +sd->cid[1] = OID[0];/* OEM/Application ID (OID) */ +sd->cid[2] = OID[1]; +sd->cid[3] = PNM[0];/* Fake product name (PNM) 40bit */ +sd->cid[4] = PNM[1]; +sd->cid[5] = PNM[2]; +sd->cid[6] = PNM[3]; +sd->cid[7] = PNM[4]; +sd->cid[8] = PRV; /* Fake product revision (PRV) */ +sd->cid[9] = 0xde; /* Fake serial number (PSN) */ +sd->cid[10] = 0xad; +sd->cid[11] = 0xbe; +sd->cid[12] = 0xef; +sd->cid[13] = 0x00 |/* Manufacture date (MDT) */ +((MDT_YR - 2000) / 10); +sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; + } + sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; } #define HWBLOCK_SHIFT 9 /* 512 bytes */ -- 2.7.4
[RFC PATCH 09/15] sd: emmc: Add support for emmc erase
Add CMD35 and CMD36 which sets the erase start and end. Signed-off-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias --- hw/sd/sd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 236f2b8..7aab647 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1544,6 +1544,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) /* Erase commands (Class 5) */ case 32: /* CMD32: ERASE_WR_BLK_START */ +case 35: switch (sd->state) { case sd_transfer_state: sd->erase_start = req.arg; @@ -1555,6 +1556,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) break; case 33: /* CMD33: ERASE_WR_BLK_END */ +case 36: switch (sd->state) { case sd_transfer_state: sd->erase_end = req.arg; -- 2.7.4
[RFC PATCH 01/15] block: add eMMC block device type
From: Vincent Palatin Add new block device type. Signed-off-by: Vincent Palatin [SPB: Rebased over 5.1 version] Signed-off-by: Sai Pavan Boddu Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater --- blockdev.c| 1 + include/sysemu/blockdev.h | 1 + 2 files changed, 2 insertions(+) diff --git a/blockdev.c b/blockdev.c index b250b9b..593ce44 100644 --- a/blockdev.c +++ b/blockdev.c @@ -83,6 +83,7 @@ static const char *const if_name[IF_COUNT] = { [IF_SD] = "sd", [IF_VIRTIO] = "virtio", [IF_XEN] = "xen", +[IF_EMMC] = "emmc", }; static int if_max_devs[IF_COUNT] = { diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 3b5fcda..eefae9f 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -24,6 +24,7 @@ typedef enum { */ IF_NONE = 0, IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, +IF_EMMC, IF_COUNT } BlockInterfaceType; -- 2.7.4
[RFC PATCH 00/15] eMMC support
Hi, This patch series add support for eMMC cards. This work was previosly submitted by Vincent, rebased few changes on top. Cedric & Joel has helped to added boot partition access support. I expect them to make a follow-up series to use it with aspeed machines. Present series adds eMMC support to Versal SOC. Regards, Sai Pavan Cédric Le Goater (1): sd: emmc: Add Extended CSD register definitions Joel Stanley (2): sd: emmc: Support boot area in emmc image sd: emmc: Subtract bootarea size from blk Sai Pavan Boddu (10): sd: emmc: Dont not update CARD_CAPACITY for eMMC cards sd: emmc: Update CMD1 definition for eMMC sd: emmc: support idle state in CMD2 sd: emmc: Add mmc switch function support sd: emmc: add CMD21 tuning sequence sd: emmc: Make ACMD41 illegal for mmc sd: emmc: Add support for emmc erase sd: emmc: Update CID structure for eMMC sd: sdhci: Support eMMC devices arm: xlnx-versal: Add emmc to versal Vincent Palatin (2): block: add eMMC block device type sd: add eMMC support blockdev.c| 1 + hw/arm/xlnx-versal-virt.c | 16 +- hw/arm/xlnx-versal.c | 14 +- hw/sd/sd.c| 369 -- hw/sd/sdhci.c | 4 - hw/sd/sdmmc-internal.c| 2 +- hw/sd/sdmmc-internal.h| 97 include/sysemu/blockdev.h | 1 + 8 files changed, 445 insertions(+), 59 deletions(-) -- 2.7.4
Re: [RFC PATCH V2 02/11] hw/block/nvme: open code for volatile write cache
Hi Minwoo, Please ignore this mail, I see a fix already floating around in the list. Regards, Sai Pavan On Thu, Feb 11, 2021 at 12:15:57PM +0530, Sai Pavan Boddu wrote: > Hi Minwoo, > > On Sun, Jan 17, 2021 at 11:53:32PM +0900, Minwoo Im wrote: > > Volatile Write Cache(VWC) feature is set in nvme_ns_setup() in the > > initial time. This feature is related to block device backed, but this > > feature is controlled in controller level via Set/Get Features command. > > > > This patch removed dependency between nvme and nvme-ns to manage the VWC > > flag value. Also, it open coded the Get Features for VWC to check all > > namespaces attached to the controller, and if false detected, return > > directly false. > > > > Signed-off-by: Minwoo Im > > --- > > hw/block/nvme-ns.c | 4 > > hw/block/nvme.c| 15 --- > > hw/block/nvme.h| 1 - > > 3 files changed, 12 insertions(+), 8 deletions(-) > > > > diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c > > index 32662230130b..c403cd36b6bd 100644 > > --- a/hw/block/nvme-ns.c > > +++ b/hw/block/nvme-ns.c > > @@ -89,10 +89,6 @@ static int nvme_ns_init_blk(NvmeCtrl *n, NvmeNamespace > > *ns, Error **errp) > > return -1; > > } > > > > -if (blk_enable_write_cache(ns->blkconf.blk)) { > > -n->features.vwc = 0x1; > > -} > > - > > return 0; > > } > > > > diff --git a/hw/block/nvme.c b/hw/block/nvme.c > > index cf0fe28fe6eb..b2a9c48a9d81 100644 > > --- a/hw/block/nvme.c > > +++ b/hw/block/nvme.c > > @@ -3033,6 +3033,7 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, > > NvmeRequest *req) > > NvmeGetFeatureSelect sel = NVME_GETFEAT_SELECT(dw10); > > uint16_t iv; > > NvmeNamespace *ns; > > +int i; > > > > static const uint32_t nvme_feature_default[NVME_FID_MAX] = { > > [NVME_ARBITRATION] = NVME_ARB_AB_NOLIMIT, > > @@ -3108,7 +3109,17 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, > > NvmeRequest *req) > > result = ns->features.err_rec; > > goto out; > > case NVME_VOLATILE_WRITE_CACHE: > > -result = n->features.vwc; > > > > This change breaks the build on ubuntu 16.04, gcc is detecting error > > as below > > ../hw/block/nvme.c: In function ‘nvme_process_sq’: > > ../hw/block/nvme.c:3242:9: error: ‘result’ may be used uninitialized > > in this function [-Werror=maybe-uninitialized] > > trace_pci_nvme_getfeat_vwcache(result ? "enabled" : > > "disabled"); > > ^ > > ../hw/block/nvme.c:3150:14: note: ‘result’ was > > declared here > >uint32_t result; > > ^ > >GCC version 5.4.0. > >Tested initilizing result variable, build looks good then. > > > >Regards, > >Sai Pavan > > > > +for (i = 1; i <= n->num_namespaces; i++) { > > +ns = nvme_ns(n, i); > > +if (!ns) { > > +continue; > > +} > > + > > +result = blk_enable_write_cache(ns->blkconf.blk); > > +if (!result) { > > +break; > > +} > > +} > > trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled"); > > goto out; > > case NVME_ASYNCHRONOUS_EVENT_CONF: > > @@ -3271,8 +3282,6 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, > > NvmeRequest *req) > > ns->features.err_rec = dw11; > > break; > > case NVME_VOLATILE_WRITE_CACHE: > > -n->features.vwc = dw11 & 0x1; > > - > > for (i = 1; i <= n->num_namespaces; i++) { > > ns = nvme_ns(n, i); > > if (!ns) { > > diff --git a/hw/block/nvme.h b/hw/block/nvme.h > > index b7fbcca39d9f..5ba83ee77841 100644 > > --- a/hw/block/nvme.h > > +++ b/hw/block/nvme.h > > @@ -117,7 +117,6 @@ typedef struct NvmeFeatureVal { > > uint16_t temp_thresh_low; > > }; > > uint32_tasync_config; > > -uint32_tvwc; > > } NvmeFeatureVal; > > > > typedef struct NvmeCtrl { > > -- > > 2.17.1 > > > > >
Re: [RFC PATCH V2 02/11] hw/block/nvme: open code for volatile write cache
Hi Minwoo, On Sun, Jan 17, 2021 at 11:53:32PM +0900, Minwoo Im wrote: > Volatile Write Cache(VWC) feature is set in nvme_ns_setup() in the > initial time. This feature is related to block device backed, but this > feature is controlled in controller level via Set/Get Features command. > > This patch removed dependency between nvme and nvme-ns to manage the VWC > flag value. Also, it open coded the Get Features for VWC to check all > namespaces attached to the controller, and if false detected, return > directly false. > > Signed-off-by: Minwoo Im > --- > hw/block/nvme-ns.c | 4 > hw/block/nvme.c| 15 --- > hw/block/nvme.h| 1 - > 3 files changed, 12 insertions(+), 8 deletions(-) > > diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c > index 32662230130b..c403cd36b6bd 100644 > --- a/hw/block/nvme-ns.c > +++ b/hw/block/nvme-ns.c > @@ -89,10 +89,6 @@ static int nvme_ns_init_blk(NvmeCtrl *n, NvmeNamespace > *ns, Error **errp) > return -1; > } > > -if (blk_enable_write_cache(ns->blkconf.blk)) { > -n->features.vwc = 0x1; > -} > - > return 0; > } > > diff --git a/hw/block/nvme.c b/hw/block/nvme.c > index cf0fe28fe6eb..b2a9c48a9d81 100644 > --- a/hw/block/nvme.c > +++ b/hw/block/nvme.c > @@ -3033,6 +3033,7 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, > NvmeRequest *req) > NvmeGetFeatureSelect sel = NVME_GETFEAT_SELECT(dw10); > uint16_t iv; > NvmeNamespace *ns; > +int i; > > static const uint32_t nvme_feature_default[NVME_FID_MAX] = { > [NVME_ARBITRATION] = NVME_ARB_AB_NOLIMIT, > @@ -3108,7 +3109,17 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, > NvmeRequest *req) > result = ns->features.err_rec; > goto out; > case NVME_VOLATILE_WRITE_CACHE: > -result = n->features.vwc; > > This change breaks the build on ubuntu 16.04, gcc is detecting error > as below > ../hw/block/nvme.c: In function ‘nvme_process_sq’: > ../hw/block/nvme.c:3242:9: error: ‘result’ may be used uninitialized > in this function [-Werror=maybe-uninitialized] > trace_pci_nvme_getfeat_vwcache(result ? "enabled" : > "disabled"); > ^ > ../hw/block/nvme.c:3150:14: note: ‘result’ was > declared here >uint32_t result; > ^ >GCC version 5.4.0. >Tested initilizing result variable, build looks good then. > >Regards, >Sai Pavan > > +for (i = 1; i <= n->num_namespaces; i++) { > +ns = nvme_ns(n, i); > +if (!ns) { > +continue; > +} > + > +result = blk_enable_write_cache(ns->blkconf.blk); > +if (!result) { > +break; > +} > +} > trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled"); > goto out; > case NVME_ASYNCHRONOUS_EVENT_CONF: > @@ -3271,8 +3282,6 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, > NvmeRequest *req) > ns->features.err_rec = dw11; > break; > case NVME_VOLATILE_WRITE_CACHE: > -n->features.vwc = dw11 & 0x1; > - > for (i = 1; i <= n->num_namespaces; i++) { > ns = nvme_ns(n, i); > if (!ns) { > diff --git a/hw/block/nvme.h b/hw/block/nvme.h > index b7fbcca39d9f..5ba83ee77841 100644 > --- a/hw/block/nvme.h > +++ b/hw/block/nvme.h > @@ -117,7 +117,6 @@ typedef struct NvmeFeatureVal { > uint16_t temp_thresh_low; > }; > uint32_tasync_config; > -uint32_tvwc; > } NvmeFeatureVal; > > typedef struct NvmeCtrl { > -- > 2.17.1 > >
[PATCH v2] sd: Exhibit support for CMD23
Update 'SCR.CMD_SUPPORT' register with support of CMD23. Signed-off-by: Sai Pavan Boddu Reported-by: Rahul Thati --- Changes for V2: Fix commit message hw/sd/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 0012882..16d1b61 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -335,7 +335,7 @@ static void sd_set_scr(SDState *sd) if (sd->spec_version >= SD_PHY_SPECv3_01_VERS) { sd->scr[2] |= 1 << 7; /* Spec Version 3.0X */ } -sd->scr[3] = 0x00; +sd->scr[3] = 0x2; /* CMD23 supported */ /* reserved for manufacturer usage */ sd->scr[4] = 0x00; sd->scr[5] = 0x00; -- 2.7.4
[PATCH] sd: Exibit support for CMD23
Update SCR.CMD_SUPPORT register with support of CMD23. Signed-off-by: Sai Pavan Boddu Reported-by: Rahul Thati --- hw/sd/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 0012882..16d1b61 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -335,7 +335,7 @@ static void sd_set_scr(SDState *sd) if (sd->spec_version >= SD_PHY_SPECv3_01_VERS) { sd->scr[2] |= 1 << 7; /* Spec Version 3.0X */ } -sd->scr[3] = 0x00; +sd->scr[3] = 0x2; /* CMD23 supported */ /* reserved for manufacturer usage */ sd->scr[4] = 0x00; sd->scr[5] = 0x00; -- 2.7.4
RE: [PATCH 07/18] hw/sd: sd: Fix incorrect populated function switch status data structure
Hi Bin, > -Original Message- > From: Bin Meng > Sent: Friday, August 21, 2020 3:38 PM > To: Sai Pavan Boddu > Cc: Philippe Mathieu-Daudé ; Alistair Francis > ; Bastian Koppelmann paderborn.de>; Palmer Dabbelt ; Sagar > Karandikar ; qemu-de...@nongnu.org; qemu- > ri...@nongnu.org; Bin Meng ; qemu- > bl...@nongnu.org; Sai Pavan Boddu > Subject: Re: [PATCH 07/18] hw/sd: sd: Fix incorrect populated function switch > status data structure > > Hi Sai, > > On Fri, Aug 21, 2020 at 6:04 PM Sai Pavan Boddu > wrote: > > > > Hi Philippe, > > > > First two patch of SD look good. Tested them over zynqmp and versal > > platforms. > > > > Thanks for testing. > > Can I add your Tested-by tag? [Sai Pavan Boddu] Sure. Thanks. Regards, Sai Pavan > > Regards, > Bin
Re: [PATCH 07/18] hw/sd: sd: Fix incorrect populated function switch status data structure
Hi Philippe, First two patch of SD look good. Tested them over zynqmp and versal platforms. Thanks, Sai Pavan On Tue, Aug 18, 2020 at 04:30:15PM +, Sai Pavan Boddu wrote: > Thanks Philippe, > > I would test this and get back. > > Regards, > Sai Pavan > > > -Original Message- > > From: Philippe Mathieu-Daudé On > > Behalf Of Philippe Mathieu-Daudé > > Sent: Saturday, August 15, 2020 1:29 PM > > To: Bin Meng ; Alistair Francis > > ; Bastian Koppelmann > paderborn.de>; Palmer Dabbelt ; Sagar > > Karandikar ; qemu-de...@nongnu.org; qemu- > > ri...@nongnu.org; Sai Pavan Boddu > > Cc: Bin Meng ; qemu-block@nongnu.org > > Subject: Re: [PATCH 07/18] hw/sd: sd: Fix incorrect populated function > > switch > > status data structure > > > > +Sai Pavan > > > > On 8/14/20 6:40 PM, Bin Meng wrote: > > > From: Bin Meng > > > > > > At present the function switch status data structure bit [399:376] are > > > wrongly pupulated. These 3 bytes encode function switch status for the > > > 6 function groups, with 4 bits per group, starting from function group > > > 6 at bit 399, then followed by function group 5 at bit 395, and so on. > > > > > > However the codes mistakenly fills in the function group 1 status at > > > bit 399. This fixes the code logic. > > > > > > > Fixes: a1bb27b1e9 ("SD card emulation (initial implementation)") > > > > > Signed-off-by: Bin Meng > > > --- > > > > > > hw/sd/sd.c | 6 +- > > > 1 file changed, 5 insertions(+), 1 deletion(-) > > > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > > index fad9cf1..51f5900 100644 > > > --- a/hw/sd/sd.c > > > +++ b/hw/sd/sd.c > > > @@ -806,11 +806,15 @@ static void sd_function_switch(SDState *sd, > > uint32_t arg) > > > sd->data[11] = 0x43; > > > sd->data[12] = 0x80; /* Supported group 1 functions */ > > > sd->data[13] = 0x03; > > > + > > > +sd->data[14] = 0; > > > +sd->data[15] = 0; > > > +sd->data[16] = 0; > > > > Pointless zero initialization. > > > > Reviewed-by: Philippe Mathieu-Daudé > > > > I'll wait until next week in case Sai Pavan wants to test this patch (I > > don't have > > access to the Xilinx images anymore) then I'll queue this via my sd-next > > tree. > > > > Regards, > > > > Phil. > > > > > for (i = 0; i < 6; i ++) { > > > new_func = (arg >> (i * 4)) & 0x0f; > > > if (mode && new_func != 0x0f) > > > sd->function_group[i] = new_func; > > > -sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4); > > > +sd->data[16 - (i >> 1)] |= new_func << ((i % 2) * 4); > > > } > > > memset(>data[17], 0, 47); > > > stw_be_p(sd->data + 64, sd_crc16(sd->data, 64)); > > > >