diff options
Diffstat (limited to 'drivers/net/ethernet/apm/xgene')
-rw-r--r-- | drivers/net/ethernet/apm/xgene/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c | 200 | ||||
-rw-r--r-- | drivers/net/ethernet/apm/xgene/xgene_enet_ring2.h | 49 |
5 files changed, 253 insertions, 1 deletions
diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile index 68be565548c0..700b5abe5de5 100644 --- a/drivers/net/ethernet/apm/xgene/Makefile +++ b/drivers/net/ethernet/apm/xgene/Makefile | |||
@@ -3,5 +3,5 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \ | 5 | xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \ |
6 | xgene_enet_main.o xgene_enet_ethtool.o | 6 | xgene_enet_main.o xgene_enet_ring2.o xgene_enet_ethtool.o |
7 | obj-$(CONFIG_NET_XGENE) += xgene-enet.o | 7 | obj-$(CONFIG_NET_XGENE) += xgene-enet.o |
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h index 00a37787bfea..1dbc10a63458 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | |||
@@ -262,6 +262,7 @@ enum xgene_enet_ring_type { | |||
262 | 262 | ||
263 | enum xgene_ring_owner { | 263 | enum xgene_ring_owner { |
264 | RING_OWNER_ETH0, | 264 | RING_OWNER_ETH0, |
265 | RING_OWNER_ETH1, | ||
265 | RING_OWNER_CPU = 15, | 266 | RING_OWNER_CPU = 15, |
266 | RING_OWNER_INVALID | 267 | RING_OWNER_INVALID |
267 | }; | 268 | }; |
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h index 577c63c55b54..a44f4a3e9388 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h | |||
@@ -72,6 +72,8 @@ struct xgene_enet_desc_ring { | |||
72 | void __iomem *cmd_base; | 72 | void __iomem *cmd_base; |
73 | void __iomem *cmd; | 73 | void __iomem *cmd; |
74 | dma_addr_t dma; | 74 | dma_addr_t dma; |
75 | dma_addr_t irq_mbox_dma; | ||
76 | void *irq_mbox_addr; | ||
75 | u16 dst_ring_num; | 77 | u16 dst_ring_num; |
76 | u8 nbufpool; | 78 | u8 nbufpool; |
77 | struct sk_buff *(*rx_skb); | 79 | struct sk_buff *(*rx_skb); |
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c new file mode 100644 index 000000000000..0b6896bb351e --- /dev/null +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* Applied Micro X-Gene SoC Ethernet Driver | ||
2 | * | ||
3 | * Copyright (c) 2015, Applied Micro Circuits Corporation | ||
4 | * Author: Iyappan Subramanian <isubramanian@apm.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include "xgene_enet_main.h" | ||
21 | #include "xgene_enet_hw.h" | ||
22 | #include "xgene_enet_ring2.h" | ||
23 | |||
24 | static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring) | ||
25 | { | ||
26 | u32 *ring_cfg = ring->state; | ||
27 | u64 addr = ring->dma; | ||
28 | |||
29 | if (xgene_enet_ring_owner(ring->id) == RING_OWNER_CPU) { | ||
30 | ring_cfg[0] |= SET_VAL(X2_INTLINE, ring->id & RING_BUFNUM_MASK); | ||
31 | ring_cfg[3] |= SET_BIT(X2_DEQINTEN); | ||
32 | } | ||
33 | ring_cfg[0] |= SET_VAL(X2_CFGCRID, 1); | ||
34 | |||
35 | addr >>= 8; | ||
36 | ring_cfg[2] |= QCOHERENT | SET_VAL(RINGADDRL, addr); | ||
37 | |||
38 | addr >>= 27; | ||
39 | ring_cfg[3] |= SET_VAL(RINGSIZE, ring->cfgsize) | ||
40 | | ACCEPTLERR | ||
41 | | SET_VAL(RINGADDRH, addr); | ||
42 | ring_cfg[4] |= SET_VAL(X2_SELTHRSH, 1); | ||
43 | ring_cfg[5] |= SET_BIT(X2_QBASE_AM) | SET_BIT(X2_MSG_AM); | ||
44 | } | ||
45 | |||
46 | static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring) | ||
47 | { | ||
48 | u32 *ring_cfg = ring->state; | ||
49 | bool is_bufpool; | ||
50 | u32 val; | ||
51 | |||
52 | is_bufpool = xgene_enet_is_bufpool(ring->id); | ||
53 | val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR; | ||
54 | ring_cfg[4] |= SET_VAL(X2_RINGTYPE, val); | ||
55 | if (is_bufpool) | ||
56 | ring_cfg[3] |= SET_VAL(RINGMODE, BUFPOOL_MODE); | ||
57 | } | ||
58 | |||
59 | static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring) | ||
60 | { | ||
61 | u32 *ring_cfg = ring->state; | ||
62 | |||
63 | ring_cfg[3] |= RECOMBBUF; | ||
64 | ring_cfg[4] |= SET_VAL(X2_RECOMTIMEOUT, 0x7); | ||
65 | } | ||
66 | |||
67 | static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring, | ||
68 | u32 offset, u32 data) | ||
69 | { | ||
70 | struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); | ||
71 | |||
72 | iowrite32(data, pdata->ring_csr_addr + offset); | ||
73 | } | ||
74 | |||
75 | static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring) | ||
76 | { | ||
77 | struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); | ||
78 | int i; | ||
79 | |||
80 | xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num); | ||
81 | for (i = 0; i < pdata->ring_ops->num_ring_config; i++) { | ||
82 | xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4), | ||
83 | ring->state[i]); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring) | ||
88 | { | ||
89 | memset(ring->state, 0, sizeof(ring->state)); | ||
90 | xgene_enet_write_ring_state(ring); | ||
91 | } | ||
92 | |||
93 | static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring) | ||
94 | { | ||
95 | enum xgene_ring_owner owner; | ||
96 | |||
97 | xgene_enet_ring_set_type(ring); | ||
98 | |||
99 | owner = xgene_enet_ring_owner(ring->id); | ||
100 | if (owner == RING_OWNER_ETH0 || owner == RING_OWNER_ETH1) | ||
101 | xgene_enet_ring_set_recombbuf(ring); | ||
102 | |||
103 | xgene_enet_ring_init(ring); | ||
104 | xgene_enet_write_ring_state(ring); | ||
105 | } | ||
106 | |||
107 | static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring) | ||
108 | { | ||
109 | u32 ring_id_val, ring_id_buf; | ||
110 | bool is_bufpool; | ||
111 | |||
112 | if (xgene_enet_ring_owner(ring->id) == RING_OWNER_CPU) | ||
113 | return; | ||
114 | |||
115 | is_bufpool = xgene_enet_is_bufpool(ring->id); | ||
116 | |||
117 | ring_id_val = ring->id & GENMASK(9, 0); | ||
118 | ring_id_val |= OVERWRITE; | ||
119 | |||
120 | ring_id_buf = (ring->num << 9) & GENMASK(18, 9); | ||
121 | ring_id_buf |= PREFETCH_BUF_EN; | ||
122 | if (is_bufpool) | ||
123 | ring_id_buf |= IS_BUFFER_POOL; | ||
124 | |||
125 | xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val); | ||
126 | xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf); | ||
127 | } | ||
128 | |||
129 | static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring) | ||
130 | { | ||
131 | u32 ring_id; | ||
132 | |||
133 | ring_id = ring->id | OVERWRITE; | ||
134 | xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id); | ||
135 | xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0); | ||
136 | } | ||
137 | |||
138 | static struct xgene_enet_desc_ring *xgene_enet_setup_ring( | ||
139 | struct xgene_enet_desc_ring *ring) | ||
140 | { | ||
141 | bool is_bufpool; | ||
142 | u32 addr, i; | ||
143 | |||
144 | xgene_enet_clr_ring_state(ring); | ||
145 | xgene_enet_set_ring_state(ring); | ||
146 | xgene_enet_set_ring_id(ring); | ||
147 | |||
148 | ring->slots = xgene_enet_get_numslots(ring->id, ring->size); | ||
149 | |||
150 | is_bufpool = xgene_enet_is_bufpool(ring->id); | ||
151 | if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU) | ||
152 | return ring; | ||
153 | |||
154 | addr = CSR_VMID0_INTR_MBOX + (4 * (ring->id & RING_BUFNUM_MASK)); | ||
155 | xgene_enet_ring_wr32(ring, addr, ring->irq_mbox_dma >> 10); | ||
156 | |||
157 | for (i = 0; i < ring->slots; i++) | ||
158 | xgene_enet_mark_desc_slot_empty(&ring->raw_desc[i]); | ||
159 | |||
160 | return ring; | ||
161 | } | ||
162 | |||
163 | static void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring) | ||
164 | { | ||
165 | xgene_enet_clr_desc_ring_id(ring); | ||
166 | xgene_enet_clr_ring_state(ring); | ||
167 | } | ||
168 | |||
169 | static void xgene_enet_wr_cmd(struct xgene_enet_desc_ring *ring, int count) | ||
170 | { | ||
171 | u32 data = 0; | ||
172 | |||
173 | if (xgene_enet_ring_owner(ring->id) == RING_OWNER_CPU) { | ||
174 | data = SET_VAL(X2_INTLINE, ring->id & RING_BUFNUM_MASK) | | ||
175 | INTR_CLEAR; | ||
176 | } | ||
177 | data |= (count & GENMASK(16, 0)); | ||
178 | |||
179 | iowrite32(data, ring->cmd); | ||
180 | } | ||
181 | |||
182 | static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring) | ||
183 | { | ||
184 | u32 __iomem *cmd_base = ring->cmd_base; | ||
185 | u32 ring_state, num_msgs; | ||
186 | |||
187 | ring_state = ioread32(&cmd_base[1]); | ||
188 | num_msgs = GET_VAL(X2_NUMMSGSINQ, ring_state); | ||
189 | |||
190 | return num_msgs; | ||
191 | } | ||
192 | |||
193 | struct xgene_ring_ops xgene_ring2_ops = { | ||
194 | .num_ring_config = X2_NUM_RING_CONFIG, | ||
195 | .num_ring_id_shift = 13, | ||
196 | .setup = xgene_enet_setup_ring, | ||
197 | .clear = xgene_enet_clear_ring, | ||
198 | .wr_cmd = xgene_enet_wr_cmd, | ||
199 | .len = xgene_enet_ring_len, | ||
200 | }; | ||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.h b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.h new file mode 100644 index 000000000000..8b235db23c42 --- /dev/null +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* Applied Micro X-Gene SoC Ethernet Driver | ||
2 | * | ||
3 | * Copyright (c) 2015, Applied Micro Circuits Corporation | ||
4 | * Author: Iyappan Subramanian <isubramanian@apm.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #ifndef __XGENE_ENET_RING2_H__ | ||
21 | #define __XGENE_ENET_RING2_H__ | ||
22 | |||
23 | #include "xgene_enet_main.h" | ||
24 | |||
25 | #define X2_NUM_RING_CONFIG 6 | ||
26 | |||
27 | #define INTR_MBOX_SIZE 1024 | ||
28 | #define CSR_VMID0_INTR_MBOX 0x0270 | ||
29 | #define INTR_CLEAR BIT(23) | ||
30 | |||
31 | #define X2_MSG_AM_POS 10 | ||
32 | #define X2_QBASE_AM_POS 11 | ||
33 | #define X2_INTLINE_POS 24 | ||
34 | #define X2_INTLINE_LEN 5 | ||
35 | #define X2_CFGCRID_POS 29 | ||
36 | #define X2_CFGCRID_LEN 3 | ||
37 | #define X2_SELTHRSH_POS 7 | ||
38 | #define X2_SELTHRSH_LEN 3 | ||
39 | #define X2_RINGTYPE_POS 23 | ||
40 | #define X2_RINGTYPE_LEN 2 | ||
41 | #define X2_DEQINTEN_POS 29 | ||
42 | #define X2_RECOMTIMEOUT_POS 0 | ||
43 | #define X2_RECOMTIMEOUT_LEN 7 | ||
44 | #define X2_NUMMSGSINQ_POS 0 | ||
45 | #define X2_NUMMSGSINQ_LEN 17 | ||
46 | |||
47 | extern struct xgene_ring_ops xgene_ring2_ops; | ||
48 | |||
49 | #endif /* __XGENE_ENET_RING2_H__ */ | ||