diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-07-23 17:09:20 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-07-23 17:09:20 +0000 |
commit | 7f5f770dcb6b8b75129680fc85b3d1c7797b1e38 (patch) | |
tree | cbb886e82064f08c7bf3a04184ec5f92c7c19a15 /sys/dev | |
parent | 4aa8212481fd6a13c598d4567344ed9faf2c135e (diff) |
RK3288 support.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/fdt/if_dwge_fdt.c | 84 | ||||
-rw-r--r-- | sys/dev/fdt/rkpinctrl.c | 168 |
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 */ |