dect
/
linux-2.6
Archived
13
0
Fork 0

Merge branch 'upstream-greg' of gregkh@master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

This commit is contained in:
Greg Kroah-Hartman 2006-08-23 21:58:48 -07:00
commit 20253de9d5
81 changed files with 8661 additions and 1610 deletions

View File

@ -29,6 +29,7 @@
#include <linux/initrd.h>
#include <linux/module.h>
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@ -58,6 +59,71 @@
* Setup the architecture
*
*/
static void init_fcc_ioports(void)
{
struct immap *immap;
struct io_port *io;
u32 tempval;
immap = cpm2_immr;
io = &immap->im_ioport;
/* FCC2/3 are on the ports B/C. */
tempval = in_be32(&io->iop_pdirb);
tempval &= ~PB2_DIRB0;
tempval |= PB2_DIRB1;
out_be32(&io->iop_pdirb, tempval);
tempval = in_be32(&io->iop_psorb);
tempval &= ~PB2_PSORB0;
tempval |= PB2_PSORB1;
out_be32(&io->iop_psorb, tempval);
tempval = in_be32(&io->iop_pparb);
tempval |= (PB2_DIRB0 | PB2_DIRB1);
out_be32(&io->iop_pparb, tempval);
tempval = in_be32(&io->iop_pdirb);
tempval &= ~PB3_DIRB0;
tempval |= PB3_DIRB1;
out_be32(&io->iop_pdirb, tempval);
tempval = in_be32(&io->iop_psorb);
tempval &= ~PB3_PSORB0;
tempval |= PB3_PSORB1;
out_be32(&io->iop_psorb, tempval);
tempval = in_be32(&io->iop_pparb);
tempval |= (PB3_DIRB0 | PB3_DIRB1);
out_be32(&io->iop_pparb, tempval);
tempval = in_be32(&io->iop_pdirc);
tempval |= PC3_DIRC1;
out_be32(&io->iop_pdirc, tempval);
tempval = in_be32(&io->iop_pparc);
tempval |= PC3_DIRC1;
out_be32(&io->iop_pparc, tempval);
/* Port C has clocks...... */
tempval = in_be32(&io->iop_psorc);
tempval &= ~(CLK_TRX);
out_be32(&io->iop_psorc, tempval);
tempval = in_be32(&io->iop_pdirc);
tempval &= ~(CLK_TRX);
out_be32(&io->iop_pdirc, tempval);
tempval = in_be32(&io->iop_pparc);
tempval |= (CLK_TRX);
out_be32(&io->iop_pparc, tempval);
/* Configure Serial Interface clock routing.
* First, clear all FCC bits to zero,
* then set the ones we want.
*/
immap->im_cpmux.cmx_fcr &= ~(CPMUX_CLK_MASK);
immap->im_cpmux.cmx_fcr |= CPMUX_CLK_ROUTE;
}
static void __init
mpc8560ads_setup_arch(void)
@ -66,6 +132,7 @@ mpc8560ads_setup_arch(void)
unsigned int freq;
struct gianfar_platform_data *pdata;
struct gianfar_mdio_data *mdata;
struct fs_platform_info *fpi;
cpm2_reset();
@ -110,6 +177,28 @@ mpc8560ads_setup_arch(void)
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
init_fcc_ioports();
ppc_sys_device_remove(MPC85xx_CPM_FCC1);
fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC2);
if (fpi) {
memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
fpi->bus_id = "0:02";
fpi->phy_addr = 2;
fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[1];
}
fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC3);
if (fpi) {
memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
fpi->macaddr[5] += 1;
fpi->bus_id = "0:03";
fpi->phy_addr = 3;
fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[2];
}
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
ROOT_DEV = Root_RAM0;

View File

@ -45,4 +45,23 @@ extern void mpc85xx_ads_map_io(void) __init;
#define MPC85XX_PCI1_IO_SIZE 0x01000000
/* FCC1 Clock Source Configuration. These can be
* redefined in the board specific file.
* Can only choose from CLK9-12 */
#define F1_RXCLK 12
#define F1_TXCLK 11
/* FCC2 Clock Source Configuration. These can be
* redefined in the board specific file.
* Can only choose from CLK13-16 */
#define F2_RXCLK 13
#define F2_TXCLK 14
/* FCC3 Clock Source Configuration. These can be
* redefined in the board specific file.
* Can only choose from CLK13-16 */
#define F3_RXCLK 15
#define F3_TXCLK 16
#endif /* __MACH_MPC85XX_ADS_H__ */

View File

@ -56,64 +56,51 @@ static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
},
};
static struct fs_mii_bus_info mii_bus_info = {
.method = fsmii_bitbang,
.id = 0,
.i.bitbang = {
.mdio_port = fsiop_portc,
.mdio_bit = 18,
.mdc_port = fsiop_portc,
.mdc_bit = 19,
.delay = 1,
static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = {
.mdio_dat.bit = 18,
.mdio_dir.bit = 18,
.mdc_dat.bit = 19,
.delay = 1,
};
static struct fs_platform_info mpc82xx_enet_pdata[] = {
[fsid_fcc1] = {
.fs_no = fsid_fcc1,
.cp_page = CPM_CR_FCC1_PAGE,
.cp_block = CPM_CR_FCC1_SBLOCK,
.clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
.clk_route = CMX1_CLK_ROUTE,
.clk_mask = CMX1_CLK_MASK,
.init_ioports = init_fcc1_ioports,
.mem_offset = FCC1_MEM_OFFSET,
.rx_ring = 32,
.tx_ring = 32,
.rx_copybreak = 240,
.use_napi = 0,
.napi_weight = 17,
.bus_id = "0:00",
},
};
[fsid_fcc2] = {
.fs_no = fsid_fcc2,
.cp_page = CPM_CR_FCC2_PAGE,
.cp_block = CPM_CR_FCC2_SBLOCK,
.clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
.clk_route = CMX2_CLK_ROUTE,
.clk_mask = CMX2_CLK_MASK,
.init_ioports = init_fcc2_ioports,
static struct fs_platform_info mpc82xx_fcc1_pdata = {
.fs_no = fsid_fcc1,
.cp_page = CPM_CR_FCC1_PAGE,
.cp_block = CPM_CR_FCC1_SBLOCK,
.clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
.clk_route = CMX1_CLK_ROUTE,
.clk_mask = CMX1_CLK_MASK,
.init_ioports = init_fcc1_ioports,
.mem_offset = FCC2_MEM_OFFSET,
.phy_addr = 0,
#ifdef PHY_INTERRUPT
.phy_irq = PHY_INTERRUPT,
#else
.phy_irq = -1;
#endif
.mem_offset = FCC1_MEM_OFFSET,
.bus_info = &mii_bus_info,
.rx_ring = 32,
.tx_ring = 32,
.rx_copybreak = 240,
.use_napi = 0,
.napi_weight = 17,
};
static struct fs_platform_info mpc82xx_fcc2_pdata = {
.fs_no = fsid_fcc2,
.cp_page = CPM_CR_FCC2_PAGE,
.cp_block = CPM_CR_FCC2_SBLOCK,
.clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
.clk_route = CMX2_CLK_ROUTE,
.clk_mask = CMX2_CLK_MASK,
.init_ioports = init_fcc2_ioports,
.phy_addr = 3,
#ifdef PHY_INTERRUPT
.phy_irq = PHY_INTERRUPT,
#else
.phy_irq = -1;
#endif
.mem_offset = FCC2_MEM_OFFSET,
.bus_info = &mii_bus_info,
.rx_ring = 32,
.tx_ring = 32,
.rx_copybreak = 240,
.use_napi = 0,
.napi_weight = 17,
.rx_ring = 32,
.tx_ring = 32,
.rx_copybreak = 240,
.use_napi = 0,
.napi_weight = 17,
.bus_id = "0:03",
},
};
static void init_fcc1_ioports(void)
@ -209,20 +196,21 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
bd_t* bi = (void*)__res;
int fs_no = fsid_fcc1+pdev->id-1;
mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;
switch(fs_no) {
case fsid_fcc1:
memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
break;
case fsid_fcc2:
memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
break;
if(fs_no > ARRAY_SIZE(mpc82xx_enet_pdata)) {
return;
}
mpc82xx_enet_pdata[fs_no].dpram_offset=
(u32)cpm2_immr->im_dprambase;
mpc82xx_enet_pdata[fs_no].fcc_regs_c =
(u32)cpm2_immr->im_fcc_c;
memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6);
/* prevent dup mac */
if(fs_no == fsid_fcc2)
mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1;
pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no];
}
static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
@ -274,6 +262,29 @@ static void init_scc4_uart_ioports(void)
iounmap(immap);
}
static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
int idx)
{
m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
m82xx_mii_bb_pdata.irq[1] = -1;
m82xx_mii_bb_pdata.irq[2] = -1;
m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
m82xx_mii_bb_pdata.irq[31] = -1;
m82xx_mii_bb_pdata.mdio_dat.offset =
(u32)&cpm2_immr->im_ioport.iop_pdatc;
m82xx_mii_bb_pdata.mdio_dir.offset =
(u32)&cpm2_immr->im_ioport.iop_pdirc;
m82xx_mii_bb_pdata.mdc_dat.offset =
(u32)&cpm2_immr->im_ioport.iop_pdatc;
pdev->dev.platform_data = &m82xx_mii_bb_pdata;
}
static int mpc8272ads_platform_notify(struct device *dev)
{
static const struct platform_notify_dev_map dev_map[] = {
@ -285,6 +296,10 @@ static int mpc8272ads_platform_notify(struct device *dev)
.bus_id = "fsl-cpm-scc:uart",
.rtn = mpc8272ads_fixup_uart_pdata,
},
{
.bus_id = "fsl-bb-mdio",
.rtn = mpc8272ads_fixup_mdio_pdata,
},
{
.bus_id = NULL
}
@ -319,6 +334,7 @@ int __init mpc8272ads_init(void)
ppc_sys_device_enable(MPC82xx_CPM_SCC4);
#endif
ppc_sys_device_enable(MPC82xx_MDIO_BB);
return 0;
}

View File

