2009-10-14 15:13:45 -07:00
/*******************************************************************************
This is the driver for the MAC 10 / 100 on - chip Ethernet controller
currently tested on all the ST boards based on STb7109 and stx7200 SoCs .
DWC Ether MAC 10 / 100 Universal version 4.0 has been used for developing
this code .
2010-04-13 20:21:12 +00:00
This contains the functions to handle the dma .
2010-04-13 20:21:11 +00:00
2009-10-14 15:13:45 -07:00
Copyright ( C ) 2007 - 2009 STMicroelectronics Ltd
This program is free software ; you can redistribute it and / or modify it
under the terms and conditions of the GNU General Public License ,
version 2 , as published by the Free Software Foundation .
This program is distributed in the hope it will be useful , but WITHOUT
ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
more details .
You should have received a copy of the GNU General Public License along with
this program ; if not , write to the Free Software Foundation , Inc . ,
51 Franklin St - Fifth Floor , Boston , MA 02110 - 1301 USA .
The full GNU General Public License is included in this distribution in
the file called " COPYING " .
Author : Giuseppe Cavallaro < peppe . cavallaro @ st . com >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-06-16 11:01:34 +00:00
# include <asm/io.h>
2010-01-06 23:07:19 +00:00
# include "dwmac100.h"
2010-01-06 23:07:18 +00:00
# include "dwmac_dma.h"
2009-10-14 15:13:45 -07:00
2010-08-23 20:40:42 +00:00
static int dwmac100_dma_init ( void __iomem * ioaddr , int pbl , u32 dma_tx ,
2010-04-13 20:21:11 +00:00
u32 dma_rx )
2009-10-14 15:13:45 -07:00
{
u32 value = readl ( ioaddr + DMA_BUS_MODE ) ;
2010-09-17 03:23:41 +00:00
int limit ;
2009-10-14 15:13:45 -07:00
/* DMA SW reset */
value | = DMA_BUS_MODE_SFT_RESET ;
writel ( value , ioaddr + DMA_BUS_MODE ) ;
2010-09-17 03:23:41 +00:00
limit = 15000 ;
while ( limit - - ) {
if ( ! ( readl ( ioaddr + DMA_BUS_MODE ) & DMA_BUS_MODE_SFT_RESET ) )
break ;
}
if ( limit < 0 )
return - EBUSY ;
2009-10-14 15:13:45 -07:00
/* Enable Application Access by writing to DMA CSR0 */
writel ( DMA_BUS_MODE_DEFAULT | ( pbl < < DMA_BUS_MODE_PBL_SHIFT ) ,
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 ;
}
/* Store and Forward capability is not used at all..
* The transmit threshold can be programmed by
* setting the TTC bits in the DMA control register . */
2010-08-23 20:40:42 +00:00
static void dwmac100_dma_operation_mode ( void __iomem * ioaddr , int txmode ,
2010-04-13 20:21:11 +00:00
int rxmode )
2009-10-14 15:13:45 -07:00
{
u32 csr6 = readl ( ioaddr + DMA_CONTROL ) ;
if ( txmode < = 32 )
csr6 | = DMA_CONTROL_TTC_32 ;
else if ( txmode < = 64 )
csr6 | = DMA_CONTROL_TTC_64 ;
else
csr6 | = DMA_CONTROL_TTC_128 ;
writel ( csr6 , ioaddr + DMA_CONTROL ) ;
}
2010-08-23 20:40:42 +00:00
static void dwmac100_dump_dma_regs ( void __iomem * ioaddr )
2009-10-14 15:13:45 -07:00
{
int i ;
2010-04-13 20:21:12 +00:00
CHIP_DBG ( KERN_DEBUG " DWMAC 100 DMA CSR \n " ) ;
2009-10-14 15:13:45 -07:00
for ( i = 0 ; i < 9 ; i + + )
pr_debug ( " \t CSR%d (offset 0x%x): 0x%08x \n " , i ,
( DMA_BUS_MODE + i * 4 ) ,
readl ( ioaddr + DMA_BUS_MODE + i * 4 ) ) ;
2010-04-13 20:21:12 +00:00
CHIP_DBG ( KERN_DEBUG " \t CSR20 (offset 0x%x): 0x%08x \n " ,
2009-10-14 15:13:45 -07:00
DMA_CUR_TX_BUF_ADDR , readl ( ioaddr + DMA_CUR_TX_BUF_ADDR ) ) ;
2010-04-13 20:21:12 +00:00
CHIP_DBG ( KERN_DEBUG " \t CSR21 (offset 0x%x): 0x%08x \n " ,
2009-10-14 15:13:45 -07:00
DMA_CUR_RX_BUF_ADDR , readl ( ioaddr + DMA_CUR_RX_BUF_ADDR ) ) ;
}
/* DMA controller has two counters to track the number of
2010-01-06 23:07:19 +00:00
* the receive missed frames . */
2010-04-13 20:21:11 +00:00
static void dwmac100_dma_diagnostic_fr ( void * data , struct stmmac_extra_stats * x ,
2010-08-23 20:40:42 +00:00
void __iomem * ioaddr )
2009-10-14 15:13:45 -07:00
{
struct net_device_stats * stats = ( struct net_device_stats * ) data ;
u32 csr8 = readl ( ioaddr + DMA_MISSED_FRAME_CTR ) ;
if ( unlikely ( csr8 ) ) {
if ( csr8 & DMA_MISSED_FRAME_OVE ) {
stats - > rx_over_errors + = 0x800 ;
x - > rx_overflow_cntr + = 0x800 ;
} else {
unsigned int ove_cntr ;
ove_cntr = ( ( csr8 & DMA_MISSED_FRAME_OVE_CNTR ) > > 17 ) ;
stats - > rx_over_errors + = ove_cntr ;
x - > rx_overflow_cntr + = ove_cntr ;
}
if ( csr8 & DMA_MISSED_FRAME_OVE_M ) {
stats - > rx_missed_errors + = 0xffff ;
x - > rx_missed_cntr + = 0xffff ;
} else {
unsigned int miss_f = ( csr8 & DMA_MISSED_FRAME_M_CNTR ) ;
stats - > rx_missed_errors + = miss_f ;
x - > rx_missed_cntr + = miss_f ;
}
}
}
2010-10-13 14:51:25 +00:00
const struct stmmac_dma_ops dwmac100_dma_ops = {
2010-01-06 23:07:19 +00:00
. init = dwmac100_dma_init ,
. dump_regs = dwmac100_dump_dma_regs ,
. dma_mode = dwmac100_dma_operation_mode ,
. dma_diagnostic_fr = dwmac100_dma_diagnostic_fr ,
2010-01-06 23:07:18 +00:00
. enable_dma_transmission = dwmac_enable_dma_transmission ,
. enable_dma_irq = dwmac_enable_dma_irq ,
. disable_dma_irq = dwmac_disable_dma_irq ,
. start_tx = dwmac_dma_start_tx ,
. stop_tx = dwmac_dma_stop_tx ,
. start_rx = dwmac_dma_start_rx ,
. stop_rx = dwmac_dma_stop_rx ,
. dma_interrupt = dwmac_dma_interrupt ,
2010-01-06 23:07:17 +00:00
} ;