18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 10G controller driver for Samsung SoCs 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2013 Samsung Electronics Co., Ltd. 58c2ecf20Sopenharmony_ci * http://www.samsung.com 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Siva Reddy Kallam <siva.kallam@samsung.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/io.h> 138c2ecf20Sopenharmony_ci#include <linux/errno.h> 148c2ecf20Sopenharmony_ci#include <linux/export.h> 158c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "sxgbe_mtl.h" 188c2ecf20Sopenharmony_ci#include "sxgbe_reg.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic void sxgbe_mtl_init(void __iomem *ioaddr, unsigned int etsalg, 218c2ecf20Sopenharmony_ci unsigned int raa) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci u32 reg_val; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_OP_MODE_REG); 268c2ecf20Sopenharmony_ci reg_val &= ETS_RST; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci /* ETS Algorith */ 298c2ecf20Sopenharmony_ci switch (etsalg & SXGBE_MTL_OPMODE_ESTMASK) { 308c2ecf20Sopenharmony_ci case ETS_WRR: 318c2ecf20Sopenharmony_ci reg_val &= ETS_WRR; 328c2ecf20Sopenharmony_ci break; 338c2ecf20Sopenharmony_ci case ETS_WFQ: 348c2ecf20Sopenharmony_ci reg_val |= ETS_WFQ; 358c2ecf20Sopenharmony_ci break; 368c2ecf20Sopenharmony_ci case ETS_DWRR: 378c2ecf20Sopenharmony_ci reg_val |= ETS_DWRR; 388c2ecf20Sopenharmony_ci break; 398c2ecf20Sopenharmony_ci } 408c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_OP_MODE_REG); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci switch (raa & SXGBE_MTL_OPMODE_RAAMASK) { 438c2ecf20Sopenharmony_ci case RAA_SP: 448c2ecf20Sopenharmony_ci reg_val &= RAA_SP; 458c2ecf20Sopenharmony_ci break; 468c2ecf20Sopenharmony_ci case RAA_WSP: 478c2ecf20Sopenharmony_ci reg_val |= RAA_WSP; 488c2ecf20Sopenharmony_ci break; 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_OP_MODE_REG); 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* For Dynamic DMA channel mapping for Rx queue */ 548c2ecf20Sopenharmony_cistatic void sxgbe_mtl_dma_dm_rxqueue(void __iomem *ioaddr) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP0_REG); 578c2ecf20Sopenharmony_ci writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP1_REG); 588c2ecf20Sopenharmony_ci writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP2_REG); 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic void sxgbe_mtl_set_txfifosize(void __iomem *ioaddr, int queue_num, 628c2ecf20Sopenharmony_ci int queue_fifo) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci u32 fifo_bits, reg_val; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* 0 means 256 bytes */ 678c2ecf20Sopenharmony_ci fifo_bits = (queue_fifo / SXGBE_MTL_TX_FIFO_DIV) - 1; 688c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); 698c2ecf20Sopenharmony_ci reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT); 708c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic void sxgbe_mtl_set_rxfifosize(void __iomem *ioaddr, int queue_num, 748c2ecf20Sopenharmony_ci int queue_fifo) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci u32 fifo_bits, reg_val; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* 0 means 256 bytes */ 798c2ecf20Sopenharmony_ci fifo_bits = (queue_fifo / SXGBE_MTL_RX_FIFO_DIV)-1; 808c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 818c2ecf20Sopenharmony_ci reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT); 828c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic void sxgbe_mtl_enable_txqueue(void __iomem *ioaddr, int queue_num) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci u32 reg_val; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); 908c2ecf20Sopenharmony_ci reg_val |= SXGBE_MTL_ENABLE_QUEUE; 918c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic void sxgbe_mtl_disable_txqueue(void __iomem *ioaddr, int queue_num) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci u32 reg_val; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); 998c2ecf20Sopenharmony_ci reg_val &= ~SXGBE_MTL_ENABLE_QUEUE; 1008c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic void sxgbe_mtl_fc_active(void __iomem *ioaddr, int queue_num, 1048c2ecf20Sopenharmony_ci int threshold) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci u32 reg_val; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1098c2ecf20Sopenharmony_ci reg_val &= ~(SXGBE_MTL_FCMASK << RX_FC_ACTIVE); 1108c2ecf20Sopenharmony_ci reg_val |= (threshold << RX_FC_ACTIVE); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic void sxgbe_mtl_fc_enable(void __iomem *ioaddr, int queue_num) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci u32 reg_val; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1208c2ecf20Sopenharmony_ci reg_val |= SXGBE_MTL_ENABLE_FC; 1218c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic void sxgbe_mtl_fc_deactive(void __iomem *ioaddr, int queue_num, 1258c2ecf20Sopenharmony_ci int threshold) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci u32 reg_val; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1308c2ecf20Sopenharmony_ci reg_val &= ~(SXGBE_MTL_FCMASK << RX_FC_DEACTIVE); 1318c2ecf20Sopenharmony_ci reg_val |= (threshold << RX_FC_DEACTIVE); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic void sxgbe_mtl_fep_enable(void __iomem *ioaddr, int queue_num) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci u32 reg_val; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1418c2ecf20Sopenharmony_ci reg_val |= SXGBE_MTL_RXQ_OP_FEP; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic void sxgbe_mtl_fep_disable(void __iomem *ioaddr, int queue_num) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci u32 reg_val; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1518c2ecf20Sopenharmony_ci reg_val &= ~(SXGBE_MTL_RXQ_OP_FEP); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic void sxgbe_mtl_fup_enable(void __iomem *ioaddr, int queue_num) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci u32 reg_val; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1618c2ecf20Sopenharmony_ci reg_val |= SXGBE_MTL_RXQ_OP_FUP; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic void sxgbe_mtl_fup_disable(void __iomem *ioaddr, int queue_num) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci u32 reg_val; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1718c2ecf20Sopenharmony_ci reg_val &= ~(SXGBE_MTL_RXQ_OP_FUP); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void sxgbe_set_tx_mtl_mode(void __iomem *ioaddr, int queue_num, 1788c2ecf20Sopenharmony_ci int tx_mode) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci u32 reg_val; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); 1838c2ecf20Sopenharmony_ci /* TX specific MTL mode settings */ 1848c2ecf20Sopenharmony_ci if (tx_mode == SXGBE_MTL_SFMODE) { 1858c2ecf20Sopenharmony_ci reg_val |= SXGBE_MTL_SFMODE; 1868c2ecf20Sopenharmony_ci } else { 1878c2ecf20Sopenharmony_ci /* set the TTC values */ 1888c2ecf20Sopenharmony_ci if (tx_mode <= 64) 1898c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_TTC_64; 1908c2ecf20Sopenharmony_ci else if (tx_mode <= 96) 1918c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_TTC_96; 1928c2ecf20Sopenharmony_ci else if (tx_mode <= 128) 1938c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_TTC_128; 1948c2ecf20Sopenharmony_ci else if (tx_mode <= 192) 1958c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_TTC_192; 1968c2ecf20Sopenharmony_ci else if (tx_mode <= 256) 1978c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_TTC_256; 1988c2ecf20Sopenharmony_ci else if (tx_mode <= 384) 1998c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_TTC_384; 2008c2ecf20Sopenharmony_ci else 2018c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_TTC_512; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* write into TXQ operation register */ 2058c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic void sxgbe_set_rx_mtl_mode(void __iomem *ioaddr, int queue_num, 2098c2ecf20Sopenharmony_ci int rx_mode) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci u32 reg_val; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 2148c2ecf20Sopenharmony_ci /* RX specific MTL mode settings */ 2158c2ecf20Sopenharmony_ci if (rx_mode == SXGBE_RX_MTL_SFMODE) { 2168c2ecf20Sopenharmony_ci reg_val |= SXGBE_RX_MTL_SFMODE; 2178c2ecf20Sopenharmony_ci } else { 2188c2ecf20Sopenharmony_ci if (rx_mode <= 64) 2198c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_RTC_64; 2208c2ecf20Sopenharmony_ci else if (rx_mode <= 96) 2218c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_RTC_96; 2228c2ecf20Sopenharmony_ci else if (rx_mode <= 128) 2238c2ecf20Sopenharmony_ci reg_val |= MTL_CONTROL_RTC_128; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci /* write into RXQ operation register */ 2278c2ecf20Sopenharmony_ci writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic const struct sxgbe_mtl_ops mtl_ops = { 2318c2ecf20Sopenharmony_ci .mtl_set_txfifosize = sxgbe_mtl_set_txfifosize, 2328c2ecf20Sopenharmony_ci .mtl_set_rxfifosize = sxgbe_mtl_set_rxfifosize, 2338c2ecf20Sopenharmony_ci .mtl_enable_txqueue = sxgbe_mtl_enable_txqueue, 2348c2ecf20Sopenharmony_ci .mtl_disable_txqueue = sxgbe_mtl_disable_txqueue, 2358c2ecf20Sopenharmony_ci .mtl_dynamic_dma_rxqueue = sxgbe_mtl_dma_dm_rxqueue, 2368c2ecf20Sopenharmony_ci .set_tx_mtl_mode = sxgbe_set_tx_mtl_mode, 2378c2ecf20Sopenharmony_ci .set_rx_mtl_mode = sxgbe_set_rx_mtl_mode, 2388c2ecf20Sopenharmony_ci .mtl_init = sxgbe_mtl_init, 2398c2ecf20Sopenharmony_ci .mtl_fc_active = sxgbe_mtl_fc_active, 2408c2ecf20Sopenharmony_ci .mtl_fc_deactive = sxgbe_mtl_fc_deactive, 2418c2ecf20Sopenharmony_ci .mtl_fc_enable = sxgbe_mtl_fc_enable, 2428c2ecf20Sopenharmony_ci .mtl_fep_enable = sxgbe_mtl_fep_enable, 2438c2ecf20Sopenharmony_ci .mtl_fep_disable = sxgbe_mtl_fep_disable, 2448c2ecf20Sopenharmony_ci .mtl_fup_enable = sxgbe_mtl_fup_enable, 2458c2ecf20Sopenharmony_ci .mtl_fup_disable = sxgbe_mtl_fup_disable 2468c2ecf20Sopenharmony_ci}; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciconst struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci return &mtl_ops; 2518c2ecf20Sopenharmony_ci} 252