@ -1,10 +1,10 @@
/*arch/ppc/platforms/mpc885ads-setup.c
/*arch/ppc/platforms/mpc866ads-setup.c
*
* Platform setup for the Freescale mpc885ads board
* Platform setup for the Freescale mpc866ads board
*
* Vitaly Bordug <vbordug@ru.mvista.com>
*
* Copyright 2005 MontaVista Software Inc.
* Copyright 2005-2006 MontaVista Software Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
@ -42,49 +42,36 @@ static void setup_scc1_ioports(void);
static void setup_smc1_ioports(void);
static void setup_smc2_ioports(void);
static struct fs_mii_bus_info fec_mii_bus_info = {
.method = fsmii_fec,
.id = 0,
};
static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
static struct fs_mii_bus_info scc_mii_bus_info = {
.method = fsmii_fixed,
.id = 0,
.i.fixed.speed = 10,
.i.fixed.duplex = 0,
};
static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
static struct fs_platform_info mpc8xx_fec_pdata[] = {
{
.rx_ring = 128,
.tx_ring = 16,
.rx_copybreak = 240,
static struct fs_platform_info mpc8xx_enet_pdata[] = {
[fsid_fec1] = {
.rx_ring = 128,
.tx_ring = 16,
.rx_copybreak = 240,
.use_napi = 1,
.napi_weight = 17,
.use_napi = 1,
.napi_weight = 17,
.phy_addr = 15,
.phy_irq = -1,
.init_ioports = setup_fec1_ioports,
.use_rmii = 0,
.bus_id = "0:0f",
.has_phy = 1,
},
[fsid_scc1] = {
.rx_ring = 64,
.tx_ring = 8,
.rx_copybreak = 240,
.use_napi = 1,
.napi_weight = 17,
.bus_info = &fec_mii_bus_info,
}
};
static struct fs_platform_info mpc8xx_scc_pdata = {
.rx_ring = 64,
.tx_ring = 8,
.rx_copybreak = 240,
.use_napi = 1,
.napi_weight = 17,
.phy_addr = -1,
.phy_irq = -1,
.bus_info = &scc_mii_bus_info,
.init_ioports = setup_scc1_ioports,
.bus_id = "fixed@100:1",
},
};
static struct fs_uart_platform_info mpc866_uart_pdata[] = {
@ -207,63 +194,6 @@ static void setup_scc1_ioports(void)
}
static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
{
struct fs_platform_info *fpi = pdev->dev.platform_data;
volatile cpm8xx_t *cp;
bd_t *bd = (bd_t *) __res;
char *e;
int i;
/* Get pointer to Communication Processor */
cp = cpmp;
switch (fs_no) {
case fsid_fec1:
fpi = &mpc8xx_fec_pdata[0];
fpi->init_ioports = &setup_fec1_ioports;
break;
case fsid_scc1:
fpi = &mpc8xx_scc_pdata;
fpi->init_ioports = &setup_scc1_ioports;
break;
default:
printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
return;
}
pdev->dev.platform_data = fpi;
fpi->fs_no = fs_no;
e = (unsigned char *)&bd->bi_enetaddr;
for (i = 0; i < 6; i++)
fpi->macaddr[i] = *e++;
fpi->macaddr[5 - pdev->id]++;
}
static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
int idx)
{
/* This is for FEC devices only */
if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
return;
mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
}
static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
int idx)
{
/* This is for SCC devices only */
if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
return;
mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
static void setup_smc1_ioports(void)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
@ -315,6 +245,56 @@ static void setup_smc2_ioports(void)
}
static int ma_count = 0;
static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
{
struct fs_platform_info *fpi;
volatile cpm8xx_t *cp;
bd_t *bd = (bd_t *) __res;
char *e;
int i;
/* Get pointer to Communication Processor */
cp = cpmp;
if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
return;
}
fpi = &mpc8xx_enet_pdata[fs_no];
fpi->fs_no = fs_no;
pdev->dev.platform_data = fpi;
e = (unsigned char *)&bd->bi_enetaddr;
for (i = 0; i < 6; i++)
fpi->macaddr[i] = *e++;
fpi->macaddr[5] += ma_count++;
}
static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
int idx)
{
/* This is for FEC devices only */
if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
return;
mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
}
static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
int idx)
{
/* This is for SCC devices only */
if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
return;
mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
int idx)
{
@ -359,6 +339,9 @@ static int mpc866ads_platform_notify(struct device *dev)
int __init mpc866ads_init(void)
{
bd_t *bd = (bd_t *) __res;
struct fs_mii_fec_platform_info* fmpi;
printk(KERN_NOTICE "mpc866ads: Init\n");
platform_notify = mpc866ads_platform_notify;
@ -366,11 +349,20 @@ int __init mpc866ads_init(void)
ppc_sys_device_initfunc();
ppc_sys_device_disable_all();
#ifdef MPC8xx_SECOND_ETH_SCC1
#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC1
ppc_sys_device_enable(MPC8xx_CPM_SCC1);
#endif
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
ppc_sys_device_enable(MPC8xx_MDIO_FEC);
fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
&mpc8xx_mdio_fec_pdata;
fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
/* No PHY interrupt line here */
fmpi->irq[0xf] = -1;
/* Since either of the uarts could be used as console, they need to ready */
#ifdef CONFIG_SERIAL_CPM_SMC1
ppc_sys_device_enable(MPC8xx_CPM_SMC1);
@ -381,6 +373,14 @@ int __init mpc866ads_init(void)
ppc_sys_device_enable(MPC8xx_CPM_SMC2);
ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
#endif
ppc_sys_device_enable(MPC8xx_MDIO_FEC);
fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
&mpc8xx_mdio_fec_pdata;
fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
/* No PHY interrupt line here */
fmpi->irq[0xf] = -1;
return 0;
}

View File

@ -38,7 +38,10 @@ extern unsigned char __res[];
static void setup_smc1_ioports(void);
static void setup_smc2_ioports(void);
static void __init mpc885ads_scc_phy_init(char);
static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
static void setup_fec1_ioports(void);
static void setup_fec2_ioports(void);
static void setup_scc3_ioports(void);
static struct fs_uart_platform_info mpc885_uart_pdata[] = {
[fsid_smc1_uart] = {
@ -61,23 +64,8 @@ static struct fs_uart_platform_info mpc885_uart_pdata[] = {
},
};
static struct fs_mii_bus_info fec_mii_bus_info = {
.method = fsmii_fec,
.id = 0,
};
static struct fs_mii_bus_info scc_mii_bus_info = {
#ifdef CONFIG_SCC_ENET_8xx_FIXED
.method = fsmii_fixed,
#else
.method = fsmii_fec,
#endif
.id = 0,
};
static struct fs_platform_info mpc8xx_fec_pdata[] = {
{
static struct fs_platform_info mpc8xx_enet_pdata[] = {
[fsid_fec1] = {
.rx_ring = 128,
.tx_ring = 16,
.rx_copybreak = 240,
@ -85,11 +73,12 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
.use_napi = 1,
.napi_weight = 17,
.phy_addr = 0,
.phy_irq = SIU_IRQ7,
.init_ioports = setup_fec1_ioports,
.bus_info = &fec_mii_bus_info,
}, {
.bus_id = "0:00",
.has_phy = 1,
},
[fsid_fec2] = {
.rx_ring = 128,
.tx_ring = 16,
.rx_copybreak = 240,
@ -97,35 +86,32 @@ static struct fs_platform_info mpc8xx_fec_pdata[] = {
.use_napi = 1,
.napi_weight = 17,
.phy_addr = 1,
.phy_irq = SIU_IRQ7,
.init_ioports = setup_fec2_ioports,
.bus_info = &fec_mii_bus_info,
}
};
.bus_id = "0:01",
.has_phy = 1,
},
[fsid_scc3] = {
.rx_ring = 64,
.tx_ring = 8,
.rx_copybreak = 240,
static struct fs_platform_info mpc8xx_scc_pdata = {
.rx_ring = 64,
.tx_ring = 8,
.rx_copybreak = 240,
.use_napi = 1,
.napi_weight = 17,
.use_napi = 1,
.napi_weight = 17,
.phy_addr = 2,
#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
.phy_irq = -1,
.init_ioports = setup_scc3_ioports,
#ifdef CONFIG_FIXED_MII_10_FDX
.bus_id = "fixed@100:1",
#else
.phy_irq = SIU_IRQ7,
#endif
.bus_info = &scc_mii_bus_info,
.bus_id = "0:02",
#endif
},
};
void __init board_init(void)
{
volatile cpm8xx_t *cp = cpmp;
unsigned int *bcsr_io;
cpm8xx_t *cp = cpmp;
unsigned int *bcsr_io;
#ifdef CONFIG_FS_ENET
immap_t *immap = (immap_t *) IMAP_ADDR;
@ -164,6 +150,14 @@ void __init board_init(void)
/* use MDC for MII (common) */
setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
clrbits32(bcsr_io,BCSR5_MII1_EN);
clrbits32(bcsr_io,BCSR5_MII1_RST);
#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
clrbits32(bcsr_io,BCSR5_MII2_EN);
clrbits32(bcsr_io,BCSR5_MII2_RST);
#endif
iounmap(bcsr_io);
#endif
}
@ -194,8 +188,8 @@ static void setup_fec2_ioports(void)
/* configure FEC2 pins */
setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
setbits32(&immap->im_cpm.cp_peso, 0x00037800);
clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
setbits32(&immap->im_cpm.cp_peso, 0x00037800);
clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
}
@ -213,6 +207,8 @@ static void setup_scc3_ioports(void)
/* Enable the PHY.
*/
clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
udelay(1000);
setbits32(bcsr_io+4, BCSR4_ETH10_RST);
/* Configure port A pins for Txd and Rxd.
*/
@ -254,37 +250,38 @@ static void setup_scc3_ioports(void)
clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
setbits32(bcsr_io+1, BCSR1_ETHEN);
setbits32(bcsr_io+4, BCSR1_ETHEN);
iounmap(bcsr_io);
}
static int mac_count = 0;
static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
{
struct fs_platform_info *fpi = pdev->dev.platform_data;
volatile cpm8xx_t *cp;
struct fs_platform_info *fpi;
bd_t *bd = (bd_t *) __res;
char *e;
int i;
/* Get pointer to Communication Processor */
cp = cpmp;
if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
return;
}
fpi = &mpc8xx_enet_pdata[fs_no];
switch (fs_no) {
case fsid_fec1:
fpi = &mpc8xx_fec_pdata[0];
fpi->init_ioports = &setup_fec1_ioports;
break;
case fsid_fec2:
fpi = &mpc8xx_fec_pdata[1];
fpi->init_ioports = &setup_fec2_ioports;
break;
case fsid_scc3:
fpi = &mpc8xx_scc_pdata;
fpi->init_ioports = &setup_scc3_ioports;
mpc885ads_scc_phy_init(fpi->phy_addr);
break;
default:
printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
printk(KERN_WARNING "Device %s is not supported!\n", pdev->name);
return;
}
@ -295,7 +292,7 @@ static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
for (i = 0; i < 6; i++)
fpi->macaddr[i] = *e++;
fpi->macaddr[5 - pdev->id]++;
fpi->macaddr[5] += mac_count++;
}
@ -318,58 +315,6 @@ static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
/* SCC ethernet controller does not have MII management channel. FEC1 MII
* channel is used to communicate with the 10Mbit PHY.
*/
#define MII_ECNTRL_PINMUX 0x4
#define FEC_ECNTRL_PINMUX 0x00000004
#define FEC_RCNTRL_MII_MODE 0x00000004
/* Make MII read/write commands.
*/
#define mk_mii_write(REG, VAL, PHY_ADDR) (0x50020000 | (((REG) & 0x1f) << 18) | \
((VAL) & 0xffff) | ((PHY_ADDR) << 23))
static void mpc885ads_scc_phy_init(char phy_addr)
{
volatile immap_t *immap;
volatile fec_t *fecp;
bd_t *bd;
bd = (bd_t *) __res;
immap = (immap_t *) IMAP_ADDR; /* pointer to internal registers */
fecp = &(immap->im_cpm.cp_fec);
/* Enable MII pins of the FEC1
*/
setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
/* Set MII speed to 2.5 MHz
*/
out_be32(&fecp->fec_mii_speed,
((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
/* Enable FEC pin MUX
*/
setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
out_be32(&fecp->fec_mii_data,
mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
udelay(100);
out_be32(&fecp->fec_mii_data,
mk_mii_write(MII_ADVERTISE,
ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
udelay(100);
/* Disable FEC MII settings
*/
clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
out_be32(&fecp->fec_mii_speed, 0);
}
static void setup_smc1_ioports(void)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
@ -462,6 +407,9 @@ static int mpc885ads_platform_notify(struct device *dev)
int __init mpc885ads_init(void)
{
struct fs_mii_fec_platform_info* fmpi;
bd_t *bd = (bd_t *) __res;
printk(KERN_NOTICE "mpc885ads: Init\n");
platform_notify = mpc885ads_platform_notify;
@ -471,8 +419,17 @@ int __init mpc885ads_init(void)
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
ppc_sys_device_enable(MPC8xx_MDIO_FEC);
fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
&mpc8xx_mdio_fec_pdata;
fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
/* No PHY interrupt line here */
fmpi->irq[0xf] = SIU_IRQ7;
#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
ppc_sys_device_enable(MPC8xx_CPM_SCC1);
ppc_sys_device_enable(MPC8xx_CPM_SCC3);
#endif
#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2

View File

@ -29,86 +29,4 @@
#define F3_RXCLK 13
#define F3_TXCLK 14
/* Automatically generates register configurations */
#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */
#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */
#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */
#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */
#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */
#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */
#define PC_F1RXCLK PC_CLK(F1_RXCLK)
#define PC_F1TXCLK PC_CLK(F1_TXCLK)
#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
#define CMX1_CLK_MASK ((uint)0xff000000)
#define PC_F2RXCLK PC_CLK(F2_RXCLK)
#define PC_F2TXCLK PC_CLK(F2_TXCLK)
#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
#define CMX2_CLK_MASK ((uint)0x00ff0000)
#define PC_F3RXCLK PC_CLK(F3_RXCLK)
#define PC_F3TXCLK PC_CLK(F3_TXCLK)
#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
#define CMX3_CLK_MASK ((uint)0x0000ff00)
/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
* but there is little variation among the choices.
*/
#define PA1_COL 0x00000001U
#define PA1_CRS 0x00000002U
#define PA1_TXER 0x00000004U
#define PA1_TXEN 0x00000008U
#define PA1_RXDV 0x00000010U
#define PA1_RXER 0x00000020U
#define PA1_TXDAT 0x00003c00U
#define PA1_RXDAT 0x0003c000U
#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
PA1_RXDV | PA1_RXER)
#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
* but there is little variation among the choices.
*/
#define PB2_TXER 0x00000001U
#define PB2_RXDV 0x00000002U
#define PB2_TXEN 0x00000004U
#define PB2_RXER 0x00000008U
#define PB2_COL 0x00000010U
#define PB2_CRS 0x00000020U
#define PB2_TXDAT 0x000003c0U
#define PB2_RXDAT 0x00003c00U
#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
PB2_RXER | PB2_RXDV | PB2_TXER)
#define PB2_PSORB1 (PB2_TXEN)
#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
* but there is little variation among the choices.
*/
#define PB3_RXDV 0x00004000U
#define PB3_RXER 0x00008000U
#define PB3_TXER 0x00010000U
#define PB3_TXEN 0x00020000U
#define PB3_COL 0x00040000U
#define PB3_CRS 0x00080000U
#define PB3_TXDAT 0x0f000000U
#define PB3_RXDAT 0x00f00000U
#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
#define PB3_PSORB1 0
#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
#endif

View File

@ -16,9 +16,11 @@
#include <linux/device.h>
#include <linux/serial_8250.h>
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
#include <asm/mpc85xx.h>
#include <asm/irq.h>
#include <asm/ppc_sys.h>
#include <asm/cpm2.h>
/* We use offsets for IORESOURCE_MEM since we do not know at compile time
* what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
@ -82,6 +84,60 @@ static struct fsl_i2c_platform_data mpc85xx_fsl_i2c2_pdata = {
.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
};
static struct fs_platform_info mpc85xx_fcc1_pdata = {
.fs_no = fsid_fcc1,
.cp_page = CPM_CR_FCC1_PAGE,
.cp_block = CPM_CR_FCC1_SBLOCK,
.rx_ring = 32,
.tx_ring = 32,
.rx_copybreak = 240,
.use_napi = 0,
.napi_weight = 17,
.clk_mask = CMX1_CLK_MASK,
.clk_route = CMX1_CLK_ROUTE,
.clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
.mem_offset = FCC1_MEM_OFFSET,
};
static struct fs_platform_info mpc85xx_fcc2_pdata = {
.fs_no = fsid_fcc2,
.cp_page = CPM_CR_FCC2_PAGE,
.cp_block = CPM_CR_FCC2_SBLOCK,
.rx_ring = 32,
.tx_ring = 32,
.rx_copybreak = 240,
.use_napi = 0,
.napi_weight = 17,
.clk_mask = CMX2_CLK_MASK,
.clk_route = CMX2_CLK_ROUTE,
.clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
.mem_offset = FCC2_MEM_OFFSET,
};
static struct fs_platform_info mpc85xx_fcc3_pdata = {
.fs_no = fsid_fcc3,
.cp_page = CPM_CR_FCC3_PAGE,
.cp_block = CPM_CR_FCC3_SBLOCK,
.rx_ring = 32,
.tx_ring = 32,
.rx_copybreak = 240,
.use_napi = 0,
.napi_weight = 17,
.clk_mask = CMX3_CLK_MASK,
.clk_route = CMX3_CLK_ROUTE,
.clk_trx = (PC_F3RXCLK | PC_F3TXCLK),
.mem_offset = FCC3_MEM_OFFSET,
};
static struct plat_serial8250_port serial_platform_data[] = {
[0] = {
.mapbase = 0x4500,
@ -318,18 +374,27 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC85xx_CPM_FCC1] = {
.name = "fsl-cpm-fcc",
.id = 1,
.num_resources = 3,
.num_resources = 4,
.dev.platform_data = &mpc85xx_fcc1_pdata,
.resource = (struct resource[]) {
{
.name = "fcc_regs",
.start = 0x91300,
.end = 0x9131F,
.flags = IORESOURCE_MEM,
},
{
.name = "fcc_regs_c",
.start = 0x91380,
.end = 0x9139F,
.flags = IORESOURCE_MEM,
},
{
.name = "fcc_pram",
.start = 0x88400,
.end = 0x884ff,
.flags = IORESOURCE_MEM,
},
{
.start = SIU_INT_FCC1,
.end = SIU_INT_FCC1,
@ -340,18 +405,27 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC85xx_CPM_FCC2] = {
.name = "fsl-cpm-fcc",
.id = 2,
.num_resources = 3,
.num_resources = 4,
.dev.platform_data = &mpc85xx_fcc2_pdata,
.resource = (struct resource[]) {
{
.name = "fcc_regs",
.start = 0x91320,
.end = 0x9133F,
.flags = IORESOURCE_MEM,
},
{
.name = "fcc_regs_c",
.start = 0x913A0,
.end = 0x913CF,
.flags = IORESOURCE_MEM,
},
{
.name = "fcc_pram",
.start = 0x88500,
.end = 0x885ff,
.flags = IORESOURCE_MEM,
},
{
.start = SIU_INT_FCC2,
.end = SIU_INT_FCC2,
@ -362,18 +436,27 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC85xx_CPM_FCC3] = {
.name = "fsl-cpm-fcc",
.id = 3,
.num_resources = 3,
.num_resources = 4,
.dev.platform_data = &mpc85xx_fcc3_pdata,
.resource = (struct resource[]) {
{
.name = "fcc_regs",
.start = 0x91340,
.end = 0x9135F,
.flags = IORESOURCE_MEM,
},
{
.name = "fcc_regs_c",
.start = 0x913D0,
.end = 0x913FF,
.flags = IORESOURCE_MEM,
},
{
.name = "fcc_pram",
.start = 0x88600,
.end = 0x886ff,
.flags = IORESOURCE_MEM,
},
{
.start = SIU_INT_FCC3,
.end = SIU_INT_FCC3,

View File

@ -218,6 +218,14 @@ struct platform_device ppc_sys_platform_devices[] = {
},
},
},
[MPC8xx_MDIO_FEC] = {
.name = "fsl-cpm-fec-mdio",
.id = 0,
.num_resources = 0,
},
};
static int __init mach_mpc8xx_fixup(struct platform_device *pdev)

View File

@ -22,7 +22,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "MPC86X",
.mask = 0xFFFFFFFF,
.value = 0x00000000,
.num_devices = 7,
.num_devices = 8,
.device_list = (enum ppc_sys_devices[])
{
MPC8xx_CPM_FEC1,
@ -32,13 +32,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC8xx_CPM_SCC4,
MPC8xx_CPM_SMC1,
MPC8xx_CPM_SMC2,
MPC8xx_MDIO_FEC,
},
},
{
.ppc_sys_name = "MPC885",
.mask = 0xFFFFFFFF,
.value = 0x00000000,
.num_devices = 8,
.num_devices = 9,
.device_list = (enum ppc_sys_devices[])
{
MPC8xx_CPM_FEC1,
@ -49,6 +50,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC8xx_CPM_SCC4,
MPC8xx_CPM_SMC1,
MPC8xx_CPM_SMC2,
MPC8xx_MDIO_FEC,
},
},
{ /* default match */

View File

@ -369,6 +369,11 @@ struct platform_device ppc_sys_platform_devices[] = {
},
},
},
[MPC82xx_MDIO_BB] = {
.name = "fsl-bb-mdio",
.id = 0,
.num_resources = 0,
},
};
static int __init mach_mpc82xx_fixup(struct platform_device *pdev)

View File

@ -139,13 +139,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8272",
.mask = 0x0000ff00,
.value = 0x00000c00,
.num_devices = 12,
.num_devices = 13,
.device_list = (enum ppc_sys_devices[])
{
MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
MPC82xx_MDIO_BB,
},
},
/* below is a list of the 8280 family of processors */

View File

@ -1003,7 +1003,8 @@ static int corkscrew_start_xmit(struct sk_buff *skb,
/* Calculate the next Tx descriptor entry. */
int entry = vp->cur_tx % TX_RING_SIZE;
struct boom_tx_desc *prev_entry;
unsigned long flags, i;
unsigned long flags;
int i;
if (vp->tx_full) /* No room to transmit with */
return 1;

View File

@ -899,7 +899,7 @@ memory_squeeze:
}
static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
static void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
{
struct i596_cmd *ptr;
@ -932,7 +932,8 @@ static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private
lp->scb.cmd = I596_NULL;
}
static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr)
static void i596_reset(struct net_device *dev, struct i596_private *lp,
int ioaddr)
{
unsigned long flags;
@ -1578,7 +1579,7 @@ static int debug = -1;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "i82596 debug mask");
int init_module(void)
int __init init_module(void)
{
if (debug >= 0)
i596_debug = debug;
@ -1588,7 +1589,7 @@ int init_module(void)
return 0;
}
void cleanup_module(void)
void __exit cleanup_module(void)
{
unregister_netdev(dev_82596);
#ifdef __mc68000__

View File

@ -1724,6 +1724,20 @@ config VIA_RHINE_MMIO
If unsure, say Y.
config VIA_RHINE_NAPI
bool "Use Rx Polling (NAPI)"
depends on VIA_RHINE
help
NAPI is a new driver API designed to reduce CPU and interrupt load
when the driver is receiving lots of packets from the card.
If your estimated Rx load is 10kpps or more, or if the card will be
deployed on potentially unfriendly networks (e.g. in a firewall),
then say Y here.
See <file:Documentation/networking/NAPI_HOWTO.txt> for more
information.
config LAN_SAA9730
bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
depends on NET_PCI && EXPERIMENTAL && MIPS
@ -2219,6 +2233,33 @@ config GFAR_NAPI
bool "NAPI Support"
depends on GIANFAR
config UCC_GETH
tristate "Freescale QE UCC GETH"
depends on QUICC_ENGINE && UCC_FAST
help
This driver supports the Gigabit Ethernet mode of QE UCC.
QE can be found on MPC836x CPUs.
config UGETH_NAPI
bool "NAPI Support"
depends on UCC_GETH
config UGETH_MAGIC_PACKET
bool "Magic Packet detection support"
depends on UCC_GETH
config UGETH_FILTERING
bool "Mac address filtering support"
depends on UCC_GETH
config UGETH_TX_ON_DEMOND
bool "Transmit on Demond support"
depends on UCC_GETH
config UGETH_HAS_GIGA
bool
depends on UCC_GETH && MPC836x
config MV643XX_ETH
tristate "MV-643XX Ethernet support"
depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || PPC_MULTIPLATFORM

View File

@ -18,6 +18,9 @@ gianfar_driver-objs := gianfar.o \
gianfar_mii.o \
gianfar_sysfs.o
obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
ucc_geth_driver-objs := ucc_geth.o ucc_geth_phy.o
#
# link order important here
#

View File

@ -370,8 +370,7 @@ MODULE_PARM_DESC(mem, "Memory base address(es)");
MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
MODULE_LICENSE("GPL");
int
init_module(void)
int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;

View File

@ -1030,7 +1030,7 @@ module_param(io, int, 0);
module_param(irq, int, 0);
module_param(board_type, int, 0);
int init_module(void)
int __init init_module(void)
{
if (io == 0)
printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",

View File

@ -901,7 +901,7 @@ MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address");
MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
int init_module(void)
int __init init_module(void)
{
if (io == 0)
printk("at1700: You should not use auto-probing with insmod!\n");

View File

@ -1905,8 +1905,7 @@ MODULE_LICENSE("GPL");
*/
int
init_module(void)
int __init init_module(void)
{
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
struct net_local *lp;

View File

@ -339,6 +339,17 @@ static void dm9000_timeout(struct net_device *dev)
spin_unlock_irqrestore(&db->lock,flags);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
*Used by netconsole
*/
static void dm9000_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
dm9000_interrupt(dev->irq,dev,NULL);
enable_irq(dev->irq);
}
#endif
/* dm9000_release_board
*
@ -538,6 +549,9 @@ dm9000_probe(struct platform_device *pdev)
ndev->stop = &dm9000_stop;
ndev->get_stats = &dm9000_get_stats;
ndev->set_multicast_list = &dm9000_hash_table;
#ifdef CONFIG_NET_POLL_CONTROLLER
ndev->poll_controller = &dm9000_poll_controller;
#endif
#ifdef DM9000_PROGRAM_EEPROM
program_eeprom(db);

View File

@ -105,6 +105,33 @@ static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
uint16_t duplex);
static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw,
uint32_t segment);
static int32_t e1000_get_software_flag(struct e1000_hw *hw);
static int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
static int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
static int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
static int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
uint16_t words, uint16_t *data);
static int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
uint8_t* data);
static int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
uint16_t *data);
static int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr,
uint16_t *data);
static void e1000_release_software_flag(struct e1000_hw *hw);
static void e1000_release_software_semaphore(struct e1000_hw *hw);
static int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw,
uint32_t no_snoop);
static int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw,
uint32_t index, uint8_t byte);
static int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
uint16_t words, uint16_t *data);
static int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
uint8_t data);
static int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr,
uint16_t data);
/* IGP cable length table */
static const
uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
@ -3233,7 +3260,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
return data;
}
int32_t
static int32_t
e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
{
uint32_t swfw_sync = 0;
@ -3277,7 +3304,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
return E1000_SUCCESS;
}
void
static void
e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
{
uint32_t swfw_sync;
@ -3575,7 +3602,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw,
return E1000_SUCCESS;
}
int32_t
static int32_t
e1000_read_kmrn_reg(struct e1000_hw *hw,
uint32_t reg_addr,
uint16_t *data)
@ -3608,7 +3635,7 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
return E1000_SUCCESS;
}
int32_t
static int32_t
e1000_write_kmrn_reg(struct e1000_hw *hw,
uint32_t reg_addr,
uint16_t data)
@ -3839,7 +3866,7 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
*
* hw - struct containing variables accessed by shared code
******************************************************************************/
int32_t
static int32_t
e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
{
int32_t ret_val;
@ -4086,7 +4113,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
int32_t
static int32_t
e1000_phy_ife_get_info(struct e1000_hw *hw,
struct e1000_phy_info *phy_info)
{
@ -5643,6 +5670,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
* for the first 15 multicast addresses, and hashes the rest into the
* multicast table.
*****************************************************************************/
#if 0
void
e1000_mc_addr_list_update(struct e1000_hw *hw,
uint8_t *mc_addr_list,
@ -5719,6 +5747,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
}
DEBUGOUT("MC Update Complete\n");
}
#endif /* 0 */
/******************************************************************************
* Hashes an address to determine its location in the multicast table
@ -6587,6 +6616,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* offset - offset to read from
*****************************************************************************/
#if 0
uint32_t
e1000_read_reg_io(struct e1000_hw *hw,
uint32_t offset)
@ -6597,6 +6627,7 @@ e1000_read_reg_io(struct e1000_hw *hw,
e1000_io_write(hw, io_addr, offset);
return e1000_io_read(hw, io_data);
}
#endif /* 0 */
/******************************************************************************
* Writes a value to one of the devices registers using port I/O (as opposed to
@ -7909,6 +7940,7 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
* returns: - none.
*
***************************************************************************/
#if 0
void
e1000_enable_pciex_master(struct e1000_hw *hw)
{
@ -7923,6 +7955,7 @@ e1000_enable_pciex_master(struct e1000_hw *hw)
ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE;
E1000_WRITE_REG(hw, CTRL, ctrl);
}
#endif /* 0 */
/*******************************************************************************
*
@ -8148,7 +8181,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
***************************************************************************/
int32_t
static int32_t
e1000_get_software_semaphore(struct e1000_hw *hw)
{
int32_t timeout = hw->eeprom.word_size + 1;
@ -8183,7 +8216,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
void
static void
e1000_release_software_semaphore(struct e1000_hw *hw)
{
uint32_t swsm;
@ -8265,7 +8298,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
* returns: E1000_SUCCESS
*
*****************************************************************************/
int32_t
static int32_t
e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
{
uint32_t gcr_reg = 0;
@ -8306,7 +8339,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
int32_t
static int32_t
e1000_get_software_flag(struct e1000_hw *hw)
{
int32_t timeout = PHY_CFG_TIMEOUT;
@ -8345,7 +8378,7 @@ e1000_get_software_flag(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
void
static void
e1000_release_software_flag(struct e1000_hw *hw)
{
uint32_t extcnf_ctrl;
@ -8369,6 +8402,7 @@ e1000_release_software_flag(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
#if 0
int32_t
e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
{
@ -8388,6 +8422,7 @@ e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
return ret_val;
}
#endif /* 0 */
/***************************************************************************
*
@ -8397,6 +8432,7 @@ e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
#if 0
int32_t
e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
{
@ -8416,6 +8452,7 @@ e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
return ret_val;
}
#endif /* 0 */
/******************************************************************************
* Reads a 16 bit word or words from the EEPROM using the ICH8's flash access
@ -8426,7 +8463,7 @@ e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
int32_t
static int32_t
e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
uint16_t *data)
{
@ -8482,7 +8519,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
* words - number of words to write
* data - words to write to the EEPROM
*****************************************************************************/
int32_t
static int32_t
e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
uint16_t *data)
{
@ -8529,7 +8566,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
*
* hw - The pointer to the hw structure
****************************************************************************/
int32_t
static int32_t
e1000_ich8_cycle_init(struct e1000_hw *hw)
{
union ich8_hws_flash_status hsfsts;
@ -8596,7 +8633,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
*
* hw - The pointer to the hw structure
****************************************************************************/
int32_t
static int32_t
e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
{
union ich8_hws_flash_ctrl hsflctl;
@ -8631,7 +8668,7 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
* size - Size of data to read, 1=byte 2=word
* data - Pointer to the word to store the value read.
*****************************************************************************/
int32_t
static int32_t
e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
uint32_t size, uint16_t* data)
{
@ -8710,7 +8747,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
* size - Size of data to read, 1=byte 2=word
* data - The byte(s) to write to the NVM.
*****************************************************************************/
int32_t
static int32_t
e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
uint16_t data)
{
@ -8785,7 +8822,7 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
* index - The index of the byte to read.
* data - Pointer to a byte to store the value read.
*****************************************************************************/
int32_t
static int32_t
e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
{
int32_t status = E1000_SUCCESS;
@ -8808,7 +8845,7 @@ e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
* index - The index of the byte to write.
* byte - The byte to write to the NVM.
*****************************************************************************/
int32_t
static int32_t
e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
{
int32_t error = E1000_SUCCESS;
@ -8839,7 +8876,7 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
* index - The index of the byte to read.
* data - The byte to write to the NVM.
*****************************************************************************/
int32_t
static int32_t
e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
{
int32_t status = E1000_SUCCESS;
@ -8857,7 +8894,7 @@ e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
* index - The starting byte index of the word to read.
* data - Pointer to a word to store the value read.
*****************************************************************************/
int32_t
static int32_t
e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
{
int32_t status = E1000_SUCCESS;
@ -8872,6 +8909,7 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
* index - The starting byte index of the word to read.
* data - The word to write to the NVM.
*****************************************************************************/
#if 0
int32_t
e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
{
@ -8879,6 +8917,7 @@ e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
status = e1000_write_ich8_data(hw, index, 2, data);
return status;
}
#endif /* 0 */
/******************************************************************************
* Erases the bank specified. Each bank is a 4k block. Segments are 0 based.
@ -8887,7 +8926,7 @@ e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
* hw - pointer to e1000_hw structure
* segment - 0 for first segment, 1 for second segment, etc.
*****************************************************************************/
int32_t
static int32_t
e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment)
{
union ich8_hws_flash_status hsfsts;
@ -8984,6 +9023,7 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment)
* hw: Struct containing variables accessed by shared code
*
*****************************************************************************/
#if 0
int32_t
e1000_duplex_reversal(struct e1000_hw *hw)
{
@ -9012,8 +9052,9 @@ e1000_duplex_reversal(struct e1000_hw *hw)
return ret_val;
}
#endif /* 0 */
int32_t
static int32_t
e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
uint32_t cnf_base_addr, uint32_t cnf_size)
{
@ -9047,7 +9088,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
}
int32_t
static int32_t
e1000_init_lcd_from_nvm(struct e1000_hw *hw)
{
uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop;

View File

@ -323,13 +323,8 @@ int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t dat
int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
int32_t e1000_phy_reset(struct e1000_hw *hw);
void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size);
int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data);
int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
/* EEPROM Functions */
int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
@ -400,13 +395,8 @@ int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
int32_t e1000_read_mac_addr(struct e1000_hw * hw);
int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
void e1000_release_software_flag(struct e1000_hw *hw);
int32_t e1000_get_software_flag(struct e1000_hw *hw);
/* Filters (multicast, vlan, receive) */
void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@ -431,31 +421,9 @@ void e1000_pci_clear_mwi(struct e1000_hw *hw);
void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
/* Port I/O is only supported on 82544 and newer */
uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
void e1000_enable_pciex_master(struct e1000_hw *hw);
int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
void e1000_release_software_semaphore(struct e1000_hw *hw);
int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop);
int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
uint8_t *data);
int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
uint8_t byte);
int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
uint8_t byte);
int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
uint16_t *data);
int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
uint32_t size, uint16_t *data);
int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
uint16_t words, uint16_t *data);
int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
uint16_t words, uint16_t *data);
int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment);
#define E1000_READ_REG_IO(a, reg) \

View File

@ -4386,11 +4386,13 @@ e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
pci_write_config_word(adapter->pdev, reg, *value);
}
#if 0
uint32_t
e1000_io_read(struct e1000_hw *hw, unsigned long port)
{
return inl(port);
}
#endif /* 0 */
void
e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)

View File

@ -425,8 +425,8 @@ MODULE_LICENSE("GPL");
/* This is set up so that only a single autoprobe takes place per call.
ISA device autoprobes on a running machine are not recommended. */
int
init_module(void)
int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;

View File

@ -1807,8 +1807,7 @@ MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
int
init_module(void)
int __init init_module(void)
{
struct net_device *dev;
int i;

View File

@ -1698,7 +1698,7 @@ MODULE_LICENSE("GPL");
* are specified, we verify and then use them. If no parameters are given, we
* autoprobe for one card only.
*/
int init_module(void)
int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;

View File

@ -421,8 +421,7 @@ MODULE_PARM_DESC(mem, "memory base address(es)");
MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver");
MODULE_LICENSE("GPL");
int
init_module(void)
int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;

View File

@ -1434,7 +1434,7 @@ MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto,
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
int init_module(void)
int __init init_module(void)
{
int this_dev, found = 0;
struct net_device *dev;

View File

@ -92,7 +92,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
#include <asm/uaccess.h>
/* These identify the driver base version and may not be removed. */
static char version[] __devinitdata =
static char version[] =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";

View File

@ -4,7 +4,7 @@
obj-$(CONFIG_FS_ENET) += fs_enet.o
obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o
obj-$(CONFIG_8260) += mac-fcc.o
obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o
obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o
fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o
fs_enet-objs := fs_enet-main.o

42
drivers/net/fs_enet/fec.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef FS_ENET_FEC_H
#define FS_ENET_FEC_H
/* CRC polynomium used by the FEC for the multicast group filtering */
#define FEC_CRC_POLY 0x04C11DB7
#define FEC_MAX_MULTICAST_ADDRS 64
/* Interrupt events/masks.
*/
#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */
#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */
#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */
#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */
#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */
#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */
#define FEC_ENET_RXF 0x02000000U /* Full frame received */
#define FEC_ENET_RXB 0x01000000U /* A buffer was received */
#define FEC_ENET_MII 0x00800000U /* MII interrupt */
#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */
#define FEC_ECNTRL_PINMUX 0x00000004
#define FEC_ECNTRL_ETHER_EN 0x00000002
#define FEC_ECNTRL_RESET 0x00000001
#define FEC_RCNTRL_BC_REJ 0x00000010
#define FEC_RCNTRL_PROM 0x00000008
#define FEC_RCNTRL_MII_MODE 0x00000004
#define FEC_RCNTRL_DRT 0x00000002
#define FEC_RCNTRL_LOOP 0x00000001
#define FEC_TCNTRL_FDEN 0x00000004
#define FEC_TCNTRL_HBC 0x00000002
#define FEC_TCNTRL_GTS 0x00000001
/*
* Delay to wait for FEC reset command to complete (in us)
*/
#define FEC_RESET_DELAY 50
#endif

View File

@ -37,6 +37,7 @@
#include <linux/bitops.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
#include <linux/vmalloc.h>
#include <asm/pgtable.h>
@ -682,35 +683,6 @@ static void fs_free_irq(struct net_device *dev, int irq)
(*fep->ops->post_free_irq)(dev, irq);
}
/**********************************************************************************/
/* This interrupt occurs when the PHY detects a link change. */
static irqreturn_t
fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct fs_enet_private *fep;
const struct fs_platform_info *fpi;
fep = netdev_priv(dev);
fpi = fep->fpi;
/*
* Acknowledge the interrupt if possible. If we have not
* found the PHY yet we can't process or acknowledge the
* interrupt now. Instead we ignore this interrupt for now,
* which we can do since it is edge triggered. It will be
* acknowledged later by fs_enet_open().
*/
if (!fep->phy)
return IRQ_NONE;
fs_mii_ack_int(dev);
fs_mii_link_status_change_check(dev, 0);
return IRQ_HANDLED;
}
static void fs_timeout(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
@ -722,10 +694,13 @@ static void fs_timeout(struct net_device *dev)
spin_lock_irqsave(&fep->lock, flags);
if (dev->flags & IFF_UP) {
phy_stop(fep->phydev);
(*fep->ops->stop)(dev);
(*fep->ops->restart)(dev);
phy_start(fep->phydev);
}
phy_start(fep->phydev);
wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);
spin_unlock_irqrestore(&fep->lock, flags);
@ -733,35 +708,112 @@ static void fs_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
/*-----------------------------------------------------------------------------
* generic link-change handler - should be sufficient for most cases
*-----------------------------------------------------------------------------*/
static void generic_adjust_link(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct phy_device *phydev = fep->phydev;
int new_state = 0;
if (phydev->link) {
/* adjust to duplex mode */
if (phydev->duplex != fep->oldduplex){
new_state = 1;
fep->oldduplex = phydev->duplex;
}
if (phydev->speed != fep->oldspeed) {
new_state = 1;
fep->oldspeed = phydev->speed;
}
if (!fep->oldlink) {
new_state = 1;
fep->oldlink = 1;
netif_schedule(dev);
netif_carrier_on(dev);
netif_start_queue(dev);
}
if (new_state)
fep->ops->restart(dev);
} else if (fep->oldlink) {
new_state = 1;
fep->oldlink = 0;
fep->oldspeed = 0;
fep->oldduplex = -1;
netif_carrier_off(dev);
netif_stop_queue(dev);
}
if (new_state && netif_msg_link(fep))
phy_print_status(phydev);
}
static void fs_adjust_link(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&fep->lock, flags);
if(fep->ops->adjust_link)
fep->ops->adjust_link(dev);
else
generic_adjust_link(dev);
spin_unlock_irqrestore(&fep->lock, flags);
}
static int fs_init_phy(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct phy_device *phydev;
fep->oldlink = 0;
fep->oldspeed = 0;
fep->oldduplex = -1;
if(fep->fpi->bus_id)
phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0);
else {
printk("No phy bus ID specified in BSP code\n");
return -EINVAL;
}
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
return PTR_ERR(phydev);
}
fep->phydev = phydev;
return 0;
}
static int fs_enet_open(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
int r;
int err;
/* Install our interrupt handler. */
r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
if (r != 0) {
printk(KERN_ERR DRV_MODULE_NAME
": %s Could not allocate FEC IRQ!", dev->name);
": %s Could not allocate FS_ENET IRQ!", dev->name);
return -EINVAL;
}
/* Install our phy interrupt handler */
if (fpi->phy_irq != -1) {
err = fs_init_phy(dev);
if(err)
return err;
r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);
if (r != 0) {
printk(KERN_ERR DRV_MODULE_NAME
": %s Could not allocate PHY IRQ!", dev->name);
fs_free_irq(dev, fep->interrupt);
return -EINVAL;
}
}
fs_mii_startup(dev);
netif_carrier_off(dev);
fs_mii_link_status_change_check(dev, 1);
phy_start(fep->phydev);
return 0;
}
@ -769,20 +821,19 @@ static int fs_enet_open(struct net_device *dev)
static int fs_enet_close(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
unsigned long flags;
netif_stop_queue(dev);
netif_carrier_off(dev);
fs_mii_shutdown(dev);
phy_stop(fep->phydev);
spin_lock_irqsave(&fep->lock, flags);
(*fep->ops->stop)(dev);
spin_unlock_irqrestore(&fep->lock, flags);
/* release any irqs */
if (fpi->phy_irq != -1)
fs_free_irq(dev, fpi->phy_irq);
phy_disconnect(fep->phydev);
fep->phydev = NULL;
fs_free_irq(dev, fep->interrupt);
return 0;
@ -830,33 +881,19 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct fs_enet_private *fep = netdev_priv(dev);
unsigned long flags;
int rc;
spin_lock_irqsave(&fep->lock, flags);
rc = mii_ethtool_gset(&fep->mii_if, cmd);
spin_unlock_irqrestore(&fep->lock, flags);
return rc;
return phy_ethtool_gset(fep->phydev, cmd);
}
static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct fs_enet_private *fep = netdev_priv(dev);
unsigned long flags;
int rc;
spin_lock_irqsave(&fep->lock, flags);
rc = mii_ethtool_sset(&fep->mii_if, cmd);
spin_unlock_irqrestore(&fep->lock, flags);
return rc;
phy_ethtool_sset(fep->phydev, cmd);
return 0;
}
static int fs_nway_reset(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
return mii_nway_restart(&fep->mii_if);
return 0;
}
static u32 fs_get_msglevel(struct net_device *dev)
@ -898,7 +935,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EINVAL;
spin_lock_irqsave(&fep->lock, flags);
rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);
rc = phy_mii_ioctl(fep->phydev, mii, cmd);
spin_unlock_irqrestore(&fep->lock, flags);
return rc;
}
@ -1030,12 +1067,6 @@ static struct net_device *fs_init_instance(struct device *dev,
}
registered = 1;
err = fs_mii_connect(ndev);
if (err != 0) {
printk(KERN_ERR DRV_MODULE_NAME
": %s fs_mii_connect failed.\n", ndev->name);
goto err;
}
return ndev;
@ -1073,8 +1104,6 @@ static int fs_cleanup_instance(struct net_device *ndev)
fpi = fep->fpi;
fs_mii_disconnect(ndev);
unregister_netdev(ndev);
dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
@ -1196,17 +1225,39 @@ static int __init fs_init(void)
r = setup_immap();
if (r != 0)
return r;
r = driver_register(&fs_enet_fec_driver);
if (r != 0)
goto err;
#ifdef CONFIG_FS_ENET_HAS_FCC
/* let's insert mii stuff */
r = fs_enet_mdio_bb_init();
if (r != 0) {
printk(KERN_ERR DRV_MODULE_NAME
"BB PHY init failed.\n");
return r;
}
r = driver_register(&fs_enet_fcc_driver);
if (r != 0)
goto err;
#endif
#ifdef CONFIG_FS_ENET_HAS_FEC
r = fs_enet_mdio_fec_init();
if (r != 0) {
printk(KERN_ERR DRV_MODULE_NAME
"FEC PHY init failed.\n");
return r;
}
r = driver_register(&fs_enet_fec_driver);
if (r != 0)
goto err;
#endif
#ifdef CONFIG_FS_ENET_HAS_SCC
r = driver_register(&fs_enet_scc_driver);
if (r != 0)
goto err;
#endif
return 0;
err:

