#include "bpfilter.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/timeout.h>
#include <sys/task.h>
#include <machine/bus.h>
#include <machine/fdt.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_clock.h>
#include <dev/ofw/ofw_gpio.h>
#include <dev/ofw/ofw_misc.h>
#include <dev/ofw/ofw_pinctrl.h>
#include <dev/ofw/ofw_regulator.h>
#include <dev/ofw/fdt.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#if NBPFILTER > 0
#include <net/bpf.h>
#endif
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <dev/ic/dwqevar.h>
#include <dev/ic/dwqereg.h>
struct dwqe_fdt_softc {
struct dwqe_softc sc_sc;
struct if_device sc_ifd;
int sc_gmac_id;
};
int dwqe_fdt_match(struct device *, void *, void *);
void dwqe_fdt_attach(struct device *, struct device *, void *);
void dwqe_setup_jh7110(struct dwqe_softc *);
void dwqe_mii_statchg_jh7110(struct device *);
void dwqe_setup_rk3528(struct dwqe_fdt_softc *);
void dwqe_mii_statchg_rk3528(struct device *);
void dwqe_setup_rk3568(struct dwqe_fdt_softc *);
void dwqe_mii_statchg_rk3568(struct device *);
void dwqe_setup_rk3576(struct dwqe_fdt_softc *);
void dwqe_mii_statchg_rk3576(struct device *);
void dwqe_setup_rk3588(struct dwqe_fdt_softc *);
void dwqe_mii_statchg_rk3588(struct device *);
const struct cfattach dwqe_fdt_ca = {
sizeof(struct dwqe_fdt_softc), dwqe_fdt_match, dwqe_fdt_attach
};
void dwqe_reset_phy(struct dwqe_softc *, uint32_t);
int
dwqe_fdt_match(struct device *parent, void *cfdata, void *aux)
{
struct fdt_attach_args *faa = aux;
return OF_is_compatible(faa->fa_node, "snps,dwmac-4.20a") ||
OF_is_compatible(faa->fa_node, "snps,dwmac-5.20");
}
void
dwqe_fdt_attach(struct device *parent, struct device *self, void *aux)
{
struct dwqe_fdt_softc *fsc = (void *)self;
struct dwqe_softc *sc = &fsc->sc_sc;
struct fdt_attach_args *faa = aux;
char phy_mode[16] = { 0 };
uint32_t phy, phy_supply;
uint32_t axi_config;
struct ifnet *ifp = &sc->sc_ac.ac_if;
int i, node;
sc->sc_node = faa->fa_node;
sc->sc_iot = faa->fa_iot;
if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
printf(": cannot map registers\n");
return;
}
sc->sc_dmat = faa->fa_dmat;
switch (faa->fa_reg[0].addr) {
case 0xffbd0000:
case 0xfe2a0000:
case 0x2a220000:
case 0xfe1b0000:
case 0x16030000:
fsc->sc_gmac_id = 0;
break;
case 0xffbe0000:
case 0xfe010000:
case 0x2a230000:
case 0xfe1c0000:
case 0x16040000:
fsc->sc_gmac_id = 1;
break;
default:
printf(": unknown controller at 0x%llx\n", faa->fa_reg[0].addr);
return;
}
printf(" gmac %d", fsc->sc_gmac_id);
OF_getprop(faa->fa_node, "phy-mode", phy_mode, sizeof(phy_mode));
if (strcmp(phy_mode, "rgmii") == 0)
sc->sc_phy_mode = DWQE_PHY_MODE_RGMII;
else if (strcmp(phy_mode, "rgmii-rxid") == 0)
sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_RXID;
else if (strcmp(phy_mode, "rgmii-txid") == 0)
sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_TXID;
else if (strcmp(phy_mode, "rgmii-id") == 0)
sc->sc_phy_mode = DWQE_PHY_MODE_RGMII_ID;
else if (strcmp(phy_mode, "rmii") == 0)
sc->sc_phy_mode = DWQE_PHY_MODE_RMII;
else
sc->sc_phy_mode = DWQE_PHY_MODE_UNKNOWN;
phy = OF_getpropint(faa->fa_node, "phy", 0);
if (phy == 0)
phy = OF_getpropint(faa->fa_node, "phy-handle", 0);
node = OF_getnodebyphandle(phy);
if (node)
sc->sc_phyloc = OF_getpropint(node, "reg", MII_PHY_ANY);
else
sc->sc_phyloc = MII_PHY_ANY;
sc->sc_mii.mii_node = node;
pinctrl_byname(faa->fa_node, "default");
clock_set_assigned(faa->fa_node);
clock_enable(faa->fa_node, "stmmaceth");
clock_enable(faa->fa_node, "pclk");
reset_deassert(faa->fa_node, "stmmaceth");
reset_deassert(faa->fa_node, "ahb");
if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac")) {
clock_enable(faa->fa_node, "tx");
clock_enable(faa->fa_node, "gtx");
} else if (OF_is_compatible(faa->fa_node, "rockchip,rk3528-gmac") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3576-gmac") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac")) {
clock_enable(faa->fa_node, "aclk_mac");
clock_enable(faa->fa_node, "pclk_mac");
clock_enable(faa->fa_node, "mac_clk_tx");
clock_enable(faa->fa_node, "clk_mac_speed");
if (strcmp(phy_mode, "rmii") == 0) {
clock_enable(faa->fa_node, "mac_clk_rx");
clock_enable(faa->fa_node, "clk_mac_ref");
clock_enable(faa->fa_node, "clk_mac_refout");
}
}
delay(5000);
if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac"))
dwqe_setup_jh7110(sc);
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3528-gmac"))
dwqe_setup_rk3528(fsc);
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac"))
dwqe_setup_rk3568(fsc);
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3576-gmac"))
dwqe_setup_rk3576(fsc);
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac"))
dwqe_setup_rk3588(fsc);
phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0);
if (phy_supply)
regulator_enable(phy_supply);
dwqe_reset_phy(sc, phy);
node = OF_getnodebyname(sc->sc_node, "fixed-link");
if (node) {
sc->sc_fixed_link = 1;
ifp->if_baudrate = IF_Mbps(OF_getpropint(node, "speed", 0));
ifp->if_link_state = OF_getpropbool(node, "full-duplex") ?
LINK_STATE_FULL_DUPLEX : LINK_STATE_HALF_DUPLEX;
}
sc->sc_clkrate = clock_get_frequency(faa->fa_node, "stmmaceth");
if (sc->sc_clkrate > 500000000)
sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_500_800;
else if (sc->sc_clkrate > 300000000)
sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_300_500;
else if (sc->sc_clkrate > 150000000)
sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_150_250;
else if (sc->sc_clkrate > 100000000)
sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_100_150;
else if (sc->sc_clkrate > 60000000)
sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_60_100;
else if (sc->sc_clkrate > 35000000)
sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_35_60;
else
sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_20_35;
for (i = 0; i < 4; i++)
sc->sc_hw_feature[i] = dwqe_read(sc, GMAC_MAC_HW_FEATURE(i));
if (OF_getprop(faa->fa_node, "local-mac-address",
&sc->sc_lladdr, ETHER_ADDR_LEN) != ETHER_ADDR_LEN)
dwqe_lladdr_read(sc, sc->sc_lladdr);
sc->sc_force_thresh_dma_mode =
OF_getpropbool(faa->fa_node, "snps,force_thresh_dma_mode");
dwqe_reset(sc);
sc->sc_fixed_burst = OF_getpropbool(faa->fa_node, "snps,fixed-burst");
sc->sc_mixed_burst = OF_getpropbool(faa->fa_node, "snps,mixed-burst");
sc->sc_aal = OF_getpropbool(faa->fa_node, "snps,aal");
sc->sc_8xpbl = !OF_getpropbool(faa->fa_node, "snps,no-pbl-x8");
sc->sc_pbl = OF_getpropint(faa->fa_node, "snps,pbl", 8);
sc->sc_txpbl = OF_getpropint(faa->fa_node, "snps,txpbl", sc->sc_pbl);
sc->sc_rxpbl = OF_getpropint(faa->fa_node, "snps,rxpbl", sc->sc_pbl);
axi_config = OF_getpropint(faa->fa_node, "snps,axi-config", 0);
node = OF_getnodebyphandle(axi_config);
if (node) {
sc->sc_axi_config = 1;
sc->sc_lpi_en = OF_getpropbool(node, "snps,lpi_en");
sc->sc_xit_frm = OF_getpropbool(node, "snps,xit_frm");
sc->sc_wr_osr_lmt = OF_getpropint(node, "snps,wr_osr_lmt", 1);
sc->sc_rd_osr_lmt = OF_getpropint(node, "snps,rd_osr_lmt", 1);
OF_getpropintarray(node, "snps,blen", sc->sc_blen, sizeof(sc->sc_blen));
}
if (dwqe_attach(sc) != 0)
return;
if (OF_is_compatible(faa->fa_node, "starfive,jh7110-dwmac") &&
!OF_getpropbool(faa->fa_node, "starfive,tx-use-rgmii-clk"))
sc->sc_mii.mii_statchg = dwqe_mii_statchg_jh7110;
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3528-gmac"))
sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3528;
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-gmac"))
sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3568;
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3576-gmac"))
sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3576;
else if (OF_is_compatible(faa->fa_node, "rockchip,rk3588-gmac"))
sc->sc_mii.mii_statchg = dwqe_mii_statchg_rk3588;
sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_NET | IPL_MPSAFE,
dwqe_intr, sc, sc->sc_dev.dv_xname);
if (sc->sc_ih == NULL)
printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
fsc->sc_ifd.if_node = faa->fa_node;
fsc->sc_ifd.if_ifp = ifp;
if_register(&fsc->sc_ifd);
if (sc->sc_fixed_link)
sc->sc_mii.mii_statchg(self);
}
void
dwqe_reset_phy(struct dwqe_softc *sc, uint32_t phy)
{
uint32_t *gpio;
uint32_t delays[3];
int active = 1;
int node, len;
node = OF_getnodebyphandle(phy);
if (node && OF_getproplen(node, "reset-gpios") > 0) {
len = OF_getproplen(node, "reset-gpios");
gpio = malloc(len, M_TEMP, M_WAITOK);
OF_getpropintarray(node, "reset-gpios", gpio, len);
delays[0] = OF_getpropint(node, "reset-deassert-us", 0);
delays[1] = OF_getpropint(node, "reset-assert-us", 0);
delays[2] = OF_getpropint(node, "reset-deassert-us", 0);
} else {
len = OF_getproplen(sc->sc_node, "snps,reset-gpio");
if (len <= 0)
return;
gpio = malloc(len, M_TEMP, M_WAITOK);
OF_getpropintarray(sc->sc_node, "snps,reset-gpio", gpio, len);
if (OF_getpropbool(sc->sc_node, "snps-reset-active-low"))
active = 0;
delays[0] = delays[1] = delays[2] = 0;
OF_getpropintarray(sc->sc_node, "snps,reset-delays-us", delays,
sizeof(delays));
}
gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
gpio_controller_set_pin(gpio, !active);
delay(delays[0]);
gpio_controller_set_pin(gpio, active);
delay(delays[1]);
gpio_controller_set_pin(gpio, !active);
delay(delays[2]);
free(gpio, M_TEMP, len);
}
#define JH7110_PHY_INTF_RGMII 1
#define JH7110_PHY_INTF_RMII 4
#define RK3528_VO_GRF_GMAC_CON 0x0018
#define RK3528_GMAC0_PHY_INTF_SEL_RMII ((1U << 1) << 16 | (1 << 1))
#define RK3528_GMAC0_CLK_RMII_DIV2 ((1U << 3) << 16 | (1 << 3))
#define RK3528_GMAC0_CLK_RMII_DIV20 ((1U << 3) << 16 | (0 << 3))
#define RK3528_VPU_GRF_GMAC_CON5 0x0018
#define RK3528_GMAC1_PHY_INTF_SEL_RMII ((1U << 8) << 16 | (1 << 8))
#define RK3528_GMAC1_PHY_INTF_SEL_RGMII ((1U << 8) << 16 | (0 << 8))
#define RK3528_GMAC1_CLK_RMII_DIV2 ((1U << 10) << 16 | (1 << 10))
#define RK3528_GMAC1_CLK_RMII_DIV20 ((1U << 10) << 16 | (0 << 10))
#define RK3528_GMAC_TXCLK_DLY_SET(_v) ((1U << 14) << 16 | ((_v) << 14))
#define RK3528_GMAC_RXCLK_DLY_SET(_v) ((1U << 15) << 16 | ((_v) << 15))
#define RK3528_GMAC1_CLK_RGMII_DIV1 ((0x3U << 10) << 16 | (0x0 << 10))
#define RK3528_GMAC1_CLK_RGMII_DIV5 ((0x3U << 10) << 16 | (0x3 << 10))
#define RK3528_GMAC1_CLK_RGMII_DIV50 ((0x3U << 10) << 16 | (0x2 << 10))
#define RK3528_VPU_GRF_GMAC_CON6 0x001c
#define RK3528_GMAC_CLK_RX_DL_CFG(_v) ((0xffU << 8) << 16 | ((_v) << 8))
#define RK3528_GMAC_CLK_TX_DL_CFG(_v) ((0xffU << 0) << 16 | ((_v) << 0))
#define RK3568_GRF_GMACx_CON0(x) (0x0380 + (x) * 0x8)
#define RK3568_GMAC_CLK_RX_DL_CFG(val) ((0x7f << 8) << 16 | ((val) << 8))
#define RK3568_GMAC_CLK_TX_DL_CFG(val) ((0x7f << 0) << 16 | ((val) << 0))
#define RK3568_GRF_GMACx_CON1(x) (0x0384 + (x) * 0x8)
#define RK3568_GMAC_PHY_INTF_SEL_RGMII ((0x7 << 4) << 16 | (0x1 << 4))
#define RK3568_GMAC_PHY_INTF_SEL_RMII ((0x7 << 4) << 16 | (0x4 << 4))
#define RK3568_GMAC_TXCLK_DLY_SET(_v) ((1 << 0) << 16 | ((_v) << 0))
#define RK3568_GMAC_RXCLK_DLY_SET(_v) ((1 << 1) << 16 | ((_v) << 1))
#define RK3576_SDGMAC_GRF_GMAC_CON(id) (0x0020 + (id) * 0x0004)
#define RK3576_GMACx_CLK_CON_MODE_RMII ((1U << 3) << 16 | (1 << 3))
#define RK3576_GMACx_CLK_CON_MODE_RGMII ((1U << 3) << 16 | (0 << 3))
#define RK3576_GMACx_CLK_CON_SEL_RGMII_2_5 ((0x3 << 5) << 16 | (0x2 << 5))
#define RK3576_GMACx_CLK_CON_SEL_RGMII_25 ((0x3 << 5) << 16 | (0x3 << 5))
#define RK3576_GMACx_CLK_CON_SEL_RGMII_125 ((0x3 << 5) << 16 | (0x0 << 5))
#define RK3576_GMACx_CLK_CON_SEL_RMII_2_5 ((0x3 << 5) << 16 | (0x1 << 5))
#define RK3576_GMACx_CLK_CON_SEL_RMII_25 ((0x3 << 5) << 16 | (0x0 << 5))
#define RK3576_VCCIO_IOC_MISC_CON2 0x6408
#define RK3576_VCCIO_IOC_MISC_CON4 0x6410
#define RK3576_GMACx_Mx_TXCLK_DLY_ENA ((1U << 7) << 16 | (1 << 7))
#define RK3576_GMACx_Mx_RXCLK_DLY_ENA ((1U << 15) << 16 | (1 << 15))
#define RK3576_GMACx_Mx_TXCLK_DELAYLINE_NUM(_v) ((0x7f << 0) << 16 | ((_v) << 0))
#define RK3576_GMACx_Mx_RXCLK_DELAYLINE_NUM(_v) ((0x7f << 8) << 16 | ((_v) << 8))
#define RK3588_GRF_GMAC_CON7 0x031c
#define RK3588_GMACx_RXCLK_DLY_ENA(id) ((1 << (2 * (id) + 3)) << 16 | (1 << (2 * (id) + 3)))
#define RK3588_GMACx_TXCLK_DLY_ENA(id) ((1 << (2 * (id) + 2)) << 16 | (1 << (2 * (id) + 2)))
#define RK3588_GRF_GMAC_CON8 0x0320
#define RK3588_GRF_GMAC_CON9 0x0324
#define RK3588_GMAC_CLK_RX_DL_CFG(val) ((0x7f << 8) << 16 | ((val) << 8))
#define RK3588_GMAC_CLK_TX_DL_CFG(val) ((0x7f << 0) << 16 | ((val) << 0))
#define RK3588_PHP_GRF_GMAC_CON0 0x0008
#define RK3588_GMACx_PHY_INTF_SEL_RGMII(id) ((0x7 << (6 * (id) + 3)) << 16 | (0x1 << (6 * (id) + 3)))
#define RK3588_GMACx_PHY_INTF_SEL_RMII(id) ((0x7 << (6 * (id) + 3)) << 16 | (0x4 << (6 * (id) + 3)))
#define RK3588_PHP_GRF_CLK_CON1 0x0070
#define RK3588_RMII_MODE_GMACx_RMII(id) ((0x1 << (5 * (id))) << 16 | (0x1 << (5 * (id))))
#define RK3588_RMII_MODE_GMACx_RGMII(id) ((0x1 << (5 * (id))) << 16 | (0x0 << (5 * (id))))
#define RK3588_MII_TX_CLK_SEL_RMII_2_5(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x1 << (5 * (id) + 2)))
#define RK3588_MII_TX_CLK_SEL_RMII_25(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x0 << (5 * (id) + 2)))
#define RK3588_MII_TX_CLK_SEL_RGMII_2_5(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x2 << (5 * (id) + 2)))
#define RK3588_MII_TX_CLK_SEL_RGMII_25(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x3 << (5 * (id) + 2)))
#define RK3588_MII_TX_CLK_SEL_RGMII_125(id) ((0x3 << (5 * (id) + 2)) << 16 | (0x0 << (5 * (id) + 2)))
void dwqe_mii_statchg_jh7110_task(void *);
void dwqe_mii_statchg_rk3568_task(void *);
void
dwqe_setup_jh7110(struct dwqe_softc *sc)
{
struct regmap *rm;
uint32_t cells[3];
uint32_t phandle, offset, reg, shift;
char phy_mode[32];
uint32_t iface;
if (OF_getpropintarray(sc->sc_node, "starfive,syscon", cells,
sizeof(cells)) != sizeof(cells)) {
printf("%s: failed to get starfive,syscon\n", __func__);
return;
}
phandle = cells[0];
offset = cells[1];
shift = cells[2];
rm = regmap_byphandle(phandle);
if (rm == NULL) {
printf("%s: failed to get regmap\n", __func__);
return;
}
if (OF_getprop(sc->sc_node, "phy-mode", phy_mode,
sizeof(phy_mode)) <= 0)
return;
if (strcmp(phy_mode, "rgmii") == 0 ||
strcmp(phy_mode, "rgmii-id") == 0) {
iface = JH7110_PHY_INTF_RGMII;
} else if (strcmp(phy_mode, "rmii") == 0) {
iface = JH7110_PHY_INTF_RMII;
} else
return;
reg = regmap_read_4(rm, offset);
reg &= ~(((1U << 3) - 1) << shift);
reg |= iface << shift;
regmap_write_4(rm, offset, reg);
task_set(&sc->sc_statchg_task,
dwqe_mii_statchg_jh7110_task, sc);
}
void
dwqe_mii_statchg_jh7110_task(void *arg)
{
struct dwqe_softc *sc = arg;
struct ifnet *ifp = &sc->sc_ac.ac_if;
dwqe_mii_statchg(&sc->sc_dev);
switch (ifp->if_baudrate) {
case IF_Mbps(10):
clock_set_frequency(sc->sc_node, "tx", 2500000);
break;
case IF_Mbps(100):
clock_set_frequency(sc->sc_node, "tx", 25000000);
break;
case IF_Mbps(1000):
clock_set_frequency(sc->sc_node, "tx", 125000000);
break;
}
}
void
dwqe_mii_statchg_jh7110(struct device *self)
{
struct dwqe_softc *sc = (void *)self;
task_add(systq, &sc->sc_statchg_task);
}
void
dwqe_setup_rk3528(struct dwqe_fdt_softc *fsc)
{
struct dwqe_softc *sc = &fsc->sc_sc;
struct regmap *rm;
uint32_t grf;
int tx_delay, rx_delay;
uint32_t iface;
grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
rm = regmap_byphandle(grf);
if (rm == NULL)
return;
if (fsc->sc_gmac_id == 0) {
regmap_write_4(rm, RK3528_VO_GRF_GMAC_CON,
RK3528_GMAC0_PHY_INTF_SEL_RMII |
RK3528_GMAC0_CLK_RMII_DIV2);
return;
}
switch (sc->sc_phy_mode) {
case DWQE_PHY_MODE_RGMII:
case DWQE_PHY_MODE_RGMII_ID:
case DWQE_PHY_MODE_RGMII_RXID:
case DWQE_PHY_MODE_RGMII_TXID:
iface = RK3528_GMAC1_PHY_INTF_SEL_RGMII;
break;
case DWQE_PHY_MODE_RMII:
iface = RK3528_GMAC1_PHY_INTF_SEL_RMII;
break;
default:
return;
}
tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30);
rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10);
switch (sc->sc_phy_mode) {
case DWQE_PHY_MODE_RGMII_ID:
tx_delay = rx_delay = 0;
break;
case DWQE_PHY_MODE_RGMII_RXID:
rx_delay = 0;
break;
case DWQE_PHY_MODE_RGMII_TXID:
tx_delay = 0;
break;
default:
break;
}
regmap_write_4(rm, RK3528_VPU_GRF_GMAC_CON6,
RK3528_GMAC_CLK_TX_DL_CFG(tx_delay) |
RK3528_GMAC_CLK_RX_DL_CFG(rx_delay));
regmap_write_4(rm, RK3528_VPU_GRF_GMAC_CON5, iface |
RK3528_GMAC_TXCLK_DLY_SET(tx_delay > 0 ? 1 : 0) |
RK3528_GMAC_RXCLK_DLY_SET(rx_delay > 0 ? 1 : 0));
}
void
dwqe_mii_statchg_rk3528(struct device *self)
{
struct dwqe_fdt_softc *fsc = (void *)self;
struct dwqe_softc *sc = &fsc->sc_sc;
struct ifnet *ifp = &sc->sc_ac.ac_if;
struct regmap *rm;
uint32_t grf;
uint32_t reg, clk_sel = 0;
dwqe_mii_statchg(self);
grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
rm = regmap_byphandle(grf);
if (rm == NULL)
return;
if (fsc->sc_gmac_id == 1)
reg = RK3528_VPU_GRF_GMAC_CON5;
else
reg = RK3528_VO_GRF_GMAC_CON;
if (sc->sc_phy_mode == DWQE_PHY_MODE_RMII) {
switch (ifp->if_baudrate) {
case IF_Mbps(10):
if (fsc->sc_gmac_id == 1)
clk_sel = RK3528_GMAC1_CLK_RMII_DIV20;
else
clk_sel = RK3528_GMAC0_CLK_RMII_DIV20;
break;
case IF_Mbps(100):
if (fsc->sc_gmac_id == 1)
clk_sel = RK3528_GMAC1_CLK_RMII_DIV2;
else
clk_sel = RK3528_GMAC0_CLK_RMII_DIV2;
break;
}
} else {
switch (ifp->if_baudrate) {
case IF_Mbps(10):
clk_sel = RK3528_GMAC1_CLK_RGMII_DIV50;
break;
case IF_Mbps(100):
clk_sel = RK3528_GMAC1_CLK_RGMII_DIV5;
break;
case IF_Mbps(1000):
clk_sel = RK3528_GMAC1_CLK_RGMII_DIV1;
break;
}
}
regmap_write_4(rm, reg, clk_sel);
}
void
dwqe_setup_rk3568(struct dwqe_fdt_softc *fsc)
{
struct dwqe_softc *sc = &fsc->sc_sc;
struct regmap *rm;
uint32_t grf;
int tx_delay, rx_delay;
uint32_t iface;
grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
rm = regmap_byphandle(grf);
if (rm == NULL)
return;
switch (sc->sc_phy_mode) {
case DWQE_PHY_MODE_RGMII:
case DWQE_PHY_MODE_RGMII_ID:
case DWQE_PHY_MODE_RGMII_RXID:
case DWQE_PHY_MODE_RGMII_TXID:
iface = RK3568_GMAC_PHY_INTF_SEL_RGMII;
break;
case DWQE_PHY_MODE_RMII:
iface = RK3568_GMAC_PHY_INTF_SEL_RMII;
break;
default:
return;
}
tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30);
rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10);
switch (sc->sc_phy_mode) {
case DWQE_PHY_MODE_RGMII_ID:
tx_delay = rx_delay = 0;
break;
case DWQE_PHY_MODE_RGMII_RXID:
rx_delay = 0;
break;
case DWQE_PHY_MODE_RGMII_TXID:
tx_delay = 0;
break;
default:
break;
}
regmap_write_4(rm, RK3568_GRF_GMACx_CON0(fsc->sc_gmac_id),
RK3568_GMAC_CLK_TX_DL_CFG(tx_delay) |
RK3568_GMAC_CLK_RX_DL_CFG(rx_delay));
regmap_write_4(rm, RK3568_GRF_GMACx_CON1(fsc->sc_gmac_id), iface |
RK3568_GMAC_TXCLK_DLY_SET(tx_delay > 0 ? 1 : 0) |
RK3568_GMAC_RXCLK_DLY_SET(rx_delay > 0 ? 1 : 0));
task_set(&sc->sc_statchg_task,
dwqe_mii_statchg_rk3568_task, sc);
}
void
dwqe_mii_statchg_rk3568_task(void *arg)
{
struct dwqe_softc *sc = arg;
struct ifnet *ifp = &sc->sc_ac.ac_if;
dwqe_mii_statchg(&sc->sc_dev);
switch (ifp->if_baudrate) {
case IF_Mbps(10):
clock_set_frequency(sc->sc_node, "clk_mac_speed", 2500000);
break;
case IF_Mbps(100):
clock_set_frequency(sc->sc_node, "clk_mac_speed", 25000000);
break;
case IF_Mbps(1000):
clock_set_frequency(sc->sc_node, "clk_mac_speed", 125000000);
break;
}
}
void
dwqe_mii_statchg_rk3568(struct device *self)
{
struct dwqe_softc *sc = (void *)self;
task_add(systq, &sc->sc_statchg_task);
}
void
dwqe_setup_rk3576(struct dwqe_fdt_softc *fsc)
{
struct dwqe_softc *sc = &fsc->sc_sc;
struct regmap *rm;
struct regmap *php_rm;
uint32_t grf, php_grf;
int tx_delay, rx_delay;
uint32_t mode;
bus_addr_t base;
grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
rm = regmap_byphandle(grf);
if (rm == NULL)
return;
php_grf = OF_getpropint(sc->sc_node, "rockchip,php-grf", 0);
php_rm = regmap_byphandle(php_grf);
if (php_rm == NULL)
return;
switch (sc->sc_phy_mode) {
case DWQE_PHY_MODE_RGMII:
case DWQE_PHY_MODE_RGMII_ID:
case DWQE_PHY_MODE_RGMII_RXID:
case DWQE_PHY_MODE_RGMII_TXID:
mode = RK3576_GMACx_CLK_CON_MODE_RGMII;
sc->sc_clk_sel_2_5 = RK3576_GMACx_CLK_CON_SEL_RGMII_2_5;
sc->sc_clk_sel_25 = RK3576_GMACx_CLK_CON_SEL_RGMII_25;
sc->sc_clk_sel_125 = RK3576_GMACx_CLK_CON_SEL_RGMII_125;
break;
case DWQE_PHY_MODE_RMII:
mode = RK3576_GMACx_CLK_CON_MODE_RMII;
sc->sc_clk_sel_2_5 = RK3576_GMACx_CLK_CON_SEL_RMII_2_5;
sc->sc_clk_sel_25 = RK3576_GMACx_CLK_CON_SEL_RMII_25;
break;
default:
return;
}
tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30);
rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10);
switch (sc->sc_phy_mode) {
case DWQE_PHY_MODE_RGMII_ID:
tx_delay = rx_delay = 0;
break;
case DWQE_PHY_MODE_RGMII_RXID:
rx_delay = 0;
break;
case DWQE_PHY_MODE_RGMII_TXID:
tx_delay = 0;
break;
default:
break;
}
regmap_write_4(rm, RK3576_SDGMAC_GRF_GMAC_CON(fsc->sc_gmac_id), mode);
if (fsc->sc_gmac_id == 0)
base = RK3576_VCCIO_IOC_MISC_CON2;
else
base = RK3576_VCCIO_IOC_MISC_CON4;
regmap_write_4(php_rm, base + 0x0000, RK3576_GMACx_Mx_TXCLK_DLY_ENA |
RK3576_GMACx_Mx_RXCLK_DLY_ENA);
regmap_write_4(php_rm, base + 0x0004, RK3576_GMACx_Mx_TXCLK_DLY_ENA |
RK3576_GMACx_Mx_RXCLK_DLY_ENA);
regmap_write_4(php_rm, base + 0x0000,
RK3576_GMACx_Mx_TXCLK_DELAYLINE_NUM(tx_delay) |
RK3576_GMACx_Mx_RXCLK_DELAYLINE_NUM(rx_delay));
regmap_write_4(php_rm, base + 0x0004,
RK3576_GMACx_Mx_TXCLK_DELAYLINE_NUM(tx_delay) |
RK3576_GMACx_Mx_RXCLK_DELAYLINE_NUM(rx_delay));
}
void
dwqe_mii_statchg_rk3576(struct device *self)
{
struct dwqe_fdt_softc *fsc = (void *)self;
struct dwqe_softc *sc = &fsc->sc_sc;
struct ifnet *ifp = &sc->sc_ac.ac_if;
struct regmap *rm;
uint32_t grf;
uint32_t gmac_clk_sel = 0;
dwqe_mii_statchg(self);
grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
rm = regmap_byphandle(grf);
if (rm == NULL)
return;
switch (ifp->if_baudrate) {
case IF_Mbps(10):
gmac_clk_sel = sc->sc_clk_sel_2_5;
break;
case IF_Mbps(100):
gmac_clk_sel = sc->sc_clk_sel_25;
break;
case IF_Mbps(1000):
gmac_clk_sel = sc->sc_clk_sel_125;
break;
}
regmap_write_4(rm, RK3576_SDGMAC_GRF_GMAC_CON(fsc->sc_gmac_id),
gmac_clk_sel);
}
void
dwqe_setup_rk3588(struct dwqe_fdt_softc *fsc)
{
struct dwqe_softc *sc = &fsc->sc_sc;
struct regmap *rm;
struct regmap *php_rm;
uint32_t grf, php_grf;
int tx_delay, rx_delay;
uint32_t iface, clk;
grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
rm = regmap_byphandle(grf);
if (rm == NULL)
return;
php_grf = OF_getpropint(sc->sc_node, "rockchip,php-grf", 0);
php_rm = regmap_byphandle(php_grf);
if (php_rm == NULL)
return;
switch (sc->sc_phy_mode) {
case DWQE_PHY_MODE_RGMII:
case DWQE_PHY_MODE_RGMII_ID:
case DWQE_PHY_MODE_RGMII_RXID:
case DWQE_PHY_MODE_RGMII_TXID:
iface = RK3588_GMACx_PHY_INTF_SEL_RGMII(fsc->sc_gmac_id);
clk = RK3588_RMII_MODE_GMACx_RGMII(fsc->sc_gmac_id);
sc->sc_clk_sel_2_5 =
RK3588_MII_TX_CLK_SEL_RGMII_2_5(fsc->sc_gmac_id);
sc->sc_clk_sel_25 =
RK3588_MII_TX_CLK_SEL_RGMII_25(fsc->sc_gmac_id);
sc->sc_clk_sel_125 =
RK3588_MII_TX_CLK_SEL_RGMII_125(fsc->sc_gmac_id);
break;
case DWQE_PHY_MODE_RMII:
iface = RK3588_GMACx_PHY_INTF_SEL_RMII(fsc->sc_gmac_id);
clk = RK3588_RMII_MODE_GMACx_RMII(fsc->sc_gmac_id);
sc->sc_clk_sel_2_5 =
RK3588_MII_TX_CLK_SEL_RMII_2_5(fsc->sc_gmac_id);
sc->sc_clk_sel_25 =
RK3588_MII_TX_CLK_SEL_RMII_25(fsc->sc_gmac_id);
break;
default:
return;
}
tx_delay = OF_getpropint(sc->sc_node, "tx_delay", 0x30);
rx_delay = OF_getpropint(sc->sc_node, "rx_delay", 0x10);
switch (sc->sc_phy_mode) {
case DWQE_PHY_MODE_RGMII_ID:
tx_delay = rx_delay = 0;
break;
case DWQE_PHY_MODE_RGMII_RXID:
rx_delay = 0;
break;
case DWQE_PHY_MODE_RGMII_TXID:
tx_delay = 0;
break;
default:
break;
}
regmap_write_4(php_rm, RK3588_PHP_GRF_GMAC_CON0, iface);
regmap_write_4(php_rm, RK3588_PHP_GRF_CLK_CON1, clk);
regmap_write_4(rm, RK3588_GRF_GMAC_CON7,
RK3588_GMACx_TXCLK_DLY_ENA(fsc->sc_gmac_id) |
RK3588_GMACx_RXCLK_DLY_ENA(fsc->sc_gmac_id));
regmap_write_4(rm, fsc->sc_gmac_id == 1 ?
RK3588_GRF_GMAC_CON9 : RK3588_GRF_GMAC_CON8,
RK3588_GMAC_CLK_TX_DL_CFG(tx_delay) |
RK3588_GMAC_CLK_RX_DL_CFG(rx_delay));
}
void
dwqe_mii_statchg_rk3588(struct device *self)
{
struct dwqe_softc *sc = (void *)self;
struct ifnet *ifp = &sc->sc_ac.ac_if;
struct regmap *php_rm;
uint32_t php_grf;
uint32_t gmac_clk_sel = 0;
dwqe_mii_statchg(self);
php_grf = OF_getpropint(sc->sc_node, "rockchip,php-grf", 0);
php_rm = regmap_byphandle(php_grf);
if (php_rm == NULL)
return;
switch (ifp->if_baudrate) {
case IF_Mbps(10):
gmac_clk_sel = sc->sc_clk_sel_2_5;
break;
case IF_Mbps(100):
gmac_clk_sel = sc->sc_clk_sel_25;
break;
case IF_Mbps(1000):
gmac_clk_sel = sc->sc_clk_sel_125;
break;
}
regmap_write_4(php_rm, RK3588_PHP_GRF_CLK_CON1, gmac_clk_sel);
}