OpenWrt – Blame information for rev 2
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --- a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c |
2 | +++ b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c |
||
3 | @@ -17,6 +17,11 @@ |
||
4 | #include <linux/of.h> |
||
5 | #include <linux/of_net.h> |
||
6 | #include <linux/timer.h> |
||
7 | +#include <linux/of_platform.h> |
||
8 | +#include <linux/of_address.h> |
||
9 | +#include <linux/clk.h> |
||
10 | +#include <linux/string.h> |
||
11 | +#include <linux/reset.h> |
||
12 | #include "edma.h" |
||
13 | #include "ess_edma.h" |
||
14 | |||
15 | @@ -83,7 +88,103 @@ void edma_read_reg(u16 reg_addr, volatil |
||
16 | *reg_value = readl((void __iomem *)(edma_hw_addr + reg_addr)); |
||
17 | } |
||
18 | |||
19 | -/* edma_change_tx_coalesce() |
||
20 | +static void ess_write_reg(struct edma_common_info *edma, u16 reg_addr, u32 reg_value) |
||
21 | +{ |
||
22 | + writel(reg_value, ((void __iomem *) |
||
23 | + ((unsigned long)edma->ess_hw_addr + reg_addr))); |
||
24 | +} |
||
25 | + |
||
26 | +static void ess_read_reg(struct edma_common_info *edma, u16 reg_addr, |
||
27 | + volatile u32 *reg_value) |
||
28 | +{ |
||
29 | + *reg_value = readl((void __iomem *) |
||
30 | + ((unsigned long)edma->ess_hw_addr + reg_addr)); |
||
31 | +} |
||
32 | + |
||
33 | +static int ess_reset(struct edma_common_info *edma) |
||
34 | +{ |
||
35 | + struct device_node *switch_node = NULL; |
||
36 | + struct reset_control *ess_rst; |
||
37 | + u32 regval; |
||
38 | + |
||
39 | + switch_node = of_find_node_by_name(NULL, "ess-switch"); |
||
40 | + if (!switch_node) { |
||
41 | + pr_err("switch-node not found\n"); |
||
42 | + return -EINVAL; |
||
43 | + } |
||
44 | + |
||
45 | + ess_rst = of_reset_control_get(switch_node, "ess_rst"); |
||
46 | + of_node_put(switch_node); |
||
47 | + |
||
48 | + if (IS_ERR(ess_rst)) { |
||
49 | + pr_err("failed to find ess_rst!\n"); |
||
50 | + return -ENOENT; |
||
51 | + } |
||
52 | + |
||
53 | + reset_control_assert(ess_rst); |
||
54 | + msleep(10); |
||
55 | + reset_control_deassert(ess_rst); |
||
56 | + msleep(100); |
||
57 | + reset_control_put(ess_rst); |
||
58 | + |
||
59 | + /* Enable only port 5 <--> port 0 |
||
60 | + * bits 0:6 bitmap of ports it can fwd to */ |
||
61 | +#define SET_PORT_BMP(r,v) \ |
||
62 | + ess_read_reg(edma, r, ®val); \ |
||
63 | + ess_write_reg(edma, r, ((regval & ~0x3F) | v)); |
||
64 | + |
||
65 | + SET_PORT_BMP(ESS_PORT0_LOOKUP_CTRL,0x20); |
||
66 | + SET_PORT_BMP(ESS_PORT1_LOOKUP_CTRL,0x00); |
||
67 | + SET_PORT_BMP(ESS_PORT2_LOOKUP_CTRL,0x00); |
||
68 | + SET_PORT_BMP(ESS_PORT3_LOOKUP_CTRL,0x00); |
||
69 | + SET_PORT_BMP(ESS_PORT4_LOOKUP_CTRL,0x00); |
||
70 | + SET_PORT_BMP(ESS_PORT5_LOOKUP_CTRL,0x01); |
||
71 | + ess_write_reg(edma, ESS_RGMII_CTRL, 0x400); |
||
72 | + ess_write_reg(edma, ESS_PORT0_STATUS, ESS_PORT_1G_FDX); |
||
73 | + ess_write_reg(edma, ESS_PORT5_STATUS, ESS_PORT_1G_FDX); |
||
74 | + ess_write_reg(edma, ESS_PORT0_HEADER_CTRL, 0); |
||
75 | +#undef SET_PORT_BMP |
||
76 | + |
||
77 | + /* forward multicast and broadcast frames to CPU */ |
||
78 | + ess_write_reg(edma, ESS_FWD_CTRL1, |
||
79 | + (ESS_PORTS_ALL << ESS_FWD_CTRL1_UC_FLOOD_S) | |
||
80 | + (ESS_PORTS_ALL << ESS_FWD_CTRL1_MC_FLOOD_S) | |
||
81 | + (ESS_PORTS_ALL << ESS_FWD_CTRL1_BC_FLOOD_S)); |
||
82 | + |
||
83 | + return 0; |
||
84 | +} |
||
85 | + |
||
86 | +void ess_set_port_status_speed(struct edma_common_info *edma, |
||
87 | + struct phy_device *phydev, uint8_t port_id) |
||
88 | +{ |
||
89 | + uint16_t reg_off = ESS_PORT0_STATUS + (4 * port_id); |
||
90 | + uint32_t reg_val = 0; |
||
91 | + |
||
92 | + ess_read_reg(edma, reg_off, ®_val); |
||
93 | + |
||
94 | + /* reset the speed bits [0:1] */ |
||
95 | + reg_val &= ~ESS_PORT_STATUS_SPEED_INV; |
||
96 | + |
||
97 | + /* set the new speed */ |
||
98 | + switch(phydev->speed) { |
||
99 | + case SPEED_1000: reg_val |= ESS_PORT_STATUS_SPEED_1000; break; |
||
100 | + case SPEED_100: reg_val |= ESS_PORT_STATUS_SPEED_100; break; |
||
101 | + case SPEED_10: reg_val |= ESS_PORT_STATUS_SPEED_10; break; |
||
102 | + default: reg_val |= ESS_PORT_STATUS_SPEED_INV; break; |
||
103 | + } |
||
104 | + |
||
105 | + /* check full/half duplex */ |
||
106 | + if (phydev->duplex) { |
||
107 | + reg_val |= ESS_PORT_STATUS_DUPLEX_MODE; |
||
108 | + } else { |
||
109 | + reg_val &= ~ESS_PORT_STATUS_DUPLEX_MODE; |
||
110 | + } |
||
111 | + |
||
112 | + ess_write_reg(edma, reg_off, reg_val); |
||
113 | +} |
||
114 | + |
||
115 | +/* |
||
116 | + * edma_change_tx_coalesce() |
||
117 | * change tx interrupt moderation timer |
||
118 | */ |
||
119 | void edma_change_tx_coalesce(int usecs) |
||
120 | @@ -551,6 +652,31 @@ static struct ctl_table edma_table[] = { |
||
121 | {} |
||
122 | }; |
||
123 | |||
124 | +static int ess_parse(struct edma_common_info *edma) |
||
125 | +{ |
||
126 | + struct device_node *switch_node; |
||
127 | + int ret = -EINVAL; |
||
128 | + |
||
129 | + switch_node = of_find_node_by_name(NULL, "ess-switch"); |
||
130 | + if (!switch_node) { |
||
131 | + pr_err("cannot find ess-switch node\n"); |
||
132 | + goto out; |
||
133 | + } |
||
134 | + |
||
135 | + edma->ess_hw_addr = of_io_request_and_map(switch_node, |
||
136 | + 0, KBUILD_MODNAME); |
||
137 | + if (!edma->ess_hw_addr) { |
||
138 | + pr_err("%s ioremap fail.", __func__); |
||
139 | + goto out; |
||
140 | + } |
||
141 | + |
||
142 | + edma->ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); |
||
143 | + ret = clk_prepare_enable(edma->ess_clk); |
||
144 | +out: |
||
145 | + of_node_put(switch_node); |
||
146 | + return ret; |
||
147 | +} |
||
148 | + |
||
149 | /* edma_axi_netdev_ops |
||
150 | * Describe the operations supported by registered netdevices |
||
151 | * |
||
152 | @@ -786,6 +912,17 @@ static int edma_axi_probe(struct platfor |
||
153 | miibus = mdio_data->mii_bus; |
||
154 | } |
||
155 | |||
156 | + if (of_property_read_bool(np, "qcom,single-phy") && |
||
157 | + edma_cinfo->num_gmac == 1) { |
||
158 | + err = ess_parse(edma_cinfo); |
||
159 | + if (!err) |
||
160 | + err = ess_reset(edma_cinfo); |
||
161 | + if (err) |
||
162 | + goto err_single_phy_init; |
||
163 | + else |
||
164 | + edma_cinfo->is_single_phy = true; |
||
165 | + } |
||
166 | + |
||
167 | for_each_available_child_of_node(np, pnp) { |
||
168 | const char *mac_addr; |
||
169 | |||
170 | @@ -1074,11 +1211,15 @@ static int edma_axi_probe(struct platfor |
||
171 | |||
172 | for (i = 0; i < edma_cinfo->num_gmac; i++) { |
||
173 | if (adapter[i]->poll_required) { |
||
174 | + int phy_mode = of_get_phy_mode(np); |
||
175 | + |
||
176 | + if (phy_mode < 0) |
||
177 | + phy_mode = PHY_INTERFACE_MODE_SGMII; |
||
178 | adapter[i]->phydev = |
||
179 | phy_connect(edma_netdev[i], |
||
180 | (const char *)adapter[i]->phy_id, |
||
181 | &edma_adjust_link, |
||
182 | - PHY_INTERFACE_MODE_SGMII); |
||
183 | + phy_mode); |
||
184 | if (IS_ERR(adapter[i]->phydev)) { |
||
185 | dev_dbg(&pdev->dev, "PHY attach FAIL"); |
||
186 | err = -EIO; |
||
187 | @@ -1125,6 +1266,9 @@ err_rmap_alloc_fail: |
||
188 | for (i = 0; i < edma_cinfo->num_gmac; i++) |
||
189 | unregister_netdev(edma_netdev[i]); |
||
190 | err_register: |
||
191 | +err_single_phy_init: |
||
192 | + iounmap(edma_cinfo->ess_hw_addr); |
||
193 | + clk_disable_unprepare(edma_cinfo->ess_clk); |
||
194 | err_mdiobus_init_fail: |
||
195 | edma_free_rx_rings(edma_cinfo); |
||
196 | err_rx_rinit: |
||
197 | @@ -1185,6 +1329,8 @@ static int edma_axi_remove(struct platfo |
||
198 | del_timer_sync(&edma_stats_timer); |
||
199 | edma_free_irqs(adapter); |
||
200 | unregister_net_sysctl_table(edma_cinfo->edma_ctl_table_hdr); |
||
201 | + iounmap(edma_cinfo->ess_hw_addr); |
||
202 | + clk_disable_unprepare(edma_cinfo->ess_clk); |
||
203 | edma_free_tx_resources(edma_cinfo); |
||
204 | edma_free_rx_resources(edma_cinfo); |
||
205 | edma_free_tx_rings(edma_cinfo); |
||
206 | --- a/drivers/net/ethernet/qualcomm/essedma/edma.c |
||
207 | +++ b/drivers/net/ethernet/qualcomm/essedma/edma.c |
||
208 | @@ -161,8 +161,10 @@ static void edma_configure_rx(struct edm |
||
209 | /* Set Rx FIFO threshold to start to DMA data to host */ |
||
210 | rxq_ctrl_data = EDMA_FIFO_THRESH_128_BYTE; |
||
211 | |||
212 | - /* Set RX remove vlan bit */ |
||
213 | - rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN; |
||
214 | + if (!edma_cinfo->is_single_phy) { |
||
215 | + /* Set RX remove vlan bit */ |
||
216 | + rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN; |
||
217 | + } |
||
218 | |||
219 | edma_write_reg(EDMA_REG_RXQ_CTRL, rxq_ctrl_data); |
||
220 | } |
||
221 | @@ -1295,6 +1297,10 @@ void edma_adjust_link(struct net_device |
||
222 | if (status == __EDMA_LINKUP && adapter->link_state == __EDMA_LINKDOWN) { |
||
223 | dev_info(&adapter->pdev->dev, "%s: GMAC Link is up with phy_speed=%d\n", netdev->name, phydev->speed); |
||
224 | adapter->link_state = __EDMA_LINKUP; |
||
225 | + if (adapter->edma_cinfo->is_single_phy) { |
||
226 | + ess_set_port_status_speed(adapter->edma_cinfo, phydev, |
||
227 | + ffs(adapter->dp_bitmap) - 1); |
||
228 | + } |
||
229 | netif_carrier_on(netdev); |
||
230 | if (netif_running(netdev)) |
||
231 | netif_tx_wake_all_queues(netdev); |
||
232 | @@ -1388,10 +1394,12 @@ netdev_tx_t edma_xmit(struct sk_buff *sk |
||
233 | } |
||
234 | |||
235 | /* Check and mark VLAN tag offload */ |
||
236 | - if (skb_vlan_tag_present(skb)) |
||
237 | - flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; |
||
238 | - else if (adapter->default_vlan_tag) |
||
239 | - flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; |
||
240 | + if (!adapter->edma_cinfo->is_single_phy) { |
||
241 | + if (unlikely(skb_vlan_tag_present(skb))) |
||
242 | + flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; |
||
243 | + else if (adapter->default_vlan_tag) |
||
244 | + flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; |
||
245 | + } |
||
246 | |||
247 | /* Check and mark checksum offload */ |
||
248 | if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) |
||
249 | --- a/drivers/net/ethernet/qualcomm/essedma/edma.h |
||
250 | +++ b/drivers/net/ethernet/qualcomm/essedma/edma.h |
||
251 | @@ -31,6 +31,7 @@ |
||
252 | #include <linux/platform_device.h> |
||
253 | #include <linux/of.h> |
||
254 | #include <linux/of_device.h> |
||
255 | +#include <linux/clk.h> |
||
256 | #include <linux/kernel.h> |
||
257 | #include <linux/device.h> |
||
258 | #include <linux/sysctl.h> |
||
259 | @@ -331,6 +332,10 @@ struct edma_common_info { |
||
260 | struct edma_hw hw; /* edma hw specific structure */ |
||
261 | struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */ |
||
262 | spinlock_t stats_lock; /* protect edma stats area for updation */ |
||
263 | + |
||
264 | + bool is_single_phy; |
||
265 | + void __iomem *ess_hw_addr; |
||
266 | + struct clk *ess_clk; |
||
267 | }; |
||
268 | |||
269 | /* transimit packet descriptor (tpd) ring */ |
||
270 | @@ -443,4 +448,6 @@ void edma_change_tx_coalesce(int usecs); |
||
271 | void edma_change_rx_coalesce(int usecs); |
||
272 | void edma_get_tx_rx_coalesce(u32 *reg_val); |
||
273 | void edma_clear_irq_status(void); |
||
274 | +void ess_set_port_status_speed(struct edma_common_info *edma_cinfo, |
||
275 | + struct phy_device *phydev, uint8_t port_id); |
||
276 | #endif /* _EDMA_H_ */ |
||
277 | --- a/drivers/net/ethernet/qualcomm/essedma/ess_edma.h |
||
278 | +++ b/drivers/net/ethernet/qualcomm/essedma/ess_edma.h |
||
279 | @@ -329,4 +329,61 @@ struct edma_hw; |
||
280 | #define EDMA_RRD_PRIORITY_MASK 0x7 |
||
281 | #define EDMA_RRD_PORT_TYPE_SHIFT 7 |
||
282 | #define EDMA_RRD_PORT_TYPE_MASK 0x1F |
||
283 | + |
||
284 | +#define ESS_RGMII_CTRL 0x0004 |
||
285 | + |
||
286 | +/* Port status registers */ |
||
287 | +#define ESS_PORT0_STATUS 0x007C |
||
288 | +#define ESS_PORT1_STATUS 0x0080 |
||
289 | +#define ESS_PORT2_STATUS 0x0084 |
||
290 | +#define ESS_PORT3_STATUS 0x0088 |
||
291 | +#define ESS_PORT4_STATUS 0x008C |
||
292 | +#define ESS_PORT5_STATUS 0x0090 |
||
293 | + |
||
294 | +#define ESS_PORT_STATUS_HDX_FLOW_CTL 0x80 |
||
295 | +#define ESS_PORT_STATUS_DUPLEX_MODE 0x40 |
||
296 | +#define ESS_PORT_STATUS_RX_FLOW_EN 0x20 |
||
297 | +#define ESS_PORT_STATUS_TX_FLOW_EN 0x10 |
||
298 | +#define ESS_PORT_STATUS_RX_MAC_EN 0x08 |
||
299 | +#define ESS_PORT_STATUS_TX_MAC_EN 0x04 |
||
300 | +#define ESS_PORT_STATUS_SPEED_INV 0x03 |
||
301 | +#define ESS_PORT_STATUS_SPEED_1000 0x02 |
||
302 | +#define ESS_PORT_STATUS_SPEED_100 0x01 |
||
303 | +#define ESS_PORT_STATUS_SPEED_10 0x00 |
||
304 | + |
||
305 | +#define ESS_PORT_1G_FDX (ESS_PORT_STATUS_DUPLEX_MODE | ESS_PORT_STATUS_RX_FLOW_EN | \ |
||
306 | + ESS_PORT_STATUS_TX_FLOW_EN | ESS_PORT_STATUS_RX_MAC_EN | \ |
||
307 | + ESS_PORT_STATUS_TX_MAC_EN | ESS_PORT_STATUS_SPEED_1000) |
||
308 | + |
||
309 | +#define PHY_STATUS_REG 0x11 |
||
310 | +#define PHY_STATUS_SPEED 0xC000 |
||
311 | +#define PHY_STATUS_SPEED_SHIFT 14 |
||
312 | +#define PHY_STATUS_DUPLEX 0x2000 |
||
313 | +#define PHY_STATUS_DUPLEX_SHIFT 13 |
||
314 | +#define PHY_STATUS_SPEED_DUPLEX_RESOLVED 0x0800 |
||
315 | +#define PHY_STATUS_CARRIER 0x0400 |
||
316 | +#define PHY_STATUS_CARRIER_SHIFT 10 |
||
317 | + |
||
318 | +/* Port lookup control registers */ |
||
319 | +#define ESS_PORT0_LOOKUP_CTRL 0x0660 |
||
320 | +#define ESS_PORT1_LOOKUP_CTRL 0x066C |
||
321 | +#define ESS_PORT2_LOOKUP_CTRL 0x0678 |
||
322 | +#define ESS_PORT3_LOOKUP_CTRL 0x0684 |
||
323 | +#define ESS_PORT4_LOOKUP_CTRL 0x0690 |
||
324 | +#define ESS_PORT5_LOOKUP_CTRL 0x069C |
||
325 | + |
||
326 | +#define ESS_PORT0_HEADER_CTRL 0x009C |
||
327 | + |
||
328 | +#define ESS_PORTS_ALL 0x3f |
||
329 | + |
||
330 | +#define ESS_FWD_CTRL1 0x0624 |
||
331 | +#define ESS_FWD_CTRL1_UC_FLOOD BITS(0, 7) |
||
332 | +#define ESS_FWD_CTRL1_UC_FLOOD_S 0 |
||
333 | +#define ESS_FWD_CTRL1_MC_FLOOD BITS(8, 7) |
||
334 | +#define ESS_FWD_CTRL1_MC_FLOOD_S 8 |
||
335 | +#define ESS_FWD_CTRL1_BC_FLOOD BITS(16, 7) |
||
336 | +#define ESS_FWD_CTRL1_BC_FLOOD_S 16 |
||
337 | +#define ESS_FWD_CTRL1_IGMP BITS(24, 7) |
||
338 | +#define ESS_FWD_CTRL1_IGMP_S 24 |
||
339 | + |
||
340 | #endif /* _ESS_EDMA_H_ */ |