OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Atheros AR71xx built-in ethernet mac driver |
||
3 | * |
||
4 | * This program is free software; you can redistribute it and/or modify it |
||
5 | * under the terms of the GNU General Public License version 2 as published |
||
6 | * by the Free Software Foundation. |
||
7 | */ |
||
8 | |||
9 | #include <linux/sizes.h> |
||
10 | #include <linux/of_address.h> |
||
11 | #include "ag71xx.h" |
||
12 | |||
13 | static void ag71xx_of_set(struct device_node *np, const char *prop, |
||
14 | u32 *reg, u32 shift, u32 mask) |
||
15 | { |
||
16 | u32 val; |
||
17 | |||
18 | if (of_property_read_u32(np, prop, &val)) |
||
19 | return; |
||
20 | |||
21 | *reg &= ~(mask << shift); |
||
22 | *reg |= ((val & mask) << shift); |
||
23 | } |
||
24 | |||
25 | static void ag71xx_of_bit(struct device_node *np, const char *prop, |
||
26 | u32 *reg, u32 mask) |
||
27 | { |
||
28 | u32 val; |
||
29 | |||
30 | if (of_property_read_u32(np, prop, &val)) |
||
31 | return; |
||
32 | |||
33 | if (val) |
||
34 | *reg |= mask; |
||
35 | else |
||
36 | *reg &= ~mask; |
||
37 | } |
||
38 | |||
39 | static void ag71xx_setup_gmac_933x(struct device_node *np, void __iomem *base) |
||
40 | { |
||
41 | u32 val = __raw_readl(base + AR933X_GMAC_REG_ETH_CFG); |
||
42 | |||
43 | ag71xx_of_bit(np, "switch-phy-swap", &val, AR933X_ETH_CFG_SW_PHY_SWAP); |
||
44 | ag71xx_of_bit(np, "switch-phy-addr-swap", &val, |
||
45 | AR933X_ETH_CFG_SW_PHY_ADDR_SWAP); |
||
46 | |||
47 | __raw_writel(val, base + AR933X_GMAC_REG_ETH_CFG); |
||
48 | } |
||
49 | |||
50 | static void ag71xx_setup_gmac_934x(struct device_node *np, void __iomem *base) |
||
51 | { |
||
52 | u32 val = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); |
||
53 | |||
54 | ag71xx_of_bit(np, "rgmii-gmac0", &val, AR934X_ETH_CFG_RGMII_GMAC0); |
||
55 | ag71xx_of_bit(np, "mii-gmac0", &val, AR934X_ETH_CFG_MII_GMAC0); |
||
56 | ag71xx_of_bit(np, "gmii-gmac0", &val, AR934X_ETH_CFG_GMII_GMAC0); |
||
57 | ag71xx_of_bit(np, "switch-phy-swap", &val, AR934X_ETH_CFG_SW_PHY_SWAP); |
||
58 | ag71xx_of_bit(np, "switch-only-mode", &val, |
||
59 | AR934X_ETH_CFG_SW_ONLY_MODE); |
||
60 | ag71xx_of_set(np, "rxdv-delay", &val, |
||
61 | AR934X_ETH_CFG_RDV_DELAY_SHIFT, 0x3); |
||
62 | ag71xx_of_set(np, "rxd-delay", &val, |
||
63 | AR934X_ETH_CFG_RXD_DELAY_SHIFT, 0x3); |
||
64 | ag71xx_of_set(np, "txd-delay", &val, |
||
65 | AR934X_ETH_CFG_TXD_DELAY_SHIFT, 0x3); |
||
66 | ag71xx_of_set(np, "txen-delay", &val, |
||
67 | AR934X_ETH_CFG_TXE_DELAY_SHIFT, 0x3); |
||
68 | |||
69 | __raw_writel(val, base + AR934X_GMAC_REG_ETH_CFG); |
||
70 | } |
||
71 | |||
72 | static void ag71xx_setup_gmac_955x(struct device_node *np, void __iomem *base) |
||
73 | { |
||
74 | u32 val = __raw_readl(base + QCA955X_GMAC_REG_ETH_CFG); |
||
75 | |||
76 | ag71xx_of_bit(np, "rgmii-enabled", &val, QCA955X_ETH_CFG_RGMII_EN); |
||
77 | ag71xx_of_bit(np, "ge0-sgmii", &val, QCA955X_ETH_CFG_GE0_SGMII); |
||
78 | ag71xx_of_set(np, "txen-delay", &val, QCA955X_ETH_CFG_TXE_DELAY_SHIFT, 0x3); |
||
79 | ag71xx_of_set(np, "txd-delay", &val, QCA955X_ETH_CFG_TXD_DELAY_SHIFT, 0x3); |
||
80 | ag71xx_of_set(np, "rxdv-delay", &val, QCA955X_ETH_CFG_RDV_DELAY_SHIFT, 0x3); |
||
81 | ag71xx_of_set(np, "rxd-delay", &val, QCA955X_ETH_CFG_RXD_DELAY_SHIFT, 0x3); |
||
82 | |||
83 | __raw_writel(val, base + QCA955X_GMAC_REG_ETH_CFG); |
||
84 | } |
||
85 | |||
86 | static void ag71xx_setup_gmac_956x(struct device_node *np, void __iomem *base) |
||
87 | { |
||
88 | u32 val = __raw_readl(base + QCA956X_GMAC_REG_ETH_CFG); |
||
89 | |||
90 | ag71xx_of_bit(np, "switch-phy-swap", &val, QCA956X_ETH_CFG_SW_PHY_SWAP); |
||
91 | ag71xx_of_bit(np, "switch-phy-addr-swap", &val, |
||
92 | QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP); |
||
93 | |||
94 | __raw_writel(val, base + QCA956X_GMAC_REG_ETH_CFG); |
||
95 | } |
||
96 | |||
97 | int ag71xx_setup_gmac(struct device_node *np) |
||
98 | { |
||
99 | struct device_node *np_dev; |
||
100 | void __iomem *base; |
||
101 | int err = 0; |
||
102 | |||
103 | np = of_get_child_by_name(np, "gmac-config"); |
||
104 | if (!np) |
||
105 | return 0; |
||
106 | |||
107 | np_dev = of_parse_phandle(np, "device", 0); |
||
108 | if (!np_dev) |
||
109 | goto out; |
||
110 | |||
111 | base = of_iomap(np_dev, 0); |
||
112 | if (!base) { |
||
113 | pr_err("%pOF: can't map GMAC registers\n", np_dev); |
||
114 | err = -ENOMEM; |
||
115 | goto err_iomap; |
||
116 | } |
||
117 | |||
118 | if (of_device_is_compatible(np_dev, "qca,ar9330-gmac")) |
||
119 | ag71xx_setup_gmac_933x(np, base); |
||
120 | else if (of_device_is_compatible(np_dev, "qca,ar9340-gmac")) |
||
121 | ag71xx_setup_gmac_934x(np, base); |
||
122 | else if (of_device_is_compatible(np_dev, "qca,qca9550-gmac")) |
||
123 | ag71xx_setup_gmac_955x(np, base); |
||
124 | else if (of_device_is_compatible(np_dev, "qca,qca9560-gmac")) |
||
125 | ag71xx_setup_gmac_956x(np, base); |
||
126 | |||
127 | iounmap(base); |
||
128 | |||
129 | err_iomap: |
||
130 | of_node_put(np_dev); |
||
131 | out: |
||
132 | of_node_put(np); |
||
133 | return err; |
||
134 | } |