On Mon, Jul 10, 2023 at 12:16:35PM +0200, Philippe Mathieu-Daudé wrote:
> On 9/7/23 10:09, Bernhard Beschow wrote:
> > Since commit c0a55a0c9da2 "hw/sd/sdhci: Support big endian SD host 
> > controller
> > interfaces" sdhci_common_realize() forces all SD card controllers to use 
> > either
> > sdhci_mmio_le_ops or sdhci_mmio_be_ops, depending on the "endianness" 
> > property.
> > However, there are device models which use different MMIO ops: 
> > TYPE_IMX_USDHC
> > uses usdhc_mmio_ops and TYPE_S3C_SDHCI uses sdhci_s3c_mmio_ops.
> > 
> > Forcing sdhci_mmio_le_ops breaks SD card handling on the "sabrelite" board, 
> > for
> > example. Fix this by defaulting the io_ops to little endian and switch to 
> > big
> > endian in sdhci_common_realize() only if there is a matchig big endian 
> > variant
> > available.
> > 
> > Fixes: c0a55a0c9da2 ("hw/sd/sdhci: Support big endian SD host controller
> > interfaces")
> > 
> > Signed-off-by: Bernhard Beschow <shen...@gmail.com>
> > ---
> >   hw/sd/sdhci.c | 8 +++++++-
> >   1 file changed, 7 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> > index 6811f0f1a8..362c2c86aa 100644
> > --- a/hw/sd/sdhci.c
> > +++ b/hw/sd/sdhci.c
> > @@ -1382,6 +1382,8 @@ void sdhci_initfn(SDHCIState *s)
> >       s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
> > sdhci_raise_insertion_irq, s);
> >       s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
> > sdhci_data_transfer, s);
> > +
> > +    s->io_ops = &sdhci_mmio_le_ops;
> >   }
> >   void sdhci_uninitfn(SDHCIState *s)
> > @@ -1399,9 +1401,13 @@ void sdhci_common_realize(SDHCIState *s, Error 
> > **errp)
> 
> What about simply keeping the same code guarded with 'if (!s->io_ops)'?
> 

That was my quick fix which I considered a hack, and I didn't submit it
because I thought it was a hack ;-).

On the other side, this solution would probably break on big endian systems
which have their own io ops, so I am not sure if it is any better.

Guenter

> >       switch (s->endianness) {
> >       case DEVICE_LITTLE_ENDIAN:
> > -        s->io_ops = &sdhci_mmio_le_ops;
> > +        /* s->io_ops is little endian by default */
> >           break;
> >       case DEVICE_BIG_ENDIAN:
> > +        if (s->io_ops != &sdhci_mmio_le_ops) {
> > +            error_setg(errp, "SD controller doesn't support big 
> > endianness");
> > +            return;
> > +        }
> >           s->io_ops = &sdhci_mmio_be_ops;
> >           break;
> >       default:
> 

Reply via email to