On Wed, May 10, 2023 at 12:30 PM <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. > > Also fix allwinner-r40's mmc controller type. > > Signed-off-by: qianfan Zhao <qianfangui...@163.com> > --- > hw/arm/allwinner-r40.c | 2 +- > hw/sd/allwinner-sdhost.c | 70 ++++++++++++++++++++++++++++++-- > include/hw/sd/allwinner-sdhost.h | 9 ++++ > 3 files changed, 77 insertions(+), 4 deletions(-) > > diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c > index 0e4542d35f..b148c56449 100644 > --- a/hw/arm/allwinner-r40.c > +++ b/hw/arm/allwinner-r40.c > @@ -271,7 +271,7 @@ static void allwinner_r40_init(Object *obj) > > for (int i = 0; i < AW_R40_NUM_MMCS; i++) { > object_initialize_child(obj, mmc_names[i], &s->mmc[i], > - TYPE_AW_SDHOST_SUN5I); > + TYPE_AW_SDHOST_SUN50I_A64); > } > > object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I); > diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c > index 92a0f42708..f4fa2d179b 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, > }; > > @@ -459,6 +461,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) { > @@ -577,13 +580,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 */ > + 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; > } > @@ -602,6 +616,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); > > @@ -725,10 +740,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; > } > } > > @@ -777,6 +803,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() > } > }; > @@ -815,6 +842,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; > @@ -855,6 +883,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) > @@ -888,6 +920,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; >
For the existing functions allwinner_sdhost_sun4i_class_init() and allwinner_sdhost_sun5i_class_init(), could you please add 'sc->can_calibrate = false'? That way, we make it explicit that those types do not support the sample delay register. With that resolved, the code looks good to me: Reviewed-by: Niek Linnenbank <nieklinnenb...@gmail.com> > +} > + > +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, > @@ -910,6 +960,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, > @@ -922,6 +984,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 > > -- Niek Linnenbank