#include "gsc3280mac1000.h" #include "gsc3280mac_dma.h" static int gsc3280mac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, u32 dma_rx) { u32 value = readl(ioaddr + DMA_BUS_MODE); int limit; /* DMA SW reset */ value |= DMA_BUS_MODE_SFT_RESET; writel(value, ioaddr + DMA_BUS_MODE); limit = 15000; while (limit--) { if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)) break; } if (limit < 0) return -EBUSY; //value = /*DMA_BUS_MODE_FB |*/ DMA_BUS_MODE_4PBL | value = DMA_BUS_MODE_FB | DMA_BUS_MODE_4PBL | ((pbl << DMA_BUS_MODE_PBL_SHIFT) | (pbl << DMA_BUS_MODE_RPBL_SHIFT)); #ifdef CONFIG_GSC3280MAC_DA value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */ #endif writel(value, ioaddr + DMA_BUS_MODE); /* Mask interrupts by writing to CSR7 */ writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); /* The base address of the RX/TX descriptor lists must be written into * DMA CSR3 and CSR4, respectively. */ writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR); writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR); return 0; } static void gsc3280mac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, int rxmode) { u32 csr6 = readl(ioaddr + DMA_CONTROL); if (txmode == SF_DMA_MODE) { CHIP_DBG(KERN_DEBUG "GMAC: enable TX store and forward mode\n"); /* Transmit COE type 2 cannot be done in cut-through mode. */ csr6 |= DMA_CONTROL_TSF; /* Operating on second frame increase the performance * especially when transmit store-and-forward is used.*/ csr6 |= DMA_CONTROL_OSF; } else { CHIP_DBG(KERN_DEBUG "GMAC: disabling TX store and forward mode" " (threshold = %d)\n", txmode); csr6 &= ~DMA_CONTROL_TSF; csr6 &= DMA_CONTROL_TC_TX_MASK; /* Set the transmit threshold */ if (txmode <= 32) csr6 |= DMA_CONTROL_TTC_32; else if (txmode <= 64) csr6 |= DMA_CONTROL_TTC_64; else if (txmode <= 128) csr6 |= DMA_CONTROL_TTC_128; else if (txmode <= 192) csr6 |= DMA_CONTROL_TTC_192; else csr6 |= DMA_CONTROL_TTC_256; } if (rxmode == SF_DMA_MODE) { CHIP_DBG(KERN_DEBUG "GMAC: enable RX store and forward mode\n"); csr6 |= DMA_CONTROL_RSF; // csr6 |= DMA_CONTROL_DT; //NOTE: set 1 to report IP/TCP/UDP/ICMP checksum error frame to CPU, set 0 to drop the frame silently. } else { CHIP_DBG(KERN_DEBUG "GMAC: disabling RX store and forward mode" " (threshold = %d)\n", rxmode); csr6 &= ~DMA_CONTROL_RSF; csr6 &= DMA_CONTROL_TC_RX_MASK; if (rxmode <= 32) csr6 |= DMA_CONTROL_RTC_32; else if (rxmode <= 64) csr6 |= DMA_CONTROL_RTC_64; else if (rxmode <= 96) csr6 |= DMA_CONTROL_RTC_96; else csr6 |= DMA_CONTROL_RTC_128; } writel(csr6, ioaddr + DMA_CONTROL); } /* Not yet implemented --- no RMON module */ static void gsc3280mac1000_dma_diagnostic_fr(void *data, struct gsc3280mac_extra_stats *x, void __iomem *ioaddr) { return; } static void gsc3280mac1000_dump_dma_regs(void __iomem *ioaddr) { int i; pr_info(" DMA registers\n"); for (i = 0; i < 22; i++) { if ((i < 9) || (i > 17)) { int offset = i * 4; pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i, (DMA_BUS_MODE + offset), readl(ioaddr + DMA_BUS_MODE + offset)); } } } const struct gsc3280mac_dma_ops gsc3280mac1000_dma_ops = { .init = gsc3280mac1000_dma_init, .dump_regs = gsc3280mac1000_dump_dma_regs, .dma_mode = gsc3280mac1000_dma_operation_mode, .dma_diagnostic_fr = gsc3280mac1000_dma_diagnostic_fr, .enable_dma_transmission = gsc3280mac_enable_dma_transmission, .enable_dma_irq = gsc3280mac_enable_dma_irq, .disable_dma_irq = gsc3280mac_disable_dma_irq, .start_tx = gsc3280mac_dma_start_tx, .stop_tx = gsc3280mac_dma_stop_tx, .start_rx = gsc3280mac_dma_start_rx, .stop_rx = gsc3280mac_dma_stop_rx, .dma_interrupt = gsc3280mac_dma_interrupt, };