Linux Audio

Check our new training course

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