On Sat, 22 Aug 2020 14:09:53 +0200 (CEST) Mark Kettenis <mark.kette...@xs4all.nl> wrote:
> > Date: Mon, 17 Aug 2020 12:57:58 +0200 (CEST) > > From: Mark Kettenis <mark.kette...@xs4all.nl> > > > > > Date: Sun, 16 Aug 2020 19:32:03 +0200 (CEST) > > > From: Mark Kettenis <mark.kette...@xs4all.nl> > > > > > > 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 -0000 1.57 > > +++ dev/sdmmc/sdmmc.c 17 Aug 2020 10:38:11 -0000 > > @@ -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 -0000 > > 1.34 +++ dev/sdmmc/sdmmc_mem.c 17 Aug 2020 10:38:11 -0000 > > @@ -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->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, &new_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(&cmd, 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, &cmd); > > + 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. > > + */ > > + DPRINTF(("%s: switching host to %s\n", SDMMCDEVNAME(sc), > > + signal_voltage == SDMMC_SIGNAL_VOLTAGE_180 ? "1.8V" : > > "3.3V")); > > + error = sdmmc_chip_signal_voltage(sc->sct, sc->sch, > > signal_voltage); > > + if (error) > > + return error; > > + > > + delay(5000); > > + > > + /* > > + * Switch to SDR12 timing > > + */ > > + error = sdmmc_chip_bus_clock(sc->sct, sc->sch, > > SDMMC_SDCLK_25MHZ, > > + SDMMC_TIMING_LEGACY); > > + if (error) > > + return error; > > + > > + delay(1000); > > + > > return 0; > > } > > > > @@ -609,6 +686,30 @@ sdmmc_be512_to_bitfield512(sdmmc_bitfiel > > } > > > > int > > +sdmmc_mem_select_transfer_mode(struct sdmmc_softc *sc, int > > support_func) +{ > > + if (ISSET(sc->sc_flags, SMF_UHS_MODE)) { > > + if (ISSET(sc->sc_caps, SMC_CAPS_UHS_SDR104) && > > + ISSET(support_func, 1 << > > SD_ACCESS_MODE_SDR104)) { > > + return SD_ACCESS_MODE_SDR104; > > + } > > + if (ISSET(sc->sc_caps, SMC_CAPS_UHS_DDR50) && > > + ISSET(support_func, 1 << > > SD_ACCESS_MODE_DDR50)) { > > + return SD_ACCESS_MODE_DDR50; > > + } > > + if (ISSET(sc->sc_caps, SMC_CAPS_UHS_SDR50) && > > + ISSET(support_func, 1 << > > SD_ACCESS_MODE_SDR50)) { > > + return SD_ACCESS_MODE_SDR50; > > + } > > + } > > + if (ISSET(sc->sc_caps, SMC_CAPS_SD_HIGHSPEED) && > > + ISSET(support_func, 1 << SD_ACCESS_MODE_SDR25)) { > > + return SD_ACCESS_MODE_SDR25; > > + } > > + return SD_ACCESS_MODE_SDR12; > > +} > > + > > +int > > sdmmc_mem_execute_tuning(struct sdmmc_softc *sc, struct > > sdmmc_function *sf) { > > int timing = -1; > > @@ -646,7 +747,7 @@ sdmmc_mem_execute_tuning(struct sdmmc_so > > int > > sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function > > *sf) { > > - int support_func, best_func, error; > > + int support_func, best_func, error, i; > > sdmmc_bitfield512_t status; /* Switch Function Status */ > > uint32_t raw_scr[2]; > > > > @@ -695,8 +796,32 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc > > > > support_func = SFUNC_STATUS_GROUP(&status, 1); > > > > - if (support_func & (1 << SD_ACCESS_MODE_SDR25)) > > - best_func = 1; > > + if (!ISSET(sc->sc_flags, SMF_UHS_MODE) && > > + (ISSET(support_func, 1 << > > SD_ACCESS_MODE_SDR50) || > > + ISSET(support_func, 1 << > > SD_ACCESS_MODE_DDR50) || > > + ISSET(support_func, 1 << > > SD_ACCESS_MODE_SDR104))) { > > + /* XXX UHS-I card started in 1.8V mode, > > switch now */ > > + error = sdmmc_mem_signal_voltage(sc, > > + SDMMC_SIGNAL_VOLTAGE_180); > > + if (error) { > > + printf("%s: failed to recover UHS > > card\n", DEVNAME(sc)); > > + return error; > > + } > > + SET(sc->sc_flags, SMF_UHS_MODE); > > + } > > + > > + for (i = 0; i < nitems(switch_group0_functions); > > i++) { > > + if (!(support_func & (1 << i))) > > + continue; > > + DPRINTF(("%s: card supports mode %s\n", > > + SDMMCDEVNAME(sc), > > + switch_group0_functions[i].name)); > > + } > > + > > + best_func = sdmmc_mem_select_transfer_mode(sc, > > support_func); + > > + DPRINTF(("%s: using mode %s\n", SDMMCDEVNAME(sc), > > + switch_group0_functions[best_func].name)); > > } > > > > if (best_func != 0) { > > @@ -716,13 +841,20 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc > > /* Wait 400KHz x 8 clock (2.5us * 8 + slop) */ > > delay(25); > > > > - /* High Speed mode, Frequency up to 50MHz. */ > > + /* change bus clock */ > > error = sdmmc_chip_bus_clock(sc->sct, sc->sch, > > - SDMMC_SDCLK_50MHZ, SDMMC_TIMING_HIGHSPEED); > > + sf->csd.tran_speed, SDMMC_TIMING_HIGHSPEED); > > if (error) { > > printf("%s: can't change bus clock\n", > > DEVNAME(sc)); return error; > > } > > + > > + /* execute tuning (UHS) */ > > + error = sdmmc_mem_execute_tuning(sc, sf); > > + if (error) { > > + printf("%s: can't execute SD tuning\n", > > DEVNAME(sc)); > > + return error; > > + } > > } > > > > return 0; > > @@ -937,7 +1069,7 @@ sdmmc_mem_send_op_cond(struct sdmmc_soft > > error = sdmmc_app_command(sc, &cmd); > > } else { > > cmd.c_arg &= ~MMC_OCR_ACCESS_MODE_MASK; > > - cmd.c_arg |= MMC_OCR_SECTOR_MODE; > > + cmd.c_arg |= MMC_OCR_ACCESS_MODE_SECTOR; > > cmd.c_opcode = MMC_SEND_OP_COND; > > error = sdmmc_mmc_command(sc, &cmd); > > } > > Index: dev/sdmmc/sdmmcreg.h > > =================================================================== > > RCS file: /cvs/src/sys/dev/sdmmc/sdmmcreg.h,v > > retrieving revision 1.12 > > diff -u -p -r1.12 sdmmcreg.h > > --- dev/sdmmc/sdmmcreg.h 14 Aug 2020 14:49:04 -0000 > > 1.12 +++ dev/sdmmc/sdmmcreg.h 17 Aug 2020 10:38:11 -0000 > > @@ -44,6 +44,7 @@ > > #define SD_SEND_RELATIVE_ADDR 3 /* R6 */ > > #define SD_SEND_SWITCH_FUNC 6 /* R1 */ > > #define SD_SEND_IF_COND 8 /* R7 */ > > +#define SD_VOLTAGE_SWITCH 11 /* R1 */ > > > > /* SD application commands */ /* response > > type */ #define SD_APP_SET_BUS_WIDTH 6 /* R1 > > */ @@ -52,9 +53,11 @@ > > > > /* OCR bits */ > > #define MMC_OCR_MEM_READY (1<<31) /* memory > > power-up status bit */ -#define MMC_OCR_ACCESS_MODE_MASK > > 0x60000000 /* bits 30:29 */ -#define MMC_OCR_SECTOR_MODE > > (1<<30) -#define MMC_OCR_BYTE_MODE (1<<29) > > +#define MMC_OCR_HCS (1<<30) /* SD > > only */ +#define MMC_OCR_ACCESS_MODE_MASK (3<<29) /* > > MMC only */ +#define MMC_OCR_ACCESS_MODE_BYTE (0<<29) > > /* MMC only */ +#define MMC_OCR_ACCESS_MODE_SECTOR > > (2<<29) /* MMC only */ +#define MMC_OCR_S18A > > (1<<24) #define MMC_OCR_3_5V_3_6V (1<<23) > > #define MMC_OCR_3_4V_3_5V (1<<22) > > #define MMC_OCR_3_3V_3_4V (1<<21) > > @@ -73,7 +76,6 @@ > > #define MMC_OCR_2_0V_2_1V (1<<8) > > #define MMC_OCR_1_65V_1_95V (1<<7) > > > > -#define SD_OCR_SDHC_CAP (1<<30) > > #define SD_OCR_VOL_MASK 0xFF8000 /* bits > > 23:15 */ > > /* R1 response type bits */ > > Index: dev/ic/rtsxreg.h > > =================================================================== > > RCS file: /cvs/src/sys/dev/ic/rtsxreg.h,v > > retrieving revision 1.4 > > diff -u -p -r1.4 rtsxreg.h > > --- dev/ic/rtsxreg.h 6 Sep 2017 13:07:38 -0000 1.4 > > +++ dev/ic/rtsxreg.h 17 Aug 2020 10:38:11 -0000 > > @@ -387,8 +387,7 @@ > > #define RTSX_PPBUF_SIZE 256 > > > > #define RTSX_SUPPORT_VOLTAGE > > (MMC_OCR_3_3V_3_4V|MMC_OCR_3_2V_3_3V|\ > > - > > MMC_OCR_3_1V_3_2V|MMC_OCR_3_0V_3_1V|\ > > - SD_OCR_SDHC_CAP) > > + > > MMC_OCR_3_1V_3_2V|MMC_OCR_3_0V_3_1V) > > #define RTSX_CFG_PCI 0x1C > > #define RTSX_CFG_ASIC 0x10 > > >