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