On Tue, Mar 28, 2023 at 7:47 AM <qianfangui...@163.com> wrote: > From: qianfan Zhao <qianfangui...@163.com> > > A64's sd register was similar to H3, and it introduced a new register > named SAMP_DL_REG location at 0x144. The dma descriptor buffer size of > mmc2 is only 8K and the other mmc controllers has 64K. > > Signed-off-by: qianfan Zhao <qianfangui...@163.com> > --- > hw/sd/allwinner-sdhost.c | 70 ++++++++++++++++++++++++++++++-- > include/hw/sd/allwinner-sdhost.h | 9 ++++ > 2 files changed, 76 insertions(+), 3 deletions(-) > > diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c > index 51e5e90830..38e7844399 100644 > --- a/hw/sd/allwinner-sdhost.c > +++ b/hw/sd/allwinner-sdhost.c > @@ -77,6 +77,7 @@ enum { > REG_SD_DATA1_CRC = 0x12C, /* CRC Data 1 from card/eMMC */ > REG_SD_DATA0_CRC = 0x130, /* CRC Data 0 from card/eMMC */ > REG_SD_CRC_STA = 0x134, /* CRC status from card/eMMC during write > */ > + REG_SD_SAMP_DL = 0x144, /* Sample Delay Control (sun50i-a64) */ > REG_SD_FIFO = 0x200, /* Read/Write FIFO */ > }; > > @@ -158,6 +159,7 @@ enum { > REG_SD_RES_CRC_RST = 0x0, > REG_SD_DATA_CRC_RST = 0x0, > REG_SD_CRC_STA_RST = 0x0, > + REG_SD_SAMPLE_DL_RST = 0x00002000, > REG_SD_FIFO_RST = 0x0, > }; > > @@ -438,6 +440,7 @@ static uint64_t allwinner_sdhost_read(void *opaque, > hwaddr offset, > { > AwSdHostState *s = AW_SDHOST(opaque); > AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s); > + bool out_of_bounds = false; > uint32_t res = 0; > > switch (offset) { > @@ -556,13 +559,24 @@ static uint64_t allwinner_sdhost_read(void *opaque, > hwaddr offset, > case REG_SD_FIFO: /* Read/Write FIFO */ > res = allwinner_sdhost_fifo_read(s); > break; > + case REG_SD_SAMP_DL: /* Sample Delay */ > Sample Delay Control
> + if (sc->can_calibrate) { > + res = s->sample_delay; > + } else { > + out_of_bounds = true; > + } > + break; > default: > - qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %" > - HWADDR_PRIx"\n", __func__, offset); > + out_of_bounds = true; > res = 0; > break; > } > > + if (out_of_bounds) { > + qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %" > + HWADDR_PRIx"\n", __func__, offset); > + } > + > trace_allwinner_sdhost_read(offset, res, size); > return res; > } > @@ -581,6 +595,7 @@ static void allwinner_sdhost_write(void *opaque, > hwaddr offset, > { > AwSdHostState *s = AW_SDHOST(opaque); > AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s); > + bool out_of_bounds = false; > > trace_allwinner_sdhost_write(offset, value, size); > > @@ -704,10 +719,21 @@ static void allwinner_sdhost_write(void *opaque, > hwaddr offset, > case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */ > case REG_SD_CRC_STA: /* CRC status from card/eMMC in write > operation */ > break; > + case REG_SD_SAMP_DL: /* Sample delay control */ > + if (sc->can_calibrate) { > + s->sample_delay = value; > + } else { > + out_of_bounds = true; > + } > + break; > default: > + out_of_bounds = true; > + break; > + } > + > + if (out_of_bounds) { > qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %" > HWADDR_PRIx"\n", __func__, offset); > - break; > } > } > > @@ -756,6 +782,7 @@ static const VMStateDescription > vmstate_allwinner_sdhost = { > VMSTATE_UINT32(response_crc, AwSdHostState), > VMSTATE_UINT32_ARRAY(data_crc, AwSdHostState, 8), > VMSTATE_UINT32(status_crc, AwSdHostState), > + VMSTATE_UINT32(sample_delay, AwSdHostState), > VMSTATE_END_OF_LIST() > } > }; > @@ -794,6 +821,7 @@ static void allwinner_sdhost_realize(DeviceState *dev, > Error **errp) > static void allwinner_sdhost_reset(DeviceState *dev) > { > AwSdHostState *s = AW_SDHOST(dev); > + AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s); > > s->global_ctl = REG_SD_GCTL_RST; > s->clock_ctl = REG_SD_CKCR_RST; > @@ -834,6 +862,10 @@ static void allwinner_sdhost_reset(DeviceState *dev) > } > > s->status_crc = REG_SD_CRC_STA_RST; > + > + if (sc->can_calibrate) { > + s->sample_delay = REG_SD_SAMPLE_DL_RST; > + } > } > > static void allwinner_sdhost_bus_class_init(ObjectClass *klass, void > *data) > @@ -867,6 +899,24 @@ static void > allwinner_sdhost_sun5i_class_init(ObjectClass *klass, void *data) > sc->is_sun4i = false; > } > > +static void allwinner_sdhost_sun50i_a64_class_init(ObjectClass *klass, > + void *data) > +{ > + AwSdHostClass *sc = AW_SDHOST_CLASS(klass); > + sc->max_desc_size = 64 * KiB; > + sc->is_sun4i = false; > + sc->can_calibrate = true; > perhaps in the other two existing _init() functions for sun4i/sun5i, we should also explicitly set the new can_calibrate value to false, to avoid the risk of using uninitialized data in the other machines/socs. > +} > + > +static void allwinner_sdhost_sun50i_a64_emmc_class_init(ObjectClass > *klass, > + void *data) > +{ > + AwSdHostClass *sc = AW_SDHOST_CLASS(klass); > + sc->max_desc_size = 8 * KiB; > + sc->is_sun4i = false; > + sc->can_calibrate = true; > +} > + > static const TypeInfo allwinner_sdhost_info = { > .name = TYPE_AW_SDHOST, > .parent = TYPE_SYS_BUS_DEVICE, > @@ -889,6 +939,18 @@ static const TypeInfo allwinner_sdhost_sun5i_info = { > .class_init = allwinner_sdhost_sun5i_class_init, > }; > > +static const TypeInfo allwinner_sdhost_sun50i_a64_info = { > + .name = TYPE_AW_SDHOST_SUN50I_A64, > + .parent = TYPE_AW_SDHOST, > + .class_init = allwinner_sdhost_sun50i_a64_class_init, > +}; > + > +static const TypeInfo allwinner_sdhost_sun50i_a64_emmc_info = { > + .name = TYPE_AW_SDHOST_SUN50I_A64_EMMC, > + .parent = TYPE_AW_SDHOST, > + .class_init = allwinner_sdhost_sun50i_a64_emmc_class_init, > +}; > + > static const TypeInfo allwinner_sdhost_bus_info = { > .name = TYPE_AW_SDHOST_BUS, > .parent = TYPE_SD_BUS, > @@ -901,6 +963,8 @@ static void allwinner_sdhost_register_types(void) > type_register_static(&allwinner_sdhost_info); > type_register_static(&allwinner_sdhost_sun4i_info); > type_register_static(&allwinner_sdhost_sun5i_info); > + type_register_static(&allwinner_sdhost_sun50i_a64_info); > + type_register_static(&allwinner_sdhost_sun50i_a64_emmc_info); > type_register_static(&allwinner_sdhost_bus_info); > } > > diff --git a/include/hw/sd/allwinner-sdhost.h > b/include/hw/sd/allwinner-sdhost.h > index 30c1e60404..1b951177dd 100644 > --- a/include/hw/sd/allwinner-sdhost.h > +++ b/include/hw/sd/allwinner-sdhost.h > @@ -38,6 +38,12 @@ > /** Allwinner sun5i family and newer (A13, H2+, H3, etc) */ > #define TYPE_AW_SDHOST_SUN5I TYPE_AW_SDHOST "-sun5i" > > +/** Allwinner sun50i-a64 */ > +#define TYPE_AW_SDHOST_SUN50I_A64 TYPE_AW_SDHOST "-sun50i-a64" > + > +/** Allwinner sun50i-a64 emmc */ > +#define TYPE_AW_SDHOST_SUN50I_A64_EMMC TYPE_AW_SDHOST "-sun50i-a64-emmc" > + > /** @} */ > > /** > @@ -110,6 +116,7 @@ struct AwSdHostState { > uint32_t startbit_detect; /**< eMMC DDR Start Bit Detection Control > */ > uint32_t response_crc; /**< Response CRC */ > uint32_t data_crc[8]; /**< Data CRC */ > + uint32_t sample_delay; /**< Sample delay control */ > uint32_t status_crc; /**< Status CRC */ > > /** @} */ > @@ -132,6 +139,8 @@ struct AwSdHostClass { > size_t max_desc_size; > bool is_sun4i; > > + /** does the IP block support autocalibration? */ > + bool can_calibrate; > }; > > #endif /* HW_SD_ALLWINNER_SDHOST_H */ > -- > 2.25.1 > > In this patch, I don't see any update to the new allwinner-r40.c file. If you make the required changes to allwinner-r40.c in this patch, you can also avoid having patch 08. Regards, Niek -- Niek Linnenbank