Re: sdmmc(4): check and retry bus width change

2021-06-02 Thread Raf Czlonka
On Tue, Jun 01, 2021 at 09:29:55AM BST, Patrick Wildt wrote:
> Am Mon, Feb 22, 2021 at 08:10:21PM +0100 schrieb Patrick Wildt:
> > Hi,
> > 
> > it seems like some eMMCs are not capable of doing 8-bit operation,
> > even if the controller supports it.  I was questioning our drivers
> > first, but it looks like it's the same on Linux.  In the case that
> > 8-bit doesn't work, they seem to fall back to lower values to make
> > that HW work.
> > 
> > This diff implements a mechanism that tries 8-bit, if available,
> > then 4-bit and in the end falls back to 1-bit.  This makes my HW
> > work, but I would like to have this tested by a broader audience.
> > 
> > Apparently there's a "bus test" command, but it isn't implemented
> > on all host controllers.  Hence I simply try to read the EXT_CSD
> > to make sure the transfer works.
> > 
> > For testing, a print like
> > 
> > printf("%s: using %u-bit width\n", DEVNAME(sc), width);
> > 
> > could be added at line 928.
> > 
> > What could possible regressions be?  The width could become smaller
> > then previously.  This would reduce the read/write transfer speed.
> > Also it's possible that eMMCs are not recognized/initialized anymore.
> > 
> > What could possible improvements be?  eMMCs that previously didn't
> > work now work, with at least 1-bit or 4-bit wide transfers.
> > 
> > Please note that this only works for eMMCs.  SD cards are *not* using
> > this code path.  SD cards have a different initialization code path.
> > 
> > Please report any changes or non-changes.  If nothing changes, that's
> > perfect.
> > 
> > Patrick
> 
> Anyone want to give this a try?  It's basically relevant for all
> ARM machines with eMMC ('soldered SD cards'), and they should work
> as well as before.

Hi Patrick,

I've managed to build the kernel with your patch and the machine
booted up just fine the first time - it was as slow as before ;^)

Then, I rebooted to the old kernel to compare dmesg before and after
- they're identical, BTW - and I shut the machine down.

I got a crash (ddb) on the next boot - don't have the time to
transcribe it right now, I'm afraid.

https://photos.app.goo.gl/Kr54uoppT4b6gR179

On subsequent boot I got:

ehci_device_bulk_start: not done, ex=0xff800800f378

scrolling(?) continuously on the screen.

Next boot, ddb again.

Old kernel booted up just fine.

Regards,

Raf

OpenBSD 6.9-current (GENERIC.MP) #0: Wed Jun  2 09:36:58 BST 2021
r...@foo.example.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP
real mem  = 2013835264 (1920MB)
avail mem = 1919496192 (1830MB)
random: good seed from bootblocks
mainbus0 at root: Pinebook
psci0 at mainbus0: PSCI 1.1, SMCCC 1.2
cpu0 at mainbus0 mpidr 0: ARM Cortex-A53 r0p4
cpu0: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu0: 512KB 64b/line 16-way L2 cache
cpu0: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu1 at mainbus0 mpidr 1: ARM Cortex-A53 r0p4
cpu1: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu1: 512KB 64b/line 16-way L2 cache
cpu1: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu2 at mainbus0 mpidr 2: ARM Cortex-A53 r0p4
cpu2: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu2: 512KB 64b/line 16-way L2 cache
cpu2: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu3 at mainbus0 mpidr 3: ARM Cortex-A53 r0p4
cpu3: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu3: 512KB 64b/line 16-way L2 cache
cpu3: CRC32,SHA2,SHA1,AES+PMULL,ASID16
efi0 at mainbus0: UEFI 2.8
efi0: Das U-Boot rev 0x20200400
apm0 at mainbus0
"osc24M_clk" at mainbus0 not configured
"osc32k_clk" at mainbus0 not configured
"internal-osc-clk" at mainbus0 not configured
simpleaudio0 at mainbus0
"spdif-out" at mainbus0 not configured
agtimer0 at mainbus0: 24000 kHz
simplebus0 at mainbus0: "soc"
sxisyscon0 at simplebus0
sxisid0 at simplebus0
sxiccmu0 at simplebus0
sxipio0 at simplebus0: 103 pins
ampintc0 at simplebus0 nirq 224, ncpu 4 ipi: 0, 1: "interrupt-controller"
sxirtc0 at simplebus0
sxiccmu1 at simplebus0
sxipio1 at simplebus0: 13 pins
sxirsb0 at simplebus0
axppmic0 at sxirsb0 addr 0x3a3: AXP803
"de2" at simplebus0 not configured
"dma-controller" at simplebus0 not configured
"lcd-controller" at simplebus0 not configured
"lcd-controller" at simplebus0 not configured
sximmc0 at simplebus0
sdmmc0 at sximmc0: 4-bit, sd high-speed, mmc high-speed, dma
sximmc1 at simplebus0
sdmmc1 at sximmc1: 4-bit, sd high-speed, mmc high-speed, dma
sximmc2 at simplebus0
sdmmc2 at sximmc2: 8-bit, sd high-speed, mmc high-speed, dma
"phy" at simplebus0 not configured
ehci0 at simplebus0
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 configuration 1 interface 0 "Generic EHCI root hub" rev 2.00/1.00 
addr 1
ohci0 at simplebus0: version 1.0
ehci1 at simplebus0
usb1 at ehci1: USB revision 2.0
uhub1 at usb1 configuration 1 interface 0 "Generic EHCI root hub" rev 2.00/1.00 
addr 1
ohci1 at simplebus0: version 1.0
com0 at simplebus0: ns16550, no working fifo
sxipwm0 at simplebus0
"hdmi-phy" at simplebus0

