Author: ian Date: Wed Mar 1 21:02:26 2017 New Revision: 314510 URL: https://svnweb.freebsd.org/changeset/base/314510
Log: MFC r308186, r308188, r308231, r308232: Move imx_sdhci driver over to a dev/sdhci in preparation for QorIQ support. Freescale uses eSDHC in both i.MX (ARM) and QorIQ (PowerPC), with slight differences. This is part one in unifying the drivers. Merge i.MX and PowerPC SDHCI drivers Summary: i.MX5 and PowerPC use a very similar eSDHC controller, which is also similar to the uSDHC controller used by i.MX6. The imx_sdhci driver works almost completely with PowerPC, with some minor tweaks. Fix the build. protctl is only used on powerpc. While here, remove the need to check the SVR SPR, as others may be compatible with the p1022-esdhc type. Since it's no longer accessing a powerpc-specific register, drop the #ifdef. Added: stable/11/sys/dev/sdhci/fsl_sdhci.c - copied, changed from r308186, head/sys/dev/sdhci/fsl_sdhci.c Deleted: stable/11/sys/arm/freescale/imx/imx_sdhci.c stable/11/sys/powerpc/mpc85xx/fsl_sdhc.c stable/11/sys/powerpc/mpc85xx/fsl_sdhc.h Modified: stable/11/sys/arm/freescale/imx/files.imx5 stable/11/sys/arm/freescale/imx/files.imx6 stable/11/sys/conf/files.powerpc Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/arm/freescale/imx/files.imx5 ============================================================================== --- stable/11/sys/arm/freescale/imx/files.imx5 Wed Mar 1 20:23:21 2017 (r314509) +++ stable/11/sys/arm/freescale/imx/files.imx5 Wed Mar 1 21:02:26 2017 (r314510) @@ -32,7 +32,7 @@ arm/freescale/imx/imx51_ccm.c standard dev/ata/chipsets/ata-fsl.c optional imxata # SDHCI/MMC -arm/freescale/imx/imx_sdhci.c optional sdhci +dev/sdhci/fsl_sdhci.c optional sdhci # USB OH3 controller (1 OTG, 3 EHCI) arm/freescale/imx/imx_nop_usbphy.c optional ehci Modified: stable/11/sys/arm/freescale/imx/files.imx6 ============================================================================== --- stable/11/sys/arm/freescale/imx/files.imx6 Wed Mar 1 20:23:21 2017 (r314509) +++ stable/11/sys/arm/freescale/imx/files.imx6 Wed Mar 1 21:02:26 2017 (r314510) @@ -32,7 +32,7 @@ arm/freescale/imx/imx6_ipu.c optional v # # Optional devices. # -arm/freescale/imx/imx_sdhci.c optional sdhci +dev/sdhci/fsl_sdhci.c optional sdhci arm/freescale/imx/imx_wdog.c optional imxwdt Modified: stable/11/sys/conf/files.powerpc ============================================================================== --- stable/11/sys/conf/files.powerpc Wed Mar 1 20:23:21 2017 (r314509) +++ stable/11/sys/conf/files.powerpc Wed Mar 1 21:02:26 2017 (r314510) @@ -63,6 +63,7 @@ dev/ofw/ofw_subr.c optional aim powerpc dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx dev/scc/scc_bfe_macio.c optional scc powermac +dev/sdhci/fsl_sdhci.c optional mpc85xx sdhci dev/sec/sec.c optional sec mpc85xx dev/sound/macio/aoa.c optional snd_davbus | snd_ai2s powermac dev/sound/macio/davbus.c optional snd_davbus powermac @@ -135,7 +136,6 @@ powerpc/mikrotik/platform_rb.c optional powerpc/mpc85xx/atpic.c optional mpc85xx isa powerpc/mpc85xx/ds1553_bus_fdt.c optional ds1553 fdt powerpc/mpc85xx/ds1553_core.c optional ds1553 -powerpc/mpc85xx/fsl_sdhc.c optional mpc85xx sdhc | qoriq_dpaa sdhc powerpc/mpc85xx/i2c.c optional iicbus fdt powerpc/mpc85xx/isa.c optional mpc85xx isa powerpc/mpc85xx/lbc.c optional mpc85xx | qoriq_dpaa Copied and modified: stable/11/sys/dev/sdhci/fsl_sdhci.c (from r308186, head/sys/dev/sdhci/fsl_sdhci.c) ============================================================================== --- head/sys/dev/sdhci/fsl_sdhci.c Wed Nov 2 00:51:09 2016 (r308186, copy source) +++ stable/11/sys/dev/sdhci/fsl_sdhci.c Wed Mar 1 21:02:26 2017 (r314510) @@ -28,7 +28,7 @@ __FBSDID("$FreeBSD$"); /* - * SDHCI driver glue for Freescale i.MX SoC family. + * SDHCI driver glue for Freescale i.MX SoC and QorIQ families. * * This supports both eSDHC (earlier SoCs) and uSDHC (more recent SoCs). */ @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/bus.h> #include <sys/callout.h> +#include <sys/endian.h> #include <sys/kernel.h> #include <sys/libkern.h> #include <sys/lock.h> @@ -52,9 +53,11 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> +#ifdef __arm__ #include <machine/intr.h> #include <arm/freescale/imx/imx_ccmvar.h> +#endif #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> @@ -146,7 +149,6 @@ struct fsl_sdhci_softc { #define SDHC_PROT_CDSS (1 << 7) #define SDHC_SYS_CTRL 0x2c -#define SDHC_INT_STATUS 0x30 /* * The clock enable bits exist in different registers for ESDHC vs USDHC, but @@ -169,6 +171,7 @@ static struct ofw_compat_data compat_dat {"fsl,imx6sl-usdhc", HWTYPE_USDHC}, {"fsl,imx53-esdhc", HWTYPE_ESDHC}, {"fsl,imx51-esdhc", HWTYPE_ESDHC}, + {"fsl,esdhc", HWTYPE_ESDHC}, {NULL, HWTYPE_NONE}, }; @@ -397,6 +400,11 @@ fsl_sdhci_write_1(device_t dev, struct s if (off == SDHCI_POWER_CONTROL) { return; } +#ifdef __powerpc__ + /* XXX Reset doesn't seem to work as expected. Do nothing for now. */ + if (off == SDHCI_SOFTWARE_RESET) + return; +#endif val32 = RD4(sc, off & ~3); val32 &= ~(0xff << (off & 3) * 8); @@ -531,17 +539,20 @@ fsl_sdhc_get_clock(struct fsl_sdhci_soft val |= SDHCI_CLOCK_INT_STABLE; /* - * On ESDHC hardware the card bus clock enable is in the usual sdhci - * register but it's a different bit, so transcribe it (note the + * On i.MX ESDHC hardware the card bus clock enable is in the usual + * sdhci register but it's a different bit, so transcribe it (note the * difference between standard SDHCI_ and Freescale SDHC_ prefixes - * here). On USDHC hardware there is a force-on bit, but no force-off - * for the card bus clock (the hardware runs the clock when transfers - * are active no matter what), so we always say the clock is on. + * here). On USDHC and QorIQ ESDHC hardware there is a force-on bit, but + * no force-off for the card bus clock (the hardware runs the clock when + * transfers are active no matter what), so we always say the clock is + * on. * XXX Maybe we should say it's in whatever state the sdhci driver last * set it to. */ if (sc->hwtype == HWTYPE_ESDHC) { +#ifdef __arm__ if (RD4(sc, SDHC_SYS_CTRL) & SDHC_CLK_SDCLKEN) +#endif val |= SDHCI_CLOCK_CARD_EN; } else { val |= SDHCI_CLOCK_CARD_EN; @@ -565,15 +576,18 @@ fsl_sdhc_set_clock(struct fsl_sdhci_soft sc->sdclockreg_freq_bits = val & SDHCI_DIVIDERS_MASK; if (sc->hwtype == HWTYPE_ESDHC) { /* - * The ESDHC hardware requires the driver to manually start and - * stop the sd bus clock. If the enable bit is not set, turn - * off the clock in hardware and we're done, otherwise decode - * the requested frequency. ESDHC hardware is sdhci 2.0; the - * sdhci driver will use the original 8-bit divisor field and - * the "base / 2^N" divisor scheme. + * The i.MX5 ESDHC hardware requires the driver to manually + * start and stop the sd bus clock. If the enable bit is not + * set, turn off the clock in hardware and we're done, otherwise + * decode the requested frequency. ESDHC hardware is sdhci 2.0; + * the sdhci driver will use the original 8-bit divisor field + * and the "base / 2^N" divisor scheme. */ if ((val & SDHCI_CLOCK_CARD_EN) == 0) { +#ifdef __arm__ + /* On QorIQ, this is a reserved bit. */ WR4(sc, SDHCI_CLOCK_CONTROL, val32 & ~SDHC_CLK_SDCLKEN); +#endif return; } @@ -625,6 +639,7 @@ fsl_sdhc_set_clock(struct fsl_sdhci_soft val32 &= ~(SDHC_CLK_DIVISOR_MASK | SDHC_CLK_PRESCALE_MASK); val32 |= divisor << SDHC_CLK_DIVISOR_SHIFT; val32 |= prescale << SDHC_CLK_PRESCALE_SHIFT; + val32 |= SDHC_CLK_IPGEN; WR4(sc, SDHCI_CLOCK_CONTROL, val32); } @@ -710,10 +725,10 @@ fsl_sdhci_intr(void *arg) */ switch (sc->r1bfix_type) { case R1BFIX_NODATA: - intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_RESPONSE; + intmask = RD4(sc, SDHCI_INT_STATUS) & SDHCI_INT_RESPONSE; break; case R1BFIX_AC12: - intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_DATA_END; + intmask = RD4(sc, SDHCI_INT_STATUS) & SDHCI_INT_DATA_END; break; default: intmask = 0; @@ -722,8 +737,8 @@ fsl_sdhci_intr(void *arg) if (intmask) { sc->r1bfix_timeout_at = getsbinuptime() + 250 * SBT_1MS; if (!fsl_sdhci_r1bfix_is_wait_done(sc)) { - WR4(sc, SDHC_INT_STATUS, intmask); - bus_barrier(sc->mem_res, SDHC_INT_STATUS, 4, + WR4(sc, SDHCI_INT_STATUS, intmask); + bus_barrier(sc->mem_res, SDHCI_INT_STATUS, 4, BUS_SPACE_BARRIER_WRITE); } } @@ -735,9 +750,53 @@ fsl_sdhci_intr(void *arg) static int fsl_sdhci_get_ro(device_t bus, device_t child) { + struct fsl_sdhci_softc *sc = device_get_softc(bus); + + if (RD4(sc, SDHCI_PRESENT_STATE) & SDHC_PRES_WPSPL) + return (false); + return (true); +} + +#ifdef __powerpc__ +static uint32_t +fsl_sdhci_get_platform_clock(device_t dev) +{ + device_t parent; + phandle_t node; + uint32_t clock; + + node = ofw_bus_get_node(dev); - return (false); + /* Get sdhci node properties */ + if((OF_getprop(node, "clock-frequency", (void *)&clock, + sizeof(clock)) <= 0) || (clock == 0)) { + + /* + * Trying to get clock from parent device (soc) if correct + * clock cannot be acquired from sdhci node. + */ + parent = device_get_parent(dev); + node = ofw_bus_get_node(parent); + + /* Get soc properties */ + if ((OF_getprop(node, "bus-frequency", (void *)&clock, + sizeof(clock)) <= 0) || (clock == 0)) { + device_printf(dev,"Cannot acquire correct sdhci " + "frequency from DTS.\n"); + + return (0); + } + /* eSDHC clock is 1/2 platform clock. */ + clock /= 2; + } + + if (bootverbose) + device_printf(dev, "Acquired clock: %d from DTS\n", clock); + + return (clock); } +#endif + static int fsl_sdhci_detach(device_t dev) @@ -752,6 +811,9 @@ fsl_sdhci_attach(device_t dev) struct fsl_sdhci_softc *sc = device_get_softc(dev); int rid, err; phandle_t node; +#ifdef __powerpc__ + uint32_t protctl; +#endif sc->dev = dev; @@ -807,9 +869,21 @@ fsl_sdhci_attach(device_t dev) * * XXX need named constants for this stuff. */ - WR4(sc, SDHC_WTMK_LVL, 0x08800880); + /* P1022 has the '*_BRST_LEN' fields as reserved, always reading 0x10 */ + if (ofw_bus_is_compatible(dev, "fsl,p1022-esdhc")) + WR4(sc, SDHC_WTMK_LVL, 0x10801080); + else + WR4(sc, SDHC_WTMK_LVL, 0x08800880); + /* + * We read in native byte order in the main driver, but the register + * defaults to little endian. + */ +#ifdef __powerpc__ + sc->baseclk_hz = fsl_sdhci_get_platform_clock(dev); +#else sc->baseclk_hz = imx_ccm_sdhci_hz(); +#endif sc->slot.max_clk = sc->baseclk_hz; /* @@ -830,6 +904,16 @@ fsl_sdhci_attach(device_t dev) /* XXX put real gpio hookup here. */ sc->force_card_present = true; } +#ifdef __powerpc__ + /* Default to big-endian on powerpc */ + protctl = RD4(sc, SDHC_PROT_CTRL); + protctl &= ~SDHC_PROT_EMODE_MASK; + if (OF_hasprop(node, "little-endian")) + protctl |= SDHC_PROT_EMODE_LITTLE; + else + protctl |= SDHC_PROT_EMODE_BIG; + WR4(sc, SDHC_PROT_CTRL, protctl); +#endif callout_init(&sc->r1bfix_callout, 1); sdhci_init_slot(dev, &sc->slot, 0); _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"