summaryrefslogtreecommitdiffstats
path: root/sys/arm/freescale
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-16 00:14:50 +0000
committerian <ian@FreeBSD.org>2014-05-16 00:14:50 +0000
commite58449eb7bc00b546bc709cb6348a17b98b8e5e6 (patch)
tree22b6c19e6005b89913582be3c50a3f7a2933415b /sys/arm/freescale
parentf083c46ffb97127283c21b8ede4df56856ff45d2 (diff)
downloadFreeBSD-src-e58449eb7bc00b546bc709cb6348a17b98b8e5e6.zip
FreeBSD-src-e58449eb7bc00b546bc709cb6348a17b98b8e5e6.tar.gz
MFC r262409, r262411, r262413, r262420, r262426, r262427, r262440, r262456,
r262482, r262483, r262531, Move the declaration for mpentry() into a header file instead of pasting it into a bunch of different .c files. If the L2 cache type is PIPT, pass a physical address for a flush. Actually set the proper bit to indicate TTB shared memory. Add a new cache maintenance function, idcache_inv_all, to the table, and implementations for each of the chips we support. Invalidate caches immediately upon entry to init_secondary(). Also set the Bufferable bit in the PDE entries of the secondary processor startup pagetables. Add the bits needed to run SMP on imx6. Invalidate the SCU cache tag ram on all 4 cores, not just 1-3. Minor tweaks to the imx GPT timer Vybrid enhancements... - Pin configuration is a complete iomux register now and includes drive strength, pull mode, mux mode, speed, etc. - Add i2c devices to the tree - Add IPG clock - Add support for Quartz Module. - Pin configuration is a complete iomux register now and includes drive strength, pull mode, mux mode, speed, etc. - Add i2c devices to the tree - Add IPG clock
Diffstat (limited to 'sys/arm/freescale')
-rw-r--r--sys/arm/freescale/imx/files.imx61
-rw-r--r--sys/arm/freescale/imx/imx6_mp.c170
-rw-r--r--sys/arm/freescale/imx/imx_gpt.c12
-rw-r--r--sys/arm/freescale/imx/std.imx63
-rw-r--r--sys/arm/freescale/vybrid/vf_ccm.c13
-rw-r--r--sys/arm/freescale/vybrid/vf_iomuxc.c70
6 files changed, 229 insertions, 40 deletions
diff --git a/sys/arm/freescale/imx/files.imx6 b/sys/arm/freescale/imx/files.imx6
index 943c679..41060da 100644
--- a/sys/arm/freescale/imx/files.imx6
+++ b/sys/arm/freescale/imx/files.imx6
@@ -22,6 +22,7 @@ arm/freescale/imx/common.c standard
arm/freescale/imx/imx6_anatop.c standard
arm/freescale/imx/imx6_ccm.c standard
arm/freescale/imx/imx6_machdep.c standard
+arm/freescale/imx/imx6_mp.c optional smp
arm/freescale/imx/imx6_pl310.c standard
arm/freescale/imx/imx_machdep.c standard
arm/freescale/imx/imx_gpt.c standard
diff --git a/sys/arm/freescale/imx/imx6_mp.c b/sys/arm/freescale/imx/imx6_mp.c
new file mode 100644
index 0000000..5b5136b
--- /dev/null
+++ b/sys/arm/freescale/imx/imx6_mp.c
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 2014 Juergen Weiss <weiss@uni-mainz.de>
+ * Copyright (c) 2014 Ian Lepore <ian@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#define SCU_PHYSBASE 0x00a00000
+#define SCU_SIZE 0x00001000
+
+#define SCU_CONTROL_REG 0x00
+#define SCU_CONTROL_ENABLE (1 << 0)
+#define SCU_CONFIG_REG 0x04
+#define SCU_CONFIG_REG_NCPU_MASK 0x03
+#define SCU_CPUPOWER_REG 0x08
+#define SCU_INV_TAGS_REG 0x0c
+#define SCU_DIAG_CONTROL 0x30
+#define SCU_DIAG_DISABLE_MIGBIT (1 << 0)
+#define SCU_FILTER_START_REG 0x40
+#define SCU_FILTER_END_REG 0x44
+#define SCU_SECURE_ACCESS_REG 0x50
+#define SCU_NONSECURE_ACCESS_REG 0x54
+
+#define SRC_PHYSBASE 0x020d8000
+#define SRC_SIZE 0x4000
+#define SRC_CONTROL_REG 0x00
+#define SRC_CONTROL_C1ENA_SHIFT 22 /* Bit for Core 1 enable */
+#define SRC_CONTROL_C1RST_SHIFT 14 /* Bit for Core 1 reset */
+#define SRC_GPR0_C1FUNC 0x20 /* Register for Core 1 entry func */
+#define SRC_GPR1_C1ARG 0x24 /* Register for Core 1 entry arg */
+
+void
+platform_mp_init_secondary(void)
+{
+
+ gic_init_secondary();
+}
+
+void
+platform_mp_setmaxid(void)
+{
+ bus_space_handle_t scu;
+ uint32_t val;
+
+ /* If we've already set the global vars don't bother to do it again. */
+ if (mp_ncpus != 0)
+ return;
+
+ if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
+ panic("Couldn't map the SCU\n");
+ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONFIG_REG);
+ bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
+
+ mp_maxid = (val & SCU_CONFIG_REG_NCPU_MASK);
+ mp_ncpus = mp_maxid + 1;
+}
+
+int
+platform_mp_probe(void)
+{
+
+ /* I think platform_mp_setmaxid must get called first, but be safe. */
+ if (mp_ncpus == 0)
+ platform_mp_setmaxid();
+
+ return (mp_ncpus > 1);
+}
+
+void
+platform_mp_start_ap(void)
+{
+ bus_space_handle_t scu;
+ bus_space_handle_t src;
+
+ uint32_t val;
+ int i;
+
+ if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
+ panic("Couldn't map the SCU\n");
+ if (bus_space_map(fdtbus_bs_tag, SRC_PHYSBASE, SRC_SIZE, 0, &src) != 0)
+ panic("Couldn't map the system reset controller (SRC)\n");
+
+ /*
+ * Invalidate SCU cache tags. The 0x0000ffff constant invalidates all
+ * ways on all cores 0-3. Per the ARM docs, it's harmless to write to
+ * the bits for cores that are not present.
+ */
+ bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff);
+
+ /*
+ * Erratum ARM/MP: 764369 (problems with cache maintenance).
+ * Setting the "disable-migratory bit" in the undocumented SCU
+ * Diagnostic Control Register helps work around the problem.
+ */
+ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL);
+ bus_space_write_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL,
+ val | SCU_DIAG_DISABLE_MIGBIT);
+
+ /*
+ * Enable the SCU, then clean the cache on this core. After these two
+ * operations the cache tag ram in the SCU is coherent with the contents
+ * of the cache on this core. The other cores aren't running yet so
+ * their caches can't contain valid data yet, but we've initialized
+ * their SCU tag ram above, so they will be coherent from startup.
+ */
+ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG);
+ bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG,
+ val | SCU_CONTROL_ENABLE);
+ cpu_idcache_wbinv_all();
+
+ /*
+ * For each AP core, set the entry point address and argument registers,
+ * and set the core-enable and core-reset bits in the control register.
+ */
+ val = bus_space_read_4(fdtbus_bs_tag, src, SRC_CONTROL_REG);
+ for (i=1; i < mp_ncpus; i++) {
+ bus_space_write_4(fdtbus_bs_tag, src, SRC_GPR0_C1FUNC + 8*i,
+ pmap_kextract((vm_offset_t)mpentry));
+ bus_space_write_4(fdtbus_bs_tag, src, SRC_GPR1_C1ARG + 8*i, 0);
+
+ val |= ((1 << (SRC_CONTROL_C1ENA_SHIFT - 1 + i )) |
+ ( 1 << (SRC_CONTROL_C1RST_SHIFT - 1 + i)));
+
+ }
+ bus_space_write_4(fdtbus_bs_tag, src, 0, val);
+
+ armv7_sev();
+
+ bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
+ bus_space_unmap(fdtbus_bs_tag, src, SRC_SIZE);
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+
+ pic_ipi_send(cpus, ipi);
+}
diff --git a/sys/arm/freescale/imx/imx_gpt.c b/sys/arm/freescale/imx/imx_gpt.c
index 0e32bc9..f792a97 100644
--- a/sys/arm/freescale/imx/imx_gpt.c
+++ b/sys/arm/freescale/imx/imx_gpt.c
@@ -75,7 +75,7 @@ static int imx_gpt_probe(device_t);
static int imx_gpt_attach(device_t);
static struct timecounter imx_gpt_timecounter = {
- .tc_name = "i.MX GPT Timecounter",
+ .tc_name = "iMXGPT",
.tc_get_timecount = imx_gpt_get_timecount,
.tc_counter_mask = ~0u,
.tc_frequency = 0,
@@ -244,9 +244,9 @@ imx_gpt_attach(device_t dev)
}
/* Register as an eventtimer. */
- sc->et.et_name = "i.MXxxx GPT Eventtimer";
+ sc->et.et_name = "iMXGPT";
sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
- sc->et.et_quality = 1000;
+ sc->et.et_quality = 800;
sc->et.et_frequency = sc->clkfreq;
sc->et.et_min_period = (MIN_ET_PERIOD << 32) / sc->et.et_frequency;
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
@@ -286,9 +286,9 @@ imx_gpt_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
/* Do not disturb, otherwise event will be lost */
spinlock_enter();
/* Set expected value */
- WRITE4(sc, IMX_GPT_OCR1, READ4(sc, IMX_GPT_CNT) + ticks);
+ WRITE4(sc, IMX_GPT_OCR3, READ4(sc, IMX_GPT_CNT) + ticks);
/* Enable compare register 1 Interrupt */
- SET4(sc, IMX_GPT_IR, GPT_IR_OF1);
+ SET4(sc, IMX_GPT_IR, GPT_IR_OF3);
/* Now everybody can relax */
spinlock_exit();
return (0);
@@ -349,7 +349,7 @@ imx_gpt_intr(void *arg)
WRITE4(sc, IMX_GPT_SR, status);
/* Handle one-shot timer events. */
- if (status & GPT_IR_OF1) {
+ if (status & GPT_IR_OF3) {
if (sc->et.et_active) {
sc->et.et_event_cb(&sc->et, sc->et.et_arg);
}
diff --git a/sys/arm/freescale/imx/std.imx6 b/sys/arm/freescale/imx/std.imx6
index c328b22..51f82a8 100644
--- a/sys/arm/freescale/imx/std.imx6
+++ b/sys/arm/freescale/imx/std.imx6
@@ -10,5 +10,8 @@ options KERNPHYSADDR = 0x12000000
makeoptions KERNPHYSADDR = 0x12000000
options PHYSADDR = 0x10000000
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
+
files "../freescale/imx/files.imx6"
diff --git a/sys/arm/freescale/vybrid/vf_ccm.c b/sys/arm/freescale/vybrid/vf_ccm.c
index 9d9b517..39c3079 100644
--- a/sys/arm/freescale/vybrid/vf_ccm.c
+++ b/sys/arm/freescale/vybrid/vf_ccm.c
@@ -164,6 +164,18 @@ struct clk {
uint32_t sel_val;
};
+static struct clk ipg_clk = {
+ .reg = CCM_CACRR,
+ .enable_reg = 0,
+ .div_mask = IPG_CLK_DIV_MASK,
+ .div_shift = IPG_CLK_DIV_SHIFT,
+ .div_val = 1, /* Divide by 2 */
+ .sel_reg = 0,
+ .sel_mask = 0,
+ .sel_shift = 0,
+ .sel_val = 0,
+};
+
/*
PLL4 clock divider (before switching the clocks should be gated)
000 Divide by 1 (only if PLL frequency less than or equal to 650 MHz)
@@ -310,6 +322,7 @@ struct clock_entry {
};
static struct clock_entry clock_map[] = {
+ {"ipg", &ipg_clk},
{"pll4", &pll4_clk},
{"sai3", &sai3_clk},
{"cko1", &cko1_clk},
diff --git a/sys/arm/freescale/vybrid/vf_iomuxc.c b/sys/arm/freescale/vybrid/vf_iomuxc.c
index 8bfaa8d..8d8f7fd 100644
--- a/sys/arm/freescale/vybrid/vf_iomuxc.c
+++ b/sys/arm/freescale/vybrid/vf_iomuxc.c
@@ -56,21 +56,42 @@ __FBSDID("$FreeBSD$");
#include <arm/freescale/vybrid/vf_iomuxc.h>
#include <arm/freescale/vybrid/vf_common.h>
-#define IBE (1 << 0) /* Input Buffer Enable Field */
-#define OBE (1 << 1) /* Output Buffer Enable Field. */
-#define PUE (1 << 2) /* Pull / Keep Select Field. */
-#define PKE (1 << 3) /* Pull / Keep Enable Field. */
-#define PUS_MASK (3 << 4) /* Pull Up / Down Config Field. */
-#define DSE_MASK (7 << 6) /* Drive Strength Field. */
-#define HYS (1 << 9) /* Hysteresis Enable Field */
-
#define MUX_MODE_MASK 7
#define MUX_MODE_SHIFT 20
#define MUX_MODE_GPIO 0
#define MUX_MODE_VBUS_EN_OTG 2
-#define PUS_22_KOHM_PULL_UP (3 << 4)
-#define DSE_25_OHM (6 << 6)
+#define IBE (1 << 0) /* Input Buffer Enable Field */
+#define OBE (1 << 1) /* Output Buffer Enable Field. */
+#define PUE (1 << 2) /* Pull / Keep Select Field. */
+#define PKE (1 << 3) /* Pull / Keep Enable Field. */
+#define HYS (1 << 9) /* Hysteresis Enable Field */
+#define ODE (1 << 10) /* Open Drain Enable Field. */
+#define SRE (1 << 11) /* Slew Rate Field. */
+
+#define SPEED_SHIFT 12
+#define SPEED_MASK 0x3
+#define SPEED_LOW 0 /* 50 MHz */
+#define SPEED_MEDIUM 0x1 /* 100 MHz */
+#define SPEED_HIGH 0x3 /* 200 MHz */
+
+#define PUS_SHIFT 4 /* Pull Up / Down Config Field Shift */
+#define PUS_MASK 0x3
+#define PUS_100_KOHM_PULL_DOWN 0
+#define PUS_47_KOHM_PULL_UP 0x1
+#define PUS_100_KOHM_PULL_UP 0x2
+#define PUS_22_KOHM_PULL_UP 0x3
+
+#define DSE_SHIFT 6 /* Drive Strength Field Shift */
+#define DSE_MASK 0x7
+#define DSE_DISABLED 0 /* Output driver disabled */
+#define DSE_150_OHM 0x1
+#define DSE_75_OHM 0x2
+#define DSE_50_OHM 0x3
+#define DSE_37_OHM 0x4
+#define DSE_30_OHM 0x5
+#define DSE_25_OHM 0x6
+#define DSE_20_OHM 0x7
#define MAX_MUX_LEN 1024
@@ -101,19 +122,6 @@ iomuxc_probe(device_t dev)
}
static int
-configure_pad(struct iomuxc_softc *sc, int pad, int mux_mode)
-{
- int reg;
-
- reg = READ4(sc, pad);
- reg &= ~(MUX_MODE_MASK << MUX_MODE_SHIFT);
- reg |= (mux_mode << MUX_MODE_SHIFT);
- WRITE4(sc, pad, reg);
-
- return (0);
-}
-
-static int
pinmux_set(struct iomuxc_softc *sc)
{
phandle_t child, parent, root;
@@ -121,7 +129,7 @@ pinmux_set(struct iomuxc_softc *sc)
int len;
int values;
int pin;
- int mux_mode;
+ int pin_cfg;
int i;
root = OF_finddevice("/");
@@ -146,12 +154,12 @@ pinmux_set(struct iomuxc_softc *sc)
values = len / (sizeof(uint32_t));
for (i = 0; i < values; i += 2) {
pin = fdt32_to_cpu(iomux_config[i]);
- mux_mode = fdt32_to_cpu(iomux_config[i+1]);
+ pin_cfg = fdt32_to_cpu(iomux_config[i+1]);
#if 0
- device_printf(sc->dev, "Set pin %d to ALT%d\n",
- pin, mux_mode);
+ device_printf(sc->dev, "Set pin %d to 0x%08x\n",
+ pin, pin_cfg);
#endif
- configure_pad(sc, IOMUXC(pin), mux_mode);
+ WRITE4(sc, IOMUXC(pin), pin_cfg);
}
}
@@ -169,7 +177,6 @@ static int
iomuxc_attach(device_t dev)
{
struct iomuxc_softc *sc;
- int reg;
sc = device_get_softc(dev);
sc->dev = dev;
@@ -183,11 +190,6 @@ iomuxc_attach(device_t dev)
sc->bst = rman_get_bustag(sc->tmr_res[0]);
sc->bsh = rman_get_bushandle(sc->tmr_res[0]);
- /* USB */
- configure_pad(sc, IOMUXC_PTA17, MUX_MODE_VBUS_EN_OTG);
- reg = (PKE | PUE | PUS_22_KOHM_PULL_UP | DSE_25_OHM | OBE);
- WRITE4(sc, IOMUXC_PTA7, reg);
-
pinmux_set(sc);
return (0);
OpenPOWER on IntegriCloud