summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-12-18 22:18:56 +0000
committerpatrick <patrick@openbsd.org>2020-12-18 22:18:56 +0000
commita74ead0bc7f7379b89e2fd2137729ddd99851a28 (patch)
treee29503485906d2670edbd50a7bdcec79a7739b8a
parentEmulate open drain GPIOs. This replaces the hack added in the last commit. (diff)
downloadwireguard-openbsd-a74ead0bc7f7379b89e2fd2137729ddd99851a28.tar.xz
wireguard-openbsd-a74ead0bc7f7379b89e2fd2137729ddd99851a28.zip
Add support for the i.MX8MP second ethernet. The Plus SoC not only has the
usual fec(4), but also a variant of dwge(4). Unfortunately it seems to be a newer version, which isn't compatible to the one currently in our tree.
-rw-r--r--sys/dev/fdt/imxccm.c91
-rw-r--r--sys/dev/fdt/imxccm_clocks.h11
2 files changed, 98 insertions, 4 deletions
diff --git a/sys/dev/fdt/imxccm.c b/sys/dev/fdt/imxccm.c
index c245a5317ce..9736527fef3 100644
--- a/sys/dev/fdt/imxccm.c
+++ b/sys/dev/fdt/imxccm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: imxccm.c,v 1.24 2020/12/18 16:29:57 patrick Exp $ */
+/* $OpenBSD: imxccm.c,v 1.25 2020/12/18 22:18:56 patrick Exp $ */
/*
* Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
*
@@ -248,6 +248,8 @@ uint32_t imxccm_imx8mm_ahb(struct imxccm_softc *sc, uint32_t);
uint32_t imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t);
uint32_t imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t);
uint32_t imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t);
+uint32_t imxccm_imx8mp_enet_qos_timer(struct imxccm_softc *sc, uint32_t);
+uint32_t imxccm_imx8mp_enet_qos(struct imxccm_softc *sc, uint32_t);
uint32_t imxccm_imx8mp_hsio_axi(struct imxccm_softc *sc, uint32_t);
uint32_t imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t);
uint32_t imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t);
@@ -884,6 +886,52 @@ imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t idx)
}
uint32_t
+imxccm_imx8mp_enet_qos(struct imxccm_softc *sc, uint32_t idx)
+{
+ uint32_t mux;
+
+ if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
+ return 0;
+
+ mux = HREAD4(sc, sc->sc_muxs[idx].reg);
+ mux >>= sc->sc_muxs[idx].shift;
+ mux &= sc->sc_muxs[idx].mask;
+
+ switch (mux) {
+ case 0:
+ return clock_get_frequency(sc->sc_node, "osc_24m");
+ case 1:
+ return 125 * 1000 * 1000; /* sys2_pll_125m */
+ default:
+ printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
+ return 0;
+ }
+}
+
+uint32_t
+imxccm_imx8mp_enet_qos_timer(struct imxccm_softc *sc, uint32_t idx)
+{
+ uint32_t mux;
+
+ if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
+ return 0;
+
+ mux = HREAD4(sc, sc->sc_muxs[idx].reg);
+ mux >>= sc->sc_muxs[idx].shift;
+ mux &= sc->sc_muxs[idx].mask;
+
+ switch (mux) {
+ case 0:
+ return clock_get_frequency(sc->sc_node, "osc_24m");
+ case 1:
+ return 100 * 1000 * 1000; /* sys2_pll_100m */
+ default:
+ printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
+ return 0;
+ }
+}
+
+uint32_t
imxccm_imx8mp_hsio_axi(struct imxccm_softc *sc, uint32_t idx)
{
uint32_t mux;
@@ -1546,6 +1594,12 @@ imxccm_get_frequency(void *cookie, uint32_t *cells)
case IMX8MP_CLK_USDHC3:
freq = imxccm_imx8mm_usdhc(sc, idx);
break;
+ case IMX8MP_CLK_ENET_QOS:
+ freq = imxccm_imx8mp_enet_qos(sc, idx);
+ break;
+ case IMX8MP_CLK_ENET_QOS_TIMER:
+ freq = imxccm_imx8mp_enet_qos_timer(sc, idx);
+ break;
case IMX8MP_CLK_HSIO_AXI:
freq = imxccm_imx8mp_hsio_axi(sc, idx);
break;
@@ -1726,10 +1780,15 @@ imxccm_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
}
} else if (sc->sc_divs == imx8mp_divs) {
switch (idx) {
+ case IMX8MP_CLK_ENET_QOS:
+ parent_freq = imxccm_imx8mp_enet_qos(sc, idx);
+ return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
+ case IMX8MP_CLK_ENET_QOS_TIMER:
+ parent_freq = imxccm_imx8mp_enet_qos_timer(sc, idx);
+ return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
case IMX8MP_CLK_HSIO_AXI:
- if (imxccm_get_frequency(sc, cells) != freq)
- break;
- return 0;
+ parent_freq = imxccm_imx8mp_hsio_axi(sc, idx);
+ return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
}
} else if (sc->sc_divs == imx8mq_divs) {
switch (idx) {
@@ -1852,6 +1911,30 @@ imxccm_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
}
} else if (sc->sc_muxs == imx8mp_muxs) {
switch (idx) {
+ case IMX8MP_CLK_ENET_AXI:
+ if (pidx != IMX8MP_SYS_PLL1_266M)
+ break;
+ mux = HREAD4(sc, sc->sc_muxs[idx].reg);
+ mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
+ mux |= (0x1 << sc->sc_muxs[idx].shift);
+ HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
+ return 0;
+ case IMX8MP_CLK_ENET_QOS:
+ if (pidx != IMX8MP_SYS_PLL2_125M)
+ break;
+ mux = HREAD4(sc, sc->sc_muxs[idx].reg);
+ mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
+ mux |= (0x1 << sc->sc_muxs[idx].shift);
+ HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
+ return 0;
+ case IMX8MP_CLK_ENET_QOS_TIMER:
+ if (pidx != IMX8MP_SYS_PLL2_100M)
+ break;
+ mux = HREAD4(sc, sc->sc_muxs[idx].reg);
+ mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
+ mux |= (0x1 << sc->sc_muxs[idx].shift);
+ HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
+ return 0;
case IMX8MP_CLK_USB_PHY_REF:
if (pidx != IMX8MP_CLK_24M)
break;
diff --git a/sys/dev/fdt/imxccm_clocks.h b/sys/dev/fdt/imxccm_clocks.h
index 8fa68d8acfe..098b92186c7 100644
--- a/sys/dev/fdt/imxccm_clocks.h
+++ b/sys/dev/fdt/imxccm_clocks.h
@@ -535,6 +535,8 @@ struct imxccm_gate imx8mp_gates[] = {
[IMX8MP_CLK_AHB] = { 0x9000, 14 },
[IMX8MP_CLK_I2C5] = { 0xa480, 14 },
[IMX8MP_CLK_I2C6] = { 0xa500, 14 },
+ [IMX8MP_CLK_ENET_QOS] = { 0xa880, 14 },
+ [IMX8MP_CLK_ENET_QOS_TIMER] = { 0xa900, 14 },
[IMX8MP_CLK_ENET_REF] = { 0xa980, 14 },
[IMX8MP_CLK_ENET_TIMER] = { 0xaa00, 14 },
[IMX8MP_CLK_ENET_PHY_REF] = { 0xaa80, 14 },
@@ -556,8 +558,11 @@ struct imxccm_gate imx8mp_gates[] = {
[IMX8MP_CLK_I2C2_ROOT] = { 0x4180, 0, IMX8MP_CLK_I2C2 },
[IMX8MP_CLK_I2C3_ROOT] = { 0x4190, 0, IMX8MP_CLK_I2C3 },
[IMX8MP_CLK_I2C4_ROOT] = { 0x41a0, 0, IMX8MP_CLK_I2C4 },
+ [IMX8MP_CLK_QOS_ROOT] = { 0x42c0, 0, IMX8MP_CLK_IPG_ROOT },
+ [IMX8MP_CLK_QOS_ENET_ROOT] = { 0x42e0, 0, IMX8MP_CLK_IPG_ROOT },
[IMX8MP_CLK_I2C5_ROOT] = { 0x4330, 0, IMX8MP_CLK_I2C5 },
[IMX8MP_CLK_I2C6_ROOT] = { 0x4340, 0, IMX8MP_CLK_I2C6 },
+ [IMX8MP_CLK_ENET_QOS_ROOT] = { 0x43b0, 0, IMX8MP_CLK_SIM_ENET_ROOT },
[IMX8MP_CLK_SIM_ENET_ROOT] = { 0x4400, 0, IMX8MP_CLK_ENET_AXI },
[IMX8MP_CLK_UART1_ROOT] = { 0x4490, 0, IMX8MP_CLK_UART1 },
[IMX8MP_CLK_UART2_ROOT] = { 0x44a0, 0, IMX8MP_CLK_UART2 },
@@ -579,6 +584,8 @@ struct imxccm_divider imx8mp_divs[] = {
[IMX8MP_CLK_IPG_ROOT] = { 0x9080, 0, 0x1, IMX8MP_CLK_AHB },
[IMX8MP_CLK_I2C5] = { 0xa480, 0, 0x3f },
[IMX8MP_CLK_I2C6] = { 0xa500, 0, 0x3f },
+ [IMX8MP_CLK_ENET_QOS] = { 0xa880, 0, 0x3f },
+ [IMX8MP_CLK_ENET_QOS_TIMER] = { 0xa900, 0, 0x3f },
[IMX8MP_CLK_ENET_REF] = { 0xa980, 0, 0x3f },
[IMX8MP_CLK_ENET_TIMER] = { 0xaa00, 0, 0x3f },
[IMX8MP_CLK_ENET_PHY_REF] = { 0xaa80, 0, 0x3f},
@@ -604,6 +611,8 @@ struct imxccm_divider imx8mp_predivs[] = {
[IMX8MP_CLK_AHB] = { 0x9000, 16, 0x7 },
[IMX8MP_CLK_I2C5] = { 0xa480, 16, 0x7 },
[IMX8MP_CLK_I2C6] = { 0xa500, 16, 0x7 },
+ [IMX8MP_CLK_ENET_QOS] = { 0xa880, 16, 0x7 },
+ [IMX8MP_CLK_ENET_QOS_TIMER] = { 0xa900, 16, 0x7 },
[IMX8MP_CLK_ENET_REF] = { 0xa980, 16, 0x7 },
[IMX8MP_CLK_ENET_TIMER] = { 0xaa00, 16, 0x7 },
[IMX8MP_CLK_ENET_PHY_REF] = { 0xaa80, 16, 0x7 },
@@ -629,6 +638,8 @@ struct imxccm_mux imx8mp_muxs[] = {
[IMX8MP_CLK_AHB] = { 0x9000, 24, 0x7 },
[IMX8MP_CLK_I2C5] = { 0xa480, 24, 0x7 },
[IMX8MP_CLK_I2C6] = { 0xa500, 24, 0x7 },
+ [IMX8MP_CLK_ENET_QOS] = { 0xa880, 24, 0x7 },
+ [IMX8MP_CLK_ENET_QOS_TIMER] = { 0xa900, 24, 0x7 },
[IMX8MP_CLK_ENET_REF] = { 0xa980, 24, 0x7 },
[IMX8MP_CLK_ENET_TIMER] = { 0xaa00, 24, 0x7 },
[IMX8MP_CLK_ENET_PHY_REF] = { 0xaa80, 24, 0x7 },