ipq40xx: add support for ALFA Network AP120C-AC
[oweals/openwrt.git] / target / linux / ipq40xx / patches-4.14 / 712-mr33-essedma.patch
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, &regval); \
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, &reg_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_ */