View File

@ -1,505 +0,0 @@
/*
* Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
*
* Copyright (c) 2003 Intracom S.A.
* by Pantelis Antoniou <panto@intracom.gr>
*
* 2005 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
*
* Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
* and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.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/pci.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/pgtable.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include "fs_enet.h"
/*************************************************/
/*
* 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 fs_enet_private *fep = netdev_priv(dev);
fep->phy_timer_list.expires = jiffies + HZ / 2;
add_timer(&fep->phy_timer_list);
fs_mii_link_status_change_check(dev, 0);
}
static void generic_startup(struct net_device *dev)
{
struct fs_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 fs_enet_private *fep = netdev_priv(dev);
del_timer_sync(&fep->phy_timer_list);
}
/* ------------------------------------------------------------------------- */
/* The Davicom DM9161 is used on the NETTA board */
/* register definitions */
#define MII_DM9161_ANAR 4 /* Aux. Config Register */
#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 fs_enet_private *fep = netdev_priv(dev);
fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
/* Start autonegotiation */
fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ*8);
}
static void dm9161_ack_int(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
}
static void dm9161_shutdown(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
}
/**********************************************************************************/
static const struct phy_info phy_info[] = {
{
.id = 0x00181b88,
.name = "DM9161",
.startup = dm9161_startup,
.ack_int = dm9161_ack_int,
.shutdown = dm9161_shutdown,
}, {
.id = 0,
.name = "GENERIC",
.startup = generic_startup,
.shutdown = generic_shutdown,
},
};
/**********************************************************************************/
static int phy_id_detect(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
struct fs_enet_mii_bus *bus = fep->mii_bus;
int i, r, start, end, phytype, physubtype;
const struct phy_info *phy;
int phy_hwid, phy_id;
phy_hwid = -1;
fep->phy = NULL;
/* auto-detect? */
if (fpi->phy_addr == -1) {
start = 1;
end = 32;
} else { /* direct */
start = fpi->phy_addr;
end = start + 1;
}
for (phy_id = start; phy_id < end; phy_id++) {
/* skip already used phy addresses on this bus */
if (bus->usage_map & (1 << phy_id))
continue;
r = fs_mii_read(dev, phy_id, MII_PHYSID1);
if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
continue;
r = fs_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! range=0x%02x-0x%02x\n",
dev->name, start, end);
return -1;
}
for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++)
if (phy->id == (phy_hwid >> 4) || phy->id == 0)
break;
if (i >= ARRAY_SIZE(phy_info)) {
printk(KERN_ERR DRV_MODULE_NAME
": %s PHY id 0x%08x is not supported!\n",
dev->name, phy_hwid);
return -1;
}
fep->phy = phy;
/* mark this address as used */
bus->usage_map |= (1 << phy_id);
printk(KERN_INFO DRV_MODULE_NAME
": %s Phy @ 0x%x, type %s (0x%08x)%s\n",
dev->name, phy_id, fep->phy->name, phy_hwid,
fpi->phy_addr == -1 ? " (auto-detected)" : "");
return phy_id;
}
void fs_mii_startup(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
if (fep->phy->startup)
(*fep->phy->startup) (dev);
}
void fs_mii_shutdown(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
if (fep->phy->shutdown)
(*fep->phy->shutdown) (dev);
}
void fs_mii_ack_int(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
if (fep->phy->ack_int)
(*fep->phy->ack_int) (dev);
}
#define MII_LINK 0x0001
#define MII_HALF 0x0002
#define MII_FULL 0x0004
#define MII_BASE4 0x0008
#define MII_10M 0x0010
#define MII_100M 0x0020
#define MII_1G 0x0040
#define MII_10G 0x0080
/* return full mii info at one gulp, with a usable form */
static unsigned int mii_full_status(struct mii_if_info *mii)
{
unsigned int status;
int bmsr, adv, lpa, neg;
struct fs_enet_private* fep = netdev_priv(mii->dev);
/* first, a dummy read, needed to latch some MII phys */
(void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
/* no link */
if ((bmsr & BMSR_LSTATUS) == 0)
return 0;
status = MII_LINK;
/* Lets look what ANEG says if it's supported - otherwize we shall
take the right values from the platform info*/
if(!mii->force_media) {
/* autoneg not completed; don't bother */
if ((bmsr & BMSR_ANEGCOMPLETE) == 0)
return 0;
adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE);
lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA);
neg = lpa & adv;
} else {
neg = fep->fpi->bus_info->lpa;
}
if (neg & LPA_100FULL)
status |= MII_FULL | MII_100M;
else if (neg & LPA_100BASE4)
status |= MII_FULL | MII_BASE4 | MII_100M;
else if (neg & LPA_100HALF)
status |= MII_HALF | MII_100M;
else if (neg & LPA_10FULL)
status |= MII_FULL | MII_10M;
else
status |= MII_HALF | MII_10M;
return status;
}
void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct mii_if_info *mii = &fep->mii_if;
unsigned int mii_status;
int ok_to_print, link, duplex, speed;
unsigned long flags;
ok_to_print = netif_msg_link(fep);
mii_status = mii_full_status(mii);
if (!init_media && mii_status == fep->last_mii_status)
return;
fep->last_mii_status = mii_status;
link = !!(mii_status & MII_LINK);
duplex = !!(mii_status & MII_FULL);
speed = (mii_status & MII_100M) ? 100 : 10;
if (link == 0) {
netif_carrier_off(mii->dev);
netif_stop_queue(dev);
if (!init_media) {
spin_lock_irqsave(&fep->lock, flags);
(*fep->ops->stop)(dev);
spin_unlock_irqrestore(&fep->lock, flags);
}
if (ok_to_print)
printk(KERN_INFO "%s: link down\n", mii->dev->name);
} else {
mii->full_duplex = duplex;
netif_carrier_on(mii->dev);
spin_lock_irqsave(&fep->lock, flags);
fep->duplex = duplex;
fep->speed = speed;
(*fep->ops->restart)(dev);
spin_unlock_irqrestore(&fep->lock, flags);
netif_start_queue(dev);
if (ok_to_print)
printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n",
dev->name, speed, duplex ? "full" : "half");
}
}
/**********************************************************************************/
int fs_mii_read(struct net_device *dev, int phy_id, int location)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct fs_enet_mii_bus *bus = fep->mii_bus;
unsigned long flags;
int ret;
spin_lock_irqsave(&bus->mii_lock, flags);
ret = (*bus->mii_read)(bus, phy_id, location);
spin_unlock_irqrestore(&bus->mii_lock, flags);
return ret;
}
void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct fs_enet_mii_bus *bus = fep->mii_bus;
unsigned long flags;
spin_lock_irqsave(&bus->mii_lock, flags);
(*bus->mii_write)(bus, phy_id, location, value);
spin_unlock_irqrestore(&bus->mii_lock, flags);
}
/*****************************************************************************/
/* list of all registered mii buses */
static LIST_HEAD(fs_mii_bus_list);
static struct fs_enet_mii_bus *lookup_bus(int method, int id)
{
struct list_head *ptr;
struct fs_enet_mii_bus *bus;
list_for_each(ptr, &fs_mii_bus_list) {
bus = list_entry(ptr, struct fs_enet_mii_bus, list);
if (bus->bus_info->method == method &&
bus->bus_info->id == id)
return bus;
}
return NULL;
}
static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
{
struct fs_enet_mii_bus *bus;
int ret = 0;
bus = kmalloc(sizeof(*bus), GFP_KERNEL);
if (bus == NULL) {
ret = -ENOMEM;
goto err;
}
memset(bus, 0, sizeof(*bus));
spin_lock_init(&bus->mii_lock);
bus->bus_info = bi;
bus->refs = 0;
bus->usage_map = 0;
/* perform initialization */
switch (bi->method) {
case fsmii_fixed:
ret = fs_mii_fixed_init(bus);
if (ret != 0)
goto err;
break;
case fsmii_bitbang:
ret = fs_mii_bitbang_init(bus);
if (ret != 0)
goto err;
break;
#ifdef CONFIG_FS_ENET_HAS_FEC
case fsmii_fec:
ret = fs_mii_fec_init(bus);
if (ret != 0)
goto err;
break;
#endif
default:
ret = -EINVAL;
goto err;
}
list_add(&bus->list, &fs_mii_bus_list);
return bus;
err:
kfree(bus);
return ERR_PTR(ret);
}
static void destroy_bus(struct fs_enet_mii_bus *bus)
{
/* remove from bus list */
list_del(&bus->list);
/* nothing more needed */
kfree(bus);
}
int fs_mii_connect(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
struct fs_enet_mii_bus *bus = NULL;
/* check method validity */
switch (fpi->bus_info->method) {
case fsmii_fixed:
case fsmii_bitbang:
break;
#ifdef CONFIG_FS_ENET_HAS_FEC
case fsmii_fec:
break;
#endif
default:
printk(KERN_ERR DRV_MODULE_NAME
": %s Unknown MII bus method (%d)!\n",
dev->name, fpi->bus_info->method);
return -EINVAL;
}
bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
/* if not found create new bus */
if (bus == NULL) {
bus = create_bus(fpi->bus_info);
if (IS_ERR(bus)) {
printk(KERN_ERR DRV_MODULE_NAME
": %s MII bus creation failure!\n", dev->name);
return PTR_ERR(bus);
}
}
bus->refs++;
fep->mii_bus = bus;
fep->mii_if.dev = dev;
fep->mii_if.phy_id_mask = 0x1f;
fep->mii_if.reg_num_mask = 0x1f;
fep->mii_if.mdio_read = fs_mii_read;
fep->mii_if.mdio_write = fs_mii_write;
fep->mii_if.force_media = fpi->bus_info->disable_aneg;
fep->mii_if.phy_id = phy_id_detect(dev);
return 0;
}
void fs_mii_disconnect(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct fs_enet_mii_bus *bus = NULL;
bus = fep->mii_bus;
fep->mii_bus = NULL;
if (--bus->refs <= 0)
destroy_bus(bus);
}

