summaryrefslogtreecommitdiffstats
path: root/sys/arm/freescale
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-15 22:03:24 +0000
committerian <ian@FreeBSD.org>2014-05-15 22:03:24 +0000
commit2adbcd85c257d4cef2f521b431059e80c05f4d57 (patch)
treead43ebb893df8b629c10eba7081a65653d281d9d /sys/arm/freescale
parent4742b38bad2021d36f17b02ec7f94799806ac558 (diff)
downloadFreeBSD-src-2adbcd85c257d4cef2f521b431059e80c05f4d57.zip
FreeBSD-src-2adbcd85c257d4cef2f521b431059e80c05f4d57.tar.gz
MFC r261803, r261808, r261814, r261815, r261816, r261817, r261818, r261826,
r261848, r261855 On armv6 and later, use the WriteNotRead bit of the fault status register to decide what protections are required by the faulting access. Use the right symbols for determining arm architecture. Include the necessary header file which has the new FAULT_WNR symbol defined in it. Allow the kernel to be loaded at any 1MiB address. This requirement is because we use the 1MiB section maps as they only need a single pagetable. Add function for configuring Vybrid PLL4 (Audio) clock frequency output. imx6 changes ... - Fix the definition of the SDHCI_STATE_DAT and SDHCI_STATE_CMD fields, and add SDHCI_RETUNE_REQUEST. None of these are actually used in the code yet. - Write translation code for the SDHCI_PRESENT_STATE register. Freescale moved some bits around in their version of the register, adjust things so that the sdhci code sees the standard layout. - Add standard non-removable and cd-gpios properties to the usdhc devices. That generates references to gpio devices, so uncomment them even though there isn't a gpio driver to do anything with them yet. - Add handling of standard "non-removable" property, and also some workaround code so that if card detect is wired to a gpio pin, for now we just treat it the same as non-removable (because there isn't a gpio driver yet). - Enable both sdcard slots, but not the sdio-based wifi that we don't yet have a driver for. - Remove a couple obsolete function declarations.
Diffstat (limited to 'sys/arm/freescale')
-rw-r--r--sys/arm/freescale/imx/imx_machdep.h3
-rw-r--r--sys/arm/freescale/imx/imx_sdhci.c73
-rw-r--r--sys/arm/freescale/vybrid/vf_anadig.c35
-rw-r--r--sys/arm/freescale/vybrid/vf_common.h3
4 files changed, 100 insertions, 14 deletions
diff --git a/sys/arm/freescale/imx/imx_machdep.h b/sys/arm/freescale/imx/imx_machdep.h
index bb99111..b78f0da 100644
--- a/sys/arm/freescale/imx/imx_machdep.h
+++ b/sys/arm/freescale/imx/imx_machdep.h
@@ -33,7 +33,6 @@
/* Common functions, implemented in imx_machdep.c. */
-void imx_devmap_addentry(vm_paddr_t _pa, vm_size_t _sz);
void imx_wdog_cpu_reset(vm_offset_t _wdcr_phys) __attribute__((__noreturn__));
/* From here down, routines are implemented in imxNN_machdep.c. */
@@ -57,8 +56,6 @@ void imx_wdog_cpu_reset(vm_offset_t _wdcr_phys) __attribute__((__noreturn__));
u_int imx_soc_type(void);
u_int imx_soc_family(void);
-void imx_devmap_init(void);
-
/*
* We need a clock management system that works across unrelated SoCs and
* devices. For now, to keep imx development moving, define some barebones
diff --git a/sys/arm/freescale/imx/imx_sdhci.c b/sys/arm/freescale/imx/imx_sdhci.c
index baa9162..7c9af18 100644
--- a/sys/arm/freescale/imx/imx_sdhci.c
+++ b/sys/arm/freescale/imx/imx_sdhci.c
@@ -71,6 +71,7 @@ struct imx_sdhci_softc {
uint32_t r1bfix_intmask;
uint8_t r1bfix_type;
uint8_t hwtype;
+ boolean_t force_card_present;
};
#define R1BFIX_NONE 0 /* No fix needed at next interrupt. */
@@ -89,6 +90,27 @@ struct imx_sdhci_softc {
#define SDHC_VEND_HCKEN (1 << 12)
#define SDHC_VEND_PEREN (1 << 13)
+#define SDHC_PRES_STATE 0x24
+#define SDHC_PRES_CIHB (1 << 0)
+#define SDHC_PRES_CDIHB (1 << 1)
+#define SDHC_PRES_DLA (1 << 2)
+#define SDHC_PRES_SDSTB (1 << 3)
+#define SDHC_PRES_IPGOFF (1 << 4)
+#define SDHC_PRES_HCKOFF (1 << 5)
+#define SDHC_PRES_PEROFF (1 << 6)
+#define SDHC_PRES_SDOFF (1 << 7)
+#define SDHC_PRES_WTA (1 << 8)
+#define SDHC_PRES_RTA (1 << 9)
+#define SDHC_PRES_BWEN (1 << 10)
+#define SDHC_PRES_BREN (1 << 11)
+#define SDHC_PRES_RTR (1 << 12)
+#define SDHC_PRES_CINST (1 << 16)
+#define SDHC_PRES_CDPL (1 << 18)
+#define SDHC_PRES_WPSPL (1 << 19)
+#define SDHC_PRES_CLSL (1 << 23)
+#define SDHC_PRES_DLSL_SHIFT 24
+#define SDHC_PRES_DLSL_MASK (0xffU << SDHC_PRES_DLSL_SHIFT)
+
#define SDHC_PROT_CTRL 0x28
#define SDHC_PROT_LED (1 << 0)
#define SDHC_PROT_WIDTH_1BIT (0 << 1)
@@ -254,8 +276,8 @@ imx_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
wrk32 = RD4(sc, SDHC_VEND_SPEC);
if (wrk32 & SDHC_VEND_FRC_SDCLK_ON)
val32 |= SDHCI_CLOCK_INT_EN | SDHCI_CLOCK_CARD_EN;
- wrk32 = RD4(sc, SDHCI_PRESENT_STATE);
- if (wrk32 & 0x08)
+ wrk32 = RD4(sc, SDHC_PRES_STATE);
+ if (wrk32 & SDHC_PRES_SDSTB)
val32 |= SDHCI_CLOCK_INT_STABLE;
val32 |= sc->sdclockreg_freq_bits;
return (val32);
@@ -268,7 +290,9 @@ static uint32_t
imx_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
{
struct imx_sdhci_softc *sc = device_get_softc(dev);
- uint32_t val32;
+ uint32_t val32, wrk32;
+
+ val32 = RD4(sc, off);
/*
* The hardware leaves the base clock frequency out of the capabilities
@@ -280,7 +304,6 @@ imx_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
* doesn't yet handle (1.8v, suspend/resume, etc).
*/
if (off == SDHCI_CAPABILITIES) {
- val32 = RD4(sc, off);
val32 &= ~SDHCI_CAN_VDD_180;
val32 &= ~SDHCI_CAN_DO_SUSPEND;
val32 |= SDHCI_CAN_DO_8BITBUS;
@@ -288,14 +311,30 @@ imx_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
return (val32);
}
- val32 = RD4(sc, off);
+ /*
+ * The hardware moves bits around in the present state register to make
+ * room for all 8 data line state bits. To translate, mask out all the
+ * bits which are not in the same position in both registers (this also
+ * masks out some freescale-specific bits in locations defined as
+ * reserved by sdhci), then shift the data line and retune request bits
+ * down to their standard locations.
+ */
+ if (off == SDHCI_PRESENT_STATE) {
+ wrk32 = val32;
+ val32 &= 0x000F0F07;
+ val32 |= (wrk32 >> 4) & SDHCI_STATE_DAT_MASK;
+ val32 |= (wrk32 >> 9) & SDHCI_RETUNE_REQUEST;
+ if (sc->force_card_present)
+ val32 |= SDHCI_CARD_PRESENT;
+ return (val32);
+ }
/*
* imx_sdhci_intr() can synthesize a DATA_END interrupt following a
* command with an R1B response, mix it into the hardware status.
*/
if (off == SDHCI_INT_STATUS) {
- val32 |= sc->r1bfix_intmask;
+ return (val32 | sc->r1bfix_intmask);
}
return val32;
@@ -522,7 +561,7 @@ imx_sdhci_intr(void *arg)
count = 0;
/* XXX use a callout or something instead of busy-waiting. */
while (count < 250000 &&
- (RD4(sc, SDHCI_PRESENT_STATE) & SDHCI_DAT_ACTIVE)) {
+ (RD4(sc, SDHC_PRES_STATE) & SDHC_PRES_DLA)) {
++count;
DELAY(1);
}
@@ -555,6 +594,7 @@ imx_sdhci_attach(device_t dev)
{
struct imx_sdhci_softc *sc = device_get_softc(dev);
int rid, err;
+ phandle_t node;
sc->dev = dev;
@@ -621,6 +661,25 @@ imx_sdhci_attach(device_t dev)
sdhci_init_slot(dev, &sc->slot, 0);
+ /*
+ * If the slot is flagged with the non-removable property, set our flag
+ * to always force the SDHCI_CARD_PRESENT bit on.
+ *
+ * XXX Workaround for gpio-based card detect...
+ *
+ * We don't have gpio support yet. If there's a cd-gpios property just
+ * force the SDHCI_CARD_PRESENT bit on for now. If there isn't really a
+ * card there it will fail to probe at the mmc layer and nothing bad
+ * happens except instantiating a /dev/mmcN device for an empty slot.
+ */
+ node = ofw_bus_get_node(dev);
+ if (OF_hasprop(node, "non-removable"))
+ sc->force_card_present = true;
+ else if (OF_hasprop(node, "cd-gpios")) {
+ /* XXX put real gpio hookup here. */
+ sc->force_card_present = true;
+ }
+
bus_generic_probe(dev);
bus_generic_attach(dev);
diff --git a/sys/arm/freescale/vybrid/vf_anadig.c b/sys/arm/freescale/vybrid/vf_anadig.c
index e5c563c..0d5fda8 100644
--- a/sys/arm/freescale/vybrid/vf_anadig.c
+++ b/sys/arm/freescale/vybrid/vf_anadig.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2013-2014 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -99,14 +99,19 @@ __FBSDID("$FreeBSD$");
#define CTRL_PLL_EN (1 << 13)
#define EN_USB_CLKS (1 << 6)
+#define PLL4_CTRL_DIV_SEL_S 0
+#define PLL4_CTRL_DIV_SEL_M 0x7f
+
struct anadig_softc {
struct resource *res[1];
bus_space_tag_t bst;
bus_space_handle_t bsh;
};
+struct anadig_softc *anadig_sc;
+
static struct resource_spec anadig_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, 0 }
};
@@ -148,6 +153,28 @@ enable_pll(struct anadig_softc *sc, int pll_ctrl)
return (0);
}
+uint32_t
+pll4_configure_output(uint32_t mfi, uint32_t mfn, uint32_t mfd)
+{
+ struct anadig_softc *sc;
+ int reg;
+
+ sc = anadig_sc;
+
+ /*
+ * PLLout = Fsys * (MFI+(MFN/MFD))
+ */
+
+ reg = READ4(sc, ANADIG_PLL4_CTRL);
+ reg &= ~(PLL4_CTRL_DIV_SEL_M << PLL4_CTRL_DIV_SEL_S);
+ reg |= (mfi << PLL4_CTRL_DIV_SEL_S);
+ WRITE4(sc, ANADIG_PLL4_CTRL, reg);
+ WRITE4(sc, ANADIG_PLL4_NUM, mfn);
+ WRITE4(sc, ANADIG_PLL4_DENOM, mfd);
+
+ return (0);
+}
+
static int
anadig_attach(device_t dev)
{
@@ -165,11 +192,13 @@ anadig_attach(device_t dev)
sc->bst = rman_get_bustag(sc->res[0]);
sc->bsh = rman_get_bushandle(sc->res[0]);
+ anadig_sc = sc;
+
/* Enable USB PLLs */
enable_pll(sc, ANADIG_PLL3_CTRL);
enable_pll(sc, ANADIG_PLL7_CTRL);
- /* Enable other */
+ /* Enable other PLLs */
enable_pll(sc, ANADIG_PLL1_CTRL);
enable_pll(sc, ANADIG_PLL2_CTRL);
enable_pll(sc, ANADIG_PLL4_CTRL);
diff --git a/sys/arm/freescale/vybrid/vf_common.h b/sys/arm/freescale/vybrid/vf_common.h
index c1cba1b..44593be 100644
--- a/sys/arm/freescale/vybrid/vf_common.h
+++ b/sys/arm/freescale/vybrid/vf_common.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2013-2014 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,4 +39,5 @@
#define WRITE1(_sc, _reg, _val) \
bus_space_write_1(_sc->bst, _sc->bsh, _reg, _val)
+uint32_t pll4_configure_output(uint32_t mfi, uint32_t mfn, uint32_t mfd);
uint32_t tcon_bypass(void);
OpenPOWER on IntegriCloud