diff options
Diffstat (limited to 'target/linux/ath79')
5 files changed, 121 insertions, 58 deletions
diff --git a/target/linux/ath79/dts/qca9557.dtsi b/target/linux/ath79/dts/qca9557.dtsi index 802f2da725..980629c939 100644 --- a/target/linux/ath79/dts/qca9557.dtsi +++ b/target/linux/ath79/dts/qca9557.dtsi @@ -220,6 +220,11 @@ status = "disabled"; }; + gmac: gmac@18070000 { + compatible = "qca,qca9550-gmac"; + reg = <0x18070000 0x14>; + }; + wmac: wmac@18100000 { compatible = "qca,qca9550-wmac"; reg = <0x18100000 0x10000>; diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile index 7f396ad46e..ed74e3b5e6 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile @@ -3,6 +3,7 @@ # ag71xx-y += ag71xx_main.o +ag71xx-y += ag71xx_gmac.o ag71xx-y += ag71xx_ethtool.o ag71xx-y += ag71xx_phy.o ag71xx-y += ag71xx_mdio.o diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h index 22b22522a3..b0780a1ba9 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h @@ -447,6 +447,8 @@ void ag71xx_mdio_cleanup(struct ag71xx *ag); int ag71xx_mdio_mii_read(struct mii_bus *bus, int addr, int reg); int ag71xx_mdio_mii_write(struct mii_bus *bus, int addr, int reg, u16 val); +int ag71xx_setup_gmac(struct device_node *np); + int ar7240sw_phy_read(struct mii_bus *mii, int addr, int reg); int ar7240sw_phy_write(struct mii_bus *mii, int addr, int reg, u16 val); diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c new file mode 100644 index 0000000000..55a8f57f15 --- /dev/null +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c @@ -0,0 +1,113 @@ +/* + * Atheros AR71xx built-in ethernet mac driver + * + * 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. + */ + +#include <linux/sizes.h> +#include <linux/of_address.h> +#include "ag71xx.h" + +static void ag71xx_of_set(struct device_node *np, const char *prop, + u32 *reg, u32 shift, u32 mask) +{ + u32 val; + + if (of_property_read_u32(np, prop, &val)) + return; + + *reg &= ~(mask << shift); + *reg |= ((val & mask) << shift); +} + +static void ag71xx_of_bit(struct device_node *np, const char *prop, + u32 *reg, u32 mask) +{ + u32 val; + + if (of_property_read_u32(np, prop, &val)) + return; + + if (val) + *reg |= mask; + else + *reg &= ~mask; +} + +static void ag71xx_setup_gmac_933x(struct device_node *np, void __iomem *base) +{ + u32 val = __raw_readl(base + AR933X_GMAC_REG_ETH_CFG); + + ag71xx_of_bit(np, "switch-phy-swap", &val, AR933X_ETH_CFG_SW_PHY_SWAP); + ag71xx_of_bit(np, "switch-phy-addr-swap", &val, + AR933X_ETH_CFG_SW_PHY_ADDR_SWAP); + + __raw_writel(val, base + AR933X_GMAC_REG_ETH_CFG); +} + +static void ag71xx_setup_gmac_934x(struct device_node *np, void __iomem *base) +{ + u32 val = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); + + ag71xx_of_bit(np, "rgmii-gmac0", &val, AR934X_ETH_CFG_RGMII_GMAC0); + ag71xx_of_bit(np, "mii-gmac0", &val, AR934X_ETH_CFG_MII_GMAC0); + ag71xx_of_bit(np, "gmii-gmac0", &val, AR934X_ETH_CFG_GMII_GMAC0); + ag71xx_of_bit(np, "switch-phy-swap", &val, AR934X_ETH_CFG_SW_PHY_SWAP); + ag71xx_of_bit(np, "switch-only-mode", &val, + AR934X_ETH_CFG_SW_ONLY_MODE); + + __raw_writel(val, base + AR934X_GMAC_REG_ETH_CFG); +} + +static void ag71xx_setup_gmac_955x(struct device_node *np, void __iomem *base) +{ + u32 val = __raw_readl(base + QCA955X_GMAC_REG_ETH_CFG); + + ag71xx_of_bit(np, "rgmii-enabled", &val, QCA955X_ETH_CFG_RGMII_EN); + ag71xx_of_bit(np, "ge0-sgmii", &val, QCA955X_ETH_CFG_GE0_SGMII); + ag71xx_of_set(np, "txen-delay", &val, QCA955X_ETH_CFG_TXE_DELAY_SHIFT, 0x3); + ag71xx_of_set(np, "txd-delay", &val, QCA955X_ETH_CFG_TXD_DELAY_SHIFT, 0x3); + ag71xx_of_set(np, "rxdv-delay", &val, QCA955X_ETH_CFG_RDV_DELAY_SHIFT, 0x3); + ag71xx_of_set(np, "rxd-delay", &val, QCA955X_ETH_CFG_RXD_DELAY_SHIFT, 0x3); + + __raw_writel(val, base + QCA955X_GMAC_REG_ETH_CFG); +} + +int ag71xx_setup_gmac(struct device_node *np) +{ + struct device_node *np_dev; + void __iomem *base; + int err = 0; + + np = of_get_child_by_name(np, "gmac-config"); + if (!np) + return 0; + + np_dev = of_parse_phandle(np, "device", 0); + if (!np_dev) + goto out; + + base = of_iomap(np_dev, 0); + if (!base) { + pr_err("%pOF: can't map GMAC registers\n", np_dev); + err = -ENOMEM; + goto err_iomap; + } + + if (of_device_is_compatible(np_dev, "qca,ar9330-gmac")) + ag71xx_setup_gmac_933x(np, base); + else if (of_device_is_compatible(np_dev, "qca,ar9340-gmac")) + ag71xx_setup_gmac_934x(np, base); + else if (of_device_is_compatible(np_dev, "qca,qca9550-gmac")) + ag71xx_setup_gmac_955x(np, base); + + iounmap(base); + +err_iomap: + of_node_put(np_dev); +out: + of_node_put(np); + return err; +} diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c index 635c3b9127..acc0f089d0 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c @@ -1271,64 +1271,6 @@ static const char *ag71xx_get_phy_if_mode_name(phy_interface_t mode) return "unknown"; } -static void ag71xx_of_bit(struct device_node *np, const char *prop, - u32 *reg, u32 mask) -{ - u32 val; - - if (of_property_read_u32(np, prop, &val)) - return; - - if (val) - *reg |= mask; - else - *reg &= ~mask; -} - -static void ag71xx_setup_gmac_933x(struct device_node *np, void __iomem *base) -{ - u32 val = __raw_readl(base + AR933X_GMAC_REG_ETH_CFG); - - ag71xx_of_bit(np, "switch-phy-swap", &val, AR933X_ETH_CFG_SW_PHY_SWAP); - ag71xx_of_bit(np, "switch-phy-addr-swap", &val, - AR933X_ETH_CFG_SW_PHY_ADDR_SWAP); - - __raw_writel(val, base + AR933X_GMAC_REG_ETH_CFG); -} - -static int ag71xx_setup_gmac(struct device_node *np) -{ - struct device_node *np_dev; - void __iomem *base; - int err = 0; - - np = of_get_child_by_name(np, "gmac-config"); - if (!np) - return 0; - - np_dev = of_parse_phandle(np, "device", 0); - if (!np_dev) - goto out; - - base = of_iomap(np_dev, 0); - if (!base) { - pr_err("%pOF: can't map GMAC registers\n", np_dev); - err = -ENOMEM; - goto err_iomap; - } - - if (of_device_is_compatible(np_dev, "qca,ar9330-gmac")) - ag71xx_setup_gmac_933x(np, base); - - iounmap(base); - -err_iomap: - of_node_put(np_dev); -out: - of_node_put(np); - return err; -} - static int ag71xx_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; |