View File

@ -5,6 +5,7 @@
#include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/phy.h>
#include <linux/fs_enet_pd.h>
@ -12,12 +13,30 @@
#ifdef CONFIG_CPM1
#include <asm/commproc.h>
struct fec_info {
fec_t* fecp;
u32 mii_speed;
};
#endif
#ifdef CONFIG_CPM2
#include <asm/cpm2.h>
#endif
/* This is used to operate with pins.
Note that the actual port size may
be different; cpm(s) handle it OK */
struct bb_info {
u8 mdio_dat_msk;
u8 mdio_dir_msk;
u8 *mdio_dir;
u8 *mdio_dat;
u8 mdc_msk;
u8 *mdc_dat;
int delay;
};
/* hw driver ops */
struct fs_ops {
int (*setup_data)(struct net_device *dev);
@ -25,6 +44,7 @@ struct fs_ops {
void (*free_bd)(struct net_device *dev);
void (*cleanup_data)(struct net_device *dev);
void (*set_multicast_list)(struct net_device *dev);
void (*adjust_link)(struct net_device *dev);
void (*restart)(struct net_device *dev);
void (*stop)(struct net_device *dev);
void (*pre_request_irq)(struct net_device *dev, int irq);
@ -100,10 +120,6 @@ struct fs_enet_mii_bus {
};
};
int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus);
int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
int fs_mii_fec_init(struct fs_enet_mii_bus *bus);
struct fs_enet_private {
struct device *dev; /* pointer back to the device (must be initialized first) */
spinlock_t lock; /* during all ops except TX pckt processing */
@ -130,7 +146,8 @@ struct fs_enet_private {
struct fs_enet_mii_bus *mii_bus;
int interrupt;
int duplex, speed; /* current settings */
struct phy_device *phydev;
int oldduplex, oldspeed, oldlink; /* current settings */
/* event masks */
u32 ev_napi_rx; /* mask of NAPI rx events */
@ -168,15 +185,9 @@ struct fs_enet_private {
};
/***************************************************************************/
int fs_mii_read(struct net_device *dev, int phy_id, int location);
void fs_mii_write(struct net_device *dev, int phy_id, int location, int value);
void fs_mii_startup(struct net_device *dev);
void fs_mii_shutdown(struct net_device *dev);
void fs_mii_ack_int(struct net_device *dev);
void fs_mii_link_status_change_check(struct net_device *dev, int init_media);
int fs_enet_mdio_bb_init(void);
int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
int fs_enet_mdio_fec_init(void);
void fs_init_bds(struct net_device *dev);
void fs_cleanup_bds(struct net_device *dev);
@ -194,7 +205,6 @@ int fs_enet_platform_init(void);
void fs_enet_platform_cleanup(void);
/***************************************************************************/
/* buffer descriptor access macros */
/* access macros */

View File

@ -34,6 +34,7 @@
#include <linux/bitops.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
#include <asm/immap_cpm2.h>
#include <asm/mpc8260.h>
@ -122,22 +123,32 @@ static int do_pd_setup(struct fs_enet_private *fep)
/* Attach the memory for the FCC Parameter RAM */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
fep->fcc.ep = (void *)r->start;
fep->fcc.ep = (void *)ioremap(r->start, r->end - r->start + 1);
if (fep->fcc.ep == NULL)
return -EINVAL;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
fep->fcc.fccp = (void *)r->start;
fep->fcc.fccp = (void *)ioremap(r->start, r->end - r->start + 1);
if (fep->fcc.fccp == NULL)
return -EINVAL;
fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
if (fep->fpi->fcc_regs_c) {
fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
} else {
r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"fcc_regs_c");
fep->fcc.fcccp = (void *)ioremap(r->start,
r->end - r->start + 1);
}
if (fep->fcc.fcccp == NULL)
return -EINVAL;
fep->fcc.mem = (void *)fep->fpi->mem_offset;
if (fep->fcc.mem == NULL)
return -EINVAL;
return 0;
}
@ -155,8 +166,6 @@ static int setup_data(struct net_device *dev)
if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */
return -EINVAL;
fep->fcc.mem = (void *)fpi->mem_offset;
if (do_pd_setup(fep) != 0)
return -EINVAL;
@ -394,7 +403,7 @@ static void restart(struct net_device *dev)
/* adjust to speed (for RMII mode) */
if (fpi->use_rmii) {
if (fep->speed == 100)
if (fep->phydev->speed == 100)
C8(fcccp, fcc_gfemr, 0x20);
else
S8(fcccp, fcc_gfemr, 0x20);
@ -420,7 +429,7 @@ static void restart(struct net_device *dev)
S32(fccp, fcc_fpsmr, FCC_PSMR_RMII);
/* adjust to duplex mode */
if (fep->duplex)
if (fep->phydev->duplex)
S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
else
C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
@ -486,7 +495,10 @@ static void rx_bd_done(struct net_device *dev)
static void tx_kickstart(struct net_device *dev)
{
/* nothing */
struct fs_enet_private *fep = netdev_priv(dev);
fcc_t *fccp = fep->fcc.fccp;
S32(fccp, fcc_ftodr, 0x80);
}
static u32 get_int_events(struct net_device *dev)

View File

@ -46,6 +46,7 @@
#endif
#include "fs_enet.h"
#include "fec.h"
/*************************************************/
@ -75,50 +76,8 @@
/* clear bits */
#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
/* CRC polynomium used by the FEC for the multicast group filtering */
#define FEC_CRC_POLY 0x04C11DB7
#define FEC_MAX_MULTICAST_ADDRS 64
/* Interrupt events/masks.
*/
#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */
#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */
#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */
#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */
#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */
#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */
#define FEC_ENET_RXF 0x02000000U /* Full frame received */
#define FEC_ENET_RXB 0x01000000U /* A buffer was received */
#define FEC_ENET_MII 0x00800000U /* MII interrupt */
#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */
#define FEC_ECNTRL_PINMUX 0x00000004
#define FEC_ECNTRL_ETHER_EN 0x00000002
#define FEC_ECNTRL_RESET 0x00000001
#define FEC_RCNTRL_BC_REJ 0x00000010
#define FEC_RCNTRL_PROM 0x00000008
#define FEC_RCNTRL_MII_MODE 0x00000004
#define FEC_RCNTRL_DRT 0x00000002
#define FEC_RCNTRL_LOOP 0x00000001
#define FEC_TCNTRL_FDEN 0x00000004
#define FEC_TCNTRL_HBC 0x00000002
#define FEC_TCNTRL_GTS 0x00000001
/* 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
#define FEC_MII_LOOPS 10000
/*
* Delay to wait for FEC reset command to complete (in us)
* Delay to wait for FEC reset command to complete (in us)
*/
#define FEC_RESET_DELAY 50
@ -303,13 +262,15 @@ static void restart(struct net_device *dev)
int r;
u32 addrhi, addrlo;
struct mii_bus* mii = fep->phydev->bus;
struct fec_info* fec_inf = mii->priv;
r = whack_reset(fep->fec.fecp);
if (r != 0)
printk(KERN_ERR DRV_MODULE_NAME
": %s FEC Reset FAILED!\n", dev->name);
/*
* Set station address.
* Set station address.
*/
addrhi = ((u32) dev->dev_addr[0] << 24) |
((u32) dev->dev_addr[1] << 16) |
@ -350,12 +311,12 @@ static void restart(struct net_device *dev)
FW(fecp, fun_code, 0x78000000);
/*
* Set MII speed.
* Set MII speed.
*/
FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed);
FW(fecp, mii_speed, fec_inf->mii_speed);
/*
* Clear any outstanding interrupt.
* Clear any outstanding interrupt.
*/
FW(fecp, ievent, 0xffc0);
FW(fecp, ivec, (fep->interrupt / 2) << 29);
@ -390,11 +351,12 @@ static void restart(struct net_device *dev)
}
#endif
FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
/*
* adjust to duplex mode
* adjust to duplex mode
*/
if (fep->duplex) {
if (fep->phydev->duplex) {
FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
} else {
@ -418,9 +380,11 @@ static void restart(struct net_device *dev)
static void stop(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
fec_t *fecp = fep->fec.fecp;
struct fs_enet_mii_bus *bus = fep->mii_bus;
const struct fs_mii_bus_info *bi = bus->bus_info;
struct fec_info* feci= fep->phydev->bus->priv;
int i;
if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
@ -444,11 +408,11 @@ static void stop(struct net_device *dev)
fs_cleanup_bds(dev);
/* shut down FEC1? that's where the mii bus is */
if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) {
if (fpi->has_phy) {
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);
FW(fecp, mii_speed, bus->fec.mii_speed);
FW(fecp, mii_speed, feci->mii_speed);
}
}
@ -583,73 +547,3 @@ const struct fs_ops fs_fec_ops = {
.free_bd = free_bd,
};
/***********************************************************************/
static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
{
fec_t *fecp = bus->fec.fecp;
int i, ret = -1;
if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
BUG();
/* Add PHY address to register command. */
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;
}
return ret;
}
static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
{
fec_t *fecp = bus->fec.fecp;
int i;
/* this must never happen */
if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
BUG();
/* Add PHY address to register command. */
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);
}
int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
{
bd_t *bd = (bd_t *)__res;
const struct fs_mii_bus_info *bi = bus->bus_info;
fec_t *fecp;
if (bi->id != 0)
return -1;
bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec;
bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
& 0x3F) << 1;
fecp = bus->fec.fecp;
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);
FW(fecp, mii_speed, bus->fec.mii_speed);
bus->mii_read = mii_read;
bus->mii_write = mii_write;
return 0;
}

View File

