mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
Merge branch 'upstream-fixes' into upstream
This commit is contained in:
commit
846050dd49
74 changed files with 8617 additions and 1584 deletions
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -899,7 +899,7 @@ static inline int i596_rx(struct net_device *dev)
|
|||
}
|
||||
|
||||
|
||||
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__
|
||||
|
|
|
@ -1740,6 +1740,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
|
||||
|
@ -2235,6 +2249,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
|
||||
|
|
|
@ -14,6 +14,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
|
||||
#
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
||||
|
|
|
@ -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
42
drivers/net/fs_enet/fec.h
Normal 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
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
243
drivers/net/fs_enet/mii-fec.c
Normal file
243
drivers/net/fs_enet/mii-fec.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
358
drivers/net/phy/fixed.c
Normal 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);
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -1090,6 +1090,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -184,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>
|
||||
|
@ -367,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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -109,7 +109,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";
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 @@ static struct net_device *setup_card(int n)
|
|||
free_netdev(dev);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
||||
int init_module(void)
|
||||
int __init init_module(void)
|
||||
{
|
||||
int i, found = 0;
|
||||
struct net_device *dev;
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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
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
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
801
drivers/net/ucc_geth_phy.c
Normal 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
217
drivers/net/ucc_geth_phy.h
Normal 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__ */
|
|
@ -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() */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -82,6 +82,7 @@ enum ppc_sys_devices {
|
|||
MPC82xx_CPM_SMC2,
|
||||
MPC82xx_CPM_USB,
|
||||
MPC82xx_SEC1,
|
||||
MPC82xx_MDIO_BB,
|
||||
NUM_PPC_SYS_DEVS,
|
||||
};
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ enum ppc_sys_devices {
|
|||
MPC8xx_CPM_SMC1,
|
||||
MPC8xx_CPM_SMC2,
|
||||
MPC8xx_CPM_USB,
|
||||
MPC8xx_MDIO_FEC,
|
||||
NUM_PPC_SYS_DEVS,
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue