brintos

brintos / linux-shallow public Read only

0
0
Text · 7.6 KiB · 7d9f257 Raw
283 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* 10G controller driver for Samsung SoCs3 *4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.5 *		http://www.samsung.com6 *7 * Author: Siva Reddy Kallam <siva.kallam@samsung.com>8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 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 */21static 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, ISM28	 * needs to be set if needed29	 */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, GPSLCE36	 * WD, LM, S2KP, HDSMS, GPSL, ELEN, ARPEN needs to be37	 * set if needed38	 */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 */44static void sxgbe_core_dump_regs(void __iomem *ioaddr)45{46}47 48static 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 */69static 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) */83static void sxgbe_core_pmt(void __iomem *ioaddr, unsigned long mode)84{85}86 87/* Set/Get Unicast MAC addresses */88static void sxgbe_core_set_umac_addr(void __iomem *ioaddr,89				     const unsigned char *addr,90				     unsigned int reg_n)91{92	u32 high_word, low_word;93 94	high_word = (addr[5] << 8) | (addr[4]);95	low_word = (addr[3] << 24) | (addr[2] << 16) |96		   (addr[1] << 8) | (addr[0]);97	writel(high_word, ioaddr + SXGBE_CORE_ADD_HIGHOFFSET(reg_n));98	writel(low_word, ioaddr + SXGBE_CORE_ADD_LOWOFFSET(reg_n));99}100 101static void sxgbe_core_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,102				     unsigned int reg_n)103{104	u32 high_word, low_word;105 106	high_word = readl(ioaddr + SXGBE_CORE_ADD_HIGHOFFSET(reg_n));107	low_word = readl(ioaddr + SXGBE_CORE_ADD_LOWOFFSET(reg_n));108 109	/* extract and assign address */110	addr[5] = (high_word & 0x0000FF00) >> 8;111	addr[4] = (high_word & 0x000000FF);112	addr[3] = (low_word & 0xFF000000) >> 24;113	addr[2] = (low_word & 0x00FF0000) >> 16;114	addr[1] = (low_word & 0x0000FF00) >> 8;115	addr[0] = (low_word & 0x000000FF);116}117 118static void sxgbe_enable_tx(void __iomem *ioaddr, bool enable)119{120	u32 tx_config;121 122	tx_config = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG);123	tx_config &= ~SXGBE_TX_ENABLE;124 125	if (enable)126		tx_config |= SXGBE_TX_ENABLE;127	writel(tx_config, ioaddr + SXGBE_CORE_TX_CONFIG_REG);128}129 130static void sxgbe_enable_rx(void __iomem *ioaddr, bool enable)131{132	u32 rx_config;133 134	rx_config = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);135	rx_config &= ~SXGBE_RX_ENABLE;136 137	if (enable)138		rx_config |= SXGBE_RX_ENABLE;139	writel(rx_config, ioaddr + SXGBE_CORE_RX_CONFIG_REG);140}141 142static int sxgbe_get_controller_version(void __iomem *ioaddr)143{144	return readl(ioaddr + SXGBE_CORE_VERSION_REG);145}146 147/* If supported then get the optional core features */148static unsigned int sxgbe_get_hw_feature(void __iomem *ioaddr,149					 unsigned char feature_index)150{151	return readl(ioaddr + (SXGBE_CORE_HW_FEA_REG(feature_index)));152}153 154static void sxgbe_core_set_speed(void __iomem *ioaddr, unsigned char speed)155{156	u32 tx_cfg = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG);157 158	/* clear the speed bits */159	tx_cfg &= ~0x60000000;160	tx_cfg |= (speed << SXGBE_SPEED_LSHIFT);161 162	/* set the speed */163	writel(tx_cfg, ioaddr + SXGBE_CORE_TX_CONFIG_REG);164}165 166static void sxgbe_core_enable_rxqueue(void __iomem *ioaddr, int queue_num)167{168	u32 reg_val;169 170	reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG);171	reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num);172	reg_val |= SXGBE_CORE_RXQ_ENABLE;173	writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG);174}175 176static void sxgbe_core_disable_rxqueue(void __iomem *ioaddr, int queue_num)177{178	u32 reg_val;179 180	reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG);181	reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num);182	reg_val |= SXGBE_CORE_RXQ_DISABLE;183	writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG);184}185 186static void  sxgbe_set_eee_mode(void __iomem *ioaddr)187{188	u32 ctrl;189 190	/* Enable the LPI mode for transmit path with Tx automate bit set.191	 * When Tx Automate bit is set, MAC internally handles the entry192	 * to LPI mode after all outstanding and pending packets are193	 * transmitted.194	 */195	ctrl = readl(ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);196	ctrl |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_TXA;197	writel(ctrl, ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);198}199 200static void  sxgbe_reset_eee_mode(void __iomem *ioaddr)201{202	u32 ctrl;203 204	ctrl = readl(ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);205	ctrl &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_TXA);206	writel(ctrl, ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);207}208 209static void  sxgbe_set_eee_pls(void __iomem *ioaddr, const int link)210{211	u32 ctrl;212 213	ctrl = readl(ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);214 215	/* If the PHY link status is UP then set PLS */216	if (link)217		ctrl |= LPI_CTRL_STATUS_PLS;218	else219		ctrl &= ~LPI_CTRL_STATUS_PLS;220 221	writel(ctrl, ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);222}223 224static void  sxgbe_set_eee_timer(void __iomem *ioaddr,225				 const int ls, const int tw)226{227	int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);228 229	/* Program the timers in the LPI timer control register:230	 * LS: minimum time (ms) for which the link231	 *  status from PHY should be ok before transmitting232	 *  the LPI pattern.233	 * TW: minimum time (us) for which the core waits234	 *  after it has stopped transmitting the LPI pattern.235	 */236	writel(value, ioaddr + SXGBE_CORE_LPI_TIMER_CTRL);237}238 239static void sxgbe_enable_rx_csum(void __iomem *ioaddr)240{241	u32 ctrl;242 243	ctrl = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);244	ctrl |= SXGBE_RX_CSUMOFFLOAD_ENABLE;245	writel(ctrl, ioaddr + SXGBE_CORE_RX_CONFIG_REG);246}247 248static void sxgbe_disable_rx_csum(void __iomem *ioaddr)249{250	u32 ctrl;251 252	ctrl = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);253	ctrl &= ~SXGBE_RX_CSUMOFFLOAD_ENABLE;254	writel(ctrl, ioaddr + SXGBE_CORE_RX_CONFIG_REG);255}256 257static const struct sxgbe_core_ops core_ops = {258	.core_init		= sxgbe_core_init,259	.dump_regs		= sxgbe_core_dump_regs,260	.host_irq_status	= sxgbe_core_host_irq_status,261	.pmt			= sxgbe_core_pmt,262	.set_umac_addr		= sxgbe_core_set_umac_addr,263	.get_umac_addr		= sxgbe_core_get_umac_addr,264	.enable_rx		= sxgbe_enable_rx,265	.enable_tx		= sxgbe_enable_tx,266	.get_controller_version	= sxgbe_get_controller_version,267	.get_hw_feature		= sxgbe_get_hw_feature,268	.set_speed		= sxgbe_core_set_speed,269	.set_eee_mode		= sxgbe_set_eee_mode,270	.reset_eee_mode		= sxgbe_reset_eee_mode,271	.set_eee_timer		= sxgbe_set_eee_timer,272	.set_eee_pls		= sxgbe_set_eee_pls,273	.enable_rx_csum		= sxgbe_enable_rx_csum,274	.disable_rx_csum	= sxgbe_disable_rx_csum,275	.enable_rxqueue		= sxgbe_core_enable_rxqueue,276	.disable_rxqueue	= sxgbe_core_disable_rxqueue,277};278 279const struct sxgbe_core_ops *sxgbe_get_core_ops(void)280{281	return &core_ops;282}283