Re: sdmmc(4): check and retry bus width change

2021-06-01 Thread Patrick Wildt
Am Mon, Feb 22, 2021 at 08:10:21PM +0100 schrieb Patrick Wildt:
> Hi,
> 
> it seems like some eMMCs are not capable of doing 8-bit operation,
> even if the controller supports it.  I was questioning our drivers
> first, but it looks like it's the same on Linux.  In the case that
> 8-bit doesn't work, they seem to fall back to lower values to make
> that HW work.
> 
> This diff implements a mechanism that tries 8-bit, if available,
> then 4-bit and in the end falls back to 1-bit.  This makes my HW
> work, but I would like to have this tested by a broader audience.
> 
> Apparently there's a "bus test" command, but it isn't implemented
> on all host controllers.  Hence I simply try to read the EXT_CSD
> to make sure the transfer works.
> 
> For testing, a print like
> 
> printf("%s: using %u-bit width\n", DEVNAME(sc), width);
> 
> could be added at line 928.
> 
> What could possible regressions be?  The width could become smaller
> then previously.  This would reduce the read/write transfer speed.
> Also it's possible that eMMCs are not recognized/initialized anymore.
> 
> What could possible improvements be?  eMMCs that previously didn't
> work now work, with at least 1-bit or 4-bit wide transfers.
> 
> Please note that this only works for eMMCs.  SD cards are *not* using
> this code path.  SD cards have a different initialization code path.
> 
> Please report any changes or non-changes.  If nothing changes, that's
> perfect.
> 
> Patrick

Anyone want to give this a try?  It's basically relevant for all
ARM machines with eMMC ('soldered SD cards'), and they should work
as well as before.

> diff --git a/sys/dev/sdmmc/sdmmc_mem.c b/sys/dev/sdmmc/sdmmc_mem.c
> index 59bcb1b4a11..5856b9bb1b3 100644
> --- a/sys/dev/sdmmc/sdmmc_mem.c
> +++ b/sys/dev/sdmmc/sdmmc_mem.c
> @@ -56,6 +56,8 @@ int sdmmc_mem_signal_voltage(struct sdmmc_softc *, int);
>  
>  int  sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *);
>  int  sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *);
> +int  sdmmc_mem_mmc_select_bus_width(struct sdmmc_softc *,
> + struct sdmmc_function *, int);
>  int  sdmmc_mem_single_read_block(struct sdmmc_function *, int, u_char *,
>   size_t);
>  int  sdmmc_mem_read_block_subr(struct sdmmc_function *, bus_dmamap_t,
> @@ -908,31 +910,20 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct 
> sdmmc_function *sf)
>   ext_csd[EXT_CSD_CARD_TYPE]);
>   }
>  
> - if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE)) {
> + if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE) &&
> + sdmmc_mem_mmc_select_bus_width(sc, sf, 8) == 0)
>   width = 8;
> - value = EXT_CSD_BUS_WIDTH_8;
> - } else if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE)) {
> + else if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) &&
> + sdmmc_mem_mmc_select_bus_width(sc, sf, 4) == 0)
>   width = 4;
> - value = EXT_CSD_BUS_WIDTH_4;
> - } else {
> - width = 1;
> - value = EXT_CSD_BUS_WIDTH_1;
> - }
> -
> - if (width != 1) {
> - error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
> - EXT_CSD_BUS_WIDTH, value);
> - if (error == 0)
> - error = sdmmc_chip_bus_width(sc->sct,
> - sc->sch, width);
> - else {
> + else {
> + error = sdmmc_mem_mmc_select_bus_width(sc, sf, 1);
> + if (error != 0) {
>   DPRINTF(("%s: can't change bus width"
>   " (%d bit)\n", DEVNAME(sc), width));
>   return error;
>   }
> -
> - /* : need bus test? (using by CMD14 & CMD19) */
> - sdmmc_delay(1);
> + width = 1;
>   }
>  
>   if (timing != SDMMC_TIMING_LEGACY) {
> @@ -1041,6 +1032,59 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct 
> sdmmc_function *sf)
>   return error;
>  }
>  
> +int
> +sdmmc_mem_mmc_select_bus_width(struct sdmmc_softc *sc, struct sdmmc_function 
> *sf,
> +int width)
> +{
> + u_int8_t ext_csd[512];
> + int error, value;
> +
> + switch (width) {
> + case 8:
> + value = EXT_CSD_BUS_WIDTH_8;
> + break;
> + case 4:
> + value = EXT_CSD_BUS_WIDTH_4;
> + break;
> + case 1:
> + value = EXT_CSD_BUS_WIDTH_1;
> + break;
> + default:
> + printf("%s: invalid bus width\n", DEVNAME(sc));
> + return EINVAL;
> + }
> +
> + error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
> + EXT_CSD_BUS_WIDTH, value);
> + if (error != 0) {
> + DPRINTF(("%

sdmmc(4): check and retry bus width change

2021-02-22 Thread Patrick Wildt
Hi,

it seems like some eMMCs are not capable of doing 8-bit operation,
even if the controller supports it.  I was questioning our drivers
first, but it looks like it's the same on Linux.  In the case that
8-bit doesn't work, they seem to fall back to lower values to make
that HW work.

This diff implements a mechanism that tries 8-bit, if available,
then 4-bit and in the end falls back to 1-bit.  This makes my HW
work, but I would like to have this tested by a broader audience.

Apparently there's a "bus test" command, but it isn't implemented
on all host controllers.  Hence I simply try to read the EXT_CSD
to make sure the transfer works.

For testing, a print like

printf("%s: using %u-bit width\n", DEVNAME(sc), width);

could be added at line 928.

What could possible regressions be?  The width could become smaller
then previously.  This would reduce the read/write transfer speed.
Also it's possible that eMMCs are not recognized/initialized anymore.

What could possible improvements be?  eMMCs that previously didn't
work now work, with at least 1-bit or 4-bit wide transfers.

Please note that this only works for eMMCs.  SD cards are *not* using
this code path.  SD cards have a different initialization code path.

Please report any changes or non-changes.  If nothing changes, that's
perfect.

Patrick

diff --git a/sys/dev/sdmmc/sdmmc_mem.c b/sys/dev/sdmmc/sdmmc_mem.c
index 59bcb1b4a11..5856b9bb1b3 100644
--- a/sys/dev/sdmmc/sdmmc_mem.c
+++ b/sys/dev/sdmmc/sdmmc_mem.c
@@ -56,6 +56,8 @@ int   sdmmc_mem_signal_voltage(struct sdmmc_softc *, int);
 
 intsdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *);
 intsdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *);
+intsdmmc_mem_mmc_select_bus_width(struct sdmmc_softc *,
+   struct sdmmc_function *, int);
 intsdmmc_mem_single_read_block(struct sdmmc_function *, int, u_char *,
size_t);
 intsdmmc_mem_read_block_subr(struct sdmmc_function *, bus_dmamap_t,
@@ -908,31 +910,20 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct 
sdmmc_function *sf)
ext_csd[EXT_CSD_CARD_TYPE]);
}
 
