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(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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 248 const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void) 249 { 250 return &mtl_ops; 251 } 252