Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F176142770
D41201.id125214.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
53 KB
Referenced Files
None
Subscribers
None
D41201.id125214.diff
View Options
diff --git a/sys/arm/arm/pmu.c b/sys/arm/arm/pmu.c
--- a/sys/arm/arm/pmu.c
+++ b/sys/arm/arm/pmu.c
@@ -121,6 +121,7 @@
"Unable to setup interrupt handler.\n");
goto fail;
}
+#ifdef SMP
if (sc->irq[i].cpuid != -1) {
err = bus_bind_intr(dev, sc->irq[i].res,
sc->irq[i].cpuid);
@@ -130,6 +131,7 @@
goto fail;
}
}
+#endif
}
#if defined(__arm__) && (__ARM_ARCH > 6)
diff --git a/sys/arm/arm/pmu_fdt.c b/sys/arm/arm/pmu_fdt.c
--- a/sys/arm/arm/pmu_fdt.c
+++ b/sys/arm/arm/pmu_fdt.c
@@ -151,6 +151,10 @@
goto done;
}
+#ifndef SMP
+ return 0;
+#endif
+
/* Check if PMU have one per-CPU interrupt */
if (intr_is_per_cpu(sc->irq[0].res)) {
if (has_affinity) {
diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC
--- a/sys/arm/conf/GENERIC
+++ b/sys/arm/conf/GENERIC
@@ -60,6 +60,7 @@
options SOC_MV_ARMADAXP
options SOC_TI_AM335X
options SOC_OMAP4
+options SOC_IMX6
options SCHED_ULE # ULE scheduler
options SMP # Enable multiple cores
diff --git a/sys/arm/conf/SBC_EC9100 b/sys/arm/conf/SBC_EC9100
new file mode 100644
--- /dev/null
+++ b/sys/arm/conf/SBC_EC9100
@@ -0,0 +1,168 @@
+#
+# SBC_EC9100 -- Kernel config for EMTOP-TECH (Formerly Embest) SBC-EC9100
+# Board available at https://www.amazon.com/derp/dp/B0BHQMZGS2/
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# https://docs.freebsd.org/en/books/handbook/kernelconfig/#kernelconfig-config
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+ident SBC_EC9100
+
+cpu CPU_CORTEXA
+machine arm armv7
+makeoptions CONF_CFLAGS="-march=armv7a"
+
+include "std.armv7"
+files "../freescale/imx/files.imx6"
+
+nooptions cam
+nodevice cam
+options SOC_IMX6
+options SCHED_ULE # ULE scheduler
+options PLATFORM
+options LINUX_BOOT_ABI
+
+# pseudo devices
+device clk
+device phy
+device hwreset
+device nvmem
+device regulator
+device syscon
+
+# CPU frequency control
+device cpufreq
+
+# Interrupt controller
+device gic
+
+# PMU support (for CCNT).
+device pmu
+
+# ARM Generic Timer
+device generic_timer
+device mpcore_timer
+
+# MMC/SD/SDIO Card slot support
+device sdhci # SD controller
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+
+# Console and misc
+device uart
+device md # Memory "disks"
+device firmware # firmware assist module
+device pl310 # PL310 L2 cache controller
+
+# I2C support
+device iicbus
+device iic
+device fsliic # Freescale i2c/iic
+
+# i2c RTCs
+device nxprtc # NXP RTCs: PCA/PFC212x PCA/PCF85xx
+
+# GPIO
+device gpio
+device gpiobacklight
+device gpioled
+device gpioregulator
+
+# EVDEV support
+device evdev # input event device support
+options EVDEV_SUPPORT # evdev support in legacy drivers
+device uinput # install /dev/uinput cdev
+
+# SPI
+device spibus
+device spigen
+
+# PWM
+device pwm
+
+# Watchdog support
+# If we don't enable the watchdog driver, the BeagleBone could potentially
+# reboot automatically because the boot loader might have enabled the
+# watchdog.
+device imxwdt # Watchdog. WARNING: can't be disabled!!!
+
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+#device cd # CD
+#device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+device usb
+device uhci
+device ohci
+device ehci
+device xhci
+#device musb
+
+device axe # USB-Ethernet
+#device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+device ukbd # Allow keyboard like HIDs to control console
+
+# Device mode support
+device usb_template # Control of the gadget
+
+# Ethernet
+device loop
+device ether
+device vlan # 802.1Q VLAN support
+device bpf
+device mii
+device mdio
+
+# Ethernet NICs that use the common MII bus controller code.
+# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
+device miibus
+
+device ffec # Freescale Fast Ethernet Controller
+
+# Sound support
+#device sound
+
+# Pinmux
+device fdt_pinctrl
+
+# DMA controller
+device fslsdma
+
+# Extensible Firmware Interface
+options EFI
+
+# RTC
+device imx6_snvs # IMX6 On-chip RTC
+
+# HID support
+device hid # Generic HID support
+
+# Others from files.imx6
+device imx_gpt
+device imx_spi
+
+# New stuff
+device vf_adc
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+makeoptions MODULES_EXTRA+="dtb/imx6"
+
+# SOC-specific modules
+makeoptions MODULES_EXTRA+="imx"
diff --git a/sys/arm/freescale/fsl_ocotp.c b/sys/arm/freescale/fsl_ocotp.c
--- a/sys/arm/freescale/fsl_ocotp.c
+++ b/sys/arm/freescale/fsl_ocotp.c
@@ -47,6 +47,7 @@
#include <arm/freescale/fsl_ocotpreg.h>
#include <arm/freescale/fsl_ocotpvar.h>
+#include <arm/freescale/imx/imx_machdep.h>
/*
* Find the physical address and size of the ocotp registers and devmap them,
@@ -63,6 +64,14 @@
#include <dev/fdt/fdt_common.h>
#include <sys/devmap.h>
+/*
+ * Table of CPU max frequencies. This is used to translate the max frequency
+ * value (0-3) from the ocotp CFG3 register into a mhz value that can be looked
+ * up in the operating points table.
+ */
+static uint32_t imx6q_ocotp_mhz_tab[] = {792, 852, 996, 1200};
+static uint32_t imx6ul_ocotp_mhz_tab[] = {0, 528, 696, 0};
+
static uint32_t *ocotp_regs;
static vm_size_t ocotp_size;
@@ -75,7 +84,8 @@
if ((root = OF_finddevice("/")) == -1)
goto fatal;
if ((child = fdt_depth_search_compatible(root, "fsl,imx6q-ocotp", 0)) == 0)
- goto fatal;
+ if ((child = fdt_depth_search_compatible(root, "fsl,imx6ul-ocotp", 0)) == 0)
+ goto fatal;
if (fdt_regsize(child, &base, &size) != 0)
goto fatal;
@@ -149,12 +159,12 @@
static int
ocotp_probe(device_t dev)
{
-
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (ofw_bus_is_compatible(dev, "fsl,imx6q-ocotp") == 0)
- return (ENXIO);
+ if (ofw_bus_is_compatible(dev, "fsl,imx6ul-ocotp") == 0)
+ return (ENXIO);
device_set_desc(dev,
"Freescale On-Chip One-Time-Programmable Memory");
@@ -162,7 +172,7 @@
return (BUS_PROBE_DEFAULT);
}
-uint32_t
+static uint32_t
fsl_ocotp_read_4(bus_size_t off)
{
@@ -185,6 +195,41 @@
return (ocotp_regs[off / 4]);
}
+uint32_t
+fsl_ocotp_get_max_mhz(void)
+{
+ uint32_t cfg3speed;
+
+ /*
+ * Get the maximum speed this cpu can be set to. The values in the
+ * OCOTP CFG3 register are not documented in the reference manual.
+ * The following info was in an archived email found via web search:
+ * - 2b'11: 1200000000Hz;
+ * - 2b'10: 996000000Hz;
+ * - 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
+ * - 2b'00: 792000000Hz;
+ * The default hardware max speed can be overridden by a tunable.
+ */
+ cfg3speed = (fsl_ocotp_read_4(FSL_OCOTP_CFG3) &
+ FSL_OCOTP_CFG3_SPEED_MASK) >> FSL_OCOTP_CFG3_SPEED_SHIFT;
+ if (imx_soc_type() == IMXSOC_6UL)
+ return imx6ul_ocotp_mhz_tab[cfg3speed];
+ else
+ return imx6q_ocotp_mhz_tab[cfg3speed];
+ return 0;
+}
+
+void
+fsl_ocotp_get_temp_calibration(uint32_t *room_cnt, uint32_t *high_cnt, uint32_t *high_val)
+{
+ uint32_t cal;
+
+ cal = fsl_ocotp_read_4(FSL_OCOTP_ANA1);
+ *room_cnt = (cal & 0xFFF00000) >> 20;
+ *high_cnt = (cal & 0x000FFF00) >> 8;
+ *high_val = (cal & 0x000000FF) * 10;
+}
+
static device_method_t ocotp_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ocotp_probe),
diff --git a/sys/arm/freescale/fsl_ocotpvar.h b/sys/arm/freescale/fsl_ocotpvar.h
--- a/sys/arm/freescale/fsl_ocotpvar.h
+++ b/sys/arm/freescale/fsl_ocotpvar.h
@@ -31,6 +31,7 @@
#ifndef FSL_OCOTPVAR_H
#define FSL_OCOTPVAR_H
-uint32_t fsl_ocotp_read_4(bus_size_t _offset);
+uint32_t fsl_ocotp_get_max_mhz(void);
+void fsl_ocotp_get_temp_calibration(uint32_t *room_cnt, uint32_t *high_cnt, uint32_t *high_val);
#endif
diff --git a/sys/arm/freescale/imx/files.imx6 b/sys/arm/freescale/imx/files.imx6
--- a/sys/arm/freescale/imx/files.imx6
+++ b/sys/arm/freescale/imx/files.imx6
@@ -4,6 +4,7 @@
# Standard imx6 devices and support.
#
arm/freescale/fsl_ocotp.c standard
+arm/freescale/vybrid/vf_adc.c optional vf_adc
arm/freescale/imx/imx6_anatop.c standard
arm/freescale/imx/imx6_ccm.c standard
arm/freescale/imx/imx6_machdep.c standard
diff --git a/sys/arm/freescale/imx/imx6_anatop.c b/sys/arm/freescale/imx/imx6_anatop.c
--- a/sys/arm/freescale/imx/imx6_anatop.c
+++ b/sys/arm/freescale/imx/imx6_anatop.c
@@ -110,6 +110,7 @@
uint32_t temp_throttle_reset_cnt;
uint32_t temp_throttle_trigger_cnt;
uint32_t temp_throttle_val;
+ boolean_t irq_fired;
};
static struct imx6_anatop_softc *imx6_anatop_sc;
@@ -122,10 +123,12 @@
* more than 200mV, and the minimum SOC voltage is 1150mV, so that
* dictates the 950mV entry in this table.
*/
-static struct oppt {
+struct oppt {
uint32_t mhz;
uint32_t mv;
-} imx6_oppt_table[] = {
+};
+
+static struct oppt imx6_oppt_table[] = {
{ 396, 950},
{ 792, 1150},
{ 852, 1225},
@@ -133,12 +136,11 @@
{1200, 1275},
};
-/*
- * Table of CPU max frequencies. This is used to translate the max frequency
- * value (0-3) from the ocotp CFG3 register into a mhz value that can be looked
- * up in the operating points table.
- */
-static uint32_t imx6_ocotp_mhz_tab[] = {792, 852, 996, 1200};
+static struct oppt imx6ul_oppt_table[] = {
+ {528, 1150},
+ {396, 1000},
+ {198, 950},
+};
#define TZ_ZEROC 2731 /* deci-Kelvin <-> deci-Celsius offset. */
@@ -258,20 +260,30 @@
cpufreq_nearest_oppt(struct imx6_anatop_softc *sc, uint32_t cpu_newmhz)
{
int d, diff, i, nearest;
+ static struct oppt *tbl;
+ int tblsz;
+ if (imx_soc_type() == IMXSOC_6UL) {
+ tbl = imx6ul_oppt_table;
+ tblsz = nitems(imx6ul_oppt_table);
+ }
+ else {
+ tbl = imx6_oppt_table;
+ tblsz = nitems(imx6_oppt_table);
+ }
if (cpu_newmhz > sc->cpu_maxmhz_hw && !sc->cpu_overclock_enable)
cpu_newmhz = sc->cpu_maxmhz_hw;
diff = INT_MAX;
nearest = 0;
- for (i = 0; i < nitems(imx6_oppt_table); ++i) {
- d = abs((int)cpu_newmhz - (int)imx6_oppt_table[i].mhz);
+ for (i = 0; i < tblsz; ++i) {
+ d = abs((int)cpu_newmhz - (int)tbl[i].mhz);
if (diff > d) {
diff = d;
nearest = i;
}
}
- return (&imx6_oppt_table[nearest]);
+ return (&tbl[nearest]);
}
static void
@@ -392,7 +404,6 @@
static void
cpufreq_initialize(struct imx6_anatop_softc *sc)
{
- uint32_t cfg3speed;
struct oppt * op;
SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
@@ -435,9 +446,7 @@
* - 2b'00: 792000000Hz;
* The default hardware max speed can be overridden by a tunable.
*/
- cfg3speed = (fsl_ocotp_read_4(FSL_OCOTP_CFG3) &
- FSL_OCOTP_CFG3_SPEED_MASK) >> FSL_OCOTP_CFG3_SPEED_SHIFT;
- sc->cpu_maxmhz_hw = imx6_ocotp_mhz_tab[cfg3speed];
+ sc->cpu_maxmhz_hw = fsl_ocotp_get_max_mhz();
sc->cpu_maxmhz = sc->cpu_maxmhz_hw;
TUNABLE_INT_FETCH("hw.imx6.cpu_minmhz", &sc->cpu_minmhz);
@@ -550,18 +559,49 @@
}
}
+static void
+tempmon_apply_speed(struct imx6_anatop_softc *sc)
+{
+ /* Lower counts are higher temperatures. */
+ if (sc->temp_last_cnt < sc->temp_throttle_trigger_cnt)
+ tempmon_goslow(sc);
+ else if (sc->temp_last_cnt > (sc->temp_throttle_reset_cnt))
+ tempmon_gofast(sc);
+}
+
static int
tempmon_intr(void *arg)
{
struct imx6_anatop_softc *sc = arg;
+ uint32_t misc1;
/*
* XXX Note that this code doesn't currently run (for some mysterious
* reason we just never get an interrupt), so the real monitoring is
* done by tempmon_throttle_check().
+ * XXX Runs for me, 14-CURRENT July 26, 2023 - shurd@
+ * I've made it so the callout stops being scheduled if the intr fires
*/
- tempmon_goslow(sc);
+ sc->irq_fired = true;
+ temp_update_count(sc);
+ misc1 = imx6_anatop_read_4(IMX6_ANALOG_PMU_MISC1);
+ if (misc1 & IMX6_ANALOG_PMU_MISC1_IRQ_TEMPPANIC)
+ panic("Temperature panic triggered\n");
+ // Clear the interrupt
+ misc1 &= ~(IMX6_ANALOG_PMU_MISC1_IRQ_TEMPHIGH | IMX6_ANALOG_PMU_MISC1_IRQ_TEMPLOW);
+ imx6_anatop_write_4(IMX6_ANALOG_PMU_MISC1, misc1);
+
+ if (sc->temp_last_cnt < sc->temp_throttle_trigger_cnt) {
+ sc->temp_last_cnt = sc->temp_throttle_reset_cnt + 1;
+ tempmon_gofast(sc);
+ }
+ else if (sc->temp_last_cnt > (sc->temp_throttle_reset_cnt)) {
+ sc->temp_last_cnt = sc->temp_throttle_trigger_cnt - 1;
+ tempmon_goslow(sc);
+ }
+ // Clear the interrupt
/* XXX Schedule callout to speed back up eventually. */
+
return (FILTER_HANDLED);
}
@@ -570,30 +610,21 @@
{
struct imx6_anatop_softc *sc = arg;
- /* Lower counts are higher temperatures. */
- if (sc->temp_last_cnt < sc->temp_throttle_trigger_cnt)
- tempmon_goslow(sc);
- else if (sc->temp_last_cnt > (sc->temp_throttle_reset_cnt))
- tempmon_gofast(sc);
-
- callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay,
- 0, tempmon_throttle_check, sc, 0);
+ tempmon_apply_speed(sc);
+ if (!sc->irq_fired)
+ callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay,
+ 0, tempmon_throttle_check, sc, 0);
}
static void
initialize_tempmon(struct imx6_anatop_softc *sc)
{
- uint32_t cal;
-
/*
* Fetch calibration data: a sensor count at room temperature (25C),
* a sensor count at a high temperature, and that temperature
*/
- cal = fsl_ocotp_read_4(FSL_OCOTP_ANA1);
- sc->temp_room_cnt = (cal & 0xFFF00000) >> 20;
- sc->temp_high_cnt = (cal & 0x000FFF00) >> 8;
- sc->temp_high_val = (cal & 0x000000FF) * 10;
+ fsl_ocotp_get_temp_calibration(&sc->temp_room_cnt, &sc->temp_high_cnt, &sc->temp_high_val);
/*
* Throttle to a lower cpu freq at 10C below the "hot" temperature, and
@@ -614,6 +645,11 @@
(sc->temp_throttle_trigger_cnt <<
IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT) |
IMX6_ANALOG_TEMPMON_TEMPSENSE0_MEASURE);
+ imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE2,
+ ((sc->temp_high_val & IMX6_ANALOG_TEMPMON_TEMPSENSE2_VALUE_MASK) <<
+ IMX6_ANALOG_TEMPMON_TEMPSENSE2_PANIC_SHIFT) |
+ (IMX6_ANALOG_TEMPMON_TEMPSENSE2_VALUE_MASK <<
+ IMX6_ANALOG_TEMPMON_TEMPSENSE2_LOW_SHIFT));
/*
* XXX Note that the alarm-interrupt feature isn't working yet, so
diff --git a/sys/arm/freescale/imx/imx6_anatopreg.h b/sys/arm/freescale/imx/imx6_anatopreg.h
--- a/sys/arm/freescale/imx/imx6_anatopreg.h
+++ b/sys/arm/freescale/imx/imx6_anatopreg.h
@@ -112,7 +112,9 @@
#define IMX6_ANALOG_PMU_MISC1_SET 0x164
#define IMX6_ANALOG_PMU_MISC1_CLR 0x168
#define IMX6_ANALOG_PMU_MISC1_TOG 0x16C
-#define IMX6_ANALOG_PMU_MISC1_IRQ_TEMPSENSE (1 << 29)
+#define IMX6_ANALOG_PMU_MISC1_IRQ_TEMPHIGH (1 << 29)
+#define IMX6_ANALOG_PMU_MISC1_IRQ_TEMPLOW (1 << 28)
+#define IMX6_ANALOG_PMU_MISC1_IRQ_TEMPPANIC (1 << 27)
#define IMX6_ANALOG_PMU_MISC2 0x170
#define IMX6_ANALOG_PMU_MISC2_SET 0x174
@@ -153,6 +155,11 @@
#define IMX6_ANALOG_TEMPMON_TEMPSENSE1_CLR 0x198
#define IMX6_ANALOG_TEMPMON_TEMPSENSE1_TOG 0x19C
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE2 0x290
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE2_VALUE_MASK 0xFFF
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE2_PANIC_SHIFT 16
+#define IMX6_ANALOG_TEMPMON_TEMPSENSE2_LOW_SHIFT 0
+
#define IMX6_ANALOG_USB1_VBUS_DETECT 0x1A0
#define IMX6_ANALOG_USB1_VBUS_DETECT_SET 0x1A4
#define IMX6_ANALOG_USB1_VBUS_DETECT_CLR 0x1A8
diff --git a/sys/arm/freescale/imx/imx6_ccm.c b/sys/arm/freescale/imx/imx6_ccm.c
--- a/sys/arm/freescale/imx/imx6_ccm.c
+++ b/sys/arm/freescale/imx/imx6_ccm.c
@@ -51,6 +51,12 @@
#include <arm/freescale/imx/imx_machdep.h>
#include <arm/freescale/imx/imx_ccmvar.h>
+#include <arm/freescale/imx/imx_iomuxvar.h>
+#include <arm/freescale/imx/imx_iomuxreg.h>
+#include <dev/extres/syscon/syscon.h>
+
+#include "syscon_if.h"
+
#ifndef CCGR_CLK_MODE_ALWAYS
#define CCGR_CLK_MODE_OFF 0
#define CCGR_CLK_MODE_RUNMODE 1
@@ -64,6 +70,8 @@
static struct ccm_softc *ccm_sc;
+static int imx6ul_ccm_enet_enable(uint32_t div);
+
static inline uint32_t
RD4(struct ccm_softc *sc, bus_size_t off)
{
@@ -91,41 +99,66 @@
ccm_init_gates(struct ccm_softc *sc)
{
uint32_t reg;
+ u_int soc = imx_soc_type();
- /* ahpbdma, aipstz 1 & 2 buses */
- reg = CCGR0_AIPS_TZ1 | CCGR0_AIPS_TZ2 | CCGR0_ABPHDMA;
+ if (soc == IMXSOC_6UL)
+ reg = 0xffffffff;
+ else
+ /* ahpbdma, aipstz 1 & 2 buses */
+ reg = CCGR1_ENET | CCGR1_EPIT1 | CCGR1_GPT | CCGR1_ECSPI1 |
+ CCGR1_ECSPI2 | CCGR1_ECSPI3 | CCGR1_ECSPI4 | CCGR1_ECSPI5;
WR4(sc, CCM_CCGR0, reg);
- /* enet, epit, gpt, spi */
- reg = CCGR1_ENET | CCGR1_EPIT1 | CCGR1_GPT | CCGR1_ECSPI1 |
- CCGR1_ECSPI2 | CCGR1_ECSPI3 | CCGR1_ECSPI4 | CCGR1_ECSPI5;
+ if (soc == IMXSOC_6UL)
+ reg = 0xffffffff;
+ else
+ /* enet, epit, gpt, spi */
+ reg = CCGR2_I2C1 | CCGR2_I2C2 | CCGR2_I2C3 | CCGR2_IIM |
+ CCGR2_IOMUX_IPT | CCGR2_IPMUX1 | CCGR2_IPMUX2 | CCGR2_IPMUX3 |
+ CCGR2_IPSYNC_IP2APB_TZASC1 | CCGR2_IPSYNC_IP2APB_TZASC2 |
+ CCGR2_IPSYNC_VDOA;
WR4(sc, CCM_CCGR1, reg);
- /* ipmux & ipsync (bridges), iomux, i2c */
- reg = CCGR2_I2C1 | CCGR2_I2C2 | CCGR2_I2C3 | CCGR2_IIM |
- CCGR2_IOMUX_IPT | CCGR2_IPMUX1 | CCGR2_IPMUX2 | CCGR2_IPMUX3 |
- CCGR2_IPSYNC_IP2APB_TZASC1 | CCGR2_IPSYNC_IP2APB_TZASC2 |
- CCGR2_IPSYNC_VDOA;
+ if (soc == IMXSOC_6UL)
+ reg = 0xfc3fffff;
+ else
+ /* ipmux & ipsync (bridges), iomux, i2c */
+ reg = CCGR2_I2C1 | CCGR2_I2C2 | CCGR2_I2C3 | CCGR2_IIM |
+ CCGR2_IOMUX_IPT | CCGR2_IPMUX1 | CCGR2_IPMUX2 | CCGR2_IPMUX3 |
+ CCGR2_IPSYNC_IP2APB_TZASC1 | CCGR2_IPSYNC_IP2APB_TZASC2 |
+ CCGR2_IPSYNC_VDOA;
WR4(sc, CCM_CCGR2, reg);
- /* DDR memory controller */
- reg = CCGR3_OCRAM | CCGR3_MMDC_CORE_IPG |
- CCGR3_MMDC_CORE_ACLK_FAST | CCGR3_CG11 | CCGR3_CG13;
+ if (soc == IMXSOC_6UL)
+ reg = 0xffffffff;
+ else
+ /* DDR memory controller */
+ reg = CCGR3_OCRAM | CCGR3_MMDC_CORE_IPG |
+ CCGR3_MMDC_CORE_ACLK_FAST | CCGR3_CG11 | CCGR3_CG13;
WR4(sc, CCM_CCGR3, reg);
- /* pl301 bus crossbar */
- reg = CCGR4_PL301_MX6QFAST1_S133 |
- CCGR4_PL301_MX6QPER1_BCH | CCGR4_PL301_MX6QPER2_MAIN;
+ if (soc == IMXSOC_6UL)
+ reg = 0xffffffff;
+ else
+ /* pl301 bus crossbar */
+ reg = CCGR4_PL301_MX6QFAST1_S133 |
+ CCGR4_PL301_MX6QPER1_BCH | CCGR4_PL301_MX6QPER2_MAIN;
WR4(sc, CCM_CCGR4, reg);
- /* uarts, ssi, sdma */
- reg = CCGR5_SDMA | CCGR5_SSI1 | CCGR5_SSI2 | CCGR5_SSI3 |
- CCGR5_UART | CCGR5_UART_SERIAL;
+ if (soc == IMXSOC_6UL)
+ reg = 0xffffffff;
+ else
+ /* uarts, ssi, sdma */
+ reg = CCGR5_SDMA | CCGR5_SSI1 | CCGR5_SSI2 | CCGR5_SSI3 |
+ CCGR5_UART | CCGR5_UART_SERIAL;
WR4(sc, CCM_CCGR5, reg);
- /* usdhc 1-4, usboh3 */
- reg = CCGR6_USBOH3 | CCGR6_USDHC1 | CCGR6_USDHC2 |
- CCGR6_USDHC3 | CCGR6_USDHC4;
+ if (soc == IMXSOC_6UL)
+ reg = 0xffffffff;
+ else
+ /* usdhc 1-4, usboh3 */
+ reg = CCGR6_USBOH3 | CCGR6_USDHC1 | CCGR6_USDHC2 |
+ CCGR6_USDHC3 | CCGR6_USDHC4;
WR4(sc, CCM_CCGR6, reg);
}
@@ -202,8 +235,9 @@
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (ofw_bus_is_compatible(dev, "fsl,imx6q-ccm") == 0)
- return (ENXIO);
+ if (ofw_bus_is_compatible(dev, "fsl,imx6q-ccm") == 0)
+ if (ofw_bus_is_compatible(dev, "fsl,imx6ul-ccm") == 0)
+ return (ENXIO);
device_set_desc(dev, "Freescale i.MX6 Clock Control Module");
@@ -317,6 +351,67 @@
#endif
}
+int
+imx6ul_ccm_enet_set50(void)
+{
+ return imx6ul_ccm_enet_enable(CCM_ANALOG_PLL_ENET0_DIV_SELECT_50);
+}
+
+/*
+ * XXX This is really only for board designs that use the ENET_REF
+ * clock as a 50MHz output to drive the (presumably RMII) PHY.
+ * For MII or RGMII, something very different will need to happen.
+ */
+static int
+imx6ul_ccm_enet_enable(uint32_t div)
+{
+ uint32_t v;
+ int timeout;
+ phandle_t gpr_node;
+
+ gpr_node = ofw_bus_find_compatible(OF_finddevice("/"), "fsl,imx6ul-iomuxc-gpr");
+ if (gpr_node) {
+ struct syscon *gpr;
+
+ if (syscon_get_by_ofw_node(ccm_sc->dev, gpr_node, &gpr) == 0) {
+ SYSCON_MODIFY_4(gpr, IOMUXC_GPR1, IOMUXC_GPR1_ENET1_CLK_SEL, IOMUXC_GPR1_ENET1_TX_CLK_DIR);
+ }
+ }
+
+ v = RD4(ccm_sc, CCM_ANALOG_PLL_ENET);
+
+ /* Power up the PLL that feeds ENET phys. */
+ if (v & CCM_ANALOG_PLL_ENET_POWERDOWN) {
+ v &= ~CCM_ANALOG_PLL_ENET_POWERDOWN;
+ WR4(ccm_sc, CCM_ANALOG_PLL_ENET, v);
+ }
+
+ /* Wait for lock. */
+ if (!(v & CCM_ANALOG_PLL_ENET_LOCK)) {
+ for (timeout = 100000; timeout > 0; timeout--) {
+ if ((v = RD4(ccm_sc, CCM_ANALOG_PLL_ENET)) &
+ CCM_ANALOG_PLL_ENET_LOCK) {
+ break;
+ }
+ }
+ if (timeout <= 0)
+ return ETIMEDOUT;
+ }
+
+ /* Enable the PLL */
+ v |= CCM_ANALOG_PLL_ENET_ENABLE;
+ v &= ~CCM_ANALOG_PLL_ENET_BYPASS;
+ v &= ~(CCM_ANALOG_PLL_ENET0_DIV_MASK | CCM_ANALOG_PLL_ENET1_DIV_MASK);
+ v |= div;
+ WR4(ccm_sc, CCM_ANALOG_PLL_ENET, v);
+ /* Set up as output to PHY */
+
+ /* Un-gate the enet controller. */
+ WR4(ccm_sc, CCM_CCGR3, RD4(ccm_sc, CCM_CCGR3) | CCGR3_UL_ENET);
+
+ return 0;
+}
+
int
imx6_ccm_sata_enable(void)
{
@@ -495,7 +590,6 @@
void
imx_ccm_set_cacrr(uint32_t divisor)
{
-
WR4(ccm_sc, CCM_CACCR, divisor);
}
diff --git a/sys/arm/freescale/imx/imx6_ccmreg.h b/sys/arm/freescale/imx/imx6_ccmreg.h
--- a/sys/arm/freescale/imx/imx6_ccmreg.h
+++ b/sys/arm/freescale/imx/imx6_ccmreg.h
@@ -82,24 +82,34 @@
#define CCGR0_AIPS_TZ1 (0x3 << 0)
#define CCGR0_AIPS_TZ2 (0x3 << 2)
#define CCGR0_ABPHDMA (0x3 << 4)
+#define CCGR0_UL_UART2 (0x3 << 28)
#define CCM_CCGR1 0x06C
#define CCGR1_ECSPI1 (0x3 << 0)
#define CCGR1_ECSPI2 (0x3 << 2)
#define CCGR1_ECSPI3 (0x3 << 4)
#define CCGR1_ECSPI4 (0x3 << 6)
+#define CCGR1_UL_ADC2 (0x3 << 8)
#define CCGR1_ECSPI5 (0x3 << 8)
+#define CCGR1_UL_UART3 (0x3 << 10)
#define CCGR1_ENET (0x3 << 10)
#define CCGR1_EPIT1 (0x3 << 12)
#define CCGR1_EPIT2 (0x3 << 14)
+#define CCGR1_UL_ADC1 (0x3 << 16)
#define CCGR1_ESAI (0x3 << 16)
+#define CCGR1_SIM_S (0x3 << 18)
#define CCGR1_GPT (0x3 << 20)
#define CCGR1_GPT_SERIAL (0x3 << 22)
+#define CCGR1_UL_UART4 (0x3 << 24)
+#define CCGR1_UL_GPIO1 (0x3 << 26)
+#define CCGR1_UL_CSU (0x3 << 28)
+#define CCGR1_UL_GPIO5 (0x3 << 30)
#define CCM_CCGR2 0x070
#define CCGR2_HDMI_TX (0x3 << 0)
#define CCGR2_HDMI_TX_ISFR (0x3 << 4)
#define CCGR2_I2C1 (0x3 << 6)
#define CCGR2_I2C2 (0x3 << 8)
#define CCGR2_I2C3 (0x3 << 10)
+#define CCGR2_UL_OCOTP (0x3 << 12)
#define CCGR2_IIM (0x3 << 12)
#define CCGR2_IOMUX_IPT (0x3 << 14)
#define CCGR2_IPMUX1 (0x3 << 16)
@@ -107,39 +117,62 @@
#define CCGR2_IPMUX3 (0x3 << 20)
#define CCGR2_IPSYNC_IP2APB_TZASC1 (0x3 << 22)
#define CCGR2_IPSYNC_IP2APB_TZASC2 (0x3 << 24)
+#define CCGR2_UL_GPIO3 (0x3 << 26)
#define CCGR2_IPSYNC_VDOA (0x3 << 26)
#define CCM_CCGR3 0x074
+#define CCGR3_UL_CSI_MCLK (0x3 << 0)
#define CCGR3_IPU1_IPU (0x3 << 0)
+#define CCGR3_UL_UART5 (0x3 << 2)
#define CCGR3_IPU1_DI0 (0x3 << 2)
+#define CCGR3_UL_ENET (0x3 << 4)
#define CCGR3_IPU1_DI1 (0x3 << 4)
+#define CCGR3_UL_UART6 (0x3 << 6)
#define CCGR3_IPU2_IPU (0x3 << 6)
+#define CCGR3_UL_CA7_CCM_DAP (0x3 << 8)
#define CCGR3_IPU2_DI0 (0x3 << 8)
+#define CCGR3_UL_LCDIF1 (0x3 << 10)
#define CCGR3_IPU2_DI1 (0x3 << 10)
+#define CCGR3_UL_GPIO4 (0x3 << 12)
#define CCGR3_LDB_DI0 (0x3 << 12)
+#define CCGR3_UL_QSPI1 (0x3 << 14)
#define CCGR3_LDB_DI1 (0x3 << 14)
+#define CCGR3_UL_WDOG1 (0x3 << 16)
#define CCGR3_MMDC_CORE_ACLK_FAST (0x3 << 20)
#define CCGR3_CG11 (0x3 << 22)
#define CCGR3_MMDC_CORE_IPG (0x3 << 24)
#define CCGR3_CG13 (0x3 << 26)
#define CCGR3_OCRAM (0x3 << 28)
#define CCM_CCGR4 0x078
+#define CCGR4_UL_IOMUXC (0x3 << 2)
+#define CCGR4_UL_IOMUXC_GPR (0x3 << 4)
+#define CCGR4_UL_SIM_CPU (0x3 << 6)
+#define CCGR4_UL_CXAPBSYNCBRIDGE_SLAVE (0x3 << 8)
#define CCGR4_PL301_MX6QFAST1_S133 (0x3 << 8)
+#define CCGR4_UL_TSC_DIG (0x3 << 10)
#define CCGR4_PL301_MX6QPER1_BCH (0x3 << 12)
#define CCGR4_PL301_MX6QPER2_MAIN (0x3 << 14)
#define CCM_CCGR5 0x07C
#define CCGR5_SATA (0x3 << 4)
#define CCGR5_SDMA (0x3 << 6)
+#define CCGR5_UL_WDOG2 (0x3 << 10)
+#define CCGR5_UL_SIM_MAIN (0x3 << 16)
#define CCGR5_SSI1 (0x3 << 18)
#define CCGR5_SSI2 (0x3 << 20)
#define CCGR5_SSI3 (0x3 << 22)
+#define CCGR5_UL_UART1 (0x3 << 24)
#define CCGR5_UART (0x3 << 24)
+#define CCGR5_UL_UART7 (0x3 << 26)
#define CCGR5_UART_SERIAL (0x3 << 26)
#define CCM_CCGR6 0x080
#define CCGR6_USBOH3 (0x3 << 0)
#define CCGR6_USDHC1 (0x3 << 2)
#define CCGR6_USDHC2 (0x3 << 4)
+#define CCGR6_UL_SIM1 (0x3 << 6)
#define CCGR6_USDHC3 (0x3 << 6)
+#define CCGR6_UL_SIM2 (0x3 << 8)
#define CCGR6_USDHC4 (0x3 << 8)
+#define CCGR6_UL_UART8 (0x3 << 14)
+#define CCGR6_UL_WDOG3 (0x3 << 20)
#define CCM_CMEOR 0x088
#define CCM_ANALOG_PLL_VIDEO 0x000040a0
@@ -157,9 +190,20 @@
#define CCM_ANALOG_PLL_ENET 0x000040e0
#define CCM_ANALOG_PLL_ENET_LOCK (1u << 31)
+#define CCM_ANALOG_PLL_ENET25 (1u << 21)
#define CCM_ANALOG_PLL_ENET_ENABLE_100M (1u << 20) /* SATA */
#define CCM_ANALOG_PLL_ENET_BYPASS (1u << 16)
#define CCM_ANALOG_PLL_ENET_ENABLE (1u << 13) /* Ether */
#define CCM_ANALOG_PLL_ENET_POWERDOWN (1u << 12)
+#define CCM_ANALOG_PLL_ENET1_DIV_SELECT_25 (0u << 2)
+#define CCM_ANALOG_PLL_ENET1_DIV_SELECT_50 (1u << 2)
+#define CCM_ANALOG_PLL_ENET1_DIV_SELECT_100 (2u << 2)
+#define CCM_ANALOG_PLL_ENET1_DIV_SELECT_125 (3u << 2)
+#define CCM_ANALOG_PLL_ENET1_DIV_MASK (3u << 2)
+#define CCM_ANALOG_PLL_ENET0_DIV_SELECT_25 (0u)
+#define CCM_ANALOG_PLL_ENET0_DIV_SELECT_50 (1u)
+#define CCM_ANALOG_PLL_ENET0_DIV_SELECT_100 (2u)
+#define CCM_ANALOG_PLL_ENET0_DIV_SELECT_125 (3u)
+#define CCM_ANALOG_PLL_ENET0_DIV_MASK (3u)
#endif
diff --git a/sys/arm/freescale/imx/imx_ccmvar.h b/sys/arm/freescale/imx/imx_ccmvar.h
--- a/sys/arm/freescale/imx/imx_ccmvar.h
+++ b/sys/arm/freescale/imx/imx_ccmvar.h
@@ -58,6 +58,7 @@
void imx_ccm_hdmi_enable(void);
void imx_ccm_ipu_enable(int ipu);
int imx6_ccm_sata_enable(void);
+int imx6ul_ccm_enet_set50(void);
/* Routines to get and set the arm clock root divisor register. */
uint32_t imx_ccm_get_cacrr(void);
diff --git a/sys/arm/freescale/imx/imx_epit.c b/sys/arm/freescale/imx/imx_epit.c
--- a/sys/arm/freescale/imx/imx_epit.c
+++ b/sys/arm/freescale/imx/imx_epit.c
@@ -374,7 +374,8 @@
bus_free_resource(dev, SYS_RES_MEMORY, memres);
if (imx_soc_family() == 6) {
- if (unit > 0)
+ // Having a second EPIT allows using it for kern.timecounter
+ if (unit > 1)
return (ENXIO);
if (ioaddr != imx6_epit_ioaddr[unit])
return (ENXIO);
diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c
--- a/sys/arm/freescale/imx/imx_gpio.c
+++ b/sys/arm/freescale/imx/imx_gpio.c
@@ -134,6 +134,7 @@
static struct ofw_compat_data compat_data[] = {
{"fsl,imx8mq-gpio", 1},
{"fsl,imx6q-gpio", 1},
+ {"fsl,imx6ul-gpio", 1},
{"fsl,imx53-gpio", 1},
{"fsl,imx51-gpio", 1},
{NULL, 0}
diff --git a/sys/arm/freescale/imx/imx_iomuxreg.h b/sys/arm/freescale/imx/imx_iomuxreg.h
--- a/sys/arm/freescale/imx/imx_iomuxreg.h
+++ b/sys/arm/freescale/imx/imx_iomuxreg.h
@@ -38,6 +38,8 @@
#define IOMUXC_GPR0 0x00
#define IOMUXC_GPR1 0x04
+#define IOMUXC_GPR1_ENET1_CLK_SEL (1u << 13)
+#define IOMUXC_GPR1_ENET1_TX_CLK_DIR (1u << 17)
#define IOMUXC_GPR2 0x08
#define IOMUXC_GPR3 0x0C
#define IOMUXC_GPR3_HDMI_MASK (3 << 2)
diff --git a/sys/arm/freescale/vybrid/vf_adc.c b/sys/arm/freescale/vybrid/vf_adc.c
--- a/sys/arm/freescale/vybrid/vf_adc.c
+++ b/sys/arm/freescale/vybrid/vf_adc.c
@@ -132,7 +132,8 @@
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "fsl,mvf600-adc"))
- return (ENXIO);
+ if (!ofw_bus_is_compatible(dev, "fsl,vf610-adc"))
+ return (ENXIO);
device_set_desc(dev, "Vybrid Family "
"12-bit Analog to Digital Converter");
diff --git a/sys/contrib/device-tree/src/arm/sbc_ec9100.dts b/sys/contrib/device-tree/src/arm/sbc_ec9100.dts
new file mode 100755
--- /dev/null
+++ b/sys/contrib/device-tree/src/arm/sbc_ec9100.dts
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx6ul.dtsi"
+
+/ {
+ model = "Embest SBC-EC9100 Board (i.MX6 UltraLite 14x14) ";
+ compatible = "fsl,embest_evk_ec9100", "fsl,imx6ul";
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ memory {
+ reg = <0x80000000 0x20000000>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led1 {
+ label = "system_leds";
+ gpios = <&gpio1 19 1>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
+
+&cpu0 {
+ arm-supply = <®_arm>;
+ soc-supply = <®_soc>;
+ clock-frequency = <528000000>;
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&gpc {
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+ dmas = <&sdma 29 4 0>, <&sdma 30 4 2>;
+ dma-names = "rx", "tx";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ cd-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
+ wp-disable;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ status = "okay";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-mode = "rmii";
+ phy-handle = <ðphy0>;
+ status = "okay";
+ // Deprecated
+ //phy-reset-gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+ //phy-reset-duration = <1>;
+ //phy-reset-postdelay = <1>;
+ // This appears to be a FreeBSD extension.
+ //phy-disable-preamble;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ suppress-preamble;
+
+ ethphy0: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <2>;
+ micrel,led-mode = <1>;
+ clocks = <&clks IMX6UL_CLK_ENET_REF>;
+ clock-names = "rmii-ref";
+ max-speed = <100>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <500>;
+ reset-deassert-us = <100>;
+ };
+ };
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ status = "okay";
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ fsl,uart-has-rtscts;
+ cts-gpio = <&gpio1 18 0>;
+ status = "okay";
+ linux,rs485-enabled-at-boot-time;
+ dmas = <&sdma 25 4 0>, <&sdma 26 4 2>;
+ dma-names = "rx", "tx";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ no-1-8-v;
+ non-removable;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze3000@8 {
+ compatible = "fsl,pfuze3001";
+ reg = <0x08>;
+ fsl,pfuze-support-disable-sw;
+
+ regulators {
+ // A7 part defaults to 1.4
+ sw1a_reg: sw1a {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ // A7 part defaults to 1.4
+ /* use sw1c_reg to align with pfuze100/pfuze200 */
+ sw1c_reg: sw1b {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ // A7 part defaults to 3.3
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ // A7 part defaults to 1.35
+ sw3a_reg: sw3 {
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ // TODO: Verify this... reset etc.
+ // It looks like this actually needs to be at least 3
+ // A7 part defaults to 3.0
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ // A7 part defaults to 3.3
+ vgen1_reg: vldo1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ // Not connected in schematic
+ // A7 part defaults to 1.5 (OFF)
+ vgen2_reg: vldo2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ // Was 1V8, 3V3 on schematic
+ // A7 part defaults to 3.3/1.85 depending on strapping
+ vgen3_reg: vccsd {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ // A7 part defaults to 3.3
+ vgen4_reg: v33 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ // Was 3V3, despite schematic, but has nothing on it.
+ // (Is for WiFi which is DNP)
+ // A7 part defaults to 1.8 (OFF)
+ vgen5_reg: vldo3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ // Nothing in schemtatic, but listed as 3V3
+ // A7 part defaults to 1.8
+ vgen6_reg: vldo4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+
+ // Serial EEPROM
+ at24@50 {
+ compatible = "at24,24c256";
+ pagesize = <64>;
+ reg = <0x50>;
+ };
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+ dmas = <&sdma 27 4 0>, <&sdma 28 4 2>;
+ dma-names = "rx", "tx";
+};
+
+&usbotg1 {
+ dr_mode = "otg";
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&adc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc1>;
+ status = "okay";
+ vref-supply = <&vgen1_reg>;
+ adc-ch-list = <4>;
+};
+
+&aips2 {
+ adc2: adc@219c000 {
+ compatible = "fsl,imx6ul-adc", "fsl,vf610-adc";
+ reg = <0x0219c000 0x4000>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ADC2>;
+ clock-names = "adc";
+ fsl,adck-max-frequency = <30000000>, <40000000>,
+ <20000000>;
+ status = "disabled";
+ };
+};
+
+&adc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc2>;
+ status = "okay";
+ vref-supply = <&vgen1_reg>;
+ adc-ch-list = <5>;
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+ imx6ul-evk {
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0 /*reset gpio*/
+ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x80000000 /*cs-gpio*/
+ MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x17059 /* GPIO EX */
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 /* GPIO/PWM2*/
+ MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x80000000 /* LED */
+ MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x80000000
+ MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0 // tsc
+ >;
+ };
+
+ pinctrl_csi1: csi1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_MCLK__CSI_MCLK 0x1b088
+ MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK 0x1b088
+ MX6UL_PAD_CSI_VSYNC__CSI_VSYNC 0x1b088
+ MX6UL_PAD_CSI_HSYNC__CSI_HSYNC 0x1b088
+ MX6UL_PAD_CSI_DATA00__CSI_DATA02 0x1b088
+ MX6UL_PAD_CSI_DATA01__CSI_DATA03 0x1b088
+ MX6UL_PAD_CSI_DATA02__CSI_DATA04 0x1b088
+ MX6UL_PAD_CSI_DATA03__CSI_DATA05 0x1b088
+ MX6UL_PAD_CSI_DATA04__CSI_DATA06 0x1b088
+ MX6UL_PAD_CSI_DATA05__CSI_DATA07 0x1b088
+ MX6UL_PAD_CSI_DATA06__CSI_DATA08 0x1b088
+ MX6UL_PAD_CSI_DATA07__CSI_DATA09 0x1b088
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x17059 /* SD1 CD */
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0xa8e8
+ /* These were all 0x1b0b0 */
+ MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0xa0e9
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b010
+ // Needs to have sion bit for Linux... 0x4001b031
+ //MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x1b031
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
+ MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
+ MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x80000000 /* PHY Reset (Active Low with pull-up) */
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp{
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
+ MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp{
+ fsl,pins = <
+ MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x1b020
+ MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x1b020
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
+ /* MX6UL_PAD_UART1_CTS_B__UART1_DCE_CTS 0x1b0b1*/
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+ MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
+ MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
+ MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
+ MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001b8b0
+ MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79
+ MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79
+ MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79
+ MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79
+ MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79
+ MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79
+ MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79
+ MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79
+ MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x79
+ MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x79
+ MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x79
+ MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x79
+ MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x79
+ MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x79
+ MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x79
+ MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x79
+ MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x79
+ MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x79
+ MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x79
+ MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x79
+ MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x79
+ MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x79
+ MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x79
+ MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x79
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x79
+ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79
+ MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79
+ MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79
+ >;
+ };
+
+ pinctrl_ecspi2_1: ecspi2grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_UART5_TX_DATA__ECSPI2_MOSI 0x0b0b0 /* CSPI_MOSI */
+ MX6UL_PAD_UART5_RX_DATA__ECSPI2_MISO 0x0b0b0 /* CSPI_MISO */
+ MX6UL_PAD_UART4_TX_DATA__ECSPI2_SCLK 0x0b0b0 /* CSPI_SCLK */
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO08__PWM1_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_adc1: adc1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
+ >;
+ };
+
+ pinctrl_adc2: adc2grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO05__GPIO1_IO05 0xb0
+ >;
+ };
+ };
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&snvs_pwrkey {
+ status = "okay";
+};
+
+&gpt2 {
+ status = "okay";
+};
diff --git a/sys/dev/cpufreq/cpufreq_dt.c b/sys/dev/cpufreq/cpufreq_dt.c
--- a/sys/dev/cpufreq/cpufreq_dt.c
+++ b/sys/dev/cpufreq/cpufreq_dt.c
@@ -500,6 +500,11 @@
else if (regulator_get_by_ofw_property(dev, node, "cpu0-supply",
&sc->reg) == 0)
device_printf(dev, "Found cpu0-supply\n");
+ else if (regulator_get_by_ofw_property(dev, node, "arm-supply",
+ &sc->reg) == 0)
+ device_printf(dev, "Found arm-supply\n");
+ else
+ device_printf(dev, "No regulator found\n");
/*
* Determine which operating mode we're in. Error out if we expect
diff --git a/sys/dev/ffec/if_ffec.c b/sys/dev/ffec/if_ffec.c
--- a/sys/dev/ffec/if_ffec.c
+++ b/sys/dev/ffec/if_ffec.c
@@ -89,6 +89,11 @@
#include <dev/mii/mii_fdt.h>
#include "miibus_if.h"
+#ifdef SOC_IMX6
+#include <arm/freescale/imx/imx_ccmvar.h>
+#include <arm/freescale/imx/imx_machdep.h>
+#endif
+
/*
* There are small differences in the hardware on various SoCs. Not every SoC
* we support has its own FECTYPE; most work as GENERIC and only the ones that
@@ -363,6 +368,29 @@
return (0);
}
+static void
+ffec_rcr_phy_flags(uint32_t *rcr, mii_contype_t t)
+{
+ switch (t) {
+ case MII_CONTYPE_MII:
+ *rcr |= FEC_RCR_MII_MODE;
+ break;
+ case MII_CONTYPE_RMII:
+ *rcr |= FEC_RCR_MII_MODE; /* Must always be on even for R[G]MII. */
+ *rcr |= FEC_RCR_RMII_MODE;
+ break;
+ case MII_CONTYPE_RGMII:
+ case MII_CONTYPE_RGMII_ID:
+ case MII_CONTYPE_RGMII_RXID:
+ case MII_CONTYPE_RGMII_TXID:
+ *rcr |= FEC_RCR_MII_MODE; /* Must always be on even for R[G]MII. */
+ *rcr |= FEC_RCR_RGMII_EN;
+ break;
+ default:
+ break;
+ }
+}
+
static void
ffec_miibus_statchg(device_t dev)
{
@@ -391,20 +419,7 @@
FEC_RCR_RGMII_EN | FEC_RCR_DRT | FEC_RCR_FCE);
tcr = RD4(sc, FEC_TCR_REG) & ~FEC_TCR_FDEN;
- rcr |= FEC_RCR_MII_MODE; /* Must always be on even for R[G]MII. */
- switch (sc->phy_conn_type) {
- case MII_CONTYPE_RMII:
- rcr |= FEC_RCR_RMII_MODE;
- break;
- case MII_CONTYPE_RGMII:
- case MII_CONTYPE_RGMII_ID:
- case MII_CONTYPE_RGMII_RXID:
- case MII_CONTYPE_RGMII_TXID:
- rcr |= FEC_RCR_RGMII_EN;
- break;
- default:
- break;
- }
+ ffec_rcr_phy_flags(&rcr, sc->phy_conn_type);
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_1000_T:
@@ -420,6 +435,8 @@
case IFM_NONE:
sc->link_is_up = false;
return;
+ case IFM_AUTO:
+ break;
default:
sc->link_is_up = false;
device_printf(dev, "Unsupported media %u\n",
@@ -1154,7 +1171,9 @@
*
* Set max frame length + clean out anything left from u-boot.
*/
- WR4(sc, FEC_RCR_REG, (maxfl << FEC_RCR_MAX_FL_SHIFT));
+ regval = (maxfl << FEC_RCR_MAX_FL_SHIFT);
+ ffec_rcr_phy_flags(®val, sc->phy_conn_type);
+ WR4(sc, FEC_RCR_REG, regval);
/*
* TCR - Transmit control register.
@@ -1471,8 +1490,10 @@
if_t ifp = NULL;
struct mbuf *m;
void *dummy;
+ char *name;
uintptr_t typeflags;
phandle_t ofw_node;
+ phandle_t mdio_node;
uint32_t idx, mscr;
int error, phynum, rid, irq;
uint8_t eaddr[ETHER_ADDR_LEN];
@@ -1514,6 +1535,12 @@
error = ENOATTR;
goto out;
}
+#ifdef SOC_IMX6
+ /* Enable 50MHz ENET_REF output clock */
+ if ((imx_soc_type() == IMXSOC_6UL) &&
+ sc->phy_conn_type == MII_CONTYPE_RMII)
+ imx6ul_ccm_enet_set50();
+#endif
callout_init_mtx(&sc->ffec_callout, &sc->mtx, 0);
@@ -1734,6 +1761,30 @@
if (bootverbose)
device_printf(dev, "PHY preamble disabled\n");
}
+ /*
+ * Now look for the documented mdio.suppress-preamble...
+ * this is allowed to be named mdio@<addr>
+ */
+ for (mdio_node = OF_child(ofw_node); mdio_node != 0; mdio_node = OF_peer(mdio_node)) {
+ if (OF_getprop_alloc(mdio_node, "name", (void **)&name) != -1) {
+ if (strcmp(name, "mdio") == 0) {
+ free(name, M_OFWPROP);
+ break;
+ }
+ if (strncmp(name, "mdio@", 5) == 0) {
+ free(name, M_OFWPROP);
+ break;
+ }
+ free(name, M_OFWPROP);
+ }
+ }
+ if (mdio_node != 0) {
+ if (OF_hasprop(mdio_node, "suppress-preamble")) {
+ mscr |= FEC_MSCR_DIS_PRE;
+ if (bootverbose)
+ device_printf(dev, "PHY preamble disabled\n");
+ }
+ }
WR4(sc, FEC_MSCR_REG, mscr);
/* Set up the ethernet interface. */
@@ -1759,6 +1810,11 @@
/* Set up the miigasket hardware (if any). */
ffec_miigasket_setup(sc);
+ /* RCR - Receive control register. */
+ uint32_t regval = RD4(sc, FEC_RCR_REG);
+ ffec_rcr_phy_flags(®val, sc->phy_conn_type);
+ WR4(sc, FEC_RCR_REG, regval);
+
/* Attach the mii driver. */
if (fdt_get_phyaddr(ofw_node, dev, &phynum, &dummy) != 0) {
phynum = MII_PHY_ANY;
diff --git a/sys/dev/mii/micphy.c b/sys/dev/mii/micphy.c
--- a/sys/dev/mii/micphy.c
+++ b/sys/dev/mii/micphy.c
@@ -60,6 +60,7 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/mii/mii_fdt.h>
+#include <dev/gpio/gpiobusvar.h>
#define MII_KSZPHY_EXTREG 0x0b
#define KSZPHY_EXTREG_WRITE (1 << 15)
@@ -78,9 +79,20 @@
#define MII_KSZ9031_CLOCK_PAD_SKEW 0x8
#define MII_KSZ8081_PHYCTL2 0x1f
+#define MII_KSZ8081_PHYCTL2_LED_SHIFT 4
+#define MII_KSZ8081_PHYCTL2_LED_MASK (3 << MII_KSZ8081_PHYCTL2_LED_SHIFT)
+#define MII_KSZ8081_PHYCTL2_50MHZ_RMII (1 << 7)
#define PS_TO_REG(p) ((p) / 200)
+struct micphy_softc {
+ struct mii_softc mii_softc;
+ mii_fdt_phy_config_t *cfg;
+ device_t dev;
+ uint16_t ctrl2_set_bits;
+ uint16_t ctrl2_clr_bits;
+};
+
static int micphy_probe(device_t);
static int micphy_attach(device_t);
static void micphy_reset(struct mii_softc *);
@@ -98,7 +110,7 @@
static driver_t micphy_driver = {
"micphy",
micphy_methods,
- sizeof(struct mii_softc)
+ sizeof(struct micphy_softc)
};
DRIVER_MODULE(micphy, miibus, micphy_driver, 0, 0);
@@ -247,36 +259,69 @@
return (mii_phy_dev_probe(dev, micphys, BUS_PROBE_DEFAULT));
}
+static void
+micphy_get_ctrl2_bits(struct micphy_softc *msc)
+{
+ pcell_t val;
+
+ msc->ctrl2_set_bits = 0;
+ msc->ctrl2_clr_bits = 0;
+
+ if (msc->cfg) {
+ if (msc->cfg->phynode != -1) {
+ if (OF_getencprop(msc->cfg->phynode, "micrel,led-mode", &val, sizeof(val)) > 0) {
+ msc->ctrl2_set_bits |= (val << MII_KSZ8081_PHYCTL2_LED_SHIFT) &
+ MII_KSZ8081_PHYCTL2_LED_MASK;
+ msc->ctrl2_clr_bits |= MII_KSZ8081_PHYCTL2_LED_MASK;
+ }
+ }
+ /*
+ * Assume a 50MHz clock for RMII, for everything else,
+ * assume the defaults are fine, or the bootloader set
+ * them up properly.
+ */
+ if (msc->cfg->con_type == MII_CONTYPE_RMII) {
+ msc->ctrl2_set_bits |= MII_KSZ8081_PHYCTL2_50MHZ_RMII;
+ }
+ }
+}
+
static int
micphy_attach(device_t dev)
{
- mii_fdt_phy_config_t *cfg;
+ struct micphy_softc *msc;
struct mii_softc *sc;
phandle_t node;
device_t miibus;
device_t parent;
- sc = device_get_softc(dev);
+ msc = device_get_softc(dev);
+ sc = &msc->mii_softc;
+ msc->dev = dev;
mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &micphy_funcs, 1);
mii_phy_setmedia(sc);
- /* Nothing further to configure for 8081 model. */
- if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ8081)
- return (0);
-
miibus = device_get_parent(dev);
parent = device_get_parent(miibus);
if ((node = ofw_bus_get_node(parent)) == -1)
return (ENXIO);
- cfg = mii_fdt_get_config(dev);
+ msc->cfg = mii_fdt_get_config(dev);
+ micphy_get_ctrl2_bits(msc);
+
+ if (msc->cfg && msc->cfg->reset_gpio)
+ micphy_reset(sc);
+
+ /* Nothing further to configure for 8081 model. */
+ if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ8081)
+ return (0);
if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ9031)
- ksz9031_load_values(sc, cfg->phynode);
+ ksz9031_load_values(sc, msc->cfg->phynode);
else
- ksz9021_load_values(sc, cfg->phynode);
+ ksz9021_load_values(sc, msc->cfg->phynode);
return (0);
}
@@ -285,6 +330,8 @@
micphy_reset(struct mii_softc *sc)
{
int reg;
+ int rc;
+ struct micphy_softc *msc = (struct micphy_softc *)sc;
/*
* The 8081 has no "sticky bits" that survive a soft reset; several bits
@@ -292,11 +339,32 @@
* These bits are set up by the bootloader; they control how the phy
* interfaces to the board (such as clock frequency and LED behavior).
*/
- if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ8081)
+ if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ8081) {
reg = PHY_READ(sc, MII_KSZ8081_PHYCTL2);
- mii_phy_reset(sc);
- if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ8081)
+ if (reg == 0xffff)
+ reg = 0x8100;
+ }
+ if (msc->cfg && msc->cfg->reset_gpio) {
+ rc = gpio_pin_set_active(msc->cfg->reset_gpio, true);
+ if (rc) {
+ device_printf(msc->dev, "Failed to set reset pin active: %d\n", rc);
+ }
+ DELAY(msc->cfg->reset_assert_us);
+ if (rc == 0 && gpio_pin_set_active(msc->cfg->reset_gpio, false)) {
+ device_printf(msc->dev, "Failed to set reset pin inactive: %d\n", rc);
+ }
+ DELAY(msc->cfg->reset_deassert_us);
+ }
+ else
+ {
+ mii_phy_reset(sc);
+ }
+
+ if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ8081) {
+ reg &= ~msc->ctrl2_clr_bits;
+ reg |= msc->ctrl2_set_bits;
PHY_WRITE(sc, MII_KSZ8081_PHYCTL2, reg);
+ }
}
static int
diff --git a/sys/dev/mii/mii_fdt.h b/sys/dev/mii/mii_fdt.h
--- a/sys/dev/mii/mii_fdt.h
+++ b/sys/dev/mii/mii_fdt.h
@@ -42,6 +42,9 @@
mii_contype_t con_type; /* MAC<->PHY connection type */
u_int max_speed; /* Mbits/sec, 0 = not specified */
uint32_t flags; /* MIIF_FDT_xxx boolean properties */
+ struct gpiobus_pin *reset_gpio;
+ uint32_t reset_assert_us;
+ uint32_t reset_deassert_us;
};
typedef struct mii_fdt_phy_config mii_fdt_phy_config_t;
diff --git a/sys/dev/mii/mii_fdt.c b/sys/dev/mii/mii_fdt.c
--- a/sys/dev/mii/mii_fdt.c
+++ b/sys/dev/mii/mii_fdt.c
@@ -38,6 +38,7 @@
#include <sys/socket.h>
#include <sys/bus.h>
#include <sys/malloc.h>
+#include <sys/gpio.h>
#include <net/if.h>
#include <net/if_media.h>
@@ -45,6 +46,7 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/gpio/gpiobusvar.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
@@ -176,7 +178,10 @@
void
mii_fdt_free_config(struct mii_fdt_phy_config *cfg)
{
-
+ if (cfg->reset_gpio) {
+ gpiobus_release_pin(GPIO_GET_BUS(cfg->reset_gpio->dev), cfg->reset_gpio->pin);
+ free(cfg->reset_gpio, M_DEVBUF);
+ }
free(cfg, M_OFWPROP);
}
@@ -187,6 +192,7 @@
mii_fdt_phy_config_t *cfg;
device_t miibus, macdev;
pcell_t val;
+ int rc;
ma = device_get_ivars(phydev);
miibus = device_get_parent(phydev);
@@ -202,6 +208,21 @@
return (cfg);
cfg->con_type = mii_fdt_get_contype(cfg->macnode);
+ if (OF_hasprop(cfg->macnode, "phy-reset-gpios")) {
+ rc = gpio_pin_get_by_ofw_property(phydev, cfg->macnode, "phy-reset-gpios",
+ &cfg->reset_gpio);
+ if (rc == 0) {
+ gpio_pin_setflags(cfg->reset_gpio, GPIO_PIN_OUTPUT);
+ gpio_pin_set_active(cfg->reset_gpio, true);
+ if (OF_getencprop(cfg->phynode, "phy-reset-duration", &val, sizeof(val)) > 0)
+ cfg->reset_assert_us = val * 1000;
+ else {
+ cfg->reset_assert_us = 1000;
+ }
+ if (OF_getencprop(cfg->phynode, "phy-reset-postdelay", &val, sizeof(val)) > 0)
+ cfg->reset_assert_us = val * 1000;
+ }
+ }
/*
* If we can't find our own PHY node, there's nothing more we can fill
@@ -236,6 +257,23 @@
cfg->flags |= MIIF_FDT_EEE_BROKEN_10GKX4;
if (OF_hasprop(cfg->phynode, "eee-broken-10gkr"))
cfg->flags |= MIIF_FDT_EEE_BROKEN_10GKR;
+ if (OF_hasprop(cfg->phynode, "reset-gpios")) {
+ if (cfg->reset_gpio) {
+ gpiobus_release_pin(GPIO_GET_BUS(cfg->reset_gpio->dev), cfg->reset_gpio->pin);
+ free(cfg->reset_gpio, M_DEVBUF);
+ cfg->reset_gpio = NULL;
+ }
+ rc = gpio_pin_get_by_ofw_property(phydev, cfg->phynode, "reset-gpios",
+ &cfg->reset_gpio);
+ if (rc == 0) {
+ gpio_pin_setflags(cfg->reset_gpio, GPIO_PIN_OUTPUT);
+ gpio_pin_set_active(cfg->reset_gpio, true);
+ if (OF_getencprop(cfg->phynode, "reset-assert-us", &val, sizeof(val)) > 0)
+ cfg->reset_assert_us = val;
+ if (OF_getencprop(cfg->phynode, "reset-deassert-us", &val, sizeof(val)) > 0)
+ cfg->reset_deassert_us = val;
+ }
+ }
return (cfg);
}
diff --git a/sys/dev/sdhci/fsl_sdhci.c b/sys/dev/sdhci/fsl_sdhci.c
--- a/sys/dev/sdhci/fsl_sdhci.c
+++ b/sys/dev/sdhci/fsl_sdhci.c
@@ -178,6 +178,7 @@
static struct ofw_compat_data compat_data[] = {
{"fsl,imx6q-usdhc", HWTYPE_USDHC},
{"fsl,imx6sl-usdhc", HWTYPE_USDHC},
+ {"fsl,imx6ul-usdhc", HWTYPE_USDHC},
{"fsl,imx53-esdhc", HWTYPE_ESDHC},
{"fsl,imx51-esdhc", HWTYPE_ESDHC},
{"fsl,esdhc", HWTYPE_ESDHC},
diff --git a/sys/modules/dtb/imx6/Makefile b/sys/modules/dtb/imx6/Makefile
--- a/sys/modules/dtb/imx6/Makefile
+++ b/sys/modules/dtb/imx6/Makefile
@@ -15,5 +15,6 @@
imx6dl-wandboard-revb1.dts \
imx6q-wandboard.dts \
imx6q-wandboard-revb1.dts \
+ sbc_ec9100.dts \
.include <bsd.dtb.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 17, 11:04 AM (7 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40938247
Default Alt Text
D41201.id125214.diff (53 KB)
Attached To
Mode
D41201: Initial port to i.MX6UL for SBC-EC9100
Attached
Detach File
Event Timeline
Log In to Comment