Page MenuHomeFreeBSD

D41201.id125214.diff
No OneTemporary

D41201.id125214.diff

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 = <&reg_arm>;
+ soc-supply = <&reg_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 = <&ethphy0>;
+ 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(&regval, 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(&regval, 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

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)

Event Timeline