svn commit: r314510 - in stable/11/sys: arm/freescale/imx conf dev/sdhci powerpc/mpc85xx
Ian Lepore
ian at FreeBSD.org
Wed Mar 1 21:02:28 UTC 2017
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);
More information about the svn-src-stable
mailing list