Re: sdmmc(4): add UHS-I support

2020-08-22 Thread Marcus Glocker
On Sat, 22 Aug 2020 14:09:53 +0200 (CEST)
Mark Kettenis  wrote:

> > Date: Mon, 17 Aug 2020 12:57:58 +0200 (CEST)
> > From: Mark Kettenis 
> >   
> > > Date: Sun, 16 Aug 2020 19:32:03 +0200 (CEST)
> > > From: Mark Kettenis 
> > > 
> > > The diff below adds support for higher speeds as supported by
> > > UHS-I SD cards to the generic sdmmc(4) layer.  The diff in itself
> > > does not enable the use of those modes.  That needs separate
> > > changes to the SD/MMC controller drivers.  I have such a diff for
> > > amlmmc(4) that allows me to use SDR50 mode.
> > > 
> > > However, to make sure this diff doesn't break existing lower speed
> > > modes I'd appreciate tests on a variety of hardware.  So if
> > > sdmmc(4) shows up in your dmesg, please test this by exercising
> > > your (u)SD or (e)MMC cards.
> > > 
> > > Thanks,
> > > 
> > > Mark  
> > 
> > Previous diff didn't build properly on amd64.  Here is a new diff.  
> 
> I did not receive a lot of test reports, but the diff has been in
> snaps for about a week.
> 
> ok?

No issues found using it on my boot device:

sdmmc0 at sximmc0: 4-bit, sd high-speed, mmc high-speed, dma
scsibus0 at sdmmc0: 2 targets, initiator 0

ok mglocker@

