forked from Minki/linux
6473d160b4
I noticed that many source files include <linux/pci.h> while they do not appear to need it. Here is an attempt to clean it all up. In order to find all possibly affected files, I searched for all files including <linux/pci.h> but without any other occurence of "pci" or "PCI". I removed the include statement from all of these, then I compiled an allmodconfig kernel on both i386 and x86_64 and fixed the false positives manually. My tests covered 66% of the affected files, so there could be false positives remaining. Untested files are: arch/alpha/kernel/err_common.c arch/alpha/kernel/err_ev6.c arch/alpha/kernel/err_ev7.c arch/ia64/sn/kernel/huberror.c arch/ia64/sn/kernel/xpnet.c arch/m68knommu/kernel/dma.c arch/mips/lib/iomap.c arch/powerpc/platforms/pseries/ras.c arch/ppc/8260_io/enet.c arch/ppc/8260_io/fcc_enet.c arch/ppc/8xx_io/enet.c arch/ppc/syslib/ppc4xx_sgdma.c arch/sh64/mach-cayman/iomap.c arch/xtensa/kernel/xtensa_ksyms.c arch/xtensa/platform-iss/setup.c drivers/i2c/busses/i2c-at91.c drivers/i2c/busses/i2c-mpc.c drivers/media/video/saa711x.c drivers/misc/hdpuftrs/hdpu_cpustate.c drivers/misc/hdpuftrs/hdpu_nexus.c drivers/net/au1000_eth.c drivers/net/fec_8xx/fec_main.c drivers/net/fec_8xx/fec_mii.c drivers/net/fs_enet/fs_enet-main.c drivers/net/fs_enet/mac-fcc.c drivers/net/fs_enet/mac-fec.c drivers/net/fs_enet/mac-scc.c drivers/net/fs_enet/mii-bitbang.c drivers/net/fs_enet/mii-fec.c drivers/net/ibm_emac/ibm_emac_core.c drivers/net/lasi_82596.c drivers/parisc/hppb.c drivers/sbus/sbus.c drivers/video/g364fb.c drivers/video/platinumfb.c drivers/video/stifb.c drivers/video/valkyriefb.c include/asm-arm/arch-ixp4xx/dma.h sound/oss/au1550_ac97.c I would welcome test reports for these files. I am fine with removing the untested files from the patch if the general opinion is that these changes aren't safe. The tested part would still be nice to have. Note that this patch depends on another header fixup patch I submitted to LKML yesterday: [PATCH] scatterlist.h needs types.h http://lkml.org/lkml/2007/3/01/141 Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: Badari Pulavarty <pbadari@us.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
420 lines
10 KiB
C
420 lines
10 KiB
C
/*
|
|
* Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
|
|
*
|
|
* Copyright (c) 2003 Intracom S.A.
|
|
* by Pantelis Antoniou <panto@intracom.gr>
|
|
*
|
|
* Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
|
|
* and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
|
|
*
|
|
* Released under the GPL
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/types.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/string.h>
|
|
#include <linux/ptrace.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/init.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/etherdevice.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/mii.h>
|
|
#include <linux/ethtool.h>
|
|
#include <linux/bitops.h>
|
|
|
|
#include <asm/8xx_immap.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/mpc8xx.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/commproc.h>
|
|
|
|
/*************************************************/
|
|
|
|
#include "fec_8xx.h"
|
|
|
|
/*************************************************/
|
|
|
|
/* Make MII read/write commands for the FEC.
|
|
*/
|
|
#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
|
|
#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
|
|
#define mk_mii_end 0
|
|
|
|
/*************************************************/
|
|
|
|
/* XXX both FECs use the MII interface of FEC1 */
|
|
static DEFINE_SPINLOCK(fec_mii_lock);
|
|
|
|
#define FEC_MII_LOOPS 10000
|
|
|
|
int fec_mii_read(struct net_device *dev, int phy_id, int location)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
fec_t *fecp;
|
|
int i, ret = -1;
|
|
unsigned long flags;
|
|
|
|
/* XXX MII interface is only connected to FEC1 */
|
|
fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
|
|
|
|
spin_lock_irqsave(&fec_mii_lock, flags);
|
|
|
|
if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) {
|
|
FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
|
|
FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
|
|
FW(fecp, ievent, FEC_ENET_MII);
|
|
}
|
|
|
|
/* Add PHY address to register command. */
|
|
FW(fecp, mii_speed, fep->fec_phy_speed);
|
|
FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
|
|
|
|
for (i = 0; i < FEC_MII_LOOPS; i++)
|
|
if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
|
|
break;
|
|
|
|
if (i < FEC_MII_LOOPS) {
|
|
FW(fecp, ievent, FEC_ENET_MII);
|
|
ret = FR(fecp, mii_data) & 0xffff;
|
|
}
|
|
|
|
spin_unlock_irqrestore(&fec_mii_lock, flags);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void fec_mii_write(struct net_device *dev, int phy_id, int location, int value)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
fec_t *fecp;
|
|
unsigned long flags;
|
|
int i;
|
|
|
|
/* XXX MII interface is only connected to FEC1 */
|
|
fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
|
|
|
|
spin_lock_irqsave(&fec_mii_lock, flags);
|
|
|
|
if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) {
|
|
FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
|
|
FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
|
|
FW(fecp, ievent, FEC_ENET_MII);
|
|
}
|
|
|
|
/* Add PHY address to register command. */
|
|
FW(fecp, mii_speed, fep->fec_phy_speed); /* always adapt mii speed */
|
|
FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
|
|
|
|
for (i = 0; i < FEC_MII_LOOPS; i++)
|
|
if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
|
|
break;
|
|
|
|
if (i < FEC_MII_LOOPS)
|
|
FW(fecp, ievent, FEC_ENET_MII);
|
|
|
|
spin_unlock_irqrestore(&fec_mii_lock, flags);
|
|
}
|
|
|
|
/*************************************************/
|
|
|
|
#ifdef CONFIG_FEC_8XX_GENERIC_PHY
|
|
|
|
/*
|
|
* Generic PHY support.
|
|
* Should work for all PHYs, but link change is detected by polling
|
|
*/
|
|
|
|
static void generic_timer_callback(unsigned long data)
|
|
{
|
|
struct net_device *dev = (struct net_device *)data;
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
fep->phy_timer_list.expires = jiffies + HZ / 2;
|
|
|
|
add_timer(&fep->phy_timer_list);
|
|
|
|
fec_mii_link_status_change_check(dev, 0);
|
|
}
|
|
|
|
static void generic_startup(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
|
|
fep->phy_timer_list.data = (unsigned long)dev;
|
|
fep->phy_timer_list.function = generic_timer_callback;
|
|
add_timer(&fep->phy_timer_list);
|
|
}
|
|
|
|
static void generic_shutdown(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
del_timer_sync(&fep->phy_timer_list);
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_FEC_8XX_DM9161_PHY
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* The Davicom DM9161 is used on the NETTA board */
|
|
|
|
/* register definitions */
|
|
|
|
#define MII_DM9161_ACR 16 /* Aux. Config Register */
|
|
#define MII_DM9161_ACSR 17 /* Aux. Config/Status Register */
|
|
#define MII_DM9161_10TCSR 18 /* 10BaseT Config/Status Reg. */
|
|
#define MII_DM9161_INTR 21 /* Interrupt Register */
|
|
#define MII_DM9161_RECR 22 /* Receive Error Counter Reg. */
|
|
#define MII_DM9161_DISCR 23 /* Disconnect Counter Register */
|
|
|
|
static void dm9161_startup(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
fec_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
|
|
}
|
|
|
|
static void dm9161_ack_int(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
fec_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
|
|
}
|
|
|
|
static void dm9161_shutdown(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
fec_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_FEC_8XX_LXT971_PHY
|
|
|
|
/* Support for LXT971/972 PHY */
|
|
|
|
#define MII_LXT971_PCR 16 /* Port Control Register */
|
|
#define MII_LXT971_SR2 17 /* Status Register 2 */
|
|
#define MII_LXT971_IER 18 /* Interrupt Enable Register */
|
|
#define MII_LXT971_ISR 19 /* Interrupt Status Register */
|
|
#define MII_LXT971_LCR 20 /* LED Control Register */
|
|
#define MII_LXT971_TCR 30 /* Transmit Control Register */
|
|
|
|
static void lxt971_startup(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
fec_mii_write(dev, fep->mii_if.phy_id, MII_LXT971_IER, 0x00F2);
|
|
}
|
|
|
|
static void lxt971_ack_int(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
fec_mii_read(dev, fep->mii_if.phy_id, MII_LXT971_ISR);
|
|
}
|
|
|
|
static void lxt971_shutdown(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
|
|
fec_mii_write(dev, fep->mii_if.phy_id, MII_LXT971_IER, 0x0000);
|
|
}
|
|
#endif
|
|
|
|
/**********************************************************************************/
|
|
|
|
static const struct phy_info phy_info[] = {
|
|
#ifdef CONFIG_FEC_8XX_DM9161_PHY
|
|
{
|
|
.id = 0x00181b88,
|
|
.name = "DM9161",
|
|
.startup = dm9161_startup,
|
|
.ack_int = dm9161_ack_int,
|
|
.shutdown = dm9161_shutdown,
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_FEC_8XX_LXT971_PHY
|
|
{
|
|
.id = 0x0001378e,
|
|
.name = "LXT971/972",
|
|
.startup = lxt971_startup,
|
|
.ack_int = lxt971_ack_int,
|
|
.shutdown = lxt971_shutdown,
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_FEC_8XX_GENERIC_PHY
|
|
{
|
|
.id = 0,
|
|
.name = "GENERIC",
|
|
.startup = generic_startup,
|
|
.shutdown = generic_shutdown,
|
|
},
|
|
#endif
|
|
};
|
|
|
|
/**********************************************************************************/
|
|
|
|
int fec_mii_phy_id_detect(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
const struct fec_platform_info *fpi = fep->fpi;
|
|
int i, r, start, end, phytype, physubtype;
|
|
const struct phy_info *phy;
|
|
int phy_hwid, phy_id;
|
|
|
|
/* if no MDIO */
|
|
if (fpi->use_mdio == 0)
|
|
return -1;
|
|
|
|
phy_hwid = -1;
|
|
fep->phy = NULL;
|
|
|
|
/* auto-detect? */
|
|
if (fpi->phy_addr == -1) {
|
|
start = 0;
|
|
end = 32;
|
|
} else { /* direct */
|
|
start = fpi->phy_addr;
|
|
end = start + 1;
|
|
}
|
|
|
|
for (phy_id = start; phy_id < end; phy_id++) {
|
|
r = fec_mii_read(dev, phy_id, MII_PHYSID1);
|
|
if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
|
|
continue;
|
|
r = fec_mii_read(dev, phy_id, MII_PHYSID2);
|
|
if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
|
|
continue;
|
|
phy_hwid = (phytype << 16) | physubtype;
|
|
if (phy_hwid != -1)
|
|
break;
|
|
}
|
|
|
|
if (phy_hwid == -1) {
|
|
printk(KERN_ERR DRV_MODULE_NAME
|
|
": %s No PHY detected!\n", dev->name);
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0, phy = phy_info; i < sizeof(phy_info) / sizeof(phy_info[0]);
|
|
i++, phy++)
|
|
if (phy->id == (phy_hwid >> 4) || phy->id == 0)
|
|
break;
|
|
|
|
if (i >= sizeof(phy_info) / sizeof(phy_info[0])) {
|
|
printk(KERN_ERR DRV_MODULE_NAME
|
|
": %s PHY id 0x%08x is not supported!\n",
|
|
dev->name, phy_hwid);
|
|
return -1;
|
|
}
|
|
|
|
fep->phy = phy;
|
|
|
|
printk(KERN_INFO DRV_MODULE_NAME
|
|
": %s Phy @ 0x%x, type %s (0x%08x)\n",
|
|
dev->name, phy_id, fep->phy->name, phy_hwid);
|
|
|
|
return phy_id;
|
|
}
|
|
|
|
void fec_mii_startup(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
const struct fec_platform_info *fpi = fep->fpi;
|
|
|
|
if (!fpi->use_mdio || fep->phy == NULL)
|
|
return;
|
|
|
|
if (fep->phy->startup == NULL)
|
|
return;
|
|
|
|
(*fep->phy->startup) (dev);
|
|
}
|
|
|
|
void fec_mii_shutdown(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
const struct fec_platform_info *fpi = fep->fpi;
|
|
|
|
if (!fpi->use_mdio || fep->phy == NULL)
|
|
return;
|
|
|
|
if (fep->phy->shutdown == NULL)
|
|
return;
|
|
|
|
(*fep->phy->shutdown) (dev);
|
|
}
|
|
|
|
void fec_mii_ack_int(struct net_device *dev)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
const struct fec_platform_info *fpi = fep->fpi;
|
|
|
|
if (!fpi->use_mdio || fep->phy == NULL)
|
|
return;
|
|
|
|
if (fep->phy->ack_int == NULL)
|
|
return;
|
|
|
|
(*fep->phy->ack_int) (dev);
|
|
}
|
|
|
|
/* helper function */
|
|
static int mii_negotiated(struct mii_if_info *mii)
|
|
{
|
|
int advert, lpa, val;
|
|
|
|
if (!mii_link_ok(mii))
|
|
return 0;
|
|
|
|
val = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_BMSR);
|
|
if ((val & BMSR_ANEGCOMPLETE) == 0)
|
|
return 0;
|
|
|
|
advert = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_ADVERTISE);
|
|
lpa = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_LPA);
|
|
|
|
return mii_nway_result(advert & lpa);
|
|
}
|
|
|
|
void fec_mii_link_status_change_check(struct net_device *dev, int init_media)
|
|
{
|
|
struct fec_enet_private *fep = netdev_priv(dev);
|
|
unsigned int media;
|
|
unsigned long flags;
|
|
|
|
if (mii_check_media(&fep->mii_if, netif_msg_link(fep), init_media) == 0)
|
|
return;
|
|
|
|
media = mii_negotiated(&fep->mii_if);
|
|
|
|
if (netif_carrier_ok(dev)) {
|
|
spin_lock_irqsave(&fep->lock, flags);
|
|
fec_restart(dev, !!(media & ADVERTISE_FULL),
|
|
(media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) ?
|
|
100 : 10);
|
|
spin_unlock_irqrestore(&fep->lock, flags);
|
|
|
|
netif_start_queue(dev);
|
|
} else {
|
|
netif_stop_queue(dev);
|
|
|
|
spin_lock_irqsave(&fep->lock, flags);
|
|
fec_stop(dev);
|
|
spin_unlock_irqrestore(&fep->lock, flags);
|
|
|
|
}
|
|
}
|