-   if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE)) {
+   if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE) &&
+   sdmmc_mem_mmc_select_bus_width(sc, sf, 8) == 0)
width = 8;
-   value = EXT_CSD_BUS_WIDTH_8;
-   } else if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE)) {
+   else if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) &&
+   sdmmc_mem_mmc_select_bus_width(sc, sf, 4) == 0)
width = 4;
-   value = EXT_CSD_BUS_WIDTH_4;
-   } else {
-   width = 1;
-   value = EXT_CSD_BUS_WIDTH_1;
-   }
-
-   if (width != 1) {
-   error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
-   EXT_CSD_BUS_WIDTH, value);
-   if (error == 0)
-   error = sdmmc_chip_bus_width(sc->sct,
-   sc->sch, width);
-   else {
+   else {
+   error = sdmmc_mem_mmc_select_bus_width(sc, sf, 1);
+   if (error != 0) {
DPRINTF(("%s: can't change bus width"
" (%d bit)\n", DEVNAME(sc), width));
return error;
}
-
-   /* : need bus test? (using by CMD14 & CMD19) */
-   sdmmc_delay(1);
+   width = 1;
}
 
if (timing != SDMMC_TIMING_LEGACY) {
@@ -1041,6 +1032,59 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct 
sdmmc_function *sf)
return error;
 }
 
+int
+sdmmc_mem_mmc_select_bus_width(struct sdmmc_softc *sc, struct sdmmc_function 
*sf,
+int width)
+{
+   u_int8_t ext_csd[512];
+   int error, value;
+
+   switch (width) {
+   case 8:
+   value = EXT_CSD_BUS_WIDTH_8;
+   break;
+   case 4:
+   value = EXT_CSD_BUS_WIDTH_4;
+   break;
+   case 1:
+   value = EXT_CSD_BUS_WIDTH_1;
+   break;
+   default:
+   printf("%s: invalid bus width\n", DEVNAME(sc));
+   return EINVAL;
+   }
+
+   error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
+   EXT_CSD_BUS_WIDTH, value);
+   if (error != 0) {
+   DPRINTF(("%s: can't change card bus width"
+   " (%d bit)\n", DEVNAME(sc), width));
+   return error;
+   }
+
+   error = sdmmc_chip_bus_width(sc->sct,
+   sc->sch, width);
+   if (error != 0) {
+   DPRINTF(("%s: can't change host bus width"
+   " (%d bit)\n", DEVNAM