@ -369,7 +369,7 @@ static void restart(struct net_device *dev)
W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
/* Set full duplex mode if needed */
if (fep->duplex)
if (fep->phydev->duplex)
S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE);
S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
@ -500,6 +500,8 @@ static void tx_restart(struct net_device *dev)
scc_cr_cmd(fep, CPM_CR_RESTART_TX);
}
/*************************************************************************/
const struct fs_ops fs_scc_ops = {

View File

@ -33,6 +33,7 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
@ -40,129 +41,25 @@
#include "fs_enet.h"
#ifdef CONFIG_8xx
static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
static int bitbang_prep_bit(u8 **datp, u8 *mskp,
struct fs_mii_bit *mii_bit)
{
immap_t *im = (immap_t *)fs_enet_immap;
void *dir, *dat, *ppar;
void *dat;
int adv;
u8 msk;
switch (port) {
case fsiop_porta:
dir = &im->im_ioport.iop_padir;
dat = &im->im_ioport.iop_padat;
ppar = &im->im_ioport.iop_papar;
break;
dat = (void*) mii_bit->offset;
case fsiop_portb:
dir = &im->im_cpm.cp_pbdir;
dat = &im->im_cpm.cp_pbdat;
ppar = &im->im_cpm.cp_pbpar;
break;
case fsiop_portc:
dir = &im->im_ioport.iop_pcdir;
dat = &im->im_ioport.iop_pcdat;
ppar = &im->im_ioport.iop_pcpar;
break;
case fsiop_portd:
dir = &im->im_ioport.iop_pddir;
dat = &im->im_ioport.iop_pddat;
ppar = &im->im_ioport.iop_pdpar;
break;
case fsiop_porte:
dir = &im->im_cpm.cp_pedir;
dat = &im->im_cpm.cp_pedat;
ppar = &im->im_cpm.cp_pepar;
break;
default:
printk(KERN_ERR DRV_MODULE_NAME
"Illegal port value %d!\n", port);
return -EINVAL;
}
adv = bit >> 3;
dir = (char *)dir + adv;
adv = mii_bit->bit >> 3;
dat = (char *)dat + adv;
ppar = (char *)ppar + adv;
msk = 1 << (7 - (bit & 7));
if ((in_8(ppar) & msk) != 0) {
printk(KERN_ERR DRV_MODULE_NAME
"pin %d on port %d is not general purpose!\n", bit, port);
return -EINVAL;
}
msk = 1 << (7 - (mii_bit->bit & 7));
*dirp = dir;
*datp = dat;
*mskp = msk;
return 0;
}
#endif
#ifdef CONFIG_8260
static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
{
iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
void *dir, *dat, *ppar;
int adv;
u8 msk;
switch (port) {
case fsiop_porta:
dir = &io->iop_pdira;
dat = &io->iop_pdata;
ppar = &io->iop_ppara;
break;
case fsiop_portb:
dir = &io->iop_pdirb;
dat = &io->iop_pdatb;
ppar = &io->iop_pparb;
break;
case fsiop_portc:
dir = &io->iop_pdirc;
dat = &io->iop_pdatc;
ppar = &io->iop_pparc;
break;
case fsiop_portd:
dir = &io->iop_pdird;
dat = &io->iop_pdatd;
ppar = &io->iop_ppard;
break;
default:
printk(KERN_ERR DRV_MODULE_NAME
"Illegal port value %d!\n", port);
return -EINVAL;
}
adv = bit >> 3;
dir = (char *)dir + adv;
dat = (char *)dat + adv;
ppar = (char *)ppar + adv;
msk = 1 << (7 - (bit & 7));
if ((in_8(ppar) & msk) != 0) {
printk(KERN_ERR DRV_MODULE_NAME
"pin %d on port %d is not general purpose!\n", bit, port);
return -EINVAL;
}
*dirp = dir;
*datp = dat;
*mskp = msk;
return 0;
}
#endif
static inline void bb_set(u8 *p, u8 m)
{
@ -179,44 +76,44 @@ static inline int bb_read(u8 *p, u8 m)
return (in_8(p) & m) != 0;
}
static inline void mdio_active(struct fs_enet_mii_bus *bus)
static inline void mdio_active(struct bb_info *bitbang)
{
bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk);
}
static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
static inline void mdio_tristate(struct bb_info *bitbang )
{
bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk);
}
static inline int mdio_read(struct fs_enet_mii_bus *bus)
static inline int mdio_read(struct bb_info *bitbang )
{
return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk);
}
static inline void mdio(struct fs_enet_mii_bus *bus, int what)
static inline void mdio(struct bb_info *bitbang , int what)
{
if (what)
bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk);
else
bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk);
}
static inline void mdc(struct fs_enet_mii_bus *bus, int what)
static inline void mdc(struct bb_info *bitbang , int what)
{
if (what)
bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
bb_set(bitbang->mdc_dat, bitbang->mdc_msk);
else
bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
bb_clr(bitbang->mdc_dat, bitbang->mdc_msk);
}
static inline void mii_delay(struct fs_enet_mii_bus *bus)
static inline void mii_delay(struct bb_info *bitbang )
{
udelay(bus->bus_info->i.bitbang.delay);
udelay(bitbang->delay);
}
/* Utility to send the preamble, address, and register (common to read and write). */
static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg)
{
int j;
@ -228,177 +125,284 @@ static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
* but it is safer and will be much more robust.
*/
mdio_active(bus);
mdio(bus, 1);
mdio_active(bitbang);
mdio(bitbang, 1);
for (j = 0; j < 32; j++) {
mdc(bus, 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
}
/* send the start bit (01) and the read opcode (10) or write (10) */
mdc(bus, 0);
mdio(bus, 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bus, 0);
mdio(bus, 1);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bus, 0);
mdio(bus, read);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bus, 0);
mdio(bus, !read);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 0);
mdio(bitbang, 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
mdc(bitbang, 0);
mdio(bitbang, 1);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
mdc(bitbang, 0);
mdio(bitbang, read);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
mdc(bitbang, 0);
mdio(bitbang, !read);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
/* send the PHY address */
for (j = 0; j < 5; j++) {
mdc(bus, 0);
mdio(bus, (addr & 0x10) != 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 0);
mdio(bitbang, (addr & 0x10) != 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
addr <<= 1;
}
/* send the register address */
for (j = 0; j < 5; j++) {
mdc(bus, 0);
mdio(bus, (reg & 0x10) != 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 0);
mdio(bitbang, (reg & 0x10) != 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
reg <<= 1;
}
}
static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location)
{
u16 rdreg;
int ret, j;
u8 addr = phy_id & 0xff;
u8 reg = location & 0xff;
struct bb_info* bitbang = bus->priv;
bitbang_pre(bus, 1, addr, reg);
bitbang_pre(bitbang, 1, addr, reg);
/* tri-state our MDIO I/O pin so we can read */
mdc(bus, 0);
mdio_tristate(bus);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 0);
mdio_tristate(bitbang);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
/* check the turnaround bit: the PHY should be driving it to zero */
if (mdio_read(bus) != 0) {
if (mdio_read(bitbang) != 0) {
/* PHY didn't drive TA low */
for (j = 0; j < 32; j++) {
mdc(bus, 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
}
ret = -1;
goto out;
}
mdc(bus, 0);
mii_delay(bus);
mdc(bitbang, 0);
mii_delay(bitbang);
/* read 16 bits of register data, MSB first */
rdreg = 0;
for (j = 0; j < 16; j++) {
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 1);
mii_delay(bitbang);
rdreg <<= 1;
rdreg |= mdio_read(bus);
mdc(bus, 0);
mii_delay(bus);
rdreg |= mdio_read(bitbang);
mdc(bitbang, 0);
mii_delay(bitbang);
}
mdc(bus, 1);
mii_delay(bus);
mdc(bus, 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 1);
mii_delay(bitbang);
mdc(bitbang, 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
ret = rdreg;
out:
return ret;
}
static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val)
{
int j;
struct bb_info* bitbang = bus->priv;
u8 addr = phy_id & 0xff;
u8 reg = location & 0xff;
u16 value = val & 0xffff;
bitbang_pre(bus, 0, addr, reg);
bitbang_pre(bitbang, 0, addr, reg);
/* send the turnaround (10) */
mdc(bus, 0);
mdio(bus, 1);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bus, 0);
mdio(bus, 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 0);
mdio(bitbang, 1);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
mdc(bitbang, 0);
mdio(bitbang, 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
/* write 16 bits of register data, MSB first */
for (j = 0; j < 16; j++) {
mdc(bus, 0);
mdio(bus, (value & 0x8000) != 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdc(bitbang, 0);
mdio(bitbang, (value & 0x8000) != 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
value <<= 1;
}
/*
* Tri-state the MDIO line.
*/
mdio_tristate(bus);
mdc(bus, 0);
mii_delay(bus);
mdc(bus, 1);
mii_delay(bus);
mdio_tristate(bitbang);
mdc(bitbang, 0);
mii_delay(bitbang);
mdc(bitbang, 1);
mii_delay(bitbang);
return 0;
}
int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
static int fs_enet_mii_bb_reset(struct mii_bus *bus)
{
/*nothing here - dunno how to reset it*/
return 0;
}
static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi)
{
const struct fs_mii_bus_info *bi = bus->bus_info;
int r;
r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
&bus->bitbang.mdio_dat,
&bus->bitbang.mdio_msk,
bi->i.bitbang.mdio_port,
bi->i.bitbang.mdio_bit);
bitbang->delay = fmpi->delay;
r = bitbang_prep_bit(&bitbang->mdio_dir,
&bitbang->mdio_dir_msk,
&fmpi->mdio_dir);
if (r != 0)
return r;
r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
&bus->bitbang.mdc_dat,
&bus->bitbang.mdc_msk,
bi->i.bitbang.mdc_port,
bi->i.bitbang.mdc_bit);
r = bitbang_prep_bit(&bitbang->mdio_dat,
&bitbang->mdio_dat_msk,
&fmpi->mdio_dat);
if (r != 0)
return r;
bus->mii_read = mii_read;
bus->mii_write = mii_write;
r = bitbang_prep_bit(&bitbang->mdc_dat,
&bitbang->mdc_msk,
&fmpi->mdc_dat);
if (r != 0)
return r;
return 0;
}
static int __devinit fs_enet_mdio_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct fs_mii_bb_platform_info *pdata;
struct mii_bus *new_bus;
struct bb_info *bitbang;
int err = 0;
if (NULL == dev)
return -EINVAL;
new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
if (NULL == new_bus)
return -ENOMEM;
bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
if (NULL == bitbang)
return -ENOMEM;
new_bus->name = "BB MII Bus",
new_bus->read = &fs_enet_mii_bb_read,
new_bus->write = &fs_enet_mii_bb_write,
new_bus->reset = &fs_enet_mii_bb_reset,
new_bus->id = pdev->id;
new_bus->phy_mask = ~0x9;
pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
if (NULL == pdata) {
printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
return -ENODEV;
}
/*set up workspace*/
fs_mii_bitbang_init(bitbang, pdata);
new_bus->priv = bitbang;
new_bus->irq = pdata->irq;
new_bus->dev = dev;
dev_set_drvdata(dev, new_bus);
err = mdiobus_register(new_bus);
if (0 != err) {
printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
new_bus->name);
goto bus_register_fail;
}
return 0;
bus_register_fail:
kfree(bitbang);
kfree(new_bus);
return err;
}
static int fs_enet_mdio_remove(struct device *dev)
{
struct mii_bus *bus = dev_get_drvdata(dev);
mdiobus_unregister(bus);
dev_set_drvdata(dev, NULL);
iounmap((void *) (&bus->priv));
bus->priv = NULL;
kfree(bus);
return 0;
}
static struct device_driver fs_enet_bb_mdio_driver = {
.name = "fsl-bb-mdio",
.bus = &platform_bus_type,
.probe = fs_enet_mdio_probe,
.remove = fs_enet_mdio_remove,
};
int fs_enet_mdio_bb_init(void)
{
return driver_register(&fs_enet_bb_mdio_driver);
}
void fs_enet_mdio_bb_exit(void)
{
driver_unregister(&fs_enet_bb_mdio_driver);
}

View File

@ -0,0 +1,243 @@
/*
* Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
*
* Copyright (c) 2003 Intracom S.A.
* by Pantelis Antoniou <panto@intracom.gr>
*
* 2005 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.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/pci.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 <linux/platform_device.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include "fs_enet.h"
#include "fec.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
#define FEC_MII_LOOPS 10000
static int match_has_phy (struct device *dev, void* data)
{
struct platform_device* pdev = container_of(dev, struct platform_device, dev);
struct fs_platform_info* fpi;
if(strcmp(pdev->name, (char*)data))
{
return 0;
}
fpi = pdev->dev.platform_data;
if((fpi)&&(fpi->has_phy))
return 1;
return 0;
}
static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
{
struct resource *r;
fec_t *fecp;
char* name = "fsl-cpm-fec";
/* we need fec in order to be useful */
struct platform_device *fec_pdev =
container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy),
struct platform_device, dev);
if(fec_pdev == NULL) {
printk(KERN_ERR"Unable to find PHY for %s", name);
return -ENODEV;
}
r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs");
fec->fecp = fecp = (fec_t*)ioremap(r->start,sizeof(fec_t));
fec->mii_speed = fmpi->mii_speed;
setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
out_be32(&fecp->fec_ievent, FEC_ENET_MII);
out_be32(&fecp->fec_mii_speed, fec->mii_speed);
return 0;
}
static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
{
struct fec_info* fec = bus->priv;
fec_t *fecp = fec->fecp;
int i, ret = -1;
if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
BUG();
/* Add PHY address to register command. */
out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
for (i = 0; i < FEC_MII_LOOPS; i++)
if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
break;
if (i < FEC_MII_LOOPS) {
out_be32(&fecp->fec_ievent, FEC_ENET_MII);
ret = in_be32(&fecp->fec_mii_data) & 0xffff;
}
return ret;
}
static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
{
struct fec_info* fec = bus->priv;
fec_t *fecp = fec->fecp;
int i;
/* this must never happen */
if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
BUG();
/* Add PHY address to register command. */
out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val));
for (i = 0; i < FEC_MII_LOOPS; i++)
if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
break;
if (i < FEC_MII_LOOPS)
out_be32(&fecp->fec_ievent, FEC_ENET_MII);
return 0;
}
static int fs_enet_fec_mii_reset(struct mii_bus *bus)
{
/* nothing here - for now */
return 0;
}
static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct fs_mii_fec_platform_info *pdata;
struct mii_bus *new_bus;
struct fec_info *fec;
int err = 0;
if (NULL == dev)
return -EINVAL;
new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
if (NULL == new_bus)
return -ENOMEM;
fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
if (NULL == fec)
return -ENOMEM;
new_bus->name = "FEC MII Bus",
new_bus->read = &fs_enet_fec_mii_read,
new_bus->write = &fs_enet_fec_mii_write,
new_bus->reset = &fs_enet_fec_mii_reset,
new_bus->id = pdev->id;
pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
if (NULL == pdata) {
printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id);
return -ENODEV;
}
/*set up workspace*/
fs_mii_fec_init(fec, pdata);
new_bus->priv = fec;
new_bus->irq = pdata->irq;
new_bus->dev = dev;
dev_set_drvdata(dev, new_bus);
err = mdiobus_register(new_bus);
if (0 != err) {
printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
new_bus->name);
goto bus_register_fail;
}
return 0;
bus_register_fail:
kfree(new_bus);
return err;
}
static int fs_enet_fec_mdio_remove(struct device *dev)
{
struct mii_bus *bus = dev_get_drvdata(dev);
mdiobus_unregister(bus);
dev_set_drvdata(dev, NULL);
kfree(bus->priv);
bus->priv = NULL;
kfree(bus);
return 0;
}
static struct device_driver fs_enet_fec_mdio_driver = {
.name = "fsl-cpm-fec-mdio",
.bus = &platform_bus_type,
.probe = fs_enet_fec_mdio_probe,
.remove = fs_enet_fec_mdio_remove,
};
int fs_enet_mdio_fec_init(void)
{
return driver_register(&fs_enet_fec_mdio_driver);
}
void fs_enet_mdio_fec_exit(void)
{
driver_unregister(&fs_enet_fec_mdio_driver);
}

View File

@ -1,91 +0,0 @@
/*
* Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
*
* Copyright (c) 2003 Intracom S.A.
* by Pantelis Antoniou <panto@intracom.gr>
*
* 2005 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.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/pci.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/pgtable.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include "fs_enet.h"
static const u16 mii_regs[7] = {
0x3100,
0x786d,
0x0fff,
0x0fff,
0x01e1,
0x45e1,
0x0003,
};
static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
{
int ret = 0;
if ((unsigned int)location >= ARRAY_SIZE(mii_regs))
return -1;
if (location != 5)
ret = mii_regs[location];
else
ret = bus->fixed.lpa;
return ret;
}
static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
{
/* do nothing */
}
int fs_mii_fixed_init(struct fs_enet_mii_bus *bus)
{
const struct fs_mii_bus_info *bi = bus->bus_info;
bus->fixed.lpa = 0x45e1; /* default 100Mb, full duplex */
/* if speed is fixed at 10Mb, remove 100Mb modes */
if (bi->i.fixed.speed == 10)
bus->fixed.lpa &= ~LPA_100;
/* if duplex is half, remove full duplex modes */
if (bi->i.fixed.duplex == 0)
bus->fixed.lpa &= ~LPA_DUPLEX;
bus->mii_read = mii_read;
bus->mii_write = mii_write;
return 0;
}

View File

@ -326,7 +326,7 @@ MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)");
MODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)");
MODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)");
int init_module(void)
int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;

View File

@ -406,7 +406,7 @@ MODULE_PARM_DESC(mem, "memory base address(es)");
MODULE_DESCRIPTION("Mylex LNE390A/B EISA Ethernet driver");
MODULE_LICENSE("GPL");
int init_module(void)
int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;

View File

