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
sxgbe_mtl_init(void __iomem * ioaddr,unsigned int etsalg,unsigned int raa)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(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(reg_val, 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(reg_val, ioaddr + SXGBE_MTL_OP_MODE_REG);
51 }
52
53 /* For Dynamic DMA channel mapping for Rx queue */
sxgbe_mtl_dma_dm_rxqueue(void __iomem * ioaddr)54 static void sxgbe_mtl_dma_dm_rxqueue(void __iomem *ioaddr)
55 {
56 writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP0_REG);
57 writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP1_REG);
58 writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP2_REG);
59 }
60
sxgbe_mtl_set_txfifosize(void __iomem * ioaddr,int queue_num,int queue_fifo)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(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num));
69 reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT);
70 writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num));
71 }
72
sxgbe_mtl_set_rxfifosize(void __iomem * ioaddr,int queue_num,int queue_fifo)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(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
81 reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT);
82 writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
83 }
84
sxgbe_mtl_enable_txqueue(void __iomem * ioaddr,int queue_num)85 static void sxgbe_mtl_enable_txqueue(void __iomem *ioaddr, int queue_num)
86 {
87 u32 reg_val;
88
89 reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num));
90 reg_val |= SXGBE_MTL_ENABLE_QUEUE;
91 writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num));
92 }
93
sxgbe_mtl_disable_txqueue(void __iomem * ioaddr,int queue_num)94 static void sxgbe_mtl_disable_txqueue(void __iomem *ioaddr, int queue_num)
95 {
96 u32 reg_val;
97
98 reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num));
99 reg_val &= ~SXGBE_MTL_ENABLE_QUEUE;
100 writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num));
101 }
102
sxgbe_mtl_fc_active(void __iomem * ioaddr,int queue_num,int threshold)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(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(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
113 }
114
sxgbe_mtl_fc_enable(void __iomem * ioaddr,int queue_num)115 static void sxgbe_mtl_fc_enable(void __iomem *ioaddr, int queue_num)
116 {
117 u32 reg_val;
118
119 reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
120 reg_val |= SXGBE_MTL_ENABLE_FC;
121 writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
122 }
123
sxgbe_mtl_fc_deactive(void __iomem * ioaddr,int queue_num,int threshold)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(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(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
134 }
135
sxgbe_mtl_fep_enable(void __iomem * ioaddr,int queue_num)136 static void sxgbe_mtl_fep_enable(void __iomem *ioaddr, int queue_num)
137 {
138 u32 reg_val;
139
140 reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
141 reg_val |= SXGBE_MTL_RXQ_OP_FEP;
142
143 writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
144 }
145
sxgbe_mtl_fep_disable(void __iomem * ioaddr,int queue_num)146 static void sxgbe_mtl_fep_disable(void __iomem *ioaddr, int queue_num)
147 {
148 u32 reg_val;
149
150 reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
151 reg_val &= ~(SXGBE_MTL_RXQ_OP_FEP);
152
153 writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
154 }
155
sxgbe_mtl_fup_enable(void __iomem * ioaddr,int queue_num)156 static void sxgbe_mtl_fup_enable(void __iomem *ioaddr, int queue_num)
157 {
158 u32 reg_val;
159
160 reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
161 reg_val |= SXGBE_MTL_RXQ_OP_FUP;
162
163 writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
164 }
165
sxgbe_mtl_fup_disable(void __iomem * ioaddr,int queue_num)166 static void sxgbe_mtl_fup_disable(void __iomem *ioaddr, int queue_num)
167 {
168 u32 reg_val;
169
170 reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
171 reg_val &= ~(SXGBE_MTL_RXQ_OP_FUP);
172
173 writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num));
174 }
175
176
sxgbe_set_tx_mtl_mode(void __iomem * ioaddr,int queue_num,int tx_mode)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(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(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num));
206 }
207
sxgbe_set_rx_mtl_mode(void __iomem * ioaddr,int queue_num,int rx_mode)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(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(reg_val, 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
sxgbe_get_mtl_ops(void)248 const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void)
249 {
250 return &mtl_ops;
251 }
252