brintos

brintos / linux-shallow public Read only

0
0
Text · 10.0 KiB · 243db04 Raw
366 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#include <linux/delay.h>10#include <linux/export.h>11#include <linux/io.h>12#include <linux/netdevice.h>13#include <linux/phy.h>14 15#include "sxgbe_common.h"16#include "sxgbe_dma.h"17#include "sxgbe_reg.h"18#include "sxgbe_desc.h"19 20/* DMA core initialization */21static int sxgbe_dma_init(void __iomem *ioaddr, int fix_burst, int burst_map)22{23	u32 reg_val;24 25	reg_val = readl(ioaddr + SXGBE_DMA_SYSBUS_MODE_REG);26 27	/* if fix_burst = 0, Set UNDEF = 1 of DMA_Sys_Mode Register.28	 * if fix_burst = 1, Set UNDEF = 0 of DMA_Sys_Mode Register.29	 * burst_map is bitmap for  BLEN[4, 8, 16, 32, 64, 128 and 256].30	 * Set burst_map irrespective of fix_burst value.31	 */32	if (!fix_burst)33		reg_val |= SXGBE_DMA_AXI_UNDEF_BURST;34 35	/* write burst len map */36	reg_val |= (burst_map << SXGBE_DMA_BLENMAP_LSHIFT);37 38	writel(reg_val,	ioaddr + SXGBE_DMA_SYSBUS_MODE_REG);39 40	return 0;41}42 43static void sxgbe_dma_channel_init(void __iomem *ioaddr, int cha_num,44				   int fix_burst, int pbl, dma_addr_t dma_tx,45				   dma_addr_t dma_rx, int t_rsize, int r_rsize)46{47	u32 reg_val;48	dma_addr_t dma_addr;49 50	reg_val = readl(ioaddr + SXGBE_DMA_CHA_CTL_REG(cha_num));51	/* set the pbl */52	if (fix_burst) {53		reg_val |= SXGBE_DMA_PBL_X8MODE;54		writel(reg_val, ioaddr + SXGBE_DMA_CHA_CTL_REG(cha_num));55		/* program the TX pbl */56		reg_val = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num));57		reg_val |= (pbl << SXGBE_DMA_TXPBL_LSHIFT);58		writel(reg_val, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num));59		/* program the RX pbl */60		reg_val = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cha_num));61		reg_val |= (pbl << SXGBE_DMA_RXPBL_LSHIFT);62		writel(reg_val, ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cha_num));63	}64 65	/* program desc registers */66	writel(upper_32_bits(dma_tx),67	       ioaddr + SXGBE_DMA_CHA_TXDESC_HADD_REG(cha_num));68	writel(lower_32_bits(dma_tx),69	       ioaddr + SXGBE_DMA_CHA_TXDESC_LADD_REG(cha_num));70 71	writel(upper_32_bits(dma_rx),72	       ioaddr + SXGBE_DMA_CHA_RXDESC_HADD_REG(cha_num));73	writel(lower_32_bits(dma_rx),74	       ioaddr + SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num));75 76	/* program tail pointers */77	/* assumption: upper 32 bits are constant and78	 * same as TX/RX desc list79	 */80	dma_addr = dma_tx + ((t_rsize - 1) * SXGBE_DESC_SIZE_BYTES);81	writel(lower_32_bits(dma_addr),82	       ioaddr + SXGBE_DMA_CHA_TXDESC_TAILPTR_REG(cha_num));83 84	dma_addr = dma_rx + ((r_rsize - 1) * SXGBE_DESC_SIZE_BYTES);85	writel(lower_32_bits(dma_addr),86	       ioaddr + SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num));87	/* program the ring sizes */88	writel(t_rsize - 1, ioaddr + SXGBE_DMA_CHA_TXDESC_RINGLEN_REG(cha_num));89	writel(r_rsize - 1, ioaddr + SXGBE_DMA_CHA_RXDESC_RINGLEN_REG(cha_num));90 91	/* Enable TX/RX interrupts */92	writel(SXGBE_DMA_ENA_INT,93	       ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(cha_num));94}95 96static void sxgbe_enable_dma_transmission(void __iomem *ioaddr, int cha_num)97{98	u32 tx_config;99 100	tx_config = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num));101	tx_config |= SXGBE_TX_START_DMA;102	writel(tx_config, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num));103}104 105static void sxgbe_enable_dma_irq(void __iomem *ioaddr, int dma_cnum)106{107	/* Enable TX/RX interrupts */108	writel(SXGBE_DMA_ENA_INT,109	       ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(dma_cnum));110}111 112static void sxgbe_disable_dma_irq(void __iomem *ioaddr, int dma_cnum)113{114	/* Disable TX/RX interrupts */115	writel(0, ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(dma_cnum));116}117 118static void sxgbe_dma_start_tx(void __iomem *ioaddr, int tchannels)119{120	int cnum;121	u32 tx_ctl_reg;122 123	for (cnum = 0; cnum < tchannels; cnum++) {124		tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum));125		tx_ctl_reg |= SXGBE_TX_ENABLE;126		writel(tx_ctl_reg,127		       ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum));128	}129}130 131static void sxgbe_dma_start_tx_queue(void __iomem *ioaddr, int dma_cnum)132{133	u32 tx_ctl_reg;134 135	tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum));136	tx_ctl_reg |= SXGBE_TX_ENABLE;137	writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum));138}139 140static void sxgbe_dma_stop_tx_queue(void __iomem *ioaddr, int dma_cnum)141{142	u32 tx_ctl_reg;143 144	tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum));145	tx_ctl_reg &= ~(SXGBE_TX_ENABLE);146	writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum));147}148 149static void sxgbe_dma_stop_tx(void __iomem *ioaddr, int tchannels)150{151	int cnum;152	u32 tx_ctl_reg;153 154	for (cnum = 0; cnum < tchannels; cnum++) {155		tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum));156		tx_ctl_reg &= ~(SXGBE_TX_ENABLE);157		writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum));158	}159}160 161static void sxgbe_dma_start_rx(void __iomem *ioaddr, int rchannels)162{163	int cnum;164	u32 rx_ctl_reg;165 166	for (cnum = 0; cnum < rchannels; cnum++) {167		rx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum));168		rx_ctl_reg |= SXGBE_RX_ENABLE;169		writel(rx_ctl_reg,170		       ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum));171	}172}173 174static void sxgbe_dma_stop_rx(void __iomem *ioaddr, int rchannels)175{176	int cnum;177	u32 rx_ctl_reg;178 179	for (cnum = 0; cnum < rchannels; cnum++) {180		rx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum));181		rx_ctl_reg &= ~(SXGBE_RX_ENABLE);182		writel(rx_ctl_reg, ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum));183	}184}185 186static int sxgbe_tx_dma_int_status(void __iomem *ioaddr, int channel_no,187				   struct sxgbe_extra_stats *x)188{189	u32 int_status = readl(ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no));190	u32 clear_val = 0;191	u32 ret_val = 0;192 193	/* TX Normal Interrupt Summary */194	if (likely(int_status & SXGBE_DMA_INT_STATUS_NIS)) {195		x->normal_irq_n++;196		if (int_status & SXGBE_DMA_INT_STATUS_TI) {197			ret_val |= handle_tx;198			x->tx_normal_irq_n++;199			clear_val |= SXGBE_DMA_INT_STATUS_TI;200		}201 202		if (int_status & SXGBE_DMA_INT_STATUS_TBU) {203			x->tx_underflow_irq++;204			ret_val |= tx_bump_tc;205			clear_val |= SXGBE_DMA_INT_STATUS_TBU;206		}207	} else if (unlikely(int_status & SXGBE_DMA_INT_STATUS_AIS)) {208		/* TX Abnormal Interrupt Summary */209		if (int_status & SXGBE_DMA_INT_STATUS_TPS) {210			ret_val |= tx_hard_error;211			clear_val |= SXGBE_DMA_INT_STATUS_TPS;212			x->tx_process_stopped_irq++;213		}214 215		if (int_status & SXGBE_DMA_INT_STATUS_FBE) {216			ret_val |= tx_hard_error;217			x->fatal_bus_error_irq++;218 219			/* Assumption: FBE bit is the combination of220			 * all the bus access erros and cleared when221			 * the respective error bits cleared222			 */223 224			/* check for actual cause */225			if (int_status & SXGBE_DMA_INT_STATUS_TEB0) {226				x->tx_read_transfer_err++;227				clear_val |= SXGBE_DMA_INT_STATUS_TEB0;228			} else {229				x->tx_write_transfer_err++;230			}231 232			if (int_status & SXGBE_DMA_INT_STATUS_TEB1) {233				x->tx_desc_access_err++;234				clear_val |= SXGBE_DMA_INT_STATUS_TEB1;235			} else {236				x->tx_buffer_access_err++;237			}238 239			if (int_status & SXGBE_DMA_INT_STATUS_TEB2) {240				x->tx_data_transfer_err++;241				clear_val |= SXGBE_DMA_INT_STATUS_TEB2;242			}243		}244 245		/* context descriptor error */246		if (int_status & SXGBE_DMA_INT_STATUS_CTXTERR) {247			x->tx_ctxt_desc_err++;248			clear_val |= SXGBE_DMA_INT_STATUS_CTXTERR;249		}250	}251 252	/* clear the served bits */253	writel(clear_val, ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no));254 255	return ret_val;256}257 258static int sxgbe_rx_dma_int_status(void __iomem *ioaddr, int channel_no,259				   struct sxgbe_extra_stats *x)260{261	u32 int_status = readl(ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no));262	u32 clear_val = 0;263	u32 ret_val = 0;264 265	/* RX Normal Interrupt Summary */266	if (likely(int_status & SXGBE_DMA_INT_STATUS_NIS)) {267		x->normal_irq_n++;268		if (int_status & SXGBE_DMA_INT_STATUS_RI) {269			ret_val |= handle_rx;270			x->rx_normal_irq_n++;271			clear_val |= SXGBE_DMA_INT_STATUS_RI;272		}273	} else if (unlikely(int_status & SXGBE_DMA_INT_STATUS_AIS)) {274		/* RX Abnormal Interrupt Summary */275		if (int_status & SXGBE_DMA_INT_STATUS_RBU) {276			ret_val |= rx_bump_tc;277			clear_val |= SXGBE_DMA_INT_STATUS_RBU;278			x->rx_underflow_irq++;279		}280 281		if (int_status & SXGBE_DMA_INT_STATUS_RPS) {282			ret_val |= rx_hard_error;283			clear_val |= SXGBE_DMA_INT_STATUS_RPS;284			x->rx_process_stopped_irq++;285		}286 287		if (int_status & SXGBE_DMA_INT_STATUS_FBE) {288			ret_val |= rx_hard_error;289			x->fatal_bus_error_irq++;290 291			/* Assumption: FBE bit is the combination of292			 * all the bus access erros and cleared when293			 * the respective error bits cleared294			 */295 296			/* check for actual cause */297			if (int_status & SXGBE_DMA_INT_STATUS_REB0) {298				x->rx_read_transfer_err++;299				clear_val |= SXGBE_DMA_INT_STATUS_REB0;300			} else {301				x->rx_write_transfer_err++;302			}303 304			if (int_status & SXGBE_DMA_INT_STATUS_REB1) {305				x->rx_desc_access_err++;306				clear_val |= SXGBE_DMA_INT_STATUS_REB1;307			} else {308				x->rx_buffer_access_err++;309			}310 311			if (int_status & SXGBE_DMA_INT_STATUS_REB2) {312				x->rx_data_transfer_err++;313				clear_val |= SXGBE_DMA_INT_STATUS_REB2;314			}315		}316	}317 318	/* clear the served bits */319	writel(clear_val, ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no));320 321	return ret_val;322}323 324/* Program the HW RX Watchdog */325static void sxgbe_dma_rx_watchdog(void __iomem *ioaddr, u32 riwt)326{327	u32 que_num;328 329	SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, que_num) {330		writel(riwt,331		       ioaddr + SXGBE_DMA_CHA_INT_RXWATCHTMR_REG(que_num));332	}333}334 335static void sxgbe_enable_tso(void __iomem *ioaddr, u8 chan_num)336{337	u32 ctrl;338 339	ctrl = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(chan_num));340	ctrl |= SXGBE_DMA_CHA_TXCTL_TSE_ENABLE;341	writel(ctrl, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(chan_num));342}343 344static const struct sxgbe_dma_ops sxgbe_dma_ops = {345	.init				= sxgbe_dma_init,346	.cha_init			= sxgbe_dma_channel_init,347	.enable_dma_transmission	= sxgbe_enable_dma_transmission,348	.enable_dma_irq			= sxgbe_enable_dma_irq,349	.disable_dma_irq		= sxgbe_disable_dma_irq,350	.start_tx			= sxgbe_dma_start_tx,351	.start_tx_queue			= sxgbe_dma_start_tx_queue,352	.stop_tx			= sxgbe_dma_stop_tx,353	.stop_tx_queue			= sxgbe_dma_stop_tx_queue,354	.start_rx			= sxgbe_dma_start_rx,355	.stop_rx			= sxgbe_dma_stop_rx,356	.tx_dma_int_status		= sxgbe_tx_dma_int_status,357	.rx_dma_int_status		= sxgbe_rx_dma_int_status,358	.rx_watchdog			= sxgbe_dma_rx_watchdog,359	.enable_tso			= sxgbe_enable_tso,360};361 362const struct sxgbe_dma_ops *sxgbe_get_dma_ops(void)363{364	return &sxgbe_dma_ops;365}366