@ -1323,7 +1323,7 @@ MODULE_PARM_DESC(irq, "NI5210 IRQ number,required");
MODULE_PARM_DESC(memstart, "NI5210 memory base address,required");
MODULE_PARM_DESC(memend, "NI5210 memory end address,required");
int init_module(void)
int __init init_module(void)
{
if(io <= 0x0 || !memend || !memstart || irq < 2) {
printk("ni52: Autoprobing not allowed for modules.\nni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n");

View File

@ -1253,7 +1253,7 @@ MODULE_PARM_DESC(irq, "ni6510 IRQ number (ignored for some cards)");
MODULE_PARM_DESC(io, "ni6510 I/O base address");
MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
int init_module(void)
int __init init_module(void)
{
dev_ni65 = ni65_probe(-1);
return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0;

View File

@ -345,6 +345,7 @@ typedef struct local_info_t {
void __iomem *dingo_ccr; /* only used for CEM56 cards */
unsigned last_ptr_value; /* last packets transmitted value */
const char *manf_str;
struct work_struct tx_timeout_task;
} local_info_t;
/****************
@ -352,6 +353,7 @@ typedef struct local_info_t {
*/
static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void do_tx_timeout(struct net_device *dev);
static void xirc2ps_tx_timeout_task(void *data);
static struct net_device_stats *do_get_stats(struct net_device *dev);
static void set_addresses(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
@ -589,6 +591,7 @@ xirc2ps_probe(struct pcmcia_device *link)
#ifdef HAVE_TX_TIMEOUT
dev->tx_timeout = do_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev);
#endif
return xirc2ps_config(link);
@ -1341,17 +1344,24 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*====================================================================*/
static void
do_tx_timeout(struct net_device *dev)
xirc2ps_tx_timeout_task(void *data)
{
local_info_t *lp = netdev_priv(dev);
printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
lp->stats.tx_errors++;
struct net_device *dev = data;
/* reset the card */
do_reset(dev,1);
dev->trans_start = jiffies;
netif_wake_queue(dev);
}
static void
do_tx_timeout(struct net_device *dev)
{
local_info_t *lp = netdev_priv(dev);
lp->stats.tx_errors++;
printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
schedule_work(&lp->tx_timeout_task);
}
static int
do_start_xmit(struct sk_buff *skb, struct net_device *dev)
{

View File

@ -202,6 +202,8 @@ static int homepna[MAX_UNITS];
#define CSR15 15
#define PCNET32_MC_FILTER 8
#define PCNET32_79C970A 0x2621
/* The PCNET32 Rx and Tx ring descriptors. */
struct pcnet32_rx_head {
u32 base;
@ -289,6 +291,7 @@ struct pcnet32_private {
/* each bit indicates an available PHY */
u32 phymask;
unsigned short chip_version; /* which variant this is */
};
static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
@ -724,9 +727,11 @@ static u32 pcnet32_get_link(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
if (lp->mii) {
r = mii_link_ok(&lp->mii_if);
} else {
} else if (lp->chip_version >= PCNET32_79C970A) {
ulong ioaddr = dev->base_addr; /* card base I/O address */
r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
} else { /* can not detect link on really old chips */
r = 1;
}
spin_unlock_irqrestore(&lp->lock, flags);
@ -1091,6 +1096,10 @@ static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
ulong ioaddr = dev->base_addr;
int ticks;
/* really old chips have to be stopped. */
if (lp->chip_version < PCNET32_79C970A)
return 0;
/* set SUSPEND (SPND) - CSR5 bit 0 */
csr5 = a->read_csr(ioaddr, CSR5);
a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
@ -1529,6 +1538,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
lp->mii_if.reg_num_mask = 0x1f;
lp->dxsuflo = dxsuflo;
lp->mii = mii;
lp->chip_version = chip_version;
lp->msg_enable = pcnet32_debug;
if ((cards_found >= MAX_UNITS)
|| (options[cards_found] > sizeof(options_mapping)))
@ -1839,10 +1849,7 @@ static int pcnet32_open(struct net_device *dev)
val |= 2;
} else if (lp->options & PCNET32_PORT_ASEL) {
/* workaround of xSeries250, turn on for 79C975 only */
i = ((lp->a.read_csr(ioaddr, 88) |
(lp->a.
read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff;
if (i == 0x2627)
if (lp->chip_version == 0x2627)
val |= 3;
}
lp->a.write_bcr(ioaddr, 9, val);
@ -1986,9 +1993,11 @@ static int pcnet32_open(struct net_device *dev)
netif_start_queue(dev);
/* Print the link status and start the watchdog */
pcnet32_check_media(dev, 1);
mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
if (lp->chip_version >= PCNET32_79C970A) {
/* Print the link status and start the watchdog */
pcnet32_check_media(dev, 1);
mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
}
i = 0;
while (i++ < 100)

View File

@ -56,5 +56,22 @@ config SMSC_PHY
---help---
Currently supports the LAN83C185 PHY
config FIXED_PHY
tristate "Drivers for PHY emulation on fixed speed/link"
depends on PHYLIB
---help---
Adds the driver to PHY layer to cover the boards that do not have any PHY bound,
but with the ability to manipulate with speed/link in software. The relavant MII
speed/duplex parameters could be effectively handled in user-specified fuction.
Currently tested with mpc866ads.
config FIXED_MII_10_FDX
bool "Emulation for 10M Fdx fixed PHY behavior"
depends on FIXED_PHY
config FIXED_MII_100_FDX
bool "Emulation for 100M Fdx fixed PHY behavior"
depends on FIXED_PHY
endmenu

View File

@ -10,3 +10,4 @@ obj-$(CONFIG_LXT_PHY) += lxt.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_FIXED_PHY) += fixed.o

358
drivers/net/phy/fixed.c Normal file
View File

@ -0,0 +1,358 @@
/*
* drivers/net/phy/fixed.c
*
* Driver for fixed PHYs, when transceiver is able to operate in one fixed mode.
*
* Author: Vitaly Bordug
*
* Copyright (c) 2006 MontaVista Software, Inc.
*
* 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 <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/unistd.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/mm.h>
#include <linux/module.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#define MII_REGS_NUM 7
/*
The idea is to emulate normal phy behavior by responding with
pre-defined values to mii BMCR read, so that read_status hook could
take all the needed info.
*/
struct fixed_phy_status {
u8 link;
u16 speed;
u8 duplex;
};
/*-----------------------------------------------------------------------------
* Private information hoder for mii_bus
*-----------------------------------------------------------------------------*/
struct fixed_info {
u16 *regs;
u8 regs_num;
struct fixed_phy_status phy_status;
struct phy_device *phydev; /* pointer to the container */
/* link & speed cb */
int(*link_update)(struct net_device*, struct fixed_phy_status*);
};
/*-----------------------------------------------------------------------------
* If something weird is required to be done with link/speed,
* network driver is able to assign a function to implement this.
* May be useful for PHY's that need to be software-driven.
*-----------------------------------------------------------------------------*/
int fixed_mdio_set_link_update(struct phy_device* phydev,
int(*link_update)(struct net_device*, struct fixed_phy_status*))
{
struct fixed_info *fixed;
if(link_update == NULL)
return -EINVAL;
if(phydev) {
if(phydev->bus) {
fixed = phydev->bus->priv;
fixed->link_update = link_update;
return 0;
}
}
return -EINVAL;
}
EXPORT_SYMBOL(fixed_mdio_set_link_update);
/*-----------------------------------------------------------------------------
* This is used for updating internal mii regs from the status
*-----------------------------------------------------------------------------*/
static int fixed_mdio_update_regs(struct fixed_info *fixed)
{
u16 *regs = fixed->regs;
u16 bmsr = 0;
u16 bmcr = 0;
if(!regs) {
printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
return -EINVAL;
}
if(fixed->phy_status.link)
bmsr |= BMSR_LSTATUS;
if(fixed->phy_status.duplex) {
bmcr |= BMCR_FULLDPLX;
switch ( fixed->phy_status.speed ) {
case 100:
bmsr |= BMSR_100FULL;
bmcr |= BMCR_SPEED100;
break;
case 10:
bmsr |= BMSR_10FULL;
break;
}
} else {
switch ( fixed->phy_status.speed ) {
case 100:
bmsr |= BMSR_100HALF;
bmcr |= BMCR_SPEED100;
break;
case 10:
bmsr |= BMSR_100HALF;
break;
}
}
regs[MII_BMCR] = bmcr;
regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx*/
return 0;
}
static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
{
struct fixed_info *fixed = bus->priv;
/* if user has registered link update callback, use it */
if(fixed->phydev)
if(fixed->phydev->attached_dev) {
if(fixed->link_update) {
fixed->link_update(fixed->phydev->attached_dev,
&fixed->phy_status);
fixed_mdio_update_regs(fixed);
}
}
if ((unsigned int)location >= fixed->regs_num)
return -1;
return fixed->regs[location];
}
static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
{
/* do nothing for now*/
return 0;
}
static int fixed_mii_reset(struct mii_bus *bus)
{
/*nothing here - no way/need to reset it*/
return 0;
}
static int fixed_config_aneg(struct phy_device *phydev)
{
/* :TODO:03/13/2006 09:45:37 PM::
The full autoneg funcionality can be emulated,
but no need to have anything here for now
*/
return 0;
}
/*-----------------------------------------------------------------------------
* the manual bind will do the magic - with phy_id_mask == 0
* match will never return true...
*-----------------------------------------------------------------------------*/
static struct phy_driver fixed_mdio_driver = {
.name = "Fixed PHY",
.features = PHY_BASIC_FEATURES,
.config_aneg = fixed_config_aneg,
.read_status = genphy_read_status,
.driver = { .owner = THIS_MODULE,},
};
/*-----------------------------------------------------------------------------
* This func is used to create all the necessary stuff, bind
* the fixed phy driver and register all it on the mdio_bus_type.
* speed is either 10 or 100, duplex is boolean.
* number is used to create multiple fixed PHYs, so that several devices can
* utilize them simultaneously.
*-----------------------------------------------------------------------------*/
static int fixed_mdio_register_device(int number, int speed, int duplex)
{
struct mii_bus *new_bus;
struct fixed_info *fixed;
struct phy_device *phydev;
int err = 0;
struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
if (NULL == dev)
return -ENOMEM;
new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
if (NULL == new_bus) {
kfree(dev);
return -ENOMEM;
}
fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
if (NULL == fixed) {
kfree(dev);
kfree(new_bus);
return -ENOMEM;
}
fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
fixed->regs_num = MII_REGS_NUM;
fixed->phy_status.speed = speed;
fixed->phy_status.duplex = duplex;
fixed->phy_status.link = 1;
new_bus->name = "Fixed MII Bus",
new_bus->read = &fixed_mii_read,
new_bus->write = &fixed_mii_write,
new_bus->reset = &fixed_mii_reset,
/*set up workspace*/
fixed_mdio_update_regs(fixed);
new_bus->priv = fixed;
new_bus->dev = dev;
dev_set_drvdata(dev, new_bus);
/* create phy_device and register it on the mdio bus */
phydev = phy_device_create(new_bus, 0, 0);
/*
Put the phydev pointer into the fixed pack so that bus read/write code could
be able to access for instance attached netdev. Well it doesn't have to do
so, only in case of utilizing user-specified link-update...
*/
fixed->phydev = phydev;
if(NULL == phydev) {
err = -ENOMEM;
goto device_create_fail;
}
phydev->irq = -1;
phydev->dev.bus = &mdio_bus_type;
if(number)
snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
"fixed_%d@%d:%d", number, speed, duplex);
else
snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
"fixed@%d:%d", speed, duplex);
phydev->bus = new_bus;
err = device_register(&phydev->dev);
if(err) {
printk(KERN_ERR "Phy %s failed to register\n",
phydev->dev.bus_id);
goto bus_register_fail;
}
/*
the mdio bus has phy_id match... In order not to do it
artificially, we are binding the driver here by hand;
it will be the same for all the fixed phys anyway.
*/
down_write(&phydev->dev.bus->subsys.rwsem);
phydev->dev.driver = &fixed_mdio_driver.driver;
err = phydev->dev.driver->probe(&phydev->dev);
if(err < 0) {
printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
up_write(&phydev->dev.bus->subsys.rwsem);
goto probe_fail;
}
device_bind_driver(&phydev->dev);
up_write(&phydev->dev.bus->subsys.rwsem);
return 0;
probe_fail:
device_unregister(&phydev->dev);
bus_register_fail:
kfree(phydev);
device_create_fail:
kfree(dev);
kfree(new_bus);
kfree(fixed);
return err;
}
MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
MODULE_AUTHOR("Vitaly Bordug");
MODULE_LICENSE("GPL");
static int __init fixed_init(void)
{
int ret;
int duplex = 0;
/* register on the bus... Not expected to be matched with anything there... */
phy_driver_register(&fixed_mdio_driver);
/* So let the fun begin...
We will create several mdio devices here, and will bound the upper
driver to them.
Then the external software can lookup the phy bus by searching
fixed@speed:duplex, e.g. fixed@100:1, to be connected to the
virtual 100M Fdx phy.
In case several virtual PHYs required, the bus_id will be in form
fixed_<num>@<speed>:<duplex>, which make it able even to define
driver-specific link control callback, if for instance PHY is completely
SW-driven.
*/
#ifdef CONFIG_FIXED_MII_DUPLEX
duplex = 1;
#endif
#ifdef CONFIG_FIXED_MII_100_FDX
fixed_mdio_register_device(0, 100, 1);
#endif
#ifdef CONFIX_FIXED_MII_10_FDX
fixed_mdio_register_device(0, 10, 1);
#endif
return 0;
}
static void __exit fixed_exit(void)
{
phy_driver_unregister(&fixed_mdio_driver);
/* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */
}
module_init(fixed_init);
module_exit(fixed_exit);

View File

@ -159,6 +159,7 @@ struct bus_type mdio_bus_type = {
.suspend = mdio_bus_suspend,
.resume = mdio_bus_resume,
};
EXPORT_SYMBOL(mdio_bus_type);
int __init mdio_bus_init(void)
{

View File

@ -45,6 +45,35 @@ static struct phy_driver genphy_driver;
extern int mdio_bus_init(void);
extern void mdio_bus_exit(void);
struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
{
struct phy_device *dev;
/* We allocate the device, and initialize the
* default values */
dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
if (NULL == dev)
return (struct phy_device*) PTR_ERR((void*)-ENOMEM);
dev->speed = 0;
dev->duplex = -1;
dev->pause = dev->asym_pause = 0;
dev->link = 1;
dev->autoneg = AUTONEG_ENABLE;
dev->addr = addr;
dev->phy_id = phy_id;
dev->bus = bus;
dev->state = PHY_DOWN;
spin_lock_init(&dev->lock);
return dev;
}
EXPORT_SYMBOL(phy_device_create);
/* get_phy_device
*
* description: Reads the ID registers of the PHY at addr on the
@ -78,27 +107,7 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
if (0xffffffff == phy_id)
return NULL;
/* Otherwise, we allocate the device, and initialize the
* default values */
dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
if (NULL == dev)
return ERR_PTR(-ENOMEM);
dev->speed = 0;
dev->duplex = -1;
dev->pause = dev->asym_pause = 0;
dev->link = 1;
dev->autoneg = AUTONEG_ENABLE;
dev->addr = addr;
dev->phy_id = phy_id;
dev->bus = bus;
dev->state = PHY_DOWN;
spin_lock_init(&dev->lock);
dev = phy_device_create(bus, addr, phy_id);
return dev;
}

View File

@ -71,6 +71,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/div64.h>
#include <asm/irq.h>
/* local include */
#include "s2io.h"

View File

@ -742,7 +742,7 @@ module_param(irq, int, 0);
MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address");
MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number");
int init_module(void)
int __init init_module(void)
{
dev_seeq = seeq8005_probe(-1);
if (IS_ERR(dev_seeq))

View File

@ -2211,6 +2211,7 @@ static int skge_up(struct net_device *dev)
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
skge_led(skge, LED_MODE_ON);
netif_poll_enable(dev);
return 0;
free_rx_ring:
@ -2279,6 +2280,7 @@ static int skge_down(struct net_device *dev)
skge_led(skge, LED_MODE_OFF);
netif_poll_disable(dev);
skge_tx_clean(skge);
skge_rx_clean(skge);

View File

@ -233,6 +233,8 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
if (hw->ports > 1)
reg1 |= PCI_Y2_PHY2_COMA;
}
sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
udelay(100);
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
@ -242,9 +244,6 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
sky2_pci_write32(hw, PCI_DEV_REG5, 0);
}
sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
udelay(100);
break;
case PCI_D3hot:

View File

@ -1092,6 +1092,7 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs
/* Spurious interrupt check */
if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) !=
(INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) {
spin_unlock_irqrestore(&lp->lock, flags);
return IRQ_NONE;
}

View File

@ -321,12 +321,12 @@ static void smc_reset(struct net_device *dev)
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
/* Disable all interrupts, block TX tasklet */
spin_lock(&lp->lock);
spin_lock_irq(&lp->lock);
SMC_SELECT_BANK(2);
SMC_SET_INT_MASK(0);
pending_skb = lp->pending_tx_skb;
lp->pending_tx_skb = NULL;
spin_unlock(&lp->lock);
spin_unlock_irq(&lp->lock);
/* free any pending tx skb */
if (pending_skb) {
@ -448,12 +448,12 @@ static void smc_shutdown(struct net_device *dev)
DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
/* no more interrupts for me */
spin_lock(&lp->lock);
spin_lock_irq(&lp->lock);
SMC_SELECT_BANK(2);
SMC_SET_INT_MASK(0);
pending_skb = lp->pending_tx_skb;
lp->pending_tx_skb = NULL;
spin_unlock(&lp->lock);
spin_unlock_irq(&lp->lock);
if (pending_skb)
dev_kfree_skb(pending_skb);

View File

@ -136,14 +136,9 @@
#define SMC_CAN_USE_32BIT 0
#define SMC_IO_SHIFT 0
#define SMC_NOWAIT 1
#define SMC_USE_PXA_DMA 1
#define SMC_inb(a, r) readb((a) + (r))
#define SMC_inw(a, r) readw((a) + (r))
#define SMC_inl(a, r) readl((a) + (r))
#define SMC_outb(v, a, r) writeb(v, (a) + (r))
#define SMC_outw(v, a, r) writew(v, (a) + (r))
#define SMC_outl(v, a, r) writel(v, (a) + (r))
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
@ -189,16 +184,10 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_IO_SHIFT 0
#define SMC_NOWAIT 1
#define SMC_inb(a, r) readb((a) + (r))
#define SMC_outb(v, a, r) writeb(v, (a) + (r))
#define SMC_inw(a, r) readw((a) + (r))
#define SMC_outw(v, a, r) writew(v, (a) + (r))
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
#define SMC_inl(a, r) readl((a) + (r))
#define SMC_outl(v, a, r) writel(v, (a) + (r))
#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
#include <asm/mach-types.h>
#include <asm/arch/cpu.h>
@ -372,6 +361,24 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
#define SMC_IRQ_FLAGS (0)
#elif defined(CONFIG_ARCH_VERSATILE)
#define SMC_CAN_USE_8BIT 1
#define SMC_CAN_USE_16BIT 1
#define SMC_CAN_USE_32BIT 1
#define SMC_NOWAIT 1
#define SMC_inb(a, r) readb((a) + (r))
#define SMC_inw(a, r) readw((a) + (r))
#define SMC_inl(a, r) readl((a) + (r))
#define SMC_outb(v, a, r) writeb(v, (a) + (r))
#define SMC_outw(v, a, r) writew(v, (a) + (r))
#define SMC_outl(v, a, r) writel(v, (a) + (r))
#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
#define SMC_IRQ_FLAGS (0)
#else
#define SMC_CAN_USE_8BIT 1

View File

@ -1611,13 +1611,12 @@ spider_net_open(struct net_device *netdev)
int result;
result = -ENOMEM;
if (spider_net_init_chain(card, &card->tx_chain,
card->descr,
PCI_DMA_TODEVICE, tx_descriptors))
if (spider_net_init_chain(card, &card->tx_chain, card->descr,
PCI_DMA_TODEVICE, card->tx_desc))
goto alloc_tx_failed;
if (spider_net_init_chain(card, &card->rx_chain,
card->descr + tx_descriptors,
PCI_DMA_FROMDEVICE, rx_descriptors))
card->descr + card->rx_desc,
PCI_DMA_FROMDEVICE, card->rx_desc))
goto alloc_rx_failed;
/* allocate rx skbs */
@ -2005,6 +2004,9 @@ spider_net_setup_netdev(struct spider_net_card *card)
card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
card->tx_desc = tx_descriptors;
card->rx_desc = rx_descriptors;
spider_net_setup_netdev_ops(netdev);
netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;

View File

@ -440,6 +440,9 @@ struct spider_net_card {
/* for ethtool */
int msg_enable;
int rx_desc;
int tx_desc;
struct spider_net_descr descr[0];
};

View File

@ -130,6 +130,18 @@ spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data)
return 0;
}
static void
spider_net_ethtool_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ering)
{
struct spider_net_card *card = netdev->priv;
ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX;
ering->tx_pending = card->tx_desc;
ering->rx_max_pending = SPIDER_NET_RX_DESCRIPTORS_MAX;
ering->rx_pending = card->rx_desc;
}
struct ethtool_ops spider_net_ethtool_ops = {
.get_settings = spider_net_ethtool_get_settings,
.get_drvinfo = spider_net_ethtool_get_drvinfo,
@ -141,5 +153,6 @@ struct ethtool_ops spider_net_ethtool_ops = {
.set_rx_csum = spider_net_ethtool_set_rx_csum,
.get_tx_csum = spider_net_ethtool_get_tx_csum,
.set_tx_csum = spider_net_ethtool_set_tx_csum,
.get_ringparam = spider_net_ethtool_get_ringparam,
};

View File

@ -107,7 +107,7 @@ static char *media[MAX_UNITS];
#endif
/* These identify the driver base version and may not be removed. */
static char version[] __devinitdata =
static char version[] =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n"
KERN_INFO " http://www.scyld.com/network/sundance.html\n";

View File

@ -140,7 +140,7 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */
/* version and credits */
#ifndef PCMCIA
static char version[] __initdata =
static char version[] __devinitdata =
"\nibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n"
" v2.1.125 10/20/98 Paul Norton <pnorton@ieee.org>\n"
" v2.2.0 12/30/98 Joel Sloan <jjs@c-me.com>\n"
@ -216,7 +216,7 @@ static int __devinitdata turbo_irq[IBMTR_MAX_ADAPTERS] = {0};
static int __devinitdata turbo_searched = 0;
#ifndef PCMCIA
static __u32 ibmtr_mem_base __initdata = 0xd0000;
static __u32 ibmtr_mem_base __devinitdata = 0xd0000;
#endif
static void __devinit PrtChanID(char *pcid, short stride)

View File

@ -5666,7 +5666,7 @@ module_param_array(io, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
module_param(ringspeed, int, 0);
static struct net_device *setup_card(int n)
static struct net_device * __init setup_card(int n)
{
struct net_device *dev = alloc_trdev(sizeof(struct net_local));
int err;
@ -5696,9 +5696,8 @@ out:
free_netdev(dev);
return ERR_PTR(err);
}
int init_module(void)
int __init init_module(void)
{
int i, found = 0;
struct net_device *dev;

View File

@ -138,7 +138,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
#include <asm/irq.h>
/* These identify the driver base version and may not be removed. */
static char version[] __devinitdata =
static char version[] =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker <becker@scyld.com>\n"
KERN_INFO " http://www.scyld.com/network/drivers.html\n";

View File

@ -1264,8 +1264,7 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p
static int __init xircom_init(void)
{
pci_register_driver(&xircom_ops);
return 0;
return pci_register_driver(&xircom_ops);
}
static void __exit xircom_exit(void)

4278
drivers/net/ucc_geth.c Normal file

File diff suppressed because it is too large Load Diff

1339
drivers/net/ucc_geth.h Normal file

File diff suppressed because it is too large Load Diff

801
drivers/net/ucc_geth_phy.c Normal file
View File

@ -0,0 +1,801 @@
/*
* Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
*
* Author: Shlomi Gridish <gridish@freescale.com>
*
* Description:
* UCC GETH Driver -- PHY handling
*
* Changelog:
* Jun 28, 2006 Li Yang <LeoLi@freescale.com>
* - Rearrange code and style fixes
*
* 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 <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.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/mm.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include "ucc_geth.h"
#include "ucc_geth_phy.h"
#include <platforms/83xx/mpc8360e_pb.h>
#define ugphy_printk(level, format, arg...) \
printk(level format "\n", ## arg)
#define ugphy_dbg(format, arg...) \
ugphy_printk(KERN_DEBUG, format , ## arg)
#define ugphy_err(format, arg...) \
ugphy_printk(KERN_ERR, format , ## arg)
#define ugphy_info(format, arg...) \
ugphy_printk(KERN_INFO, format , ## arg)
#define ugphy_warn(format, arg...) \
ugphy_printk(KERN_WARNING, format , ## arg)
#ifdef UGETH_VERBOSE_DEBUG
#define ugphy_vdbg ugphy_dbg
#else
#define ugphy_vdbg(fmt, args...) do { } while (0)
#endif /* UGETH_VERBOSE_DEBUG */
static void config_genmii_advert(struct ugeth_mii_info *mii_info);
static void genmii_setup_forced(struct ugeth_mii_info *mii_info);
static void genmii_restart_aneg(struct ugeth_mii_info *mii_info);
static int gbit_config_aneg(struct ugeth_mii_info *mii_info);
static int genmii_config_aneg(struct ugeth_mii_info *mii_info);
static int genmii_update_link(struct ugeth_mii_info *mii_info);
static int genmii_read_status(struct ugeth_mii_info *mii_info);
u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum);
void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val);
static u8 *bcsr_regs = NULL;
/* Write value to the PHY for this device to the register at regnum, */
/* waiting until the write is done before it returns. All PHY */
/* configuration has to be done through the TSEC1 MIIM regs */
void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
{
ucc_geth_private_t *ugeth = netdev_priv(dev);
ucc_mii_mng_t *mii_regs;
enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
u32 tmp_reg;
ugphy_vdbg("%s: IN", __FUNCTION__);
spin_lock_irq(&ugeth->lock);
mii_regs = ugeth->mii_info->mii_regs;
/* Set this UCC to be the master of the MII managment */
ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
/* Stop the MII management read cycle */
out_be32(&mii_regs->miimcom, 0);
/* Setting up the MII Mangement Address Register */
tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
out_be32(&mii_regs->miimadd, tmp_reg);
/* Setting up the MII Mangement Control Register with the value */
out_be32(&mii_regs->miimcon, (u32) value);
/* Wait till MII management write is complete */
while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
cpu_relax();
spin_unlock_irq(&ugeth->lock);
udelay(10000);
}
/* Reads from register regnum in the PHY for device dev, */
/* returning the value. Clears miimcom first. All PHY */
/* configuration has to be done through the TSEC1 MIIM regs */
int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
{
ucc_geth_private_t *ugeth = netdev_priv(dev);
ucc_mii_mng_t *mii_regs;
enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
u32 tmp_reg;
u16 value;
ugphy_vdbg("%s: IN", __FUNCTION__);
spin_lock_irq(&ugeth->lock);
mii_regs = ugeth->mii_info->mii_regs;
/* Setting up the MII Mangement Address Register */
tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
out_be32(&mii_regs->miimadd, tmp_reg);
/* Perform an MII management read cycle */
out_be32(&mii_regs->miimcom, MIIMCOM_READ_CYCLE);
/* Wait till MII management write is complete */
while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
cpu_relax();
udelay(10000);
/* Read MII management status */
value = (u16) in_be32(&mii_regs->miimstat);
out_be32(&mii_regs->miimcom, 0);
if (value == 0xffff)
ugphy_warn("read wrong value : mii_id %d,mii_reg %d, base %08x",
mii_id, mii_reg, (u32) & (mii_regs->miimcfg));
spin_unlock_irq(&ugeth->lock);
return (value);
}
void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->phyinfo->ack_interrupt)
mii_info->phyinfo->ack_interrupt(mii_info);
}
void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
u32 interrupts)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
mii_info->interrupts = interrupts;
if (mii_info->phyinfo->config_intr)
mii_info->phyinfo->config_intr(mii_info);
}
/* Writes MII_ADVERTISE with the appropriate values, after
* sanitizing advertise to make sure only supported features
* are advertised
*/
static void config_genmii_advert(struct ugeth_mii_info *mii_info)
{
u32 advertise;
u16 adv;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Only allow advertising what this PHY supports */
mii_info->advertising &= mii_info->phyinfo->features;
advertise = mii_info->advertising;
/* Setup standard advertisement */
adv = phy_read(mii_info, MII_ADVERTISE);
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
if (advertise & ADVERTISED_10baseT_Half)
adv |= ADVERTISE_10HALF;
if (advertise & ADVERTISED_10baseT_Full)
adv |= ADVERTISE_10FULL;
if (advertise & ADVERTISED_100baseT_Half)
adv |= ADVERTISE_100HALF;
if (advertise & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL;
phy_write(mii_info, MII_ADVERTISE, adv);
}
static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
{
u16 ctrl;
u32 features = mii_info->phyinfo->features;
ugphy_vdbg("%s: IN", __FUNCTION__);
ctrl = phy_read(mii_info, MII_BMCR);
ctrl &=
~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
ctrl |= BMCR_RESET;
switch (mii_info->speed) {
case SPEED_1000:
if (features & (SUPPORTED_1000baseT_Half
| SUPPORTED_1000baseT_Full)) {
ctrl |= BMCR_SPEED1000;
break;
}
mii_info->speed = SPEED_100;
case SPEED_100:
if (features & (SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full)) {
ctrl |= BMCR_SPEED100;
break;
}
mii_info->speed = SPEED_10;
case SPEED_10:
if (features & (SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full))
break;
default: /* Unsupported speed! */
ugphy_err("%s: Bad speed!", mii_info->dev->name);
break;
}
phy_write(mii_info, MII_BMCR, ctrl);
}
/* Enable and Restart Autonegotiation */
static void genmii_restart_aneg(struct ugeth_mii_info *mii_info)
{
u16 ctl;
ugphy_vdbg("%s: IN", __FUNCTION__);
ctl = phy_read(mii_info, MII_BMCR);
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
phy_write(mii_info, MII_BMCR, ctl);
}
static int gbit_config_aneg(struct ugeth_mii_info *mii_info)
{
u16 adv;
u32 advertise;
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->autoneg) {
/* Configure the ADVERTISE register */
config_genmii_advert(mii_info);
advertise = mii_info->advertising;
adv = phy_read(mii_info, MII_1000BASETCONTROL);
adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
MII_1000BASETCONTROL_HALFDUPLEXCAP);
if (advertise & SUPPORTED_1000baseT_Half)
adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
if (advertise & SUPPORTED_1000baseT_Full)
adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
phy_write(mii_info, MII_1000BASETCONTROL, adv);
/* Start/Restart aneg */
genmii_restart_aneg(mii_info);
} else
genmii_setup_forced(mii_info);
return 0;
}
static int genmii_config_aneg(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->autoneg) {
config_genmii_advert(mii_info);
genmii_restart_aneg(mii_info);
} else
genmii_setup_forced(mii_info);
return 0;
}
static int genmii_update_link(struct ugeth_mii_info *mii_info)
{
u16 status;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Do a fake read */
phy_read(mii_info, MII_BMSR);
/* Read link and autonegotiation status */
status = phy_read(mii_info, MII_BMSR);
if ((status & BMSR_LSTATUS) == 0)
mii_info->link = 0;
else
mii_info->link = 1;
/* If we are autonegotiating, and not done,
* return an error */
if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
return -EAGAIN;
return 0;
}
static int genmii_read_status(struct ugeth_mii_info *mii_info)
{
u16 status;
int err;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Update the link, but return if there
* was an error */
err = genmii_update_link(mii_info);
if (err)
return err;
if (mii_info->autoneg) {
status = phy_read(mii_info, MII_LPA);
if (status & (LPA_10FULL | LPA_100FULL))
mii_info->duplex = DUPLEX_FULL;
else
mii_info->duplex = DUPLEX_HALF;
if (status & (LPA_100FULL | LPA_100HALF))
mii_info->speed = SPEED_100;
else
mii_info->speed = SPEED_10;
mii_info->pause = 0;
}
/* On non-aneg, we assume what we put in BMCR is the speed,
* though magic-aneg shouldn't prevent this case from occurring
*/
return 0;
}
static int marvell_init(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
phy_write(mii_info, 0x14, 0x0cd2);
phy_write(mii_info, MII_BMCR,
phy_read(mii_info, MII_BMCR) | BMCR_RESET);
msleep(4000);
return 0;
}
static int marvell_config_aneg(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
/* The Marvell PHY has an errata which requires
* that certain registers get written in order
* to restart autonegotiation */
phy_write(mii_info, MII_BMCR, BMCR_RESET);
phy_write(mii_info, 0x1d, 0x1f);
phy_write(mii_info, 0x1e, 0x200c);
phy_write(mii_info, 0x1d, 0x5);
phy_write(mii_info, 0x1e, 0);
phy_write(mii_info, 0x1e, 0x100);
gbit_config_aneg(mii_info);
return 0;
}
static int marvell_read_status(struct ugeth_mii_info *mii_info)
{
u16 status;
int err;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Update the link, but return if there
* was an error */
err = genmii_update_link(mii_info);
if (err)
return err;
/* If the link is up, read the speed and duplex */
/* If we aren't autonegotiating, assume speeds
* are as set */
if (mii_info->autoneg && mii_info->link) {
int speed;
status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
/* Get the duplexity */
if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
mii_info->duplex = DUPLEX_FULL;
else
mii_info->duplex = DUPLEX_HALF;
/* Get the speed */
speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
switch (speed) {
case MII_M1011_PHY_SPEC_STATUS_1000:
mii_info->speed = SPEED_1000;
break;
case MII_M1011_PHY_SPEC_STATUS_100:
mii_info->speed = SPEED_100;
break;
default:
mii_info->speed = SPEED_10;
break;
}
mii_info->pause = 0;
}
return 0;
}
static int marvell_ack_interrupt(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Clear the interrupts by reading the reg */
phy_read(mii_info, MII_M1011_IEVENT);
return 0;
}
static int marvell_config_intr(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
else
phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
return 0;
}
static int cis820x_init(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
MII_CIS8201_AUXCONSTAT_INIT);
phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
return 0;
}
static int cis820x_read_status(struct ugeth_mii_info *mii_info)
{
u16 status;
int err;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Update the link, but return if there
* was an error */
err = genmii_update_link(mii_info);
if (err)
return err;
/* If the link is up, read the speed and duplex */
/* If we aren't autonegotiating, assume speeds
* are as set */
if (mii_info->autoneg && mii_info->link) {
int speed;
status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
mii_info->duplex = DUPLEX_FULL;
else
mii_info->duplex = DUPLEX_HALF;
speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
switch (speed) {
case MII_CIS8201_AUXCONSTAT_GBIT:
mii_info->speed = SPEED_1000;
break;
case MII_CIS8201_AUXCONSTAT_100:
mii_info->speed = SPEED_100;
break;
default:
mii_info->speed = SPEED_10;
break;
}
}
return 0;
}
static int cis820x_ack_interrupt(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
phy_read(mii_info, MII_CIS8201_ISTAT);
return 0;
}
static int cis820x_config_intr(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
else
phy_write(mii_info, MII_CIS8201_IMASK, 0);
return 0;
}
#define DM9161_DELAY 10
static int dm9161_read_status(struct ugeth_mii_info *mii_info)
{
u16 status;
int err;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Update the link, but return if there
* was an error */
err = genmii_update_link(mii_info);
if (err)
return err;
/* If the link is up, read the speed and duplex */
/* If we aren't autonegotiating, assume speeds
* are as set */
if (mii_info->autoneg && mii_info->link) {
status = phy_read(mii_info, MII_DM9161_SCSR);
if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
mii_info->speed = SPEED_100;
else
mii_info->speed = SPEED_10;
if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
mii_info->duplex = DUPLEX_FULL;
else
mii_info->duplex = DUPLEX_HALF;
}
return 0;
}
static int dm9161_config_aneg(struct ugeth_mii_info *mii_info)
{
struct dm9161_private *priv = mii_info->priv;
ugphy_vdbg("%s: IN", __FUNCTION__);
if (0 == priv->resetdone)
return -EAGAIN;
return 0;
}
static void dm9161_timer(unsigned long data)
{
struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
struct dm9161_private *priv = mii_info->priv;
u16 status = phy_read(mii_info, MII_BMSR);
ugphy_vdbg("%s: IN", __FUNCTION__);
if (status & BMSR_ANEGCOMPLETE) {
priv->resetdone = 1;
} else
mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
}
static int dm9161_init(struct ugeth_mii_info *mii_info)
{
struct dm9161_private *priv;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Allocate the private data structure */
priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
if (NULL == priv)
return -ENOMEM;
mii_info->priv = priv;
/* Reset is not done yet */
priv->resetdone = 0;
phy_write(mii_info, MII_BMCR,
phy_read(mii_info, MII_BMCR) | BMCR_RESET);
phy_write(mii_info, MII_BMCR,
phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
config_genmii_advert(mii_info);
/* Start/Restart aneg */
genmii_config_aneg(mii_info);
/* Start a timer for DM9161_DELAY seconds to wait
* for the PHY to be ready */
init_timer(&priv->timer);
priv->timer.function = &dm9161_timer;
priv->timer.data = (unsigned long)mii_info;
mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
return 0;
}
static void dm9161_close(struct ugeth_mii_info *mii_info)
{
struct dm9161_private *priv = mii_info->priv;
ugphy_vdbg("%s: IN", __FUNCTION__);
del_timer_sync(&priv->timer);
kfree(priv);
}
static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info)
{
/* FIXME: This lines are for BUG fixing in the mpc8325.
Remove this from here when it's fixed */
if (bcsr_regs == NULL)
bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
bcsr_regs[14] |= 0x40;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Clear the interrupts by reading the reg */
phy_read(mii_info, MII_DM9161_INTR);
return 0;
}
static int dm9161_config_intr(struct ugeth_mii_info *mii_info)
{
/* FIXME: This lines are for BUG fixing in the mpc8325.
Remove this from here when it's fixed */
if (bcsr_regs == NULL) {
bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
bcsr_regs[14] &= ~0x40;
}
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
else
phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
return 0;
}
/* Cicada 820x */
static struct phy_info phy_info_cis820x = {
.phy_id = 0x000fc440,
.name = "Cicada Cis8204",
.phy_id_mask = 0x000fffc0,
.features = MII_GBIT_FEATURES,
.init = &cis820x_init,
.config_aneg = &gbit_config_aneg,
.read_status = &cis820x_read_status,
.ack_interrupt = &cis820x_ack_interrupt,
.config_intr = &cis820x_config_intr,
};
static struct phy_info phy_info_dm9161 = {
.phy_id = 0x0181b880,
.phy_id_mask = 0x0ffffff0,
.name = "Davicom DM9161E",
.init = dm9161_init,
.config_aneg = dm9161_config_aneg,
.read_status = dm9161_read_status,
.close = dm9161_close,
};
static struct phy_info phy_info_dm9161a = {
.phy_id = 0x0181b8a0,
.phy_id_mask = 0x0ffffff0,
.name = "Davicom DM9161A",
.features = MII_BASIC_FEATURES,
.init = dm9161_init,
.config_aneg = dm9161_config_aneg,
.read_status = dm9161_read_status,
.ack_interrupt = dm9161_ack_interrupt,
.config_intr = dm9161_config_intr,
.close = dm9161_close,
};
static struct phy_info phy_info_marvell = {
.phy_id = 0x01410c00,
.phy_id_mask = 0xffffff00,
.name = "Marvell 88E11x1",
.features = MII_GBIT_FEATURES,
.init = &marvell_init,
.config_aneg = &marvell_config_aneg,
.read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
};
static struct phy_info phy_info_genmii = {
.phy_id = 0x00000000,
.phy_id_mask = 0x00000000,
.name = "Generic MII",
.features = MII_BASIC_FEATURES,
.config_aneg = genmii_config_aneg,
.read_status = genmii_read_status,
};
static struct phy_info *phy_info[] = {
&phy_info_cis820x,
&phy_info_marvell,
&phy_info_dm9161,
&phy_info_dm9161a,
&phy_info_genmii,
NULL
};
u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
{
u16 retval;
unsigned long flags;
ugphy_vdbg("%s: IN", __FUNCTION__);
spin_lock_irqsave(&mii_info->mdio_lock, flags);
retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
return retval;
}
void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
{
unsigned long flags;
ugphy_vdbg("%s: IN", __FUNCTION__);
spin_lock_irqsave(&mii_info->mdio_lock, flags);
mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
}
/* Use the PHY ID registers to determine what type of PHY is attached
* to device dev. return a struct phy_info structure describing that PHY
*/
struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info)
{
u16 phy_reg;
u32 phy_ID;
int i;
struct phy_info *theInfo = NULL;
struct net_device *dev = mii_info->dev;
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Grab the bits from PHYIR1, and put them in the upper half */
phy_reg = phy_read(mii_info, MII_PHYSID1);
phy_ID = (phy_reg & 0xffff) << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
phy_reg = phy_read(mii_info, MII_PHYSID2);
phy_ID |= (phy_reg & 0xffff);
/* loop through all the known PHY types, and find one that */
/* matches the ID we read from the PHY. */
for (i = 0; phy_info[i]; i++)
if (phy_info[i]->phy_id == (phy_ID & phy_info[i]->phy_id_mask)){
theInfo = phy_info[i];
break;
}
/* This shouldn't happen, as we have generic PHY support */
if (theInfo == NULL) {
ugphy_info("%s: PHY id %x is not supported!", dev->name,
phy_ID);
return NULL;
} else {
ugphy_info("%s: PHY is %s (%x)", dev->name, theInfo->name,
phy_ID);
}
return theInfo;
}

