1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* 10G controller driver for Samsung SoCs |
3 | * |
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com |
6 | * |
7 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> |
8 | */ |
9 | |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
11 | |
12 | #include <linux/io.h> |
13 | #include <linux/errno.h> |
14 | #include <linux/export.h> |
15 | #include <linux/jiffies.h> |
16 | |
17 | #include "sxgbe_mtl.h" |
18 | #include "sxgbe_reg.h" |
19 | |
20 | static void sxgbe_mtl_init(void __iomem *ioaddr, unsigned int etsalg, |
21 | unsigned int raa) |
22 | { |
23 | u32 reg_val; |
24 | |
25 | reg_val = readl(addr: ioaddr + SXGBE_MTL_OP_MODE_REG); |
26 | reg_val &= ETS_RST; |
27 | |
28 | /* ETS Algorith */ |
29 | switch (etsalg & SXGBE_MTL_OPMODE_ESTMASK) { |
30 | case ETS_WRR: |
31 | reg_val &= ETS_WRR; |
32 | break; |
33 | case ETS_WFQ: |
34 | reg_val |= ETS_WFQ; |
35 | break; |
36 | case ETS_DWRR: |
37 | reg_val |= ETS_DWRR; |
38 | break; |
39 | } |
40 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_OP_MODE_REG); |
41 | |
42 | switch (raa & SXGBE_MTL_OPMODE_RAAMASK) { |
43 | case RAA_SP: |
44 | reg_val &= RAA_SP; |
45 | break; |
46 | case RAA_WSP: |
47 | reg_val |= RAA_WSP; |
48 | break; |
49 | } |
50 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_OP_MODE_REG); |
51 | } |
52 | |
53 | /* For Dynamic DMA channel mapping for Rx queue */ |
54 | static void sxgbe_mtl_dma_dm_rxqueue(void __iomem *ioaddr) |
55 | { |
56 | writel(RX_QUEUE_DYNAMIC, addr: ioaddr + SXGBE_MTL_RXQ_DMAMAP0_REG); |
57 | writel(RX_QUEUE_DYNAMIC, addr: ioaddr + SXGBE_MTL_RXQ_DMAMAP1_REG); |
58 | writel(RX_QUEUE_DYNAMIC, addr: ioaddr + SXGBE_MTL_RXQ_DMAMAP2_REG); |
59 | } |
60 | |
61 | static void sxgbe_mtl_set_txfifosize(void __iomem *ioaddr, int queue_num, |
62 | int queue_fifo) |
63 | { |
64 | u32 fifo_bits, reg_val; |
65 | |
66 | /* 0 means 256 bytes */ |
67 | fifo_bits = (queue_fifo / SXGBE_MTL_TX_FIFO_DIV) - 1; |
68 | reg_val = readl(addr: ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); |
69 | reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT); |
70 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); |
71 | } |
72 | |
73 | static void sxgbe_mtl_set_rxfifosize(void __iomem *ioaddr, int queue_num, |
74 | int queue_fifo) |
75 | { |
76 | u32 fifo_bits, reg_val; |
77 | |
78 | /* 0 means 256 bytes */ |
79 | fifo_bits = (queue_fifo / SXGBE_MTL_RX_FIFO_DIV)-1; |
80 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
81 | reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT); |
82 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
83 | } |
84 | |
85 | static void sxgbe_mtl_enable_txqueue(void __iomem *ioaddr, int queue_num) |
86 | { |
87 | u32 reg_val; |
88 | |
89 | reg_val = readl(addr: ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); |
90 | reg_val |= SXGBE_MTL_ENABLE_QUEUE; |
91 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); |
92 | } |
93 | |
94 | static void sxgbe_mtl_disable_txqueue(void __iomem *ioaddr, int queue_num) |
95 | { |
96 | u32 reg_val; |
97 | |
98 | reg_val = readl(addr: ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); |
99 | reg_val &= ~SXGBE_MTL_ENABLE_QUEUE; |
100 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); |
101 | } |
102 | |
103 | static void sxgbe_mtl_fc_active(void __iomem *ioaddr, int queue_num, |
104 | int threshold) |
105 | { |
106 | u32 reg_val; |
107 | |
108 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
109 | reg_val &= ~(SXGBE_MTL_FCMASK << RX_FC_ACTIVE); |
110 | reg_val |= (threshold << RX_FC_ACTIVE); |
111 | |
112 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
113 | } |
114 | |
115 | static void sxgbe_mtl_fc_enable(void __iomem *ioaddr, int queue_num) |
116 | { |
117 | u32 reg_val; |
118 | |
119 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
120 | reg_val |= SXGBE_MTL_ENABLE_FC; |
121 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
122 | } |
123 | |
124 | static void sxgbe_mtl_fc_deactive(void __iomem *ioaddr, int queue_num, |
125 | int threshold) |
126 | { |
127 | u32 reg_val; |
128 | |
129 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
130 | reg_val &= ~(SXGBE_MTL_FCMASK << RX_FC_DEACTIVE); |
131 | reg_val |= (threshold << RX_FC_DEACTIVE); |
132 | |
133 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
134 | } |
135 | |
136 | static void sxgbe_mtl_fep_enable(void __iomem *ioaddr, int queue_num) |
137 | { |
138 | u32 reg_val; |
139 | |
140 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
141 | reg_val |= SXGBE_MTL_RXQ_OP_FEP; |
142 | |
143 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
144 | } |
145 | |
146 | static void sxgbe_mtl_fep_disable(void __iomem *ioaddr, int queue_num) |
147 | { |
148 | u32 reg_val; |
149 | |
150 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
151 | reg_val &= ~(SXGBE_MTL_RXQ_OP_FEP); |
152 | |
153 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
154 | } |
155 | |
156 | static void sxgbe_mtl_fup_enable(void __iomem *ioaddr, int queue_num) |
157 | { |
158 | u32 reg_val; |
159 | |
160 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
161 | reg_val |= SXGBE_MTL_RXQ_OP_FUP; |
162 | |
163 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
164 | } |
165 | |
166 | static void sxgbe_mtl_fup_disable(void __iomem *ioaddr, int queue_num) |
167 | { |
168 | u32 reg_val; |
169 | |
170 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
171 | reg_val &= ~(SXGBE_MTL_RXQ_OP_FUP); |
172 | |
173 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
174 | } |
175 | |
176 | |
177 | static void sxgbe_set_tx_mtl_mode(void __iomem *ioaddr, int queue_num, |
178 | int tx_mode) |
179 | { |
180 | u32 reg_val; |
181 | |
182 | reg_val = readl(addr: ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); |
183 | /* TX specific MTL mode settings */ |
184 | if (tx_mode == SXGBE_MTL_SFMODE) { |
185 | reg_val |= SXGBE_MTL_SFMODE; |
186 | } else { |
187 | /* set the TTC values */ |
188 | if (tx_mode <= 64) |
189 | reg_val |= MTL_CONTROL_TTC_64; |
190 | else if (tx_mode <= 96) |
191 | reg_val |= MTL_CONTROL_TTC_96; |
192 | else if (tx_mode <= 128) |
193 | reg_val |= MTL_CONTROL_TTC_128; |
194 | else if (tx_mode <= 192) |
195 | reg_val |= MTL_CONTROL_TTC_192; |
196 | else if (tx_mode <= 256) |
197 | reg_val |= MTL_CONTROL_TTC_256; |
198 | else if (tx_mode <= 384) |
199 | reg_val |= MTL_CONTROL_TTC_384; |
200 | else |
201 | reg_val |= MTL_CONTROL_TTC_512; |
202 | } |
203 | |
204 | /* write into TXQ operation register */ |
205 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); |
206 | } |
207 | |
208 | static void sxgbe_set_rx_mtl_mode(void __iomem *ioaddr, int queue_num, |
209 | int rx_mode) |
210 | { |
211 | u32 reg_val; |
212 | |
213 | reg_val = readl(addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
214 | /* RX specific MTL mode settings */ |
215 | if (rx_mode == SXGBE_RX_MTL_SFMODE) { |
216 | reg_val |= SXGBE_RX_MTL_SFMODE; |
217 | } else { |
218 | if (rx_mode <= 64) |
219 | reg_val |= MTL_CONTROL_RTC_64; |
220 | else if (rx_mode <= 96) |
221 | reg_val |= MTL_CONTROL_RTC_96; |
222 | else if (rx_mode <= 128) |
223 | reg_val |= MTL_CONTROL_RTC_128; |
224 | } |
225 | |
226 | /* write into RXQ operation register */ |
227 | writel(val: reg_val, addr: ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); |
228 | } |
229 | |
230 | static const struct sxgbe_mtl_ops mtl_ops = { |
231 | .mtl_set_txfifosize = sxgbe_mtl_set_txfifosize, |
232 | .mtl_set_rxfifosize = sxgbe_mtl_set_rxfifosize, |
233 | .mtl_enable_txqueue = sxgbe_mtl_enable_txqueue, |
234 | .mtl_disable_txqueue = sxgbe_mtl_disable_txqueue, |
235 | .mtl_dynamic_dma_rxqueue = sxgbe_mtl_dma_dm_rxqueue, |
236 | .set_tx_mtl_mode = sxgbe_set_tx_mtl_mode, |
237 | .set_rx_mtl_mode = sxgbe_set_rx_mtl_mode, |
238 | .mtl_init = sxgbe_mtl_init, |
239 | .mtl_fc_active = sxgbe_mtl_fc_active, |
240 | .mtl_fc_deactive = sxgbe_mtl_fc_deactive, |
241 | .mtl_fc_enable = sxgbe_mtl_fc_enable, |
242 | .mtl_fep_enable = sxgbe_mtl_fep_enable, |
243 | .mtl_fep_disable = sxgbe_mtl_fep_disable, |
244 | .mtl_fup_enable = sxgbe_mtl_fup_enable, |
245 | .mtl_fup_disable = sxgbe_mtl_fup_disable |
246 | }; |
247 | |
248 | const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void) |
249 | { |
250 | return &mtl_ops; |
251 | } |
252 | |