summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-07-23 17:09:20 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-07-23 17:09:20 +0000
commit7f5f770dcb6b8b75129680fc85b3d1c7797b1e38 (patch)
treecbb886e82064f08c7bf3a04184ec5f92c7c19a15 /sys/dev
parent4aa8212481fd6a13c598d4567344ed9faf2c135e (diff)
RK3288 support.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdt/if_dwge_fdt.c84
-rw-r--r--sys/dev/fdt/rkpinctrl.c168
2 files changed, 231 insertions, 21 deletions
diff --git a/sys/dev/fdt/if_dwge_fdt.c b/sys/dev/fdt/if_dwge_fdt.c
index 2a46c704026..9626f15cf50 100644
--- a/sys/dev/fdt/if_dwge_fdt.c
+++ b/sys/dev/fdt/if_dwge_fdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_dwge_fdt.c,v 1.3 2017/05/21 11:52:04 kettenis Exp $ */
+/* $OpenBSD: if_dwge_fdt.c,v 1.4 2017/07/23 17:09:19 kettenis Exp $ */
/*
* Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
* Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org>
@@ -55,9 +55,14 @@ int dwge_fdt_match(struct device *, void *, void *);
void dwge_fdt_attach(struct device *, struct device *, void *);
struct dwge_fdt_softc {
- struct dwc_gmac_softc sc_core;
+ struct dwc_gmac_softc sc_core;
void *sc_ih;
- int sc_node;
+ int sc_node;
+
+ bus_size_t sc_clk_sel;
+ uint32_t sc_clk_sel_125;
+ uint32_t sc_clk_sel_25;
+ uint32_t sc_clk_sel_2_5;
};
struct cfattach dwge_fdt_ca = {
@@ -75,6 +80,7 @@ dwge_fdt_match(struct device *parent, void *match, void *aux)
struct fdt_attach_args *faa = aux;
return (OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-gmac") ||
+ OF_is_compatible(faa->fa_node, "rockchip,rk3288-gmac") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3399-gmac"));
}
@@ -117,6 +123,8 @@ dwge_fdt_attach(struct device *parent, struct device *self, void *aux)
/* Do hardware specific initializations. */
if (OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-gmac"))
dwge_fdt_attach_allwinner(fsc);
+ else if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-gmac"))
+ dwge_fdt_attach_rockchip(fsc);
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-gmac"))
dwge_fdt_attach_rockchip(fsc);
@@ -213,10 +221,26 @@ dwge_fdt_attach_allwinner(struct dwge_fdt_softc *sc)
}
/*
- * Rockchip RK3399
+ * Rockchip RK3288/RK3399.
*/
-/* Registers */
+/* RK3288 registers */
+#define RK3288_GRF_SOC_CON1 0x0248
+#define RK3288_GMAC_PHY_INTF_SEL_RGMII ((0x7 << 6) << 16 | (0x1 << 6))
+#define RK3288_GMAC_PHY_INTF_SEL_RMII ((0x7 << 6) << 16 | (0x4 << 6))
+#define RK3288_RMII_MODE_RMII ((1 << 14) << 16 | (1 << 14))
+#define RK3288_RMII_MODE_MII ((1 << 14) << 16 | (0 << 14))
+#define RK3288_GMAC_CLK_SEL_125 ((0x3 << 12) << 16 | (0x0 << 12))
+#define RK3288_GMAC_CLK_SEL_25 ((0x3 << 12) << 16 | (0x3 << 12))
+#define RK3288_GMAC_CLK_SEL_2_5 ((0x3 << 12) << 16 | (0x2 << 12))
+
+#define RK3288_GRF_SOC_CON3 0x0250
+#define RK3288_GMAC_RXCLK_DLY_ENA ((1 << 15) << 16 | (1 << 15))
+#define RK3288_GMAC_CLK_RX_DL_CFG(val) ((0x7f << 7) << 16 | ((val) << 7))
+#define RK3288_GMAC_TXCLK_DLY_ENA ((1 << 14) << 16 | (1 << 14))
+#define RK3288_GMAC_CLK_TX_DL_CFG(val) ((0x7f << 0) << 16 | ((val) << 0))
+
+/* RK3399 registers */
#define RK3399_GRF_SOC_CON5 0xc214
#define RK3399_GMAC_PHY_INTF_SEL_RGMII ((0x7 << 9) << 16 | (0x1 << 9))
#define RK3399_GMAC_PHY_INTF_SEL_RMII ((0x7 << 9) << 16 | (0x4 << 9))
@@ -250,16 +274,42 @@ dwge_fdt_attach_rockchip(struct dwge_fdt_softc *sc)
clock_enable(sc->sc_node, "aclk_mac");
clock_enable(sc->sc_node, "pclk_mac");
- /* Use RGMII interface. */
- regmap_write_4(rm, RK3399_GRF_SOC_CON5,
- RK3399_GMAC_PHY_INTF_SEL_RGMII | RK3399_RMII_MODE_MII);
-
- /* Program clock delay lines. */
tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30);
rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10);
- regmap_write_4(rm, RK3399_GRF_SOC_CON6,
- RK3399_GMAC_TXCLK_DLY_ENA | RK3399_GMAC_CLK_TX_DL_CFG(tx_delay) |
- RK3399_GMAC_RXCLK_DLY_ENA | RK3399_GMAC_CLK_RX_DL_CFG(rx_delay));
+
+ if (OF_is_compatible(sc->sc_node, "rockchip,rk3288-gmac")) {
+ /* Use RGMII interface. */
+ regmap_write_4(rm, RK3288_GRF_SOC_CON1,
+ RK3288_GMAC_PHY_INTF_SEL_RGMII | RK3288_RMII_MODE_MII);
+
+ /* Program clock delay lines. */
+ regmap_write_4(rm, RK3288_GRF_SOC_CON3,
+ RK3288_GMAC_TXCLK_DLY_ENA | RK3288_GMAC_RXCLK_DLY_ENA |
+ RK3288_GMAC_CLK_TX_DL_CFG(tx_delay) |
+ RK3288_GMAC_CLK_RX_DL_CFG(rx_delay));
+
+ /* Clock speed bits. */
+ sc->sc_clk_sel = RK3288_GRF_SOC_CON1;
+ sc->sc_clk_sel_2_5 = RK3288_GMAC_CLK_SEL_2_5;
+ sc->sc_clk_sel_25 = RK3288_GMAC_CLK_SEL_25;
+ sc->sc_clk_sel_125 = RK3288_GMAC_CLK_SEL_125;
+ } else {
+ /* Use RGMII interface. */
+ regmap_write_4(rm, RK3399_GRF_SOC_CON5,
+ RK3399_GMAC_PHY_INTF_SEL_RGMII | RK3399_RMII_MODE_MII);
+
+ /* Program clock delay lines. */
+ regmap_write_4(rm, RK3399_GRF_SOC_CON6,
+ RK3399_GMAC_TXCLK_DLY_ENA | RK3399_GMAC_RXCLK_DLY_ENA |
+ RK3399_GMAC_CLK_TX_DL_CFG(tx_delay) |
+ RK3399_GMAC_CLK_RX_DL_CFG(rx_delay));
+
+ /* Clock speed bits. */
+ sc->sc_clk_sel = RK3399_GRF_SOC_CON5;
+ sc->sc_clk_sel_2_5 = RK3399_GMAC_CLK_SEL_2_5;
+ sc->sc_clk_sel_25 = RK3399_GMAC_CLK_SEL_25;
+ sc->sc_clk_sel_125 = RK3399_GMAC_CLK_SEL_125;
+ }
sc->sc_core.sc_statchg = dwge_fdt_statchg_rockchip;
}
@@ -279,15 +329,15 @@ dwge_fdt_statchg_rockchip(struct device *dev)
switch (IFM_SUBTYPE(sc->sc_core.sc_mii.mii_media_active)) {
case IFM_10_T:
- gmac_clk_sel = RK3399_GMAC_CLK_SEL_2_5;
+ gmac_clk_sel = sc->sc_clk_sel_2_5;
break;
case IFM_100_TX:
- gmac_clk_sel = RK3399_GMAC_CLK_SEL_25;
+ gmac_clk_sel = sc->sc_clk_sel_25;
break;
case IFM_1000_T:
- gmac_clk_sel = RK3399_GMAC_CLK_SEL_125;
+ gmac_clk_sel = sc->sc_clk_sel_125;
break;
}
- regmap_write_4(rm, RK3399_GRF_SOC_CON5, gmac_clk_sel);
+ regmap_write_4(rm, sc->sc_clk_sel, gmac_clk_sel);
}
diff --git a/sys/dev/fdt/rkpinctrl.c b/sys/dev/fdt/rkpinctrl.c
index 6302416b884..b4818bb9bd7 100644
--- a/sys/dev/fdt/rkpinctrl.c
+++ b/sys/dev/fdt/rkpinctrl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rkpinctrl.c,v 1.3 2017/05/13 12:25:55 kettenis Exp $ */
+/* $OpenBSD: rkpinctrl.c,v 1.4 2017/07/23 17:08:29 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
*
@@ -29,9 +29,17 @@
#include <dev/ofw/ofw_pinctrl.h>
#include <dev/ofw/fdt.h>
+#ifdef __armv7__
+#include <arm/simplebus/simplebusvar.h>
+#else
#include <arm64/dev/simplebusvar.h>
+#endif
-/* Registers */
+/* RK3288 registers */
+#define RK3288_GRF_GPIO1A_IOMUX 0x0000
+#define RK3288_PMUGRF_GPIO0A_IOMUX 0x0084
+
+/* RK3399 registers */
#define RK3399_GRF_GPIO2A_IOMUX 0xe000
#define RK3399_PMUGRF_GPIO0A_IOMUX 0x0000
@@ -53,6 +61,7 @@ struct cfdriver rkpinctrl_cd = {
NULL, "rkpinctrl", DV_DULL
};
+int rk3288_pinctrl(uint32_t, void *);
int rk3399_pinctrl(uint32_t, void *);
int
@@ -60,7 +69,8 @@ rkpinctrl_match(struct device *parent, void *match, void *aux)
{
struct fdt_attach_args *faa = aux;
- return OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl");
+ return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") ||
+ OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl"));
}
void
@@ -80,12 +90,162 @@ rkpinctrl_attach(struct device *parent, struct device *self, void *aux)
return;
}
- pinctrl_register(faa->fa_node, rk3399_pinctrl, sc);
+ if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl"))
+ pinctrl_register(faa->fa_node, rk3288_pinctrl, sc);
+ else
+ pinctrl_register(faa->fa_node, rk3399_pinctrl, sc);
/* Attach GPIO banks. */
simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa);
}
+/*
+ * Rockchip RK3288
+ */
+
+int
+rk3288_pull(uint32_t bank, uint32_t idx, uint32_t phandle)
+{
+ int node;
+
+ node = OF_getnodebyphandle(phandle);
+ if (node == 0)
+ return -1;
+
+ /* XXX */
+ if (bank == 0)
+ return -1;
+
+ if (OF_getproplen(node, "bias-disable") == 0)
+ return 0;
+ if (OF_getproplen(node, "bias-pull-up") == 0)
+ return 1;
+ if (OF_getproplen(node, "bias-pull-down") == 0)
+ return 2;
+
+ return -1;
+}
+
+int
+rk3288_strength(uint32_t bank, uint32_t idx, uint32_t phandle)
+{
+ int strength, level;
+ int levels[4] = { 2, 4, 8, 12 };
+ int node;
+
+ node = OF_getnodebyphandle(phandle);
+ if (node == 0)
+ return -1;
+
+ /* XXX */
+ if (bank == 0)
+ return -1;
+
+ strength = OF_getpropint(node, "drive-strength", -1);
+ if (strength == -1)
+ return -1;
+
+ /* Convert drive strength to level. */
+ for (level = 3; level >= 0; level--) {
+ if (strength >= levels[level])
+ break;
+ }
+ return level;
+}
+
+int
+rk3288_pinctrl(uint32_t phandle, void *cookie)
+{
+ struct rkpinctrl_softc *sc = cookie;
+ uint32_t *pins;
+ int node, len, i;
+
+ node = OF_getnodebyphandle(phandle);
+ if (node == 0)
+ return -1;
+
+ len = OF_getproplen(node, "rockchip,pins");
+ if (len <= 0)
+ return -1;
+
+ pins = malloc(len, M_TEMP, M_WAITOK);
+ if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len)
+ goto fail;
+
+ for (i = 0; i < len / sizeof(uint32_t); i += 4) {
+ struct regmap *rm;
+ bus_size_t base, off;
+ uint32_t bank, idx, mux;
+ int pull, strength;
+ uint32_t mask, bits;
+ int s;
+
+ bank = pins[i];
+ idx = pins[i + 1];
+ mux = pins[i + 2];
+ pull = rk3288_pull(bank, idx, pins[i + 3]);
+ strength = rk3288_strength(bank, idx, pins[i + 3]);
+
+ if (bank > 8 || idx > 32 || mux > 7)
+ continue;
+
+ /* Bank 0 lives in the PMU. */
+ if (bank < 1) {
+ rm = sc->sc_pmu;
+ base = RK3288_PMUGRF_GPIO0A_IOMUX;
+ } else {
+ rm = sc->sc_grf;
+ base = RK3288_GRF_GPIO1A_IOMUX - 0x10;
+ }
+
+ s = splhigh();
+
+ /* IOMUX control */
+ off = bank * 0x10 + (idx / 8) * 0x04;
+
+ /* GPIO3D, GPIO4A and GPIO4B are special. */
+ if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) {
+ mask = (0x7 << ((idx % 4) * 4));
+ bits = (mux << ((idx % 4) * 4));
+ } else {
+ mask = (0x3 << ((idx % 8) * 2));
+ bits = (mux << ((idx % 8) * 2));
+ }
+ if (bank > 3 || (bank == 3 && idx >= 28))
+ off += 0x04;
+ if (bank > 4 || (bank == 4 && idx >= 4))
+ off += 0x04;
+ if (bank > 4 || (bank == 4 && idx >= 12))
+ off += 0x04;
+ regmap_write_4(rm, base + off, mask << 16 | bits);
+
+ /* GPIO pad pull down and pull up control */
+ if (pull >= 0) {
+ off = 0x140 + bank * 0x10 + (idx / 8) * 0x04;
+ mask = (0x3 << ((idx % 8) * 2));
+ bits = (pull << ((idx % 8) * 2));
+ regmap_write_4(rm, base + off, mask << 16 | bits);
+ }
+
+ /* GPIO drive strength control */
+ if (strength >= 0) {
+ off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04;
+ mask = (0x3 << ((idx % 8) * 2));
+ bits = (strength << ((idx % 8) * 2));
+ regmap_write_4(rm, base + off, mask << 16 | bits);
+ }
+
+ splx(s);
+ }
+
+ free(pins, M_TEMP, len);
+ return 0;
+
+fail:
+ free(pins, M_TEMP, len);
+ return -1;
+}
+
/*
* Rockchip RK3399
*/