217
drivers/net/ucc_geth_phy.h Normal file
View File

@ -0,0 +1,217 @@
/*
* Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
*
* Author: Shlomi Gridish <gridish@freescale.com>
*
* Description:
* UCC GETH Driver -- PHY handling
*
* Changelog:
* Jun 28, 2006 Li Yang <LeoLi@freescale.com>
* - Rearrange code and style fixes
*
* 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.
*
*/
#ifndef __UCC_GETH_PHY_H__
#define __UCC_GETH_PHY_H__
#define MII_end ((u32)-2)
#define MII_read ((u32)-1)
#define MIIMIND_BUSY 0x00000001
#define MIIMIND_NOTVALID 0x00000004
#define UGETH_AN_TIMEOUT 2000
/* 1000BT control (Marvell & BCM54xx at least) */
#define MII_1000BASETCONTROL 0x09
#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200
#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100
/* Cicada Extended Control Register 1 */
#define MII_CIS8201_EXT_CON1 0x17
#define MII_CIS8201_EXTCON1_INIT 0x0000
/* Cicada Interrupt Mask Register */
#define MII_CIS8201_IMASK 0x19
#define MII_CIS8201_IMASK_IEN 0x8000
#define MII_CIS8201_IMASK_SPEED 0x4000
#define MII_CIS8201_IMASK_LINK 0x2000
#define MII_CIS8201_IMASK_DUPLEX 0x1000
#define MII_CIS8201_IMASK_MASK 0xf000
/* Cicada Interrupt Status Register */
#define MII_CIS8201_ISTAT 0x1a
#define MII_CIS8201_ISTAT_STATUS 0x8000
#define MII_CIS8201_ISTAT_SPEED 0x4000
#define MII_CIS8201_ISTAT_LINK 0x2000
#define MII_CIS8201_ISTAT_DUPLEX 0x1000
/* Cicada Auxiliary Control/Status Register */
#define MII_CIS8201_AUX_CONSTAT 0x1c
#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
#define MII_CIS8201_AUXCONSTAT_100 0x0008
/* 88E1011 PHY Status Register */
#define MII_M1011_PHY_SPEC_STATUS 0x11
#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000
#define MII_M1011_PHY_SPEC_STATUS_100 0x4000
#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400
#define MII_M1011_IEVENT 0x13
#define MII_M1011_IEVENT_CLEAR 0x0000
#define MII_M1011_IMASK 0x12
#define MII_M1011_IMASK_INIT 0x6400
#define MII_M1011_IMASK_CLEAR 0x0000
#define MII_DM9161_SCR 0x10
#define MII_DM9161_SCR_INIT 0x0610
/* DM9161 Specified Configuration and Status Register */
#define MII_DM9161_SCSR 0x11
#define MII_DM9161_SCSR_100F 0x8000
#define MII_DM9161_SCSR_100H 0x4000
#define MII_DM9161_SCSR_10F 0x2000
#define MII_DM9161_SCSR_10H 0x1000
/* DM9161 Interrupt Register */
#define MII_DM9161_INTR 0x15
#define MII_DM9161_INTR_PEND 0x8000
#define MII_DM9161_INTR_DPLX_MASK 0x0800
#define MII_DM9161_INTR_SPD_MASK 0x0400
#define MII_DM9161_INTR_LINK_MASK 0x0200
#define MII_DM9161_INTR_MASK 0x0100
#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
#define MII_DM9161_INTR_SPD_CHANGE 0x0008
#define MII_DM9161_INTR_LINK_CHANGE 0x0004
#define MII_DM9161_INTR_INIT 0x0000
#define MII_DM9161_INTR_STOP \
(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
| MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
/* DM9161 10BT Configuration/Status */
#define MII_DM9161_10BTCSR 0x12
#define MII_DM9161_10BTCSR_INIT 0x7800
#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
SUPPORTED_10baseT_Full | \
SUPPORTED_100baseT_Half | \
SUPPORTED_100baseT_Full | \
SUPPORTED_Autoneg | \
SUPPORTED_TP | \
SUPPORTED_MII)
#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
SUPPORTED_1000baseT_Half | \
SUPPORTED_1000baseT_Full)
#define MII_READ_COMMAND 0x00000001
#define MII_INTERRUPT_DISABLED 0x0
#define MII_INTERRUPT_ENABLED 0x1
/* Taken from mii_if_info and sungem_phy.h */
struct ugeth_mii_info {
/* Information about the PHY type */
/* And management functions */
struct phy_info *phyinfo;
ucc_mii_mng_t *mii_regs;
/* forced speed & duplex (no autoneg)
* partner speed & duplex & pause (autoneg)
*/
int speed;
int duplex;
int pause;
/* The most recently read link state */
int link;
/* Enabled Interrupts */
u32 interrupts;
u32 advertising;
int autoneg;
int mii_id;
/* private data pointer */
/* For use by PHYs to maintain extra state */
void *priv;
/* Provided by host chip */
struct net_device *dev;
/* A lock to ensure that only one thing can read/write
* the MDIO bus at a time */
spinlock_t mdio_lock;
/* Provided by ethernet driver */
int (*mdio_read) (struct net_device * dev, int mii_id, int reg);
void (*mdio_write) (struct net_device * dev, int mii_id, int reg,
int val);
};
/* struct phy_info: a structure which defines attributes for a PHY
*
* id will contain a number which represents the PHY. During
* startup, the driver will poll the PHY to find out what its
* UID--as defined by registers 2 and 3--is. The 32-bit result
* gotten from the PHY will be ANDed with phy_id_mask to
* discard any bits which may change based on revision numbers
* unimportant to functionality
*
* There are 6 commands which take a ugeth_mii_info structure.
* Each PHY must declare config_aneg, and read_status.
*/
struct phy_info {
u32 phy_id;
char *name;
unsigned int phy_id_mask;
u32 features;
/* Called to initialize the PHY */
int (*init) (struct ugeth_mii_info * mii_info);
/* Called to suspend the PHY for power */
int (*suspend) (struct ugeth_mii_info * mii_info);
/* Reconfigures autonegotiation (or disables it) */
int (*config_aneg) (struct ugeth_mii_info * mii_info);
/* Determines the negotiated speed and duplex */
int (*read_status) (struct ugeth_mii_info * mii_info);
/* Clears any pending interrupts */
int (*ack_interrupt) (struct ugeth_mii_info * mii_info);
/* Enables or disables interrupts */
int (*config_intr) (struct ugeth_mii_info * mii_info);
/* Clears up any memory if needed */
void (*close) (struct ugeth_mii_info * mii_info);
};
struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info);
void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info);
void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
u32 interrupts);
struct dm9161_private {
struct timer_list timer;
int resetdone;
};
#endif /* __UCC_GETH_PHY_H__ */

