Thomas Gleixner | 4fa9c49f | 2019-05-29 07:18:05 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 2 | /******************************************************************************* |
| 3 | This is the driver for the MAC 10/100 on-chip Ethernet controller |
| 4 | currently tested on all the ST boards based on STb7109 and stx7200 SoCs. |
| 5 | |
| 6 | DWC Ether MAC 10/100 Universal version 4.0 has been used for developing |
| 7 | this code. |
| 8 | |
Giuseppe CAVALLARO | 56b106a | 2010-04-13 20:21:12 +0000 | [diff] [blame] | 9 | This contains the functions to handle the dma. |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 10 | |
| 11 | Copyright (C) 2007-2009 STMicroelectronics Ltd |
| 12 | |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 13 | |
| 14 | Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> |
| 15 | *******************************************************************************/ |
| 16 | |
Russell King (Oracle) | cd56ff7 | 2024-05-29 09:40:54 +0100 | [diff] [blame] | 17 | #include <linux/io.h> |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 18 | #include "dwmac100.h" |
| 19 | #include "dwmac_dma.h" |
| 20 | |
Niklas Cassel | 50ca903 | 2016-12-07 15:20:04 +0100 | [diff] [blame] | 21 | static void dwmac100_dma_init(void __iomem *ioaddr, |
Yanteng Si | 12dbc67 | 2024-08-07 21:45:28 +0800 | [diff] [blame] | 22 | struct stmmac_dma_cfg *dma_cfg) |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 23 | { |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 24 | /* Enable Application Access by writing to DMA CSR0 */ |
Niklas Cassel | 50ca903 | 2016-12-07 15:20:04 +0100 | [diff] [blame] | 25 | writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT), |
Giuseppe CAVALLARO | ceb69499 | 2013-04-08 02:10:01 +0000 | [diff] [blame] | 26 | ioaddr + DMA_BUS_MODE); |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 27 | |
| 28 | /* Mask interrupts by writing to CSR7 */ |
| 29 | writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); |
Jose Abreu | 24aaed0 | 2018-05-18 14:56:05 +0100 | [diff] [blame] | 30 | } |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 31 | |
Andrew Halaney | 1d84b48 | 2023-04-11 15:04:05 -0500 | [diff] [blame] | 32 | static void dwmac100_dma_init_rx(struct stmmac_priv *priv, void __iomem *ioaddr, |
Jose Abreu | 24aaed0 | 2018-05-18 14:56:05 +0100 | [diff] [blame] | 33 | struct stmmac_dma_cfg *dma_cfg, |
Jose Abreu | 06a80a7 | 2019-07-09 10:02:59 +0200 | [diff] [blame] | 34 | dma_addr_t dma_rx_phy, u32 chan) |
Jose Abreu | 24aaed0 | 2018-05-18 14:56:05 +0100 | [diff] [blame] | 35 | { |
| 36 | /* RX descriptor base addr lists must be written into DMA CSR3 */ |
Jose Abreu | 06a80a7 | 2019-07-09 10:02:59 +0200 | [diff] [blame] | 37 | writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR); |
Jose Abreu | 24aaed0 | 2018-05-18 14:56:05 +0100 | [diff] [blame] | 38 | } |
| 39 | |
Andrew Halaney | 1d84b48 | 2023-04-11 15:04:05 -0500 | [diff] [blame] | 40 | static void dwmac100_dma_init_tx(struct stmmac_priv *priv, void __iomem *ioaddr, |
Jose Abreu | 24aaed0 | 2018-05-18 14:56:05 +0100 | [diff] [blame] | 41 | struct stmmac_dma_cfg *dma_cfg, |
Jose Abreu | 06a80a7 | 2019-07-09 10:02:59 +0200 | [diff] [blame] | 42 | dma_addr_t dma_tx_phy, u32 chan) |
Jose Abreu | 24aaed0 | 2018-05-18 14:56:05 +0100 | [diff] [blame] | 43 | { |
| 44 | /* TX descriptor base addr lists must be written into DMA CSR4 */ |
Jose Abreu | 06a80a7 | 2019-07-09 10:02:59 +0200 | [diff] [blame] | 45 | writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR); |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 46 | } |
| 47 | |
Giuseppe CAVALLARO | ceb69499 | 2013-04-08 02:10:01 +0000 | [diff] [blame] | 48 | /* Store and Forward capability is not used at all. |
| 49 | * |
| 50 | * The transmit threshold can be programmed by setting the TTC bits in the DMA |
| 51 | * control register. |
| 52 | */ |
Andrew Halaney | 1d84b48 | 2023-04-11 15:04:05 -0500 | [diff] [blame] | 53 | static void dwmac100_dma_operation_mode_tx(struct stmmac_priv *priv, |
| 54 | void __iomem *ioaddr, int mode, |
Jose Abreu | ab0204e | 2018-05-18 14:56:02 +0100 | [diff] [blame] | 55 | u32 channel, int fifosz, u8 qmode) |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 56 | { |
| 57 | u32 csr6 = readl(ioaddr + DMA_CONTROL); |
| 58 | |
Jose Abreu | ab0204e | 2018-05-18 14:56:02 +0100 | [diff] [blame] | 59 | if (mode <= 32) |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 60 | csr6 |= DMA_CONTROL_TTC_32; |
Jose Abreu | ab0204e | 2018-05-18 14:56:02 +0100 | [diff] [blame] | 61 | else if (mode <= 64) |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 62 | csr6 |= DMA_CONTROL_TTC_64; |
| 63 | else |
| 64 | csr6 |= DMA_CONTROL_TTC_128; |
| 65 | |
| 66 | writel(csr6, ioaddr + DMA_CONTROL); |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 67 | } |
| 68 | |
Andrew Halaney | 1d84b48 | 2023-04-11 15:04:05 -0500 | [diff] [blame] | 69 | static void dwmac100_dump_dma_regs(struct stmmac_priv *priv, |
| 70 | void __iomem *ioaddr, u32 *reg_space) |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 71 | { |
| 72 | int i; |
| 73 | |
Thor Thayer | f4458b9 | 2017-07-21 16:35:09 -0500 | [diff] [blame] | 74 | for (i = 0; i < NUM_DWMAC100_DMA_REGS; i++) |
LABBE Corentin | fbf6822 | 2017-02-23 14:12:25 +0100 | [diff] [blame] | 75 | reg_space[DMA_BUS_MODE / 4 + i] = |
| 76 | readl(ioaddr + DMA_BUS_MODE + i * 4); |
Giuseppe CAVALLARO | 83d7af6 | 2013-07-02 14:12:36 +0200 | [diff] [blame] | 77 | |
LABBE Corentin | fbf6822 | 2017-02-23 14:12:25 +0100 | [diff] [blame] | 78 | reg_space[DMA_CUR_TX_BUF_ADDR / 4] = |
| 79 | readl(ioaddr + DMA_CUR_TX_BUF_ADDR); |
| 80 | reg_space[DMA_CUR_RX_BUF_ADDR / 4] = |
| 81 | readl(ioaddr + DMA_CUR_RX_BUF_ADDR); |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 82 | } |
| 83 | |
Giuseppe CAVALLARO | ceb69499 | 2013-04-08 02:10:01 +0000 | [diff] [blame] | 84 | /* DMA controller has two counters to track the number of the missed frames. */ |
Jisheng Zhang | 133466c | 2023-07-18 00:06:30 +0800 | [diff] [blame] | 85 | static void dwmac100_dma_diagnostic_fr(struct stmmac_extra_stats *x, |
Giuseppe CAVALLARO | ad01b7d | 2010-08-23 20:40:42 +0000 | [diff] [blame] | 86 | void __iomem *ioaddr) |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 87 | { |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 88 | u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR); |
| 89 | |
| 90 | if (unlikely(csr8)) { |
| 91 | if (csr8 & DMA_MISSED_FRAME_OVE) { |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 92 | x->rx_overflow_cntr += 0x800; |
| 93 | } else { |
| 94 | unsigned int ove_cntr; |
| 95 | ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17); |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 96 | x->rx_overflow_cntr += ove_cntr; |
| 97 | } |
| 98 | |
| 99 | if (csr8 & DMA_MISSED_FRAME_OVE_M) { |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 100 | x->rx_missed_cntr += 0xffff; |
| 101 | } else { |
| 102 | unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR); |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 103 | x->rx_missed_cntr += miss_f; |
| 104 | } |
| 105 | } |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 106 | } |
| 107 | |
stephen hemminger | cadb792 | 2010-10-13 14:51:25 +0000 | [diff] [blame] | 108 | const struct stmmac_dma_ops dwmac100_dma_ops = { |
Giuseppe Cavallaro | 495db27 | 2016-02-29 14:27:27 +0100 | [diff] [blame] | 109 | .reset = dwmac_dma_reset, |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 110 | .init = dwmac100_dma_init, |
Jose Abreu | 24aaed0 | 2018-05-18 14:56:05 +0100 | [diff] [blame] | 111 | .init_rx_chan = dwmac100_dma_init_rx, |
| 112 | .init_tx_chan = dwmac100_dma_init_tx, |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 113 | .dump_regs = dwmac100_dump_dma_regs, |
Jose Abreu | ab0204e | 2018-05-18 14:56:02 +0100 | [diff] [blame] | 114 | .dma_tx_mode = dwmac100_dma_operation_mode_tx, |
Giuseppe CAVALLARO | 3c32be6 | 2010-04-13 20:21:11 +0000 | [diff] [blame] | 115 | .dma_diagnostic_fr = dwmac100_dma_diagnostic_fr, |
| 116 | .enable_dma_transmission = dwmac_enable_dma_transmission, |
| 117 | .enable_dma_irq = dwmac_enable_dma_irq, |
| 118 | .disable_dma_irq = dwmac_disable_dma_irq, |
| 119 | .start_tx = dwmac_dma_start_tx, |
| 120 | .stop_tx = dwmac_dma_stop_tx, |
| 121 | .start_rx = dwmac_dma_start_rx, |
| 122 | .stop_rx = dwmac_dma_stop_rx, |
| 123 | .dma_interrupt = dwmac_dma_interrupt, |
| 124 | }; |