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

Reply via email to