View File

@ -30,8 +30,8 @@
*/
#define DRV_NAME "via-rhine"
#define DRV_VERSION "1.4.0"
#define DRV_RELDATE "June-27-2006"
#define DRV_VERSION "1.4.1"
#define DRV_RELDATE "July-24-2006"
/* A few user-configurable values.
@ -44,6 +44,10 @@ static int max_interrupt_work = 20;
Setting to > 1518 effectively disables this feature. */
static int rx_copybreak;
/* Work-around for broken BIOSes: they are unable to get the chip back out of
power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */
static int avoid_D3;
/*
* In case you are looking for 'options[]' or 'full_duplex[]', they
* are gone. Use ethtool(8) instead.
@ -63,7 +67,11 @@ static const int multicast_filter_limit = 32;
There are no ill effects from too-large receive rings. */
#define TX_RING_SIZE 16
#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */
#ifdef CONFIG_VIA_RHINE_NAPI
#define RX_RING_SIZE 64
#else
#define RX_RING_SIZE 16
#endif
/* Operational parameters that usually are not changed. */
@ -116,9 +124,11 @@ MODULE_LICENSE("GPL");
module_param(max_interrupt_work, int, 0);
module_param(debug, int, 0);
module_param(rx_copybreak, int, 0);
module_param(avoid_D3, bool, 0);
MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
/*
Theory of Operation
@ -396,7 +406,7 @@ static void rhine_tx_timeout(struct net_device *dev);
static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
static void rhine_tx(struct net_device *dev);
static void rhine_rx(struct net_device *dev);
static int rhine_rx(struct net_device *dev, int limit);
static void rhine_error(struct net_device *dev, int intr_status);
static void rhine_set_rx_mode(struct net_device *dev);
static struct net_device_stats *rhine_get_stats(struct net_device *dev);
@ -564,6 +574,32 @@ static void rhine_poll(struct net_device *dev)
}
#endif
#ifdef CONFIG_VIA_RHINE_NAPI
static int rhine_napipoll(struct net_device *dev, int *budget)
{
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
int done, limit = min(dev->quota, *budget);
done = rhine_rx(dev, limit);
*budget -= done;
dev->quota -= done;
if (done < limit) {
netif_rx_complete(dev);
iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
IntrTxDone | IntrTxError | IntrTxUnderrun |
IntrPCIErr | IntrStatsMax | IntrLinkChange,
ioaddr + IntrEnable);
return 0;
}
else
return 1;
}
#endif
static void rhine_hw_init(struct net_device *dev, long pioaddr)
{
struct rhine_private *rp = netdev_priv(dev);
@ -743,6 +779,10 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
dev->watchdog_timeo = TX_TIMEOUT;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = rhine_poll;
#endif
#ifdef CONFIG_VIA_RHINE_NAPI
dev->poll = rhine_napipoll;
dev->weight = 64;
#endif
if (rp->quirks & rqRhineI)
dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
@ -789,6 +829,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
}
}
rp->mii_if.phy_id = phy_id;
if (debug > 1 && avoid_D3)
printk(KERN_INFO "%s: No D3 power state at shutdown.\n",
dev->name);
return 0;
@ -1014,6 +1057,8 @@ static void init_registers(struct net_device *dev)
rhine_set_rx_mode(dev);
netif_poll_enable(dev);
/* Enable interrupts by setting the interrupt mask. */
iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
@ -1268,8 +1313,18 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
dev->name, intr_status);
if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
rhine_rx(dev);
IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
#ifdef CONFIG_VIA_RHINE_NAPI
iowrite16(IntrTxAborted |
IntrTxDone | IntrTxError | IntrTxUnderrun |
IntrPCIErr | IntrStatsMax | IntrLinkChange,
ioaddr + IntrEnable);
netif_rx_schedule(dev);
#else
rhine_rx(dev, RX_RING_SIZE);
#endif
}
if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
if (intr_status & IntrTxErrSummary) {
@ -1367,13 +1422,12 @@ static void rhine_tx(struct net_device *dev)
spin_unlock(&rp->lock);
}
/* This routine is logically part of the interrupt handler, but isolated
for clarity and better register allocation. */
static void rhine_rx(struct net_device *dev)
/* Process up to limit frames from receive ring */
static int rhine_rx(struct net_device *dev, int limit)
{
struct rhine_private *rp = netdev_priv(dev);
int count;
int entry = rp->cur_rx % RX_RING_SIZE;
int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx;
if (debug > 4) {
printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n",
@ -1382,16 +1436,18 @@ static void rhine_rx(struct net_device *dev)
}
/* If EOP is set on the next entry, it's a new packet. Send it up. */
while (!(rp->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) {
for (count = 0; count < limit; ++count) {
struct rx_desc *desc = rp->rx_head_desc;
u32 desc_status = le32_to_cpu(desc->rx_status);
int data_size = desc_status >> 16;
if (desc_status & DescOwn)
break;
if (debug > 4)
printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n",
desc_status);
if (--boguscnt < 0)
break;
if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) {
if ((desc_status & RxWholePkt) != RxWholePkt) {
printk(KERN_WARNING "%s: Oversized Ethernet "
@ -1460,7 +1516,11 @@ static void rhine_rx(struct net_device *dev)
PCI_DMA_FROMDEVICE);
}
skb->protocol = eth_type_trans(skb, dev);
#ifdef CONFIG_VIA_RHINE_NAPI
netif_receive_skb(skb);
#else
netif_rx(skb);
#endif
dev->last_rx = jiffies;
rp->stats.rx_bytes += pkt_len;
rp->stats.rx_packets++;
@ -1487,6 +1547,8 @@ static void rhine_rx(struct net_device *dev)
}
rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
}
return count;
}
/*
@ -1776,6 +1838,7 @@ static int rhine_close(struct net_device *dev)
spin_lock_irq(&rp->lock);
netif_stop_queue(dev);
netif_poll_disable(dev);
if (debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard, "
@ -1857,7 +1920,8 @@ static void rhine_shutdown (struct pci_dev *pdev)
}
/* Hit power state D3 (sleep) */
iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
if (!avoid_D3)
iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
/* TODO: Check use of pci_enable_wake() */

View File

@ -118,7 +118,7 @@ static inline void openwin(card_t *card, u8 page)
static inline void set_carrier(port_t *port)
{
if (!sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD)
if (!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD))
netif_carrier_on(port_to_dev(port));
else
netif_carrier_off(port_to_dev(port));
@ -127,10 +127,10 @@ static inline void set_carrier(port_t *port)
static void sca_msci_intr(port_t *port)
{
u8 stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI ST1 status */
u8 stat = sca_in(MSCI0_OFFSET + ST1, port); /* read MSCI ST1 status */
/* Reset MSCI TX underrun status bit */
sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, port);
/* Reset MSCI TX underrun and CDCD (ignored) status bit */
sca_out(stat & (ST1_UDRN | ST1_CDCD), MSCI0_OFFSET + ST1, port);
if (stat & ST1_UDRN) {
struct net_device_stats *stats = hdlc_stats(port_to_dev(port));
@ -138,6 +138,7 @@ static void sca_msci_intr(port_t *port)
stats->tx_fifo_errors++;
}
stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI1 ST1 status */
/* Reset MSCI CDCD status bit - uses ch#2 DCD input */
sca_out(stat & ST1_CDCD, MSCI1_OFFSET + ST1, port);

View File

@ -500,8 +500,8 @@ MODULE_LICENSE("GPL");
/* This is set up so that only a single autoprobe takes place per call.
ISA device autoprobes on a running machine are not recommended. */
int
init_module(void)
int __init init_module(void)
{
struct net_device *dev;
int this_dev, found = 0;

View File

@ -1042,6 +1042,9 @@ static int prism2_reset_port(struct net_device *dev)
dev->name, local->fragm_threshold);
}
/* Some firmwares lose antenna selection settings on reset */
(void) hostap_set_antsel(local);
return res;
}

View File

@ -242,7 +242,7 @@ spectrum_reset(struct pcmcia_device *link, int idle)
u_int save_cor;
/* Doing it if hardware is gone is guaranteed crash */
if (pcmcia_dev_present(link))
if (!pcmcia_dev_present(link))
return -ENODEV;
/* Save original COR value */

View File

@ -8510,9 +8510,9 @@ static int
qeth_ipv6_init(void)
{
qeth_old_arp_constructor = arp_tbl.constructor;
write_lock(&arp_tbl.lock);
write_lock_bh(&arp_tbl.lock);
arp_tbl.constructor = qeth_arp_constructor;
write_unlock(&arp_tbl.lock);
write_unlock_bh(&arp_tbl.lock);
arp_direct_ops = (struct neigh_ops*)
kmalloc(sizeof(struct neigh_ops), GFP_KERNEL);
@ -8528,9 +8528,9 @@ qeth_ipv6_init(void)
static void
qeth_ipv6_uninit(void)
{
write_lock(&arp_tbl.lock);
write_lock_bh(&arp_tbl.lock);
arp_tbl.constructor = qeth_old_arp_constructor;
write_unlock(&arp_tbl.lock);
write_unlock_bh(&arp_tbl.lock);
kfree(arp_direct_ops);
}
#endif /* CONFIG_QETH_IPV6 */

View File

@ -1093,5 +1093,100 @@ typedef struct im_idma {
#define FCC_PSMR_RMII ((uint)0x00020000) /* Use RMII interface */
/* FCC iop & clock configuration. BSP code is responsible to define Fx_RXCLK & Fx_TXCLK
* in order to use clock-computing stuff below for the FCC x
*/
/* Automatically generates register configurations */
#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */
#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */
#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */
#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */
#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */
#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */
#define PC_F1RXCLK PC_CLK(F1_RXCLK)
#define PC_F1TXCLK PC_CLK(F1_TXCLK)
#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
#define CMX1_CLK_MASK ((uint)0xff000000)
#define PC_F2RXCLK PC_CLK(F2_RXCLK)
#define PC_F2TXCLK PC_CLK(F2_TXCLK)
#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
#define CMX2_CLK_MASK ((uint)0x00ff0000)
#define PC_F3RXCLK PC_CLK(F3_RXCLK)
#define PC_F3TXCLK PC_CLK(F3_TXCLK)
#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
#define CMX3_CLK_MASK ((uint)0x0000ff00)
#define CPMUX_CLK_MASK (CMX3_CLK_MASK | CMX2_CLK_MASK)
#define CPMUX_CLK_ROUTE (CMX3_CLK_ROUTE | CMX2_CLK_ROUTE)
#define CLK_TRX (PC_F3TXCLK | PC_F3RXCLK | PC_F2TXCLK | PC_F2RXCLK)
/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
* but there is little variation among the choices.
*/
#define PA1_COL 0x00000001U
#define PA1_CRS 0x00000002U
#define PA1_TXER 0x00000004U
#define PA1_TXEN 0x00000008U
#define PA1_RXDV 0x00000010U
#define PA1_RXER 0x00000020U
#define PA1_TXDAT 0x00003c00U
#define PA1_RXDAT 0x0003c000U
#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
PA1_RXDV | PA1_RXER)
#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
* but there is little variation among the choices.
*/
#define PB2_TXER 0x00000001U
#define PB2_RXDV 0x00000002U
#define PB2_TXEN 0x00000004U
#define PB2_RXER 0x00000008U
#define PB2_COL 0x00000010U
#define PB2_CRS 0x00000020U
#define PB2_TXDAT 0x000003c0U
#define PB2_RXDAT 0x00003c00U
#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
PB2_RXER | PB2_RXDV | PB2_TXER)
#define PB2_PSORB1 (PB2_TXEN)
#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
* but there is little variation among the choices.
*/
#define PB3_RXDV 0x00004000U
#define PB3_RXER 0x00008000U
#define PB3_TXER 0x00010000U
#define PB3_TXEN 0x00020000U
#define PB3_COL 0x00040000U
#define PB3_CRS 0x00080000U
#define PB3_TXDAT 0x0f000000U
#define PC3_TXDAT 0x00000010U
#define PB3_RXDAT 0x00f00000U
#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
#define PB3_PSORB1 0
#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
#define PC3_DIRC1 (PC3_TXDAT)
/* Handy macro to specify mem for FCCs*/
#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(2)
#endif /* __CPM2__ */
#endif /* __KERNEL__ */

View File

@ -82,6 +82,7 @@ enum ppc_sys_devices {
MPC82xx_CPM_SMC2,
MPC82xx_CPM_USB,
MPC82xx_SEC1,
MPC82xx_MDIO_BB,
NUM_PPC_SYS_DEVS,
};

View File

@ -110,6 +110,7 @@ enum ppc_sys_devices {
MPC8xx_CPM_SMC1,
MPC8xx_CPM_SMC2,
MPC8xx_CPM_USB,
MPC8xx_MDIO_FEC,
NUM_PPC_SYS_DEVS,
};

View File

@ -69,34 +69,21 @@ enum fs_ioport {
fsiop_porte,
};
struct fs_mii_bus_info {
int method; /* mii method */
int id; /* the id of the mii_bus */
int disable_aneg; /* if the controller needs to negothiate speed & duplex */
int lpa; /* the default board-specific vallues will be applied otherwise */
union {
struct {
int duplex;
int speed;
} fixed;
struct {
/* nothing */
} fec;
struct {
/* nothing */
} scc;
struct {
int mdio_port; /* port & bit for MDIO */
int mdio_bit;
int mdc_port; /* port & bit for MDC */
int mdc_bit;
int delay; /* delay in us */
} bitbang;
} i;
struct fs_mii_bit {
u32 offset;
u8 bit;
u8 polarity;
};
struct fs_mii_bb_platform_info {
struct fs_mii_bit mdio_dir;
struct fs_mii_bit mdio_dat;
struct fs_mii_bit mdc_dat;
int mdio_port; /* port & bit for MDIO */
int mdio_bit;
int mdc_port; /* port & bit for MDC */
int mdc_bit;
int delay; /* delay in us */
int irq[32]; /* irqs per phy's */
};
struct fs_platform_info {
@ -119,6 +106,7 @@ struct fs_platform_info {
u32 device_flags;
int phy_addr; /* the phy address (-1 no phy) */
const char* bus_id;
int phy_irq; /* the phy irq (if it exists) */
const struct fs_mii_bus_info *bus_info;
@ -130,6 +118,10 @@ struct fs_platform_info {
int napi_weight; /* NAPI weight */
int use_rmii; /* use RMII mode */
int has_phy; /* if the network is phy container as well...*/
};
struct fs_mii_fec_platform_info {
u32 irq[32];
u32 mii_speed;
};
#endif

View File

@ -378,6 +378,7 @@ int phy_mii_ioctl(struct phy_device *phydev,
struct mii_ioctl_data *mii_data, int cmd);
int phy_start_interrupts(struct phy_device *phydev);
void phy_print_status(struct phy_device *phydev);
struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
extern struct bus_type mdio_bus_type;
#endif /* __PHY_H */