2019-05-19 13:08:20 +01:00
// SPDX-License-Identifier: GPL-2.0-only
2007-06-28 00:49:06 +02:00
/*
* sni_82596 . c - - driver for intel 82596 ethernet controller , as
* used in older SNI RM machines
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/string.h>
# include <linux/errno.h>
# include <linux/ioport.h>
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/netdevice.h>
# include <linux/etherdevice.h>
# include <linux/skbuff.h>
# include <linux/types.h>
# include <linux/bitops.h>
# include <linux/platform_device.h>
# include <linux/io.h>
# include <linux/irq.h>
# define SNI_82596_DRIVER_VERSION "SNI RM 82596 driver - Revision: 0.01"
static const char sni_82596_string [ ] = " snirm_82596 " ;
# define SYSBUS 0x00004400
/* big endian CPU, 82596 little endian */
# define SWAP32(x) cpu_to_le32((u32)(x))
# define SWAP16(x) cpu_to_le16((u16)(x))
# define OPT_MPU_16BIT 0x01
# include "lib82596.c"
MODULE_AUTHOR ( " Thomas Bogendoerfer " ) ;
MODULE_DESCRIPTION ( " i82596 driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
2008-04-18 13:50:44 -07:00
MODULE_ALIAS ( " platform:snirm_82596 " ) ;
2007-06-28 00:49:06 +02:00
module_param ( i596_debug , int , 0 ) ;
MODULE_PARM_DESC ( i596_debug , " 82596 debug mask " ) ;
static inline void ca ( struct net_device * dev )
{
struct i596_private * lp = netdev_priv ( dev ) ;
writel ( 0 , lp - > ca ) ;
}
static void mpu_port ( struct net_device * dev , int c , dma_addr_t x )
{
struct i596_private * lp = netdev_priv ( dev ) ;
u32 v = ( u32 ) ( c ) | ( u32 ) ( x ) ;
if ( lp - > options & OPT_MPU_16BIT ) {
writew ( v & 0xffff , lp - > mpu_port ) ;
wmb ( ) ; /* order writes to MPU port */
udelay ( 1 ) ;
writew ( v > > 16 , lp - > mpu_port ) ;
} else {
writel ( v , lp - > mpu_port ) ;
wmb ( ) ; /* order writes to MPU port */
udelay ( 1 ) ;
writel ( v , lp - > mpu_port ) ;
}
}
2012-12-03 09:22:47 -05:00
static int sni_82596_probe ( struct platform_device * dev )
2007-06-28 00:49:06 +02:00
{
struct net_device * netdevice ;
struct i596_private * lp ;
struct resource * res , * ca , * idprom , * options ;
int retval = - ENOMEM ;
void __iomem * mpu_addr ;
void __iomem * ca_addr ;
u8 __iomem * eth_addr ;
res = platform_get_resource ( dev , IORESOURCE_MEM , 0 ) ;
ca = platform_get_resource ( dev , IORESOURCE_MEM , 1 ) ;
options = platform_get_resource ( dev , 0 , 0 ) ;
idprom = platform_get_resource ( dev , IORESOURCE_MEM , 2 ) ;
if ( ! res | | ! ca | | ! options | | ! idprom )
return - ENODEV ;
2020-01-06 09:43:50 +01:00
mpu_addr = ioremap ( res - > start , 4 ) ;
2007-06-28 00:49:06 +02:00
if ( ! mpu_addr )
return - ENOMEM ;
2020-01-06 09:43:50 +01:00
ca_addr = ioremap ( ca - > start , 4 ) ;
2007-06-28 00:49:06 +02:00
if ( ! ca_addr )
goto probe_failed_free_mpu ;
printk ( KERN_INFO " Found i82596 at 0x%x \n " , res - > start ) ;
netdevice = alloc_etherdev ( sizeof ( struct i596_private ) ) ;
if ( ! netdevice )
goto probe_failed_free_ca ;
SET_NETDEV_DEV ( netdevice , & dev - > dev ) ;
platform_set_drvdata ( dev , netdevice ) ;
netdevice - > base_addr = res - > start ;
netdevice - > irq = platform_get_irq ( dev , 0 ) ;
2020-01-06 09:43:50 +01:00
eth_addr = ioremap ( idprom - > start , 0x10 ) ;
2007-06-28 00:49:06 +02:00
if ( ! eth_addr )
goto probe_failed ;
/* someone seems to like messed up stuff */
netdevice - > dev_addr [ 0 ] = readb ( eth_addr + 0x0b ) ;
netdevice - > dev_addr [ 1 ] = readb ( eth_addr + 0x0a ) ;
netdevice - > dev_addr [ 2 ] = readb ( eth_addr + 0x09 ) ;
netdevice - > dev_addr [ 3 ] = readb ( eth_addr + 0x08 ) ;
netdevice - > dev_addr [ 4 ] = readb ( eth_addr + 0x07 ) ;
netdevice - > dev_addr [ 5 ] = readb ( eth_addr + 0x06 ) ;
iounmap ( eth_addr ) ;
2022-01-14 06:57:24 +00:00
if ( netdevice - > irq < 0 ) {
2007-06-28 00:49:06 +02:00
printk ( KERN_ERR " %s: IRQ not found for i82596 at 0x%lx \n " ,
__FILE__ , netdevice - > base_addr ) ;
2022-01-14 06:57:24 +00:00
retval = netdevice - > irq ;
2007-06-28 00:49:06 +02:00
goto probe_failed ;
}
lp = netdev_priv ( netdevice ) ;
lp - > options = options - > flags & IORESOURCE_BITS ;
lp - > ca = ca_addr ;
lp - > mpu_port = mpu_addr ;
2020-08-17 15:58:21 +02:00
lp - > dma = dma_alloc_coherent ( & dev - > dev , sizeof ( struct i596_dma ) ,
& lp - > dma_addr , GFP_KERNEL ) ;
if ( ! lp - > dma )
goto probe_failed ;
2007-06-28 00:49:06 +02:00
retval = i82596_probe ( netdevice ) ;
2020-08-17 15:58:21 +02:00
if ( retval )
goto probe_failed_free_dma ;
return 0 ;
2007-06-28 00:49:06 +02:00
2020-08-17 15:58:21 +02:00
probe_failed_free_dma :
dma_free_coherent ( & dev - > dev , sizeof ( struct i596_dma ) , lp - > dma ,
lp - > dma_addr ) ;
2007-06-28 00:49:06 +02:00
probe_failed :
free_netdev ( netdevice ) ;
probe_failed_free_ca :
iounmap ( ca_addr ) ;
probe_failed_free_mpu :
iounmap ( mpu_addr ) ;
return retval ;
}
2012-12-03 09:22:47 -05:00
static int sni_82596_driver_remove ( struct platform_device * pdev )
2007-06-28 00:49:06 +02:00
{
struct net_device * dev = platform_get_drvdata ( pdev ) ;
struct i596_private * lp = netdev_priv ( dev ) ;
unregister_netdev ( dev ) ;
2020-08-17 15:58:21 +02:00
dma_free_coherent ( & pdev - > dev , sizeof ( struct i596_private ) , lp - > dma ,
lp - > dma_addr ) ;
2007-06-28 00:49:06 +02:00
iounmap ( lp - > ca ) ;
iounmap ( lp - > mpu_port ) ;
free_netdev ( dev ) ;
return 0 ;
}
static struct platform_driver sni_82596_driver = {
. probe = sni_82596_probe ,
2012-12-03 09:22:47 -05:00
. remove = sni_82596_driver_remove ,
2007-06-28 00:49:06 +02:00
. driver = {
. name = sni_82596_string ,
} ,
} ;
2012-12-03 09:22:47 -05:00
static int sni_82596_init ( void )
2007-06-28 00:49:06 +02:00
{
printk ( KERN_INFO SNI_82596_DRIVER_VERSION " \n " ) ;
return platform_driver_register ( & sni_82596_driver ) ;
}
static void __exit sni_82596_exit ( void )
{
platform_driver_unregister ( & sni_82596_driver ) ;
}
module_init ( sni_82596_init ) ;
module_exit ( sni_82596_exit ) ;