2005-10-10 16:58:14 -07:00
/*
* drivers / net / ibm_emac / ibm_emac_tah . c
*
* Driver for PowerPC 4 xx on - chip ethernet controller , TAH support .
*
* Copyright 2004 MontaVista Software , Inc .
* Matt Porter < mporter @ kernel . crashing . org >
*
* Copyright ( c ) 2005 Eugene Surovegin < ebs @ ebshome . net >
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*/
# include <asm/io.h>
# include "ibm_emac_core.h"
static int __init tah_init ( struct ocp_device * ocpdev )
{
struct tah_regs * p ;
if ( ocp_get_drvdata ( ocpdev ) ) {
printk ( KERN_ERR " tah%d: already in use! \n " , ocpdev - > def - > index ) ;
return - EBUSY ;
}
/* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
p = ( struct tah_regs * ) ioremap ( ocpdev - > def - > paddr , sizeof ( * p ) ) ;
if ( ! p ) {
printk ( KERN_ERR " tah%d: could not ioremap device registers! \n " ,
ocpdev - > def - > index ) ;
return - ENOMEM ;
}
ocp_set_drvdata ( ocpdev , p ) ;
__tah_reset ( ocpdev ) ;
return 0 ;
}
int __init tah_attach ( void * emac )
{
struct ocp_enet_private * dev = emac ;
struct ocp_func_emac_data * emacdata = dev - > def - > additions ;
/* Check if we need to attach to a TAH */
if ( emacdata - > tah_idx > = 0 ) {
dev - > tah_dev = ocp_find_device ( OCP_ANY_ID , OCP_FUNC_TAH ,
emacdata - > tah_idx ) ;
if ( ! dev - > tah_dev ) {
printk ( KERN_ERR " emac%d: unknown tah%d! \n " ,
dev - > def - > index , emacdata - > tah_idx ) ;
return - ENODEV ;
}
if ( tah_init ( dev - > tah_dev ) ) {
printk ( KERN_ERR
" emac%d: tah%d initialization failed! \n " ,
dev - > def - > index , emacdata - > tah_idx ) ;
return - ENODEV ;
}
}
return 0 ;
}
2007-05-16 11:57:37 -07:00
void __tah_fini ( struct ocp_device * ocpdev )
2005-10-10 16:58:14 -07:00
{
struct tah_regs * p = ocp_get_drvdata ( ocpdev ) ;
BUG_ON ( ! p ) ;
ocp_set_drvdata ( ocpdev , NULL ) ;
iounmap ( ( void * ) p ) ;
}
void __tah_reset ( struct ocp_device * ocpdev )
{
struct tah_regs * p = ocp_get_drvdata ( ocpdev ) ;
int n ;
/* Reset TAH */
out_be32 ( & p - > mr , TAH_MR_SR ) ;
n = 100 ;
while ( ( in_be32 ( & p - > mr ) & TAH_MR_SR ) & & n )
- - n ;
if ( unlikely ( ! n ) )
printk ( KERN_ERR " tah%d: reset timeout \n " , ocpdev - > def - > index ) ;
/* 10KB TAH TX FIFO accomodates the max MTU of 9000 */
out_be32 ( & p - > mr ,
TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
TAH_MR_DIG ) ;
}
int __tah_get_regs_len ( struct ocp_device * ocpdev )
{
return sizeof ( struct emac_ethtool_regs_subhdr ) +
sizeof ( struct tah_regs ) ;
}
void * tah_dump_regs ( struct ocp_device * ocpdev , void * buf )
{
struct tah_regs * dev = ocp_get_drvdata ( ocpdev ) ;
struct emac_ethtool_regs_subhdr * hdr = buf ;
struct tah_regs * regs = ( struct tah_regs * ) ( hdr + 1 ) ;
hdr - > version = 0 ;
hdr - > index = ocpdev - > def - > index ;
memcpy_fromio ( regs , dev , sizeof ( struct tah_regs ) ) ;
return regs + 1 ;
}