cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dwmac4_lib.c (6160B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2007-2015  STMicroelectronics Ltd
      4 *
      5 * Author: Alexandre Torgue <alexandre.torgue@st.com>
      6 */
      7
      8#include <linux/io.h>
      9#include <linux/iopoll.h>
     10#include <linux/delay.h>
     11#include "common.h"
     12#include "dwmac4_dma.h"
     13#include "dwmac4.h"
     14
     15int dwmac4_dma_reset(void __iomem *ioaddr)
     16{
     17	u32 value = readl(ioaddr + DMA_BUS_MODE);
     18
     19	/* DMA SW reset */
     20	value |= DMA_BUS_MODE_SFT_RESET;
     21	writel(value, ioaddr + DMA_BUS_MODE);
     22
     23	return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
     24				 !(value & DMA_BUS_MODE_SFT_RESET),
     25				 10000, 1000000);
     26}
     27
     28void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan)
     29{
     30	writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(chan));
     31}
     32
     33void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan)
     34{
     35	writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(chan));
     36}
     37
     38void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan)
     39{
     40	u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
     41
     42	value |= DMA_CONTROL_ST;
     43	writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
     44
     45	value = readl(ioaddr + GMAC_CONFIG);
     46	value |= GMAC_CONFIG_TE;
     47	writel(value, ioaddr + GMAC_CONFIG);
     48}
     49
     50void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan)
     51{
     52	u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
     53
     54	value &= ~DMA_CONTROL_ST;
     55	writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
     56}
     57
     58void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan)
     59{
     60	u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan));
     61
     62	value |= DMA_CONTROL_SR;
     63
     64	writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
     65
     66	value = readl(ioaddr + GMAC_CONFIG);
     67	value |= GMAC_CONFIG_RE;
     68	writel(value, ioaddr + GMAC_CONFIG);
     69}
     70
     71void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan)
     72{
     73	u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan));
     74
     75	value &= ~DMA_CONTROL_SR;
     76	writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
     77}
     78
     79void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
     80{
     81	writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(chan));
     82}
     83
     84void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
     85{
     86	writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(chan));
     87}
     88
     89void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
     90{
     91	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
     92
     93	if (rx)
     94		value |= DMA_CHAN_INTR_DEFAULT_RX;
     95	if (tx)
     96		value |= DMA_CHAN_INTR_DEFAULT_TX;
     97
     98	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
     99}
    100
    101void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
    102{
    103	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
    104
    105	if (rx)
    106		value |= DMA_CHAN_INTR_DEFAULT_RX_4_10;
    107	if (tx)
    108		value |= DMA_CHAN_INTR_DEFAULT_TX_4_10;
    109
    110	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
    111}
    112
    113void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
    114{
    115	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
    116
    117	if (rx)
    118		value &= ~DMA_CHAN_INTR_DEFAULT_RX;
    119	if (tx)
    120		value &= ~DMA_CHAN_INTR_DEFAULT_TX;
    121
    122	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
    123}
    124
    125void dwmac410_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
    126{
    127	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
    128
    129	if (rx)
    130		value &= ~DMA_CHAN_INTR_DEFAULT_RX_4_10;
    131	if (tx)
    132		value &= ~DMA_CHAN_INTR_DEFAULT_TX_4_10;
    133
    134	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
    135}
    136
    137int dwmac4_dma_interrupt(void __iomem *ioaddr,
    138			 struct stmmac_extra_stats *x, u32 chan, u32 dir)
    139{
    140	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
    141	u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
    142	int ret = 0;
    143
    144	if (dir == DMA_DIR_RX)
    145		intr_status &= DMA_CHAN_STATUS_MSK_RX;
    146	else if (dir == DMA_DIR_TX)
    147		intr_status &= DMA_CHAN_STATUS_MSK_TX;
    148
    149	/* ABNORMAL interrupts */
    150	if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) {
    151		if (unlikely(intr_status & DMA_CHAN_STATUS_RBU))
    152			x->rx_buf_unav_irq++;
    153		if (unlikely(intr_status & DMA_CHAN_STATUS_RPS))
    154			x->rx_process_stopped_irq++;
    155		if (unlikely(intr_status & DMA_CHAN_STATUS_RWT))
    156			x->rx_watchdog_irq++;
    157		if (unlikely(intr_status & DMA_CHAN_STATUS_ETI))
    158			x->tx_early_irq++;
    159		if (unlikely(intr_status & DMA_CHAN_STATUS_TPS)) {
    160			x->tx_process_stopped_irq++;
    161			ret = tx_hard_error;
    162		}
    163		if (unlikely(intr_status & DMA_CHAN_STATUS_FBE)) {
    164			x->fatal_bus_error_irq++;
    165			ret = tx_hard_error;
    166		}
    167	}
    168	/* TX/RX NORMAL interrupts */
    169	if (likely(intr_status & DMA_CHAN_STATUS_NIS))
    170		x->normal_irq_n++;
    171	if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
    172		x->rx_normal_irq_n++;
    173		x->rxq_stats[chan].rx_normal_irq_n++;
    174		ret |= handle_rx;
    175	}
    176	if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
    177		x->tx_normal_irq_n++;
    178		x->txq_stats[chan].tx_normal_irq_n++;
    179		ret |= handle_tx;
    180	}
    181	if (unlikely(intr_status & DMA_CHAN_STATUS_TBU))
    182		ret |= handle_tx;
    183	if (unlikely(intr_status & DMA_CHAN_STATUS_ERI))
    184		x->rx_early_irq++;
    185
    186	writel(intr_status & intr_en, ioaddr + DMA_CHAN_STATUS(chan));
    187	return ret;
    188}
    189
    190void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
    191				unsigned int high, unsigned int low)
    192{
    193	unsigned long data;
    194
    195	data = (addr[5] << 8) | addr[4];
    196	/* For MAC Addr registers se have to set the Address Enable (AE)
    197	 * bit that has no effect on the High Reg 0 where the bit 31 (MO)
    198	 * is RO.
    199	 */
    200	data |= (STMMAC_CHAN0 << GMAC_HI_DCS_SHIFT);
    201	writel(data | GMAC_HI_REG_AE, ioaddr + high);
    202	data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
    203	writel(data, ioaddr + low);
    204}
    205
    206/* Enable disable MAC RX/TX */
    207void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable)
    208{
    209	u32 value = readl(ioaddr + GMAC_CONFIG);
    210
    211	if (enable)
    212		value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE;
    213	else
    214		value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE);
    215
    216	writel(value, ioaddr + GMAC_CONFIG);
    217}
    218
    219void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
    220				unsigned int high, unsigned int low)
    221{
    222	unsigned int hi_addr, lo_addr;
    223
    224	/* Read the MAC address from the hardware */
    225	hi_addr = readl(ioaddr + high);
    226	lo_addr = readl(ioaddr + low);
    227
    228	/* Extract the MAC address from the high and low words */
    229	addr[0] = lo_addr & 0xff;
    230	addr[1] = (lo_addr >> 8) & 0xff;
    231	addr[2] = (lo_addr >> 16) & 0xff;
    232	addr[3] = (lo_addr >> 24) & 0xff;
    233	addr[4] = hi_addr & 0xff;
    234	addr[5] = (hi_addr >> 8) & 0xff;
    235}