root/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sxgbe_core_init
  2. sxgbe_core_dump_regs
  3. sxgbe_get_lpi_status
  4. sxgbe_core_host_irq_status
  5. sxgbe_core_pmt
  6. sxgbe_core_set_umac_addr
  7. sxgbe_core_get_umac_addr
  8. sxgbe_enable_tx
  9. sxgbe_enable_rx
  10. sxgbe_get_controller_version
  11. sxgbe_get_hw_feature
  12. sxgbe_core_set_speed
  13. sxgbe_core_enable_rxqueue
  14. sxgbe_core_disable_rxqueue
  15. sxgbe_set_eee_mode
  16. sxgbe_reset_eee_mode
  17. sxgbe_set_eee_pls
  18. sxgbe_set_eee_timer
  19. sxgbe_enable_rx_csum
  20. sxgbe_disable_rx_csum
  21. sxgbe_get_core_ops

   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/export.h>
  13 #include <linux/io.h>
  14 #include <linux/netdevice.h>
  15 #include <linux/phy.h>
  16 
  17 #include "sxgbe_common.h"
  18 #include "sxgbe_reg.h"
  19 
  20 /* MAC core initialization */
  21 static void sxgbe_core_init(void __iomem *ioaddr)
  22 {
  23         u32 regval;
  24 
  25         /* TX configuration */
  26         regval = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG);
  27         /* Other configurable parameters IFP, IPG, ISR, ISM
  28          * needs to be set if needed
  29          */
  30         regval |= SXGBE_TX_JABBER_DISABLE;
  31         writel(regval, ioaddr + SXGBE_CORE_TX_CONFIG_REG);
  32 
  33         /* RX configuration */
  34         regval = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);
  35         /* Other configurable parameters CST, SPEN, USP, GPSLCE
  36          * WD, LM, S2KP, HDSMS, GPSL, ELEN, ARPEN needs to be
  37          * set if needed
  38          */
  39         regval |= SXGBE_RX_JUMBPKT_ENABLE | SXGBE_RX_ACS_ENABLE;
  40         writel(regval, ioaddr + SXGBE_CORE_RX_CONFIG_REG);
  41 }
  42 
  43 /* Dump MAC registers */
  44 static void sxgbe_core_dump_regs(void __iomem *ioaddr)
  45 {
  46 }
  47 
  48 static int sxgbe_get_lpi_status(void __iomem *ioaddr, const u32 irq_status)
  49 {
  50         int status = 0;
  51         int lpi_status;
  52 
  53         /* Reading this register shall clear all the LPI status bits */
  54         lpi_status = readl(ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);
  55 
  56         if (lpi_status & LPI_CTRL_STATUS_TLPIEN)
  57                 status |= TX_ENTRY_LPI_MODE;
  58         if (lpi_status & LPI_CTRL_STATUS_TLPIEX)
  59                 status |= TX_EXIT_LPI_MODE;
  60         if (lpi_status & LPI_CTRL_STATUS_RLPIEN)
  61                 status |= RX_ENTRY_LPI_MODE;
  62         if (lpi_status & LPI_CTRL_STATUS_RLPIEX)
  63                 status |= RX_EXIT_LPI_MODE;
  64 
  65         return status;
  66 }
  67 
  68 /* Handle extra events on specific interrupts hw dependent */
  69 static int sxgbe_core_host_irq_status(void __iomem *ioaddr,
  70                                       struct sxgbe_extra_stats *x)
  71 {
  72         int irq_status, status = 0;
  73 
  74         irq_status = readl(ioaddr + SXGBE_CORE_INT_STATUS_REG);
  75 
  76         if (unlikely(irq_status & LPI_INT_STATUS))
  77                 status |= sxgbe_get_lpi_status(ioaddr, irq_status);
  78 
  79         return status;
  80 }
  81 
  82 /* Set power management mode (e.g. magic frame) */
  83 static void sxgbe_core_pmt(void __iomem *ioaddr, unsigned long mode)
  84 {
  85 }
  86 
  87 /* Set/Get Unicast MAC addresses */
  88 static void sxgbe_core_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
  89                                      unsigned int reg_n)
  90 {
  91         u32 high_word, low_word;
  92 
  93         high_word = (addr[5] << 8) | (addr[4]);
  94         low_word = (addr[3] << 24) | (addr[2] << 16) |
  95                    (addr[1] << 8) | (addr[0]);
  96         writel(high_word, ioaddr + SXGBE_CORE_ADD_HIGHOFFSET(reg_n));
  97         writel(low_word, ioaddr + SXGBE_CORE_ADD_LOWOFFSET(reg_n));
  98 }
  99 
 100 static void sxgbe_core_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
 101                                      unsigned int reg_n)
 102 {
 103         u32 high_word, low_word;
 104 
 105         high_word = readl(ioaddr + SXGBE_CORE_ADD_HIGHOFFSET(reg_n));
 106         low_word = readl(ioaddr + SXGBE_CORE_ADD_LOWOFFSET(reg_n));
 107 
 108         /* extract and assign address */
 109         addr[5] = (high_word & 0x0000FF00) >> 8;
 110         addr[4] = (high_word & 0x000000FF);
 111         addr[3] = (low_word & 0xFF000000) >> 24;
 112         addr[2] = (low_word & 0x00FF0000) >> 16;
 113         addr[1] = (low_word & 0x0000FF00) >> 8;
 114         addr[0] = (low_word & 0x000000FF);
 115 }
 116 
 117 static void sxgbe_enable_tx(void __iomem *ioaddr, bool enable)
 118 {
 119         u32 tx_config;
 120 
 121         tx_config = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG);
 122         tx_config &= ~SXGBE_TX_ENABLE;
 123 
 124         if (enable)
 125                 tx_config |= SXGBE_TX_ENABLE;
 126         writel(tx_config, ioaddr + SXGBE_CORE_TX_CONFIG_REG);
 127 }
 128 
 129 static void sxgbe_enable_rx(void __iomem *ioaddr, bool enable)
 130 {
 131         u32 rx_config;
 132 
 133         rx_config = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);
 134         rx_config &= ~SXGBE_RX_ENABLE;
 135 
 136         if (enable)
 137                 rx_config |= SXGBE_RX_ENABLE;
 138         writel(rx_config, ioaddr + SXGBE_CORE_RX_CONFIG_REG);
 139 }
 140 
 141 static int sxgbe_get_controller_version(void __iomem *ioaddr)
 142 {
 143         return readl(ioaddr + SXGBE_CORE_VERSION_REG);
 144 }
 145 
 146 /* If supported then get the optional core features */
 147 static unsigned int sxgbe_get_hw_feature(void __iomem *ioaddr,
 148                                          unsigned char feature_index)
 149 {
 150         return readl(ioaddr + (SXGBE_CORE_HW_FEA_REG(feature_index)));
 151 }
 152 
 153 static void sxgbe_core_set_speed(void __iomem *ioaddr, unsigned char speed)
 154 {
 155         u32 tx_cfg = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG);
 156 
 157         /* clear the speed bits */
 158         tx_cfg &= ~0x60000000;
 159         tx_cfg |= (speed << SXGBE_SPEED_LSHIFT);
 160 
 161         /* set the speed */
 162         writel(tx_cfg, ioaddr + SXGBE_CORE_TX_CONFIG_REG);
 163 }
 164 
 165 static void sxgbe_core_enable_rxqueue(void __iomem *ioaddr, int queue_num)
 166 {
 167         u32 reg_val;
 168 
 169         reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG);
 170         reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num);
 171         reg_val |= SXGBE_CORE_RXQ_ENABLE;
 172         writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG);
 173 }
 174 
 175 static void sxgbe_core_disable_rxqueue(void __iomem *ioaddr, int queue_num)
 176 {
 177         u32 reg_val;
 178 
 179         reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG);
 180         reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num);
 181         reg_val |= SXGBE_CORE_RXQ_DISABLE;
 182         writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG);
 183 }
 184 
 185 static void  sxgbe_set_eee_mode(void __iomem *ioaddr)
 186 {
 187         u32 ctrl;
 188 
 189         /* Enable the LPI mode for transmit path with Tx automate bit set.
 190          * When Tx Automate bit is set, MAC internally handles the entry
 191          * to LPI mode after all outstanding and pending packets are
 192          * transmitted.
 193          */
 194         ctrl = readl(ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);
 195         ctrl |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_TXA;
 196         writel(ctrl, ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);
 197 }
 198 
 199 static void  sxgbe_reset_eee_mode(void __iomem *ioaddr)
 200 {
 201         u32 ctrl;
 202 
 203         ctrl = readl(ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);
 204         ctrl &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_TXA);
 205         writel(ctrl, ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);
 206 }
 207 
 208 static void  sxgbe_set_eee_pls(void __iomem *ioaddr, const int link)
 209 {
 210         u32 ctrl;
 211 
 212         ctrl = readl(ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);
 213 
 214         /* If the PHY link status is UP then set PLS */
 215         if (link)
 216                 ctrl |= LPI_CTRL_STATUS_PLS;
 217         else
 218                 ctrl &= ~LPI_CTRL_STATUS_PLS;
 219 
 220         writel(ctrl, ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);
 221 }
 222 
 223 static void  sxgbe_set_eee_timer(void __iomem *ioaddr,
 224                                  const int ls, const int tw)
 225 {
 226         int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
 227 
 228         /* Program the timers in the LPI timer control register:
 229          * LS: minimum time (ms) for which the link
 230          *  status from PHY should be ok before transmitting
 231          *  the LPI pattern.
 232          * TW: minimum time (us) for which the core waits
 233          *  after it has stopped transmitting the LPI pattern.
 234          */
 235         writel(value, ioaddr + SXGBE_CORE_LPI_TIMER_CTRL);
 236 }
 237 
 238 static void sxgbe_enable_rx_csum(void __iomem *ioaddr)
 239 {
 240         u32 ctrl;
 241 
 242         ctrl = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);
 243         ctrl |= SXGBE_RX_CSUMOFFLOAD_ENABLE;
 244         writel(ctrl, ioaddr + SXGBE_CORE_RX_CONFIG_REG);
 245 }
 246 
 247 static void sxgbe_disable_rx_csum(void __iomem *ioaddr)
 248 {
 249         u32 ctrl;
 250 
 251         ctrl = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);
 252         ctrl &= ~SXGBE_RX_CSUMOFFLOAD_ENABLE;
 253         writel(ctrl, ioaddr + SXGBE_CORE_RX_CONFIG_REG);
 254 }
 255 
 256 static const struct sxgbe_core_ops core_ops = {
 257         .core_init              = sxgbe_core_init,
 258         .dump_regs              = sxgbe_core_dump_regs,
 259         .host_irq_status        = sxgbe_core_host_irq_status,
 260         .pmt                    = sxgbe_core_pmt,
 261         .set_umac_addr          = sxgbe_core_set_umac_addr,
 262         .get_umac_addr          = sxgbe_core_get_umac_addr,
 263         .enable_rx              = sxgbe_enable_rx,
 264         .enable_tx              = sxgbe_enable_tx,
 265         .get_controller_version = sxgbe_get_controller_version,
 266         .get_hw_feature         = sxgbe_get_hw_feature,
 267         .set_speed              = sxgbe_core_set_speed,
 268         .set_eee_mode           = sxgbe_set_eee_mode,
 269         .reset_eee_mode         = sxgbe_reset_eee_mode,
 270         .set_eee_timer          = sxgbe_set_eee_timer,
 271         .set_eee_pls            = sxgbe_set_eee_pls,
 272         .enable_rx_csum         = sxgbe_enable_rx_csum,
 273         .disable_rx_csum        = sxgbe_disable_rx_csum,
 274         .enable_rxqueue         = sxgbe_core_enable_rxqueue,
 275         .disable_rxqueue        = sxgbe_core_disable_rxqueue,
 276 };
 277 
 278 const struct sxgbe_core_ops *sxgbe_get_core_ops(void)
 279 {
 280         return &core_ops;
 281 }

/* [<][>][^][v][top][bottom][index][help] */