> 
> > Index: dev/sdmmc/sdmmc.c
> > ===
> > RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v
> > retrieving revision 1.57
> > diff -u -p -r1.57 sdmmc.c
> > --- dev/sdmmc/sdmmc.c   15 Aug 2020 13:21:02 -  1.57
> > +++ dev/sdmmc/sdmmc.c   17 Aug 2020 10:38:11 -
> > @@ -111,6 +111,10 @@ sdmmc_attach(struct device *parent, stru
> > printf(": 1-bit");
> > if (ISSET(saa->caps, SMC_CAPS_SD_HIGHSPEED))
> > printf(", sd high-speed");
> > +   if (ISSET(saa->caps, SMC_CAPS_UHS_SDR50))
> > +   printf(", sdr50");
> > +   if (ISSET(saa->caps, SMC_CAPS_UHS_SDR104))
> > +   printf(", sdr104");
> > if (ISSET(saa->caps, SMC_CAPS_MMC_HIGHSPEED))
> > printf(", mmc high-speed");
> > if (ISSET(saa->caps, SMC_CAPS_MMC_DDR52))
> > Index: dev/sdmmc/sdmmc_mem.c
> > ===
> > RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_mem.c,v
> > retrieving revision 1.34
> > diff -u -p -r1.34 sdmmc_mem.c
> > --- dev/sdmmc/sdmmc_mem.c   14 Aug 2020 14:49:04 -
> > 1.34 +++ dev/sdmmc/sdmmc_mem.c  17 Aug 2020 10:38:11 -
> > @@ -52,6 +52,7 @@ int   sdmmc_mem_decode_scr(struct sdmmc_so
> >  intsdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void
> > *, size_t); int sdmmc_mem_set_bus_width(struct
> > sdmmc_function *, int); int sdmmc_mem_mmc_switch(struct
> > sdmmc_function *, uint8_t, uint8_t, uint8_t); +int
> > sdmmc_mem_signal_voltage(struct sdmmc_softc *, int); 
> >  intsdmmc_mem_sd_init(struct sdmmc_softc *, struct
> > sdmmc_function *); int  sdmmc_mem_mmc_init(struct sdmmc_softc
> > *, struct sdmmc_function *); @@ -104,12 +105,16 @@ const int
> > sdmmc_mmc_timings[] = { int
> >  sdmmc_mem_enable(struct sdmmc_softc *sc)
> >  {
> > -   u_int32_t host_ocr;
> > -   u_int32_t card_ocr;
> > +   uint32_t host_ocr;
> > +   uint32_t card_ocr;
> > +   uint32_t new_ocr;
> > +   uint32_t ocr = 0;
> > +   int error;
> >  
> > rw_assert_wrlock(>sc_lock);
> >  
> > /* Set host mode to SD "combo" card or SD memory-only. */
> > +   CLR(sc->sc_flags, SMF_UHS_MODE);
> > SET(sc->sc_flags, SMF_SD_MODE|SMF_MEM_MODE);
> >  
> > /* Reset memory (*must* do that before CMD55 or CMD1). */
> > @@ -153,14 +158,86 @@ sdmmc_mem_enable(struct sdmmc_softc *sc)
> >  
> > host_ocr &= card_ocr; /* only allow the common voltages */
> >  
> > -   if (sdmmc_send_if_cond(sc, card_ocr) == 0)
> > -   host_ocr |= SD_OCR_SDHC_CAP;
> > +   if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
> > +   if (sdmmc_send_if_cond(sc, card_ocr) == 0)
> > +   SET(ocr, MMC_OCR_HCS);
> > +
> > +   if (sdmmc_chip_host_ocr(sc->sct, sc->sch) &
> > MMC_OCR_S18A)
> > +   SET(ocr, MMC_OCR_S18A);
> > +   }
> > +   host_ocr |= ocr;
> >  
> > /* Send the new OCR value until all cards are ready. */
> > -   if (sdmmc_mem_send_op_cond(sc, host_ocr, NULL) != 0) {
> > +   if (sdmmc_mem_send_op_cond(sc, host_ocr, _ocr) != 0) {
> > DPRINTF(("%s: can't send memory OCR\n",
> > DEVNAME(sc))); return 1;
> > }
> > +
> > +   if (ISSET(sc->sc_flags, SMF_SD_MODE) && ISSET(new_ocr,
> > MMC_OCR_S18A)) {
> > +   /*
> > +* Card and host support low voltage mode, begin
> > switch
> > +* sequence.
> > +*/
> > +   struct sdmmc_command cmd;
> > +
> > +   memset(, 0, sizeof(cmd));
> > +   cmd.c_arg = 0;
> > +   cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
> > +   cmd.c_opcode = SD_VOLTAGE_SWITCH;
> > +   DPRINTF(("%s: switching card to 1.8V\n",
> > DEVNAME(sc)));
> > +   error = sdmmc_mmc_command(sc, );
> > +   if (error) {
> > + 

Re: sdmmc(4): add UHS-I support

2020-08-22 Thread Mark Kettenis
> Date: Mon, 17 Aug 2020 12:57:58 +0200 (CEST)
> From: Mark Kettenis 
> 
> > Date: Sun, 16 Aug 2020 19:32:03 +0200 (CEST)
> > From: Mark Kettenis 
> > 
> > The diff below adds support for higher speeds as supported by UHS-I SD
> > cards to the generic sdmmc(4) layer.  The diff in itself does not
> > enable the use of those modes.  That needs separate changes to the
> > SD/MMC controller drivers.  I have such a diff for amlmmc(4) that
> > allows me to use SDR50 mode.
> > 
> > However, to make sure this diff doesn't break existing lower speed
> > modes I'd appreciate tests on a variety of hardware.  So if sdmmc(4)
> > shows up in your dmesg, please test this by exercising your (u)SD or
> > (e)MMC cards.
> > 
> > Thanks,
> > 
> > Mark
> 
> Previous diff didn't build properly on amd64.  Here is a new diff.

I did not receive a lot of test reports, but the diff has been in
snaps for about a week.

ok?


> Index: dev/sdmmc/sdmmc.c
> ===
> RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v
> retrieving revision 1.57
> diff -u -p -r1.57 sdmmc.c
> --- dev/sdmmc/sdmmc.c 15 Aug 2020 13:21:02 -  1.57
> +++ dev/sdmmc/sdmmc.c 17 Aug 2020 10:38:11 -
> @@ -111,6 +111,10 @@ sdmmc_attach(struct device *parent, stru
>   printf(": 1-bit");
>   if (ISSET(saa->caps, SMC_CAPS_SD_HIGHSPEED))
>   printf(", sd high-speed");
> + if (ISSET(saa->caps, SMC_CAPS_UHS_SDR50))
> + printf(", sdr50");
> + if (ISSET(saa->caps, SMC_CAPS_UHS_SDR104))
> + printf(", sdr104");
>   if (ISSET(saa->caps, SMC_CAPS_MMC_HIGHSPEED))
>   printf(", mmc high-speed");
>   if (ISSET(saa->caps, SMC_CAPS_MMC_DDR52))
> Index: dev/sdmmc/sdmmc_mem.c
> ===
> RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_mem.c,v
> retrieving revision 1.34
> diff -u -p -r1.34 sdmmc_mem.c
> --- dev/sdmmc/sdmmc_mem.c 14 Aug 2020 14:49:04 -  1.34
> +++ dev/sdmmc/sdmmc_mem.c 17 Aug 2020 10:38:11 -
> @@ -52,6 +52,7 @@ int sdmmc_mem_decode_scr(struct sdmmc_so
>  int  sdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t);
>  int  sdmmc_mem_set_bus_width(struct sdmmc_function *, int);
>  int  sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, 
> uint8_t);
> +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 *);
> @@ -104,12 +105,16 @@ const int sdmmc_mmc_timings[] = {
>  int
>  sdmmc_mem_enable(struct sdmmc_softc *sc)
>  {
> - u_int32_t host_ocr;
> - u_int32_t card_ocr;
> + uint32_t host_ocr;
> + uint32_t card_ocr;
> + uint32_t new_ocr;
> + uint32_t ocr = 0;
> + int error;
>  
>   rw_assert_wrlock(>sc_lock);
>  
>   /* Set host mode to SD "combo" card or SD memory-only. */
> + CLR(sc->sc_flags, SMF_UHS_MODE);
>   SET(sc->sc_flags, SMF_SD_MODE|SMF_MEM_MODE);
>  
>   /* Reset memory (*must* do that before CMD55 or CMD1). */
> @@ -153,14 +158,86 @@ sdmmc_mem_enable(struct sdmmc_softc *sc)
>  
>   host_ocr &= card_ocr; /* only allow the common voltages */
>  
> - if (sdmmc_send_if_cond(sc, card_ocr) == 0)
> - host_ocr |= SD_OCR_SDHC_CAP;
> + if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
> + if (sdmmc_send_if_cond(sc, card_ocr) == 0)
> + SET(ocr, MMC_OCR_HCS);
> +
> + if (sdmmc_chip_host_ocr(sc->sct, sc->sch) & MMC_OCR_S18A)
> + SET(ocr, MMC_OCR_S18A);
> + }
> + host_ocr |= ocr;
>  
>   /* Send the new OCR value until all cards are ready. */
> - if (sdmmc_mem_send_op_cond(sc, host_ocr, NULL) != 0) {
> + if (sdmmc_mem_send_op_cond(sc, host_ocr, _ocr) != 0) {
>   DPRINTF(("%s: can't send memory OCR\n", DEVNAME(sc)));
>   return 1;
>   }
> +
> + if (ISSET(sc->sc_flags, SMF_SD_MODE) && ISSET(new_ocr, MMC_OCR_S18A)) {
> + /*
> +  * Card and host support low voltage mode, begin switch
> +  * sequence.
> +  */
> + struct sdmmc_command cmd;
> +
> + memset(, 0, sizeof(cmd));
> + cmd.c_arg = 0;
> + cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
> + cmd.c_opcode = SD_VOLTAGE_SWITCH;
> + DPRINTF(("%s: switching card to 1.8V\n", DEVNAME(sc)));
> + error = sdmmc_mmc_command(sc, );
> + if (error) {
> + DPRINTF(("%s: voltage switch command failed\n",
> + SDMMCDEVNAME(sc)));
> + return error;
> + }
> +
> + error = sdmmc_mem_signal_voltage(sc, SDMMC_SIGNAL_VOLTAGE_180);
> + if (error)
> + return error;
> +
> + SET(sc->sc_flags, SMF_UHS_MODE);
> + }
> +
> + return 

Re: sdmmc(4): add UHS-I support

2020-08-18 Thread Kevin Lo
On Mon, Aug 17, 2020 at 12:57:58PM +0200, Mark Kettenis wrote:
> 
> > Date: Sun, 16 Aug 2020 19:32:03 +0200 (CEST)
> > From: Mark Kettenis 
> > 
> > The diff below adds support for higher speeds as supported by UHS-I SD
> > cards to the generic sdmmc(4) layer.  The diff in itself does not
> > enable the use of those modes.  That needs separate changes to the
> > SD/MMC controller drivers.  I have such a diff for amlmmc(4) that
> > allows me to use SDR50 mode.
> > 
> > However, to make sure this diff doesn't break existing lower speed
> > modes I'd appreciate tests on a variety of hardware.  So if sdmmc(4)
> > shows up in your dmesg, please test this by exercising your (u)SD or
> > (e)MMC cards.
> > 
> > Thanks,
> > 
> > Mark
> 
> Previous diff didn't build properly on amd64.  Here is a new diff.

Tested on the GPD Pocket, no problems seen.

OpenBSD 6.7-current (GENERIC.MP) #0: Tue Aug 18 16:08:43 CST 2020
ke...@gpdpocket.kevlo.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 8477282304 (8084MB)
avail mem = 8213426176 (7832MB)
random: good seed from bootblocks
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 3.0 @ 0x7b8de000 (51 entries)
bios0: vendor American Megatrends Inc. version "5.11" date 08/07/2017
bios0: Default string Default string
acpi0 at bios0: ACPI 5.0
acpi0: sleep states S0 S4 S5
acpi0: tables DSDT FACP APIC FPDT FIDT MCFG SSDT SSDT SSDT UEFI SSDT HPET SSDT 
SSDT SSDT LPIT BCFG PRAM BGRT TPM2 CSRT WDAT SSDT SSDT SSDT
acpi0: wakeup devices
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee0: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Atom(TM) x7-Z8750 CPU @ 1.60GHz, 1600.40 MHz, 06-4c-04
cpu0: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,RDRAND,NXE,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,TSC_ADJUST,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu0: 1MB 64b/line 16-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 8 var ranges, 88 fixed ranges
cpu0: apic clock running at 79MHz
cpu0: mwait min=64, max=64, C-substates=0.2.0.0.0.0.3.3, IBE
cpu1 at mainbus0: apid 2 (application processor)
cpu1: Intel(R) Atom(TM) x7-Z8750 CPU @ 1.60GHz, 1599.94 MHz, 06-4c-04
cpu1: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,RDRAND,NXE,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,TSC_ADJUST,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu1: 1MB 64b/line 16-way L2 cache
cpu1: smt 0, core 1, package 0
cpu2 at mainbus0: apid 4 (application processor)
cpu2: Intel(R) Atom(TM) x7-Z8750 CPU @ 1.60GHz, 1599.96 MHz, 06-4c-04
cpu2: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,RDRAND,NXE,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,TSC_ADJUST,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu2: 1MB 64b/line 16-way L2 cache
cpu2: smt 0, core 2, package 0
cpu3 at mainbus0: apid 6 (application processor)
cpu3: Intel(R) Atom(TM) x7-Z8750 CPU @ 1.60GHz, 1599.95 MHz, 06-4c-04
cpu3: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,RDRAND,NXE,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,TSC_ADJUST,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu3: 1MB 64b/line 16-way L2 cache
cpu3: smt 0, core 3, package 0
ioapic0 at mainbus0: apid 1 pa 0xfec0, version 20, 115 pins
acpimcfg0 at acpi0
acpimcfg0: addr 0xe000, bus 0-255
acpihpet0 at acpi0: 14318179 Hz
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus 1 (RP01)
acpiprt2 at acpi0: bus -1 (RP02)
acpiprt3 at acpi0: bus -1 (RP03)
acpiprt4 at acpi0: bus -1 (RP04)
acpicpu0 at acpi0: C3(10@1000 mwait.1@0x64), C2(10@500 mwait.1@0x58), C1(1000@1 
mwait.1), PSS
acpicpu1 at acpi0: C3(10@1000 mwait.1@0x64), C2(10@500 mwait.1@0x58), C1(1000@1 
mwait.1), PSS
acpicpu2 at acpi0: C3(10@1000 mwait.1@0x64), C2(10@500 mwait.1@0x58), C1(1000@1 
mwait.1), PSS
acpicpu3 at acpi0: C3(10@1000 mwait.1@0x64), C2(10@500 mwait.1@0x58), C1(1000@1 
mwait.1), PSS
acpipwrres0 at acpi0: ID3C, resource for ISP3
acpipwrres1 at acpi0: WWPR, resource for HS03, MDM1
acpipwrres2 at acpi0: WWPR, resource for HS13, MDM1
acpipwrres3 at acpi0: WWPR, resource for SSC1, MDM3
acpipwrres4 at acpi0: WWPR, resource for SSCW, MDM3
acpipwrres5 at acpi0: WWPR, resource for HSC1, MDM2
acpipwrres6 at acpi0: WWPR, resource for HSC3, MDM4
acpipwrres7 at acpi0: CLK3, resource for RTK1, RTKA

Re: sdmmc(4): add UHS-I support

2020-08-17 Thread Todd Carson


Mark Kettenis writes:

>> However, to make sure this diff doesn't break existing lower speed
>> modes I'd appreciate tests on a variety of hardware.  So if sdmmc(4)
>> shows up in your dmesg, please test this by exercising your (u)SD or
>> (e)MMC cards.

No problems encountered reading/writing the SD card with this diff
on RPi4:

sdhc0: SDHC 3.0, 250 MHz base clock
sdmmc0 at sdhc0: 4-bit, sd high-speed, mmc high-speed
...
sdhc1 at simplebus4
sdhc1: SDHC 3.0, 100 MHz base clock
sdmmc1 at sdhc1: 8-bit, sd high-speed, mmc high-speed, ddr52, dma
...
scsibus0 at sdmmc1: 2 targets, initiator 0
sd0 at scsibus0 targ 1 lun 0:  removable
sd0: 15193MB, 512 bytes/sector, 31116288 sectors
...
bwfm0 at sdmmc0 function 1
manufacturer 0x02d0, product 0xa9a6 at sdmmc0 function 2 not configured
manufacturer 0x02d0, product 0xa9a6 at sdmmc0 function 3 not configured



Re: sdmmc(4): add UHS-I support

2020-08-17 Thread Mark Kettenis
> Date: Sun, 16 Aug 2020 19:32:03 +0200 (CEST)
> From: Mark Kettenis 
> 
> The diff below adds support for higher speeds as supported by UHS-I SD
> cards to the generic sdmmc(4) layer.  The diff in itself does not
> enable the use of those modes.  That needs separate changes to the
> SD/MMC controller drivers.  I have such a diff for amlmmc(4) that
> allows me to use SDR50 mode.
> 
> However, to make sure this diff doesn't break existing lower speed
> modes I'd appreciate tests on a variety of hardware.  So if sdmmc(4)
> shows up in your dmesg, please test this by exercising your (u)SD or
> (e)MMC cards.
> 
> Thanks,
> 
> Mark

Previous diff didn't build properly on amd64.  Here is a new diff.

Index: dev/sdmmc/sdmmc.c
===
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v
retrieving revision 1.57
diff -u -p -r1.57 sdmmc.c
--- dev/sdmmc/sdmmc.c   15 Aug 2020 13:21:02 -  1.57
+++ dev/sdmmc/sdmmc.c   17 Aug 2020 10:38:11 -
@@ -111,6 +111,10 @@ sdmmc_attach(struct device *parent, stru
printf(": 1-bit");
if (ISSET(saa->caps, SMC_CAPS_SD_HIGHSPEED))
printf(", sd high-speed");
+   if (ISSET(saa->caps, SMC_CAPS_UHS_SDR50))
+   printf(", sdr50");
+   if (ISSET(saa->caps, SMC_CAPS_UHS_SDR104))
+   printf(", sdr104");
if (ISSET(saa->caps, SMC_CAPS_MMC_HIGHSPEED))
printf(", mmc high-speed");
if (ISSET(saa->caps, SMC_CAPS_MMC_DDR52))
Index: dev/sdmmc/sdmmc_mem.c
===
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_mem.c,v
retrieving revision 1.34
diff -u -p -r1.34 sdmmc_mem.c
--- dev/sdmmc/sdmmc_mem.c   14 Aug 2020 14:49:04 -  1.34
+++ dev/sdmmc/sdmmc_mem.c   17 Aug 2020 10:38:11 -
@@ -52,6 +52,7 @@ int   sdmmc_mem_decode_scr(struct sdmmc_so
 intsdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t);
 intsdmmc_mem_set_bus_width(struct sdmmc_function *, int);
 intsdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, 
uint8_t);
+intsdmmc_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 *);
@@ -104,12 +105,16 @@ const int sdmmc_mmc_timings[] = {
 int
 sdmmc_mem_enable(struct sdmmc_softc *sc)
 {
-   u_int32_t host_ocr;
-   u_int32_t card_ocr;
+   uint32_t host_ocr;
+   uint32_t card_ocr;
+   uint32_t new_ocr;
+   uint32_t ocr = 0;
+   int error;
 
rw_assert_wrlock(>sc_lock);
 
/* Set host mode to SD "combo" card or SD memory-only. */
+   CLR(sc->sc_flags, SMF_UHS_MODE);
SET(sc->sc_flags, SMF_SD_MODE|SMF_MEM_MODE);
 
/* Reset memory (*must* do that before CMD55 or CMD1). */
@@ -153,14 +158,86 @@ sdmmc_mem_enable(struct sdmmc_softc *sc)
 
host_ocr &= card_ocr; /* only allow the common voltages */
 
-   if (sdmmc_send_if_cond(sc, card_ocr) == 0)
-   host_ocr |= SD_OCR_SDHC_CAP;
+   if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
+   if (sdmmc_send_if_cond(sc, card_ocr) == 0)
+   SET(ocr, MMC_OCR_HCS);
+
+   if (sdmmc_chip_host_ocr(sc->sct, sc->sch) & MMC_OCR_S18A)
+   SET(ocr, MMC_OCR_S18A);
+   }
+   host_ocr |= ocr;
 
/* Send the new OCR value until all cards are ready. */
-   if (sdmmc_mem_send_op_cond(sc, host_ocr, NULL) != 0) {
+   if (sdmmc_mem_send_op_cond(sc, host_ocr, _ocr) != 0) {
DPRINTF(("%s: can't send memory OCR\n", DEVNAME(sc)));
return 1;
}
+
+   if (ISSET(sc->sc_flags, SMF_SD_MODE) && ISSET(new_ocr, MMC_OCR_S18A)) {
+   /*
+* Card and host support low voltage mode, begin switch
+* sequence.
+*/
+   struct sdmmc_command cmd;
+
+   memset(, 0, sizeof(cmd));
+   cmd.c_arg = 0;
+   cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
+   cmd.c_opcode = SD_VOLTAGE_SWITCH;
+   DPRINTF(("%s: switching card to 1.8V\n", DEVNAME(sc)));
+   error = sdmmc_mmc_command(sc, );
+   if (error) {
+   DPRINTF(("%s: voltage switch command failed\n",
+   SDMMCDEVNAME(sc)));
+   return error;
+   }
+
+   error = sdmmc_mem_signal_voltage(sc, SDMMC_SIGNAL_VOLTAGE_180);
+   if (error)
+   return error;
+
+   SET(sc->sc_flags, SMF_UHS_MODE);
+   }
+
+   return 0;
+}
+
+int
+sdmmc_mem_signal_voltage(struct sdmmc_softc *sc, int signal_voltage)
+{
+   int error;
+
+   /*
+* Stop the clock
+*/
+   error = sdmmc_chip_bus_clock(sc->sct, sc->sch, 0, SDMMC_TIMING_LEGACY);
+   if (error)
+ 

sdmmc(4): add UHS-I support

2020-08-16 Thread Mark Kettenis
The diff below adds support for higher speeds as supported by UHS-I SD
cards to the generic sdmmc(4) layer.  The diff in itself does not
enable the use of those modes.  That needs separate changes to the
SD/MMC controller drivers.  I have such a diff for amlmmc(4) that
allows me to use SDR50 mode.

However, to make sure this diff doesn't break existing lower speed
modes I'd appreciate tests on a variety of hardware.  So if sdmmc(4)
shows up in your dmesg, please test this by exercising your (u)SD or
(e)MMC cards.

Thanks,

Mark


Index: dev/sdmmc/sdmmc.c
===
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v
retrieving revision 1.57
diff -u -p -r1.57 sdmmc.c
--- dev/sdmmc/sdmmc.c   15 Aug 2020 13:21:02 -  1.57
+++ dev/sdmmc/sdmmc.c   16 Aug 2020 17:15:55 -
@@ -111,6 +111,10 @@ sdmmc_attach(struct device *parent, stru
printf(": 1-bit");
if (ISSET(saa->caps, SMC_CAPS_SD_HIGHSPEED))
printf(", sd high-speed");
+   if (ISSET(saa->caps, SMC_CAPS_UHS_SDR50))
+   printf(", sdr50");
+   if (ISSET(saa->caps, SMC_CAPS_UHS_SDR104))
+   printf(", sdr104");
if (ISSET(saa->caps, SMC_CAPS_MMC_HIGHSPEED))
printf(", mmc high-speed");
if (ISSET(saa->caps, SMC_CAPS_MMC_DDR52))
Index: dev/sdmmc/sdmmc_mem.c
===
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_mem.c,v
retrieving revision 1.34
diff -u -p -r1.34 sdmmc_mem.c
--- dev/sdmmc/sdmmc_mem.c   14 Aug 2020 14:49:04 -  1.34
+++ dev/sdmmc/sdmmc_mem.c   16 Aug 2020 17:15:55 -
@@ -52,6 +52,7 @@ int   sdmmc_mem_decode_scr(struct sdmmc_so
 intsdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t);
 intsdmmc_mem_set_bus_width(struct sdmmc_function *, int);
 intsdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, 
uint8_t);
+intsdmmc_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 *);
@@ -104,12 +105,16 @@ const int sdmmc_mmc_timings[] = {
 int
 sdmmc_mem_enable(struct sdmmc_softc *sc)
 {
-   u_int32_t host_ocr;
-   u_int32_t card_ocr;
+   uint32_t host_ocr;
+   uint32_t card_ocr;
+   uint32_t new_ocr;
+   uint32_t ocr = 0;
+   int error;
 
rw_assert_wrlock(>sc_lock);
 
/* Set host mode to SD "combo" card or SD memory-only. */
+   CLR(sc->sc_flags, SMF_UHS_MODE);
SET(sc->sc_flags, SMF_SD_MODE|SMF_MEM_MODE);
 
/* Reset memory (*must* do that before CMD55 or CMD1). */
@@ -153,14 +158,86 @@ sdmmc_mem_enable(struct sdmmc_softc *sc)
 
host_ocr &= card_ocr; /* only allow the common voltages */
 
-   if (sdmmc_send_if_cond(sc, card_ocr) == 0)
-   host_ocr |= SD_OCR_SDHC_CAP;
+   if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
+   if (sdmmc_send_if_cond(sc, card_ocr) == 0)
+   SET(ocr, MMC_OCR_HCS);
+
+   if (sdmmc_chip_host_ocr(sc->sct, sc->sch) & MMC_OCR_S18A)
+   SET(ocr, MMC_OCR_S18A);
+   }
+   host_ocr |= ocr;
 
/* Send the new OCR value until all cards are ready. */
-   if (sdmmc_mem_send_op_cond(sc, host_ocr, NULL) != 0) {
+   if (sdmmc_mem_send_op_cond(sc, host_ocr, _ocr) != 0) {
DPRINTF(("%s: can't send memory OCR\n", DEVNAME(sc)));
return 1;
}
+
+   if (ISSET(sc->sc_flags, SMF_SD_MODE) && ISSET(new_ocr, MMC_OCR_S18A)) {
+   /*
+* Card and host support low voltage mode, begin switch
+* sequence.
+*/
+   struct sdmmc_command cmd;
+
+   memset(, 0, sizeof(cmd));
+   cmd.c_arg = 0;
+   cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
+   cmd.c_opcode = SD_VOLTAGE_SWITCH;
+   DPRINTF(("%s: switching card to 1.8V\n", DEVNAME(sc)));
+   error = sdmmc_mmc_command(sc, );
+   if (error) {
+   DPRINTF(("%s: voltage switch command failed\n",
+   SDMMCDEVNAME(sc)));
+   return error;
+   }
+
+   error = sdmmc_mem_signal_voltage(sc, SDMMC_SIGNAL_VOLTAGE_180);
+   if (error)
+   return error;
+
+   SET(sc->sc_flags, SMF_UHS_MODE);
+   }
+
+   return 0;
+}
+
+int
+sdmmc_mem_signal_voltage(struct sdmmc_softc *sc, int signal_voltage)
+{
+   int error;
+
+   /*
+* Stop the clock
+*/
+   error = sdmmc_chip_bus_clock(sc->sct, sc->sch, 0, SDMMC_TIMING_LEGACY);
+   if (error)
+   return error;
+
+   delay(1000);
+
+   /*
+* Card switch command was successful, update host controller
+* signal voltage setting.
+