提交 37448f7d 编写于 作者: E Eugene Surovegin 提交者: Jeff Garzik

[PATCH] New PowerPC 4xx on-chip ethernet controller driver

This patch replaces current PowerPC 4xx EMAC driver with
new, re-written from the scratch version. This patch is quite big
(~234K) because there is virtualy 0% of common code between old and
new version.

New driver uses NAPI, it solves stability problems under heavy packet
load and low memory, corrects chip register access and fixes numerous
small bugs I don't even remember now.

This patch has been tested on all supported in 2.6 PPC 4xx boards.
It's been used in production for almost a year now on custom
4xx hardware. PPC32 specific parts are already upstream.

Patch was acked by the current EMAC driver maintainer (Matt Porter). I
will be maintaining this new version.
Signed-off-by: NEugene Surovegin <ebs@ebshome.net>
--

 Kconfig                   |   72
 ibm_emac/Makefile         |   13
 ibm_emac/ibm_emac.h       |  418 +++--
 ibm_emac/ibm_emac_core.c  | 3414 ++++++++++++++++++++++++----------------------
 ibm_emac/ibm_emac_core.h  |  313 ++--
 ibm_emac/ibm_emac_debug.c |  377 ++---
 ibm_emac/ibm_emac_debug.h |   63
 ibm_emac/ibm_emac_mal.c   |  674 +++++----
 ibm_emac/ibm_emac_mal.h   |  336 +++-
 ibm_emac/ibm_emac_phy.c   |  335 ++--
 ibm_emac/ibm_emac_phy.h   |  105 -
 ibm_emac/ibm_emac_rgmii.c |  201 ++
 ibm_emac/ibm_emac_rgmii.h |   68
 ibm_emac/ibm_emac_tah.c   |  111 +
 ibm_emac/ibm_emac_tah.h   |   96 -
 ibm_emac/ibm_emac_zmii.c  |  255 +++
 ibm_emac/ibm_emac_zmii.h  |  114 -
 17 files changed, 4114 insertions(+), 2851 deletions(-)
Signed-off-by: NJeff Garzik <jgarzik@pobox.com>
上级 b71b95ef
......@@ -1163,38 +1163,74 @@ config IBMVETH
be called ibmveth.
config IBM_EMAC
bool "IBM PPC4xx EMAC driver support"
tristate "PowerPC 4xx on-chip Ethernet support"
depends on 4xx
select CRC32
---help---
This driver supports the IBM PPC4xx EMAC family of on-chip
Ethernet controllers.
config IBM_EMAC_ERRMSG
bool "Verbose error messages"
depends on IBM_EMAC && BROKEN
help
This driver supports the PowerPC 4xx EMAC family of on-chip
Ethernet controllers.
config IBM_EMAC_RXB
int "Number of receive buffers"
depends on IBM_EMAC
default "128" if IBM_EMAC4
default "64"
default "128"
config IBM_EMAC_TXB
int "Number of transmit buffers"
depends on IBM_EMAC
default "128" if IBM_EMAC4
default "8"
default "64"
config IBM_EMAC_POLL_WEIGHT
int "MAL NAPI polling weight"
depends on IBM_EMAC
default "32"
config IBM_EMAC_FGAP
int "Frame gap"
config IBM_EMAC_RX_COPY_THRESHOLD
int "RX skb copy threshold (bytes)"
depends on IBM_EMAC
default "8"
default "256"
config IBM_EMAC_SKBRES
int "Skb reserve amount"
config IBM_EMAC_RX_SKB_HEADROOM
int "Additional RX skb headroom (bytes)"
depends on IBM_EMAC
default "0"
help
Additional receive skb headroom. Note, that driver
will always reserve at least 2 bytes to make IP header
aligned, so usualy there is no need to add any additional
headroom.
If unsure, set to 0.
config IBM_EMAC_PHY_RX_CLK_FIX
bool "PHY Rx clock workaround"
depends on IBM_EMAC && (405EP || 440GX || 440EP)
help
Enable this if EMAC attached to a PHY which doesn't generate
RX clock if there is no link, if this is the case, you will
see "TX disable timeout" or "RX disable timeout" in the system
log.
If unsure, say N.
config IBM_EMAC_DEBUG
bool "Debugging"
depends on IBM_EMAC
default n
config IBM_EMAC_ZMII
bool
depends on IBM_EMAC && (NP405H || NP405L || 44x)
default y
config IBM_EMAC_RGMII
bool
depends on IBM_EMAC && 440GX
default y
config IBM_EMAC_TAH
bool
depends on IBM_EMAC && 440GX
default y
config NET_PCI
bool "EISA, VLB, PCI and on board controllers"
......
#
# Makefile for the IBM PPC4xx EMAC controllers
# Makefile for the PowerPC 4xx on-chip ethernet driver
#
obj-$(CONFIG_IBM_EMAC) += ibm_emac.o
ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o
# Only need this if you want to see additional debug messages
ifeq ($(CONFIG_IBM_EMAC_ERRMSG), y)
ibm_emac-objs += ibm_emac_debug.o
endif
ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o
ibm_emac-$(CONFIG_IBM_EMAC_ZMII) += ibm_emac_zmii.o
ibm_emac-$(CONFIG_IBM_EMAC_RGMII) += ibm_emac_rgmii.o
ibm_emac-$(CONFIG_IBM_EMAC_TAH) += ibm_emac_tah.o
ibm_emac-$(CONFIG_IBM_EMAC_DEBUG) += ibm_emac_debug.o
/*
* ibm_emac.h
* drivers/net/ibm_emac/ibm_emac.h
*
* Register definitions for PowerPC 4xx on-chip ethernet contoller
*
* Armin Kuster akuster@mvista.com
* June, 2002
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
* Copyright 2002 MontaVista Softare Inc.
* Based on original work by
* Matt Porter <mporter@kernel.crashing.org>
* Armin Kuster <akuster@mvista.com>
* Copyright 2002-2004 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.
*
*/
#ifndef __IBM_EMAC_H_
#define __IBM_EMAC_H_
#include <linux/config.h>
#include <linux/types.h>
/* This is a simple check to prevent use of this driver on non-tested SoCs */
#if !defined(CONFIG_405GP) && !defined(CONFIG_405GPR) && !defined(CONFIG_405EP) && \
!defined(CONFIG_440GP) && !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && \
!defined(CONFIG_440EP) && !defined(CONFIG_NP405H)
#error "Unknown SoC. Please, check chip user manual and make sure EMAC defines are OK"
#endif
/* EMAC registers Write Access rules */
struct emac_regs {
u32 mr0; /* special */
u32 mr1; /* Reset */
u32 tmr0; /* special */
u32 tmr1; /* special */
u32 rmr; /* Reset */
u32 isr; /* Always */
u32 iser; /* Reset */
u32 iahr; /* Reset, R, T */
u32 ialr; /* Reset, R, T */
u32 vtpid; /* Reset, R, T */
u32 vtci; /* Reset, R, T */
u32 ptr; /* Reset, T */
u32 iaht1; /* Reset, R */
u32 iaht2; /* Reset, R */
u32 iaht3; /* Reset, R */
u32 iaht4; /* Reset, R */
u32 gaht1; /* Reset, R */
u32 gaht2; /* Reset, R */
u32 gaht3; /* Reset, R */
u32 gaht4; /* Reset, R */
u32 lsah;
u32 lsal;
u32 ipgvr; /* Reset, T */
u32 stacr; /* special */
u32 trtr; /* special */
u32 rwmr; /* Reset */
u32 octx;
u32 ocrx;
u32 ipcr;
};
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_ETHTOOL_REGS_VER 0
#define EMAC_ETHTOOL_REGS_SIZE (sizeof(struct emac_regs) - sizeof(u32))
#else
#define EMAC_ETHTOOL_REGS_VER 1
#define EMAC_ETHTOOL_REGS_SIZE sizeof(struct emac_regs)
#endif
#ifndef _IBM_EMAC_H_
#define _IBM_EMAC_H_
/* General defines needed for the driver */
/* EMACx_MR0 */
#define EMAC_MR0_RXI 0x80000000
#define EMAC_MR0_TXI 0x40000000
#define EMAC_MR0_SRST 0x20000000
#define EMAC_MR0_TXE 0x10000000
#define EMAC_MR0_RXE 0x08000000
#define EMAC_MR0_WKE 0x04000000
/* Emac */
typedef struct emac_regs {
u32 em0mr0;
u32 em0mr1;
u32 em0tmr0;
u32 em0tmr1;
u32 em0rmr;
u32 em0isr;
u32 em0iser;
u32 em0iahr;
u32 em0ialr;
u32 em0vtpid;
u32 em0vtci;
u32 em0ptr;
u32 em0iaht1;
u32 em0iaht2;
u32 em0iaht3;
u32 em0iaht4;
u32 em0gaht1;
u32 em0gaht2;
u32 em0gaht3;
u32 em0gaht4;
u32 em0lsah;
u32 em0lsal;
u32 em0ipgvr;
u32 em0stacr;
u32 em0trtr;
u32 em0rwmr;
} emac_t;
/* EMACx_MR1 */
#define EMAC_MR1_FDE 0x80000000
#define EMAC_MR1_ILE 0x40000000
#define EMAC_MR1_VLE 0x20000000
#define EMAC_MR1_EIFC 0x10000000
#define EMAC_MR1_APP 0x08000000
#define EMAC_MR1_IST 0x01000000
/* MODE REG 0 */
#define EMAC_M0_RXI 0x80000000
#define EMAC_M0_TXI 0x40000000
#define EMAC_M0_SRST 0x20000000
#define EMAC_M0_TXE 0x10000000
#define EMAC_M0_RXE 0x08000000
#define EMAC_M0_WKE 0x04000000
#define EMAC_MR1_MF_MASK 0x00c00000
#define EMAC_MR1_MF_10 0x00000000
#define EMAC_MR1_MF_100 0x00400000
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_MR1_MF_1000 0x00000000
#define EMAC_MR1_MF_1000GPCS 0x00000000
#define EMAC_MR1_MF_IPPA(id) 0x00000000
#else
#define EMAC_MR1_MF_1000 0x00800000
#define EMAC_MR1_MF_1000GPCS 0x00c00000
#define EMAC_MR1_MF_IPPA(id) (((id) & 0x1f) << 6)
#endif
/* MODE Reg 1 */
#define EMAC_M1_FDE 0x80000000
#define EMAC_M1_ILE 0x40000000
#define EMAC_M1_VLE 0x20000000
#define EMAC_M1_EIFC 0x10000000
#define EMAC_M1_APP 0x08000000
#define EMAC_M1_AEMI 0x02000000
#define EMAC_M1_IST 0x01000000
#define EMAC_M1_MF_1000GPCS 0x00c00000 /* Internal GPCS */
#define EMAC_M1_MF_1000MBPS 0x00800000 /* External GPCS */
#define EMAC_M1_MF_100MBPS 0x00400000
#define EMAC_M1_RFS_16K 0x00280000 /* 000 for 512 byte */
#define EMAC_M1_TR 0x00008000
#ifdef CONFIG_IBM_EMAC4
#define EMAC_M1_RFS_8K 0x00200000
#define EMAC_M1_RFS_4K 0x00180000
#define EMAC_M1_RFS_2K 0x00100000
#define EMAC_M1_RFS_1K 0x00080000
#define EMAC_M1_TX_FIFO_16K 0x00050000 /* 0's for 512 byte */
#define EMAC_M1_TX_FIFO_8K 0x00040000
#define EMAC_M1_TX_FIFO_4K 0x00030000
#define EMAC_M1_TX_FIFO_2K 0x00020000
#define EMAC_M1_TX_FIFO_1K 0x00010000
#define EMAC_M1_TX_TR 0x00008000
#define EMAC_M1_TX_MWSW 0x00001000 /* 0 wait for status */
#define EMAC_M1_JUMBO_ENABLE 0x00000800 /* Upt to 9Kr status */
#define EMAC_M1_OPB_CLK_66 0x00000008 /* 66Mhz */
#define EMAC_M1_OPB_CLK_83 0x00000010 /* 83Mhz */
#define EMAC_M1_OPB_CLK_100 0x00000018 /* 100Mhz */
#define EMAC_M1_OPB_CLK_100P 0x00000020 /* 100Mhz+ */
#else /* CONFIG_IBM_EMAC4 */
#define EMAC_M1_RFS_4K 0x00300000 /* ~4k for 512 byte */
#define EMAC_M1_RFS_2K 0x00200000
#define EMAC_M1_RFS_1K 0x00100000
#define EMAC_M1_TX_FIFO_2K 0x00080000 /* 0's for 512 byte */
#define EMAC_M1_TX_FIFO_1K 0x00040000
#define EMAC_M1_TR0_DEPEND 0x00010000 /* 0'x for single packet */
#define EMAC_M1_TR1_DEPEND 0x00004000
#define EMAC_M1_TR1_MULTI 0x00002000
#define EMAC_M1_JUMBO_ENABLE 0x00001000
#endif /* CONFIG_IBM_EMAC4 */
#define EMAC_M1_BASE (EMAC_M1_TX_FIFO_2K | \
EMAC_M1_APP | \
EMAC_M1_TR | EMAC_M1_VLE)
#define EMAC_TX_FIFO_SIZE 2048
/* Transmit Mode Register 0 */
#define EMAC_TMR0_GNP0 0x80000000
#define EMAC_TMR0_GNP1 0x40000000
#define EMAC_TMR0_GNPD 0x20000000
#define EMAC_TMR0_FC 0x10000000
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_MR1_RFS_4K 0x00300000
#define EMAC_MR1_RFS_16K 0x00000000
#define EMAC_RX_FIFO_SIZE(gige) 4096
#define EMAC_MR1_TFS_2K 0x00080000
#define EMAC_MR1_TR0_MULT 0x00008000
#define EMAC_MR1_JPSM 0x00000000
#define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR0_MULT)
#else
#define EMAC_MR1_RFS_4K 0x00180000
#define EMAC_MR1_RFS_16K 0x00280000
#define EMAC_RX_FIFO_SIZE(gige) ((gige) ? 16384 : 4096)
#define EMAC_MR1_TFS_2K 0x00020000
#define EMAC_MR1_TR 0x00008000
#define EMAC_MR1_MWSW_001 0x00001000
#define EMAC_MR1_JPSM 0x00000800
#define EMAC_MR1_OBCI_MASK 0x00000038
#define EMAC_MR1_OBCI_50 0x00000000
#define EMAC_MR1_OBCI_66 0x00000008
#define EMAC_MR1_OBCI_83 0x00000010
#define EMAC_MR1_OBCI_100 0x00000018
#define EMAC_MR1_OBCI_100P 0x00000020
#define EMAC_MR1_OBCI(freq) ((freq) <= 50 ? EMAC_MR1_OBCI_50 : \
(freq) <= 66 ? EMAC_MR1_OBCI_66 : \
(freq) <= 83 ? EMAC_MR1_OBCI_83 : \
(freq) <= 100 ? EMAC_MR1_OBCI_100 : EMAC_MR1_OBCI_100P)
#define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR | \
EMAC_MR1_MWSW_001 | EMAC_MR1_OBCI(opb))
#endif
/* EMACx_TMR0 */
#define EMAC_TMR0_GNP 0x80000000
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_TMR0_DEFAULT 0x00000000
#else
#define EMAC_TMR0_TFAE_2_32 0x00000001
#define EMAC_TMR0_TFAE_4_64 0x00000002
#define EMAC_TMR0_TFAE_8_128 0x00000003
......@@ -112,14 +144,36 @@ typedef struct emac_regs {
#define EMAC_TMR0_TFAE_32_512 0x00000005
#define EMAC_TMR0_TFAE_64_1024 0x00000006
#define EMAC_TMR0_TFAE_128_2048 0x00000007
#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_2_32
#endif
#define EMAC_TMR0_XMIT (EMAC_TMR0_GNP | EMAC_TMR0_DEFAULT)
/* EMACx_TMR1 */
/* IBM manuals are not very clear here.
* This is my interpretation of how things are. --ebs
*/
#if defined(CONFIG_40x)
#define EMAC_FIFO_ENTRY_SIZE 8
#define EMAC_MAL_BURST_SIZE (16 * 4)
#else
#define EMAC_FIFO_ENTRY_SIZE 16
#define EMAC_MAL_BURST_SIZE (64 * 4)
#endif
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_TMR1(l,h) (((l) << 27) | (((h) & 0xff) << 16))
#else
#define EMAC_TMR1(l,h) (((l) << 27) | (((h) & 0x3ff) << 14))
#endif
/* Receive Mode Register */
/* EMACx_RMR */
#define EMAC_RMR_SP 0x80000000
#define EMAC_RMR_SFCS 0x40000000
#define EMAC_RMR_ARRP 0x20000000
#define EMAC_RMR_ARP 0x10000000
#define EMAC_RMR_AROP 0x08000000
#define EMAC_RMR_ARPI 0x04000000
#define EMAC_RMR_RRP 0x20000000
#define EMAC_RMR_RFP 0x10000000
#define EMAC_RMR_ROP 0x08000000
#define EMAC_RMR_RPIR 0x04000000
#define EMAC_RMR_PPP 0x02000000
#define EMAC_RMR_PME 0x01000000
#define EMAC_RMR_PMME 0x00800000
......@@ -127,6 +181,9 @@ typedef struct emac_regs {
#define EMAC_RMR_MIAE 0x00200000
#define EMAC_RMR_BAE 0x00100000
#define EMAC_RMR_MAE 0x00080000
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_RMR_BASE 0x00000000
#else
#define EMAC_RMR_RFAF_2_32 0x00000001
#define EMAC_RMR_RFAF_4_64 0x00000002
#define EMAC_RMR_RFAF_8_128 0x00000003
......@@ -134,9 +191,21 @@ typedef struct emac_regs {
#define EMAC_RMR_RFAF_32_512 0x00000005
#define EMAC_RMR_RFAF_64_1024 0x00000006
#define EMAC_RMR_RFAF_128_2048 0x00000007
#define EMAC_RMR_BASE (EMAC_RMR_IAE | EMAC_RMR_BAE)
#define EMAC_RMR_BASE EMAC_RMR_RFAF_128_2048
#endif
/* Interrupt Status & enable Regs */
/* EMACx_ISR & EMACx_ISER */
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_ISR_TXPE 0x00000000
#define EMAC_ISR_RXPE 0x00000000
#define EMAC_ISR_TXUE 0x00000000
#define EMAC_ISR_RXOE 0x00000000
#else
#define EMAC_ISR_TXPE 0x20000000
#define EMAC_ISR_RXPE 0x10000000
#define EMAC_ISR_TXUE 0x08000000
#define EMAC_ISR_RXOE 0x04000000
#endif
#define EMAC_ISR_OVR 0x02000000
#define EMAC_ISR_PP 0x01000000
#define EMAC_ISR_BP 0x00800000
......@@ -147,53 +216,62 @@ typedef struct emac_regs {
#define EMAC_ISR_PTLE 0x00040000
#define EMAC_ISR_ORE 0x00020000
#define EMAC_ISR_IRE 0x00010000
#define EMAC_ISR_DBDM 0x00000200
#define EMAC_ISR_DB0 0x00000100
#define EMAC_ISR_SE0 0x00000080
#define EMAC_ISR_TE0 0x00000040
#define EMAC_ISR_DB1 0x00000020
#define EMAC_ISR_SE1 0x00000010
#define EMAC_ISR_TE1 0x00000008
#define EMAC_ISR_SQE 0x00000080
#define EMAC_ISR_TE 0x00000040
#define EMAC_ISR_MOS 0x00000002
#define EMAC_ISR_MOF 0x00000001
/* STA CONTROL REG */
/* EMACx_STACR */
#define EMAC_STACR_PHYD_MASK 0xffff
#define EMAC_STACR_PHYD_SHIFT 16
#define EMAC_STACR_OC 0x00008000
#define EMAC_STACR_PHYE 0x00004000
#define EMAC_STACR_WRITE 0x00002000
#define EMAC_STACR_READ 0x00001000
#define EMAC_STACR_CLK_83MHZ 0x00000800 /* 0's for 50Mhz */
#define EMAC_STACR_CLK_66MHZ 0x00000400
#define EMAC_STACR_CLK_100MHZ 0x00000C00
#define EMAC_STACR_STAC_MASK 0x00003000
#define EMAC_STACR_STAC_READ 0x00001000
#define EMAC_STACR_STAC_WRITE 0x00002000
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_STACR_OPBC_MASK 0x00000C00
#define EMAC_STACR_OPBC_50 0x00000000
#define EMAC_STACR_OPBC_66 0x00000400
#define EMAC_STACR_OPBC_83 0x00000800
#define EMAC_STACR_OPBC_100 0x00000C00
#define EMAC_STACR_OPBC(freq) ((freq) <= 50 ? EMAC_STACR_OPBC_50 : \
(freq) <= 66 ? EMAC_STACR_OPBC_66 : \
(freq) <= 83 ? EMAC_STACR_OPBC_83 : EMAC_STACR_OPBC_100)
#define EMAC_STACR_BASE(opb) EMAC_STACR_OPBC(opb)
#else
#define EMAC_STACR_BASE(opb) 0x00000000
#endif
#define EMAC_STACR_PCDA_MASK 0x1f
#define EMAC_STACR_PCDA_SHIFT 5
#define EMAC_STACR_PRA_MASK 0x1f
/* EMACx_TRTR */
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_TRTR_SHIFT 27
#else
#define EMAC_TRTR_SHIFT 24
#endif
#define EMAC_TRTR(size) ((((size) >> 6) - 1) << EMAC_TRTR_SHIFT)
/* Transmit Request Threshold Register */
#define EMAC_TRTR_1600 0x18000000 /* 0's for 64 Bytes */
#define EMAC_TRTR_1024 0x0f000000
#define EMAC_TRTR_512 0x07000000
#define EMAC_TRTR_256 0x03000000
#define EMAC_TRTR_192 0x10000000
#define EMAC_TRTR_128 0x01000000
/* EMACx_RWMR */
#if !defined(CONFIG_IBM_EMAC4)
#define EMAC_RWMR(l,h) (((l) << 23) | ( ((h) & 0x1ff) << 7))
#else
#define EMAC_RWMR(l,h) (((l) << 22) | ( ((h) & 0x3ff) << 6))
#endif
/* EMAC specific TX descriptor control fields (write access) */
#define EMAC_TX_CTRL_GFCS 0x0200
#define EMAC_TX_CTRL_GP 0x0100
#define EMAC_TX_CTRL_ISA 0x0080
#define EMAC_TX_CTRL_RSA 0x0040
#define EMAC_TX_CTRL_IVT 0x0020
#define EMAC_TX_CTRL_RVT 0x0010
#define EMAC_TX_CTRL_TAH_CSUM 0x000e /* TAH only */
#define EMAC_TX_CTRL_TAH_SEG4 0x000a /* TAH only */
#define EMAC_TX_CTRL_TAH_SEG3 0x0008 /* TAH only */
#define EMAC_TX_CTRL_TAH_SEG2 0x0006 /* TAH only */
#define EMAC_TX_CTRL_TAH_SEG1 0x0004 /* TAH only */
#define EMAC_TX_CTRL_TAH_SEG0 0x0002 /* TAH only */
#define EMAC_TX_CTRL_TAH_DIS 0x0000 /* TAH only */
#define EMAC_TX_CTRL_TAH_CSUM 0x000e
#define EMAC_TX_CTRL_DFLT ( \
MAL_TX_CTRL_INTR | EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP )
/* madmal transmit status / Control bits */
/* EMAC specific TX descriptor status fields (read access) */
#define EMAC_TX_ST_BFCS 0x0200
#define EMAC_TX_ST_BPP 0x0100
#define EMAC_TX_ST_LCS 0x0080
#define EMAC_TX_ST_ED 0x0040
#define EMAC_TX_ST_EC 0x0020
......@@ -202,8 +280,16 @@ typedef struct emac_regs {
#define EMAC_TX_ST_SC 0x0004
#define EMAC_TX_ST_UR 0x0002
#define EMAC_TX_ST_SQE 0x0001
#if !defined(CONFIG_IBM_EMAC_TAH)
#define EMAC_IS_BAD_TX(v) ((v) & (EMAC_TX_ST_LCS | EMAC_TX_ST_ED | \
EMAC_TX_ST_EC | EMAC_TX_ST_LC | \
EMAC_TX_ST_MC | EMAC_TX_ST_UR))
#else
#define EMAC_IS_BAD_TX(v) ((v) & (EMAC_TX_ST_LCS | EMAC_TX_ST_ED | \
EMAC_TX_ST_EC | EMAC_TX_ST_LC))
#endif
/* madmal receive status / Control bits */
/* EMAC specific RX descriptor status fields (read access) */
#define EMAC_RX_ST_OE 0x0200
#define EMAC_RX_ST_PP 0x0100
#define EMAC_RX_ST_BP 0x0080
......@@ -214,54 +300,10 @@ typedef struct emac_regs {
#define EMAC_RX_ST_PTL 0x0004
#define EMAC_RX_ST_ORE 0x0002
#define EMAC_RX_ST_IRE 0x0001
#define EMAC_BAD_RX_PACKET 0x02ff
#define EMAC_CSUM_VER_ERROR 0x0003
/* identify a bad rx packet dependent on emac features */
#ifdef CONFIG_IBM_EMAC4
#define EMAC_IS_BAD_RX_PACKET(desc) \
(((desc & (EMAC_BAD_RX_PACKET & ~EMAC_CSUM_VER_ERROR)) || \
((desc & EMAC_CSUM_VER_ERROR) == EMAC_RX_ST_ORE) || \
((desc & EMAC_CSUM_VER_ERROR) == EMAC_RX_ST_IRE)))
#else
#define EMAC_IS_BAD_RX_PACKET(desc) \
(desc & EMAC_BAD_RX_PACKET)
#endif
/* SoC implementation specific EMAC register defaults */
#if defined(CONFIG_440GP)
#define EMAC_RWMR_DEFAULT 0x80009000
#define EMAC_TMR0_DEFAULT 0x00000000
#define EMAC_TMR1_DEFAULT 0xf8640000
#elif defined(CONFIG_440GX)
#define EMAC_RWMR_DEFAULT 0x1000a200
#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_2_32
#define EMAC_TMR1_DEFAULT 0xa00f0000
#elif defined(CONFIG_440SP)
#define EMAC_RWMR_DEFAULT 0x08002000
#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_128_2048
#define EMAC_TMR1_DEFAULT 0xf8200000
#else
#define EMAC_RWMR_DEFAULT 0x0f002000
#define EMAC_TMR0_DEFAULT 0x00000000
#define EMAC_TMR1_DEFAULT 0x380f0000
#endif /* CONFIG_440GP */
/* Revision specific EMAC register defaults */
#ifdef CONFIG_IBM_EMAC4
#define EMAC_M1_DEFAULT (EMAC_M1_BASE | \
EMAC_M1_OPB_CLK_83 | \
EMAC_M1_TX_MWSW)
#define EMAC_RMR_DEFAULT (EMAC_RMR_BASE | \
EMAC_RMR_RFAF_128_2048)
#define EMAC_TMR0_XMIT (EMAC_TMR0_GNP0 | \
EMAC_TMR0_DEFAULT)
#define EMAC_TRTR_DEFAULT EMAC_TRTR_1024
#else /* !CONFIG_IBM_EMAC4 */
#define EMAC_M1_DEFAULT EMAC_M1_BASE
#define EMAC_RMR_DEFAULT EMAC_RMR_BASE
#define EMAC_TMR0_XMIT EMAC_TMR0_GNP0
#define EMAC_TRTR_DEFAULT EMAC_TRTR_1600
#endif /* CONFIG_IBM_EMAC4 */
#endif
#define EMAC_RX_TAH_BAD_CSUM 0x0003
#define EMAC_BAD_RX_MASK (EMAC_RX_ST_OE | EMAC_RX_ST_BP | \
EMAC_RX_ST_RP | EMAC_RX_ST_SE | \
EMAC_RX_ST_AE | EMAC_RX_ST_BFCS | \
EMAC_RX_ST_PTL | EMAC_RX_ST_ORE | \
EMAC_RX_ST_IRE )
#endif /* __IBM_EMAC_H_ */
/*
* ibm_emac_core.h
* drivers/net/ibm_emac/ibm_emac_core.h
*
* Ethernet driver for the built in ethernet on the IBM 405 PowerPC
* processor.
* Driver for PowerPC 4xx on-chip ethernet controller.
*
* Armin Kuster akuster@mvista.com
* Sept, 2001
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
* Orignial driver
* Johnnie Peters
* jpeters@mvista.com
*
* Copyright 2000 MontaVista Softare Inc.
* Based on original work by
* Armin Kuster <akuster@mvista.com>
* Johnnie Peters <jpeters@mvista.com>
* Copyright 2000, 2001 MontaVista Softare 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.
*
*/
#ifndef __IBM_EMAC_CORE_H_
#define __IBM_EMAC_CORE_H_
#ifndef _IBM_EMAC_CORE_H_
#define _IBM_EMAC_CORE_H_
#include <linux/config.h>
#include <linux/netdevice.h>
#include <linux/dma-mapping.h>
#include <asm/ocp.h>
#include <asm/mmu.h> /* For phys_addr_t */
#include "ibm_emac.h"
#include "ibm_emac_phy.h"
#include "ibm_emac_rgmii.h"
#include "ibm_emac_zmii.h"
#include "ibm_emac_rgmii.h"
#include "ibm_emac_mal.h"
#include "ibm_emac_tah.h"
#ifndef CONFIG_IBM_EMAC_TXB
#define NUM_TX_BUFF 64
#define NUM_RX_BUFF 64
#else
#define NUM_TX_BUFF CONFIG_IBM_EMAC_TXB
#define NUM_RX_BUFF CONFIG_IBM_EMAC_RXB
#endif
#define NUM_TX_BUFF CONFIG_IBM_EMAC_TXB
#define NUM_RX_BUFF CONFIG_IBM_EMAC_RXB
/* This does 16 byte alignment, exactly what we need.
* The packet length includes FCS, but we don't want to
* include that when passing upstream as it messes up
* bridging applications.
*/
#ifndef CONFIG_IBM_EMAC_SKBRES
#define SKB_RES 2
#else
#define SKB_RES CONFIG_IBM_EMAC_SKBRES
/* Simple sanity check */
#if NUM_TX_BUFF > 256 || NUM_RX_BUFF > 256
#error Invalid number of buffer descriptors (greater than 256)
#endif
/* Note about alignement. alloc_skb() returns a cache line
* aligned buffer. However, dev_alloc_skb() will add 16 more
* bytes and "reserve" them, so our buffer will actually end
* on a half cache line. What we do is to use directly
* alloc_skb, allocate 16 more bytes to match the total amount
* allocated by dev_alloc_skb(), but we don't reserve.
// XXX
#define EMAC_MIN_MTU 46
#define EMAC_MAX_MTU 9000
/* Maximum L2 header length (VLAN tagged, no FCS) */
#define EMAC_MTU_OVERHEAD (6 * 2 + 2 + 4)
/* RX BD size for the given MTU */
static inline int emac_rx_size(int mtu)
{
if (mtu > ETH_DATA_LEN)
return MAL_MAX_RX_SIZE;
else
return mal_rx_size(ETH_DATA_LEN + EMAC_MTU_OVERHEAD);
}
#define EMAC_DMA_ALIGN(x) ALIGN((x), dma_get_cache_alignment())
#define EMAC_RX_SKB_HEADROOM \
EMAC_DMA_ALIGN(CONFIG_IBM_EMAC_RX_SKB_HEADROOM)
/* Size of RX skb for the given MTU */
static inline int emac_rx_skb_size(int mtu)
{
int size = max(mtu + EMAC_MTU_OVERHEAD, emac_rx_size(mtu));
return EMAC_DMA_ALIGN(size + 2) + EMAC_RX_SKB_HEADROOM;
}
/* RX DMA sync size */
static inline int emac_rx_sync_size(int mtu)
{
return EMAC_DMA_ALIGN(emac_rx_size(mtu) + 2);
}
/* Driver statistcs is split into two parts to make it more cache friendly:
* - normal statistics (packet count, etc)
* - error statistics
*
* When statistics is requested by ethtool, these parts are concatenated,
* normal one goes first.
*
* Please, keep these structures in sync with emac_stats_keys.
*/
#define MAX_NUM_BUF_DESC 255
#define DESC_BUF_SIZE 4080 /* max 4096-16 */
#define DESC_BUF_SIZE_REG (DESC_BUF_SIZE / 16)
/* Transmitter timeout. */
#define TX_TIMEOUT (2*HZ)
/* MDIO latency delay */
#define MDIO_DELAY 250
/* Power managment shift registers */
#define IBM_CPM_EMMII 0 /* Shift value for MII */
#define IBM_CPM_EMRX 1 /* Shift value for recv */
#define IBM_CPM_EMTX 2 /* Shift value for MAC */
#define IBM_CPM_EMAC(x) (((x)>>IBM_CPM_EMMII) | ((x)>>IBM_CPM_EMRX) | ((x)>>IBM_CPM_EMTX))
#define ENET_HEADER_SIZE 14
#define ENET_FCS_SIZE 4
#define ENET_DEF_MTU_SIZE 1500
#define ENET_DEF_BUF_SIZE (ENET_DEF_MTU_SIZE + ENET_HEADER_SIZE + ENET_FCS_SIZE)
#define EMAC_MIN_FRAME 64
#define EMAC_MAX_FRAME 9018
#define EMAC_MIN_MTU (EMAC_MIN_FRAME - ENET_HEADER_SIZE - ENET_FCS_SIZE)
#define EMAC_MAX_MTU (EMAC_MAX_FRAME - ENET_HEADER_SIZE - ENET_FCS_SIZE)
#ifdef CONFIG_IBM_EMAC_ERRMSG
void emac_serr_dump_0(struct net_device *dev);
void emac_serr_dump_1(struct net_device *dev);
void emac_err_dump(struct net_device *dev, int em0isr);
void emac_phy_dump(struct net_device *);
void emac_desc_dump(struct net_device *);
void emac_mac_dump(struct net_device *);
void emac_mal_dump(struct net_device *);
#else
#define emac_serr_dump_0(dev) do { } while (0)
#define emac_serr_dump_1(dev) do { } while (0)
#define emac_err_dump(dev,x) do { } while (0)
#define emac_phy_dump(dev) do { } while (0)
#define emac_desc_dump(dev) do { } while (0)
#define emac_mac_dump(dev) do { } while (0)
#define emac_mal_dump(dev) do { } while (0)
#endif
/* Normal TX/RX Statistics */
struct ibm_emac_stats {
u64 rx_packets;
u64 rx_bytes;
u64 tx_packets;
u64 tx_bytes;
u64 rx_packets_csum;
u64 tx_packets_csum;
};
/* Error statistics */
struct ibm_emac_error_stats {
u64 tx_undo;
/* Software RX Errors */
u64 rx_dropped_stack;
u64 rx_dropped_oom;
u64 rx_dropped_error;
u64 rx_dropped_resize;
u64 rx_dropped_mtu;
u64 rx_stopped;
/* BD reported RX errors */
u64 rx_bd_errors;
u64 rx_bd_overrun;
u64 rx_bd_bad_packet;
u64 rx_bd_runt_packet;
u64 rx_bd_short_event;
u64 rx_bd_alignment_error;
u64 rx_bd_bad_fcs;
u64 rx_bd_packet_too_long;
u64 rx_bd_out_of_range;
u64 rx_bd_in_range;
/* EMAC IRQ reported RX errors */
u64 rx_parity;
u64 rx_fifo_overrun;
u64 rx_overrun;
u64 rx_bad_packet;
u64 rx_runt_packet;
u64 rx_short_event;
u64 rx_alignment_error;
u64 rx_bad_fcs;
u64 rx_packet_too_long;
u64 rx_out_of_range;
u64 rx_in_range;
/* Software TX Errors */
u64 tx_dropped;
/* BD reported TX errors */
u64 tx_bd_errors;
u64 tx_bd_bad_fcs;
u64 tx_bd_carrier_loss;
u64 tx_bd_excessive_deferral;
u64 tx_bd_excessive_collisions;
u64 tx_bd_late_collision;
u64 tx_bd_multple_collisions;
u64 tx_bd_single_collision;
u64 tx_bd_underrun;
u64 tx_bd_sqe;
/* EMAC IRQ reported TX errors */
u64 tx_parity;
u64 tx_underrun;
u64 tx_sqe;
u64 tx_errors;
};
#define EMAC_ETHTOOL_STATS_COUNT ((sizeof(struct ibm_emac_stats) + \
sizeof(struct ibm_emac_error_stats)) \
/ sizeof(u64))
struct ocp_enet_private {
struct sk_buff *tx_skb[NUM_TX_BUFF];
struct sk_buff *rx_skb[NUM_RX_BUFF];
struct mal_descriptor *tx_desc;
struct mal_descriptor *rx_desc;
struct mal_descriptor *rx_dirty;
struct net_device_stats stats;
int tx_cnt;
int rx_slot;
int dirty_rx;
int tx_slot;
int ack_slot;
int rx_buffer_size;
struct mii_phy phy_mii;
int mii_phy_addr;
int want_autoneg;
int timer_ticks;
struct timer_list link_timer;
struct net_device *mdio_dev;
struct ocp_device *rgmii_dev;
int rgmii_input;
struct ocp_device *zmii_dev;
int zmii_input;
struct ibm_ocp_mal *mal;
int mal_tx_chan, mal_rx_chan;
struct mal_commac commac;
struct ocp_device *tah_dev;
int opened;
int going_away;
int wol_irq;
emac_t *emacp;
struct ocp_device *ocpdev;
struct net_device *ndev;
spinlock_t lock;
struct net_device *ndev; /* 0 */
struct emac_regs *emacp;
struct mal_descriptor *tx_desc;
int tx_cnt;
int tx_slot;
int ack_slot;
struct mal_descriptor *rx_desc;
int rx_slot;
struct sk_buff *rx_sg_skb; /* 1 */
int rx_skb_size;
int rx_sync_size;
struct ibm_emac_stats stats;
struct ocp_device *tah_dev;
struct ibm_ocp_mal *mal;
struct mal_commac commac;
struct sk_buff *tx_skb[NUM_TX_BUFF];
struct sk_buff *rx_skb[NUM_RX_BUFF];
struct ocp_device *zmii_dev;
int zmii_input;
struct ocp_enet_private *mdio_dev;
struct ocp_device *rgmii_dev;
int rgmii_input;
struct ocp_def *def;
struct mii_phy phy;
struct timer_list link_timer;
int reset_failed;
struct ibm_emac_error_stats estats;
struct net_device_stats nstats;
struct device* ldev;
};
#endif /* _IBM_EMAC_CORE_H_ */
/* Ethtool get_regs complex data.
* We want to get not just EMAC registers, but also MAL, ZMII, RGMII, TAH
* when available.
*
* Returned BLOB consists of the ibm_emac_ethtool_regs_hdr,
* MAL registers, EMAC registers and optional ZMII, RGMII, TAH registers.
* Each register component is preceded with emac_ethtool_regs_subhdr.
* Order of the optional headers follows their relative bit posititions
* in emac_ethtool_regs_hdr.components
*/
#define EMAC_ETHTOOL_REGS_ZMII 0x00000001
#define EMAC_ETHTOOL_REGS_RGMII 0x00000002
#define EMAC_ETHTOOL_REGS_TAH 0x00000004
struct emac_ethtool_regs_hdr {
u32 components;
};
struct emac_ethtool_regs_subhdr {
u32 version;
u32 index;
};
#endif /* __IBM_EMAC_CORE_H_ */
/*
* drivers/net/ibm_emac/ibm_ocp_debug.h
*
* Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
*
* Copyright (c) 2004, 2005 Zultys Technologies
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#ifndef __IBM_EMAC_DEBUG_H_
#define __IBM_EMAC_DEBUG_H_
#include <linux/config.h>
#include <linux/init.h>
#include "ibm_emac_core.h"
#include "ibm_emac_mal.h"
#if defined(CONFIG_IBM_EMAC_DEBUG)
void emac_dbg_register(int idx, struct ocp_enet_private *dev);
void mal_dbg_register(int idx, struct ibm_ocp_mal *mal);
int emac_init_debug(void) __init;
void emac_fini_debug(void) __exit;
void emac_dbg_dump_all(void);
# define DBG_LEVEL 1
#else
# define emac_dbg_register(x,y) ((void)0)
# define mal_dbg_register(x,y) ((void)0)
# define emac_init_debug() ((void)0)
# define emac_fini_debug() ((void)0)
# define emac_dbg_dump_all() ((void)0)
# define DBG_LEVEL 0
#endif
#if DBG_LEVEL > 0
# define DBG(f,x...) printk("emac" f, ##x)
# define MAL_DBG(f,x...) printk("mal" f, ##x)
# define ZMII_DBG(f,x...) printk("zmii" f, ##x)
# define RGMII_DBG(f,x...) printk("rgmii" f, ##x)
# define NL "\n"
#else
# define DBG(f,x...) ((void)0)
# define MAL_DBG(f,x...) ((void)0)
# define ZMII_DBG(f,x...) ((void)0)
# define RGMII_DBG(f,x...) ((void)0)
#endif
#if DBG_LEVEL > 1
# define DBG2(f,x...) DBG(f, ##x)
# define MAL_DBG2(f,x...) MAL_DBG(f, ##x)
# define ZMII_DBG2(f,x...) ZMII_DBG(f, ##x)
# define RGMII_DBG2(f,x...) RGMII_DBG(f, ##x)
#else
# define DBG2(f,x...) ((void)0)
# define MAL_DBG2(f,x...) ((void)0)
# define ZMII_DBG2(f,x...) ((void)0)
# define RGMII_DBG2(f,x...) ((void)0)
#endif
#endif /* __IBM_EMAC_DEBUG_H_ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* ibm_emac_phy.h
*
* drivers/net/ibm_emac/ibm_emac_phy.h
*
* Benjamin Herrenschmidt <benh@kernel.crashing.org>
* February 2003
* Driver for PowerPC 4xx on-chip ethernet controller, PHY support
*
* 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.
* Benjamin Herrenschmidt <benh@kernel.crashing.org>
* February 2003
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
* Minor additions by Eugene Surovegin <ebs@ebshome.net>, 2004
*
* 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.
*
* This file basically duplicates sungem_phy.{c,h} with different PHYs
* supported. I'm looking into merging that in a single mii layer more
* flexible than mii.c
*/
#ifndef _IBM_EMAC_PHY_H_
#define _IBM_EMAC_PHY_H_
/*
* PHY mode settings
* Used for multi-mode capable PHYs
*/
#define PHY_MODE_NA 0
#define PHY_MODE_MII 1
#define PHY_MODE_RMII 2
#define PHY_MODE_SMII 3
#define PHY_MODE_RGMII 4
#define PHY_MODE_TBI 5
#define PHY_MODE_GMII 6
#define PHY_MODE_RTBI 7
#define PHY_MODE_SGMII 8
/*
* PHY specific registers/values
*/
/* CIS8201 */
#define MII_CIS8201_EPCR 0x17
#define EPCR_MODE_MASK 0x3000
#define EPCR_GMII_MODE 0x0000
#define EPCR_RGMII_MODE 0x1000
#define EPCR_TBI_MODE 0x2000
#define EPCR_RTBI_MODE 0x3000
#ifndef _IBM_OCP_PHY_H_
#define _IBM_OCP_PHY_H_
struct mii_phy;
......@@ -77,7 +37,8 @@ struct mii_phy_ops {
struct mii_phy_def {
u32 phy_id; /* Concatenated ID1 << 16 | ID2 */
u32 phy_id_mask; /* Significant bits */
u32 features; /* Ethtool SUPPORTED_* defines */
u32 features; /* Ethtool SUPPORTED_* defines or
0 for autodetect */
int magic_aneg; /* Autoneg does all speed test for us */
const char *name;
const struct mii_phy_ops *ops;
......@@ -86,8 +47,11 @@ struct mii_phy_def {
/* An instance of a PHY, partially borrowed from mii_if_info */
struct mii_phy {
struct mii_phy_def *def;
int advertising;
int mii_id;
u32 advertising; /* Ethtool ADVERTISED_* defines */
u32 features; /* Copied from mii_phy_def.features
or determined automaticaly */
int address; /* PHY address */
int mode; /* PHY mode */
/* 1: autoneg enabled, 0: disabled */
int autoneg;
......@@ -98,40 +62,19 @@ struct mii_phy {
int speed;
int duplex;
int pause;
/* PHY mode - if needed */
int mode;
int asym_pause;
/* Provided by host chip */
struct net_device *dev;
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 (*mdio_read) (struct net_device * dev, int addr, int reg);
void (*mdio_write) (struct net_device * dev, int addr, int reg,
int val);
};
/* Pass in a struct mii_phy with dev, mdio_read and mdio_write
* filled, the remaining fields will be filled on return
*/
extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
static inline int __phy_read(struct mii_phy *phy, int id, int reg)
{
return phy->mdio_read(phy->dev, id, reg);
}
static inline void __phy_write(struct mii_phy *phy, int id, int reg, int val)
{
phy->mdio_write(phy->dev, id, reg, val);
}
static inline int phy_read(struct mii_phy *phy, int reg)
{
return phy->mdio_read(phy->dev, phy->mii_id, reg);
}
static inline void phy_write(struct mii_phy *phy, int reg, int val)
{
phy->mdio_write(phy->dev, phy->mii_id, reg, val);
}
int mii_phy_probe(struct mii_phy *phy, int address);
int mii_reset_phy(struct mii_phy *phy);
#endif /* _IBM_EMAC_PHY_H_ */
#endif /* _IBM_OCP_PHY_H_ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册