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