diff options
author | Chuanhong Guo <gch981213@gmail.com> | 2018-07-17 17:09:13 +0800 |
---|---|---|
committer | John Crispin <john@phrozen.org> | 2018-07-30 10:43:33 +0200 |
commit | 2d081addb537ac3dc41d61487561458c7733c7ba (patch) | |
tree | 2f5506033729b8868ddc26bf4b2c1acd974c0a29 /target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c | |
parent | b346c37588873d0811785efada7aed2e52749500 (diff) | |
download | upstream-2d081addb537ac3dc41d61487561458c7733c7ba.tar.gz upstream-2d081addb537ac3dc41d61487561458c7733c7ba.tar.bz2 upstream-2d081addb537ac3dc41d61487561458c7733c7ba.zip |
ath79: ag71xx: Split gmac config into separated file and add support for ar934x/qca955x.
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
Diffstat (limited to 'target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c')
-rw-r--r-- | target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c | 113 |
1 files changed, 113 insertions, 0 deletions
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; +} |