Date: Mon, 26 Feb 2018 21:27:42 +0000 (UTC) From: Emmanuel Vadot <manu@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r330037 - head/sys/dev/mmc/host Message-ID: <201802262127.w1QLRg4i089936@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: manu Date: Mon Feb 26 21:27:42 2018 New Revision: 330037 URL: https://svnweb.freebsd.org/changeset/base/330037 Log: dwmmc: Add clock support and other improvements * If compiled with EXT_RESOURCES look up the "biu" and "ciu" clocks in the DT * Don't use custom property "bus-frequency" but the standard one "clock-frequency" * Use the DT property max-frequency and fall back to 200Mhz if it don't exists * Add more mmc caps suported by the controller * Always ack all interrupts * Subclassed driver can supply an update_ios so they can handle update the clocks accordingly * Take care of the DDR bit in update_ios (no functional change since we do not support voltage change for now) * Make use of the FDT bus-width property Modified: head/sys/dev/mmc/host/dwmmc.c head/sys/dev/mmc/host/dwmmc_var.h Modified: head/sys/dev/mmc/host/dwmmc.c ============================================================================== --- head/sys/dev/mmc/host/dwmmc.c Mon Feb 26 21:25:50 2018 (r330036) +++ head/sys/dev/mmc/host/dwmmc.c Mon Feb 26 21:27:42 2018 (r330037) @@ -56,6 +56,10 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/intr.h> +#ifdef EXT_RESOURCES +#include <dev/extres/clk/clk.h> +#endif + #include <dev/mmc/host/dwmmc_reg.h> #include <dev/mmc/host/dwmmc_var.h> @@ -341,14 +345,12 @@ dwmmc_intr(void *arg) dprintf("%s 0x%08x\n", __func__, reg); if (reg & DWMMC_CMD_ERR_FLAGS) { - WRITE4(sc, SDMMC_RINTSTS, DWMMC_CMD_ERR_FLAGS); dprintf("cmd err 0x%08x cmd 0x%08x\n", reg, cmd->opcode); cmd->error = MMC_ERR_TIMEOUT; } if (reg & DWMMC_DATA_ERR_FLAGS) { - WRITE4(sc, SDMMC_RINTSTS, DWMMC_DATA_ERR_FLAGS); dprintf("data err 0x%08x cmd 0x%08x\n", reg, cmd->opcode); cmd->error = MMC_ERR_FAILED; @@ -361,25 +363,22 @@ dwmmc_intr(void *arg) if (reg & SDMMC_INTMASK_CMD_DONE) { dwmmc_cmd_done(sc); sc->cmd_done = 1; - WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_CMD_DONE); } - if (reg & SDMMC_INTMASK_ACD) { + if (reg & SDMMC_INTMASK_ACD) sc->acd_rcvd = 1; - WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_ACD); - } - if (reg & SDMMC_INTMASK_DTO) { + if (reg & SDMMC_INTMASK_DTO) sc->dto_rcvd = 1; - WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_DTO); - } if (reg & SDMMC_INTMASK_CD) { /* XXX: Handle card detect */ - WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_CD); } } + /* Ack interrupts */ + WRITE4(sc, SDMMC_RINTSTS, reg); + if (sc->use_pio) { if (reg & (SDMMC_INTMASK_RXDR|SDMMC_INTMASK_DTO)) { pio_read(sc, cmd); @@ -411,37 +410,88 @@ parse_fdt(struct dwmmc_softc *sc) { pcell_t dts_value[3]; phandle_t node; + uint32_t bus_hz = 0, bus_width; int len; +#ifdef EXT_RESOURCES + int error; +#endif if ((node = ofw_bus_get_node(sc->dev)) == -1) return (ENXIO); + /* bus-width */ + if (OF_getencprop(node, "bus-width", &bus_width, sizeof(uint32_t)) <= 0) + bus_width = 4; + if (bus_width >= 4) + sc->host.caps |= MMC_CAP_4_BIT_DATA; + if (bus_width >= 8) + sc->host.caps |= MMC_CAP_8_BIT_DATA; + + /* max-frequency */ + if (OF_getencprop(node, "max-frequency", &sc->max_hz, sizeof(uint32_t)) <= 0) + sc->max_hz = 200000000; + /* fifo-depth */ if ((len = OF_getproplen(node, "fifo-depth")) > 0) { OF_getencprop(node, "fifo-depth", dts_value, len); sc->fifo_depth = dts_value[0]; } - /* num-slots */ + /* num-slots (Deprecated) */ sc->num_slots = 1; if ((len = OF_getproplen(node, "num-slots")) > 0) { + device_printf(sc->dev, "num-slots property is deprecated\n"); OF_getencprop(node, "num-slots", dts_value, len); sc->num_slots = dts_value[0]; } + /* clock-frequency */ + if ((len = OF_getproplen(node, "clock-frequency")) > 0) { + OF_getencprop(node, "clock-frequency", dts_value, len); + bus_hz = dts_value[0]; + } + +#ifdef EXT_RESOURCES + /* BIU (Bus Interface Unit clock) is optional */ + error = clk_get_by_ofw_name(sc->dev, 0, "biu", &sc->biu); + if (sc->biu) { + error = clk_enable(sc->biu); + if (error != 0) { + device_printf(sc->dev, "cannot enable biu clock\n"); + goto fail; + } + } + /* - * We need some platform-specific code to know - * what the clock is supplied for our device. - * For now rely on the value specified in FDT. + * CIU (Controller Interface Unit clock) is mandatory + * if no clock-frequency property is given */ + error = clk_get_by_ofw_name(sc->dev, 0, "ciu", &sc->ciu); + if (sc->ciu) { + error = clk_enable(sc->ciu); + if (error != 0) { + device_printf(sc->dev, "cannot enable ciu clock\n"); + goto fail; + } + if (bus_hz != 0) { + error = clk_set_freq(sc->ciu, bus_hz, 0); + if (error != 0) + device_printf(sc->dev, + "cannot set ciu clock to %u\n", bus_hz); + } + clk_get_freq(sc->ciu, &sc->bus_hz); + } +#endif /* EXT_RESOURCES */ + if (sc->bus_hz == 0) { - if ((len = OF_getproplen(node, "bus-frequency")) <= 0) - return (ENXIO); - OF_getencprop(node, "bus-frequency", dts_value, len); - sc->bus_hz = dts_value[0]; + device_printf(sc->dev, "No bus speed provided\n"); + goto fail; } return (0); + +fail: + return (ENXIO); } int @@ -541,9 +591,10 @@ dwmmc_attach(device_t dev) WRITE4(sc, SDMMC_CTRL, SDMMC_CTRL_INT_ENABLE); sc->host.f_min = 400000; - sc->host.f_max = min(200000000, sc->bus_hz); + sc->host.f_max = sc->max_hz; sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; - sc->host.caps = MMC_CAP_4_BIT_DATA; + sc->host.caps |= MMC_CAP_HSPEED; + sc->host.caps |= MMC_CAP_SIGNALING_330; device_add_child(dev, "mmc", -1); return (bus_generic_attach(dev)); @@ -608,6 +659,8 @@ dwmmc_update_ios(device_t brdev, device_t reqdev) { struct dwmmc_softc *sc; struct mmc_ios *ios; + uint32_t reg; + int ret = 0; sc = device_get_softc(brdev); ios = &sc->host.ios; @@ -615,8 +668,6 @@ dwmmc_update_ios(device_t brdev, device_t reqdev) dprintf("Setting up clk %u bus_width %d\n", ios->clock, ios->bus_width); - dwmmc_setup_bus(sc, ios->clock); - if (ios->bus_width == bus_width_8) WRITE4(sc, SDMMC_CTYPE, SDMMC_CTYPE_8BIT); else if (ios->bus_width == bus_width_4) @@ -629,15 +680,22 @@ dwmmc_update_ios(device_t brdev, device_t reqdev) WRITE4(sc, SDMMC_CLKSEL, sc->sdr_timing); } - /* - * XXX: take care about DDR bit - * - * reg = READ4(sc, SDMMC_UHS_REG); - * reg |= (SDMMC_UHS_REG_DDR); - * WRITE4(sc, SDMMC_UHS_REG, reg); - */ + /* Set DDR mode */ + reg = READ4(sc, SDMMC_UHS_REG); + if (ios->timing == bus_timing_uhs_ddr50 || + ios->timing == bus_timing_mmc_ddr52 || + ios->timing == bus_timing_mmc_hs400) + reg |= (SDMMC_UHS_REG_DDR); + else + reg &= ~(SDMMC_UHS_REG_DDR); + WRITE4(sc, SDMMC_UHS_REG, reg); - return (0); + if (sc->update_ios) + ret = sc->update_ios(sc, ios); + + dwmmc_setup_bus(sc, ios->clock); + + return (ret); } static int @@ -1032,7 +1090,6 @@ dwmmc_read_ivar(device_t bus, device_t child, int whic *(int *)result = sc->host.ios.vdd; break; case MMCBR_IVAR_CAPS: - sc->host.caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; *(int *)result = sc->host.caps; break; case MMCBR_IVAR_MAX_DATA: Modified: head/sys/dev/mmc/host/dwmmc_var.h ============================================================================== --- head/sys/dev/mmc/host/dwmmc_var.h Mon Feb 26 21:25:50 2018 (r330036) +++ head/sys/dev/mmc/host/dwmmc_var.h Mon Feb 26 21:27:42 2018 (r330037) @@ -33,6 +33,10 @@ #ifndef DEV_MMC_HOST_DWMMC_VAR_H #define DEV_MMC_HOST_DWMMC_VAR_H +#ifdef EXT_RESOURCES +#include <dev/extres/clk/clk.h> +#endif + enum { HWTYPE_NONE, HWTYPE_ALTERA, @@ -56,6 +60,8 @@ struct dwmmc_softc { uint32_t pwren_inverted; u_int desc_count; + int (*update_ios)(struct dwmmc_softc *sc, struct mmc_ios *ios); + bus_dma_tag_t desc_tag; bus_dmamap_t desc_map; struct idmac_desc *desc_ring; @@ -67,11 +73,17 @@ struct dwmmc_softc { uint32_t dto_rcvd; uint32_t acd_rcvd; uint32_t cmd_done; - uint32_t bus_hz; + uint64_t bus_hz; + uint32_t max_hz; uint32_t fifo_depth; uint32_t num_slots; uint32_t sdr_timing; uint32_t ddr_timing; + +#ifdef EXT_RESOURCES + clk_t biu; + clk_t ciu; +#endif }; DECLARE_CLASS(dwmmc_driver);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802262127.w1QLRg4i089936>