diff options
Diffstat (limited to '')
-rw-r--r-- | ibm_emac.c | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/ibm_emac.c b/ibm_emac.c new file mode 100644 index 0000000..9f7cae6 --- /dev/null +++ b/ibm_emac.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2004, 2005 Zultys Technologies + * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> + */ +#include <stdio.h> +#include <stdint.h> +#include <stddef.h> + +#include "internal.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 + +#define EMAC_VERSION 3 +#define EMAC4_VERSION 4 +#define EMAC4SYNC_VERSION 5 + +struct emac_ethtool_regs_hdr { + u32 components; +}; + +struct emac_ethtool_regs_subhdr { + u32 version; + u32 index; +}; + +struct emac_regs { + /* Common registers across all EMAC implementations. */ + 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 */ + union { + /* Registers unique to EMAC4 implementations */ + struct { + 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 */ + } emac4; + /* Registers unique to EMAC4SYNC implementations */ + struct { + u32 mahr; /* Reset, R, T */ + u32 malr; /* Reset, R, T */ + u32 mmahr; /* Reset, R, T */ + u32 mmalr; /* Reset, R, T */ + u32 rsvd0[4]; + } emac4sync; + } u0; + /* Common registers across all EMAC implementations. */ + u32 lsah; + u32 lsal; + u32 ipgvr; /* Reset, T */ + u32 stacr; /* Special */ + u32 trtr; /* Special */ + u32 rwmr; /* Reset */ + u32 octx; + u32 ocrx; + union { + /* Registers unique to EMAC4 implementations */ + struct { + u32 ipcr; + } emac4; + /* Registers unique to EMAC4SYNC implementations */ + struct { + u32 rsvd1; + u32 revid; + u32 rsvd2[2]; + u32 iaht1; /* Reset, R */ + u32 iaht2; /* Reset, R */ + u32 iaht3; /* Reset, R */ + u32 iaht4; /* Reset, R */ + u32 iaht5; /* Reset, R */ + u32 iaht6; /* Reset, R */ + u32 iaht7; /* Reset, R */ + u32 iaht8; /* Reset, R */ + u32 gaht1; /* Reset, R */ + u32 gaht2; /* Reset, R */ + u32 gaht3; /* Reset, R */ + u32 gaht4; /* Reset, R */ + u32 gaht5; /* Reset, R */ + u32 gaht6; /* Reset, R */ + u32 gaht7; /* Reset, R */ + u32 gaht8; /* Reset, R */ + u32 tpc; /* Reset, T */ + } emac4sync; + } u1; +}; + +struct mal_regs { + u32 tx_count; + u32 rx_count; + + u32 cfg; + u32 esr; + u32 ier; + u32 tx_casr; + u32 tx_carr; + u32 tx_eobisr; + u32 tx_deir; + u32 rx_casr; + u32 rx_carr; + u32 rx_eobisr; + u32 rx_deir; + u32 tx_ctpr[32]; + u32 rx_ctpr[32]; + u32 rcbs[32]; +}; + +struct zmii_regs { + u32 fer; + u32 ssr; + u32 smiisr; +}; + +struct rgmii_regs { + u32 fer; + u32 ssr; +}; + +struct tah_regs { + u32 revid; + u32 pad[3]; + u32 mr; + u32 ssr0; + u32 ssr1; + u32 ssr2; + u32 ssr3; + u32 ssr4; + u32 ssr5; + u32 tsr; +}; + +static void *print_emac_regs(void *buf) +{ + struct emac_ethtool_regs_subhdr *hdr = buf; + struct emac_regs *p = (struct emac_regs *)(hdr + 1); + void *res = p + 1; + + if (!((hdr->version == EMAC_VERSION) || + (hdr->version == EMAC4_VERSION) || + (hdr->version == EMAC4SYNC_VERSION))) + { + printf("This driver version doesn't support information\n" + " output for EMAC area, please update it or use older\n" + " ethtool version\n"); + return res; + } + + printf("EMAC%d Registers\n", hdr->index); + printf("-----------------\n"); + printf("MR0 = 0x%08x MR1 = 0x%08x RMR = 0x%08x\n" + "ISR = 0x%08x ISER = 0x%08x\n" + "TMR0 = 0x%08x TMR1 = 0x%08x\n" + "TRTR = 0x%08x RWMR = 0x%08x\n" + "IAR = %04x%08x\n" + "LSA = %04x%08x\n" + "VTPID = 0x%04x VTCI = 0x%04x\n" + "IPGVR = 0x%04x STACR = 0x%08x\n" + "OCTX = 0x%08x OCRX = 0x%08x\n", + p->mr0, p->mr1, p->rmr, + p->isr, p->iser, + p->tmr0, p->tmr1, + p->trtr, p->rwmr, + p->iahr, p->ialr, + p->lsah, p->lsal, + p->vtpid, p->vtci, + p->ipgvr, p->stacr, p->octx, p->ocrx); + + if (hdr->version == EMAC4SYNC_VERSION) { + printf("MAHR = 0x%08x MALR = 0x%08x MMAHR = 0x%08x\n" + "MMALR = 0x%08x REVID = 0x%08x\n", + p->u0.emac4sync.mahr, p->u0.emac4sync.malr, + p->u0.emac4sync.mmahr, p->u0.emac4sync.mmalr, + p->u1.emac4sync.revid); + + printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", + p->u1.emac4sync.iaht1, p->u1.emac4sync.iaht2, + p->u1.emac4sync.iaht3, p->u1.emac4sync.iaht4); + printf(" 0x%04x 0x%04x 0x%04x 0x%04x\n", + p->u1.emac4sync.iaht5, p->u1.emac4sync.iaht6, + p->u1.emac4sync.iaht7, p->u1.emac4sync.iaht8); + + + printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", + p->u1.emac4sync.gaht1, p->u1.emac4sync.gaht2, + p->u1.emac4sync.gaht3, p->u1.emac4sync.gaht4); + printf(" 0x%04x 0x%04x 0x%04x 0x%04x\n\n", + p->u1.emac4sync.gaht5, p->u1.emac4sync.gaht6, + p->u1.emac4sync.gaht7, p->u1.emac4sync.gaht8); + + } else if (hdr->version == EMAC4_VERSION) { + printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", + p->u0.emac4.iaht1, p->u0.emac4.iaht2, + p->u0.emac4.iaht3, p->u0.emac4.iaht4); + + printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", + p->u0.emac4.gaht1, p->u0.emac4.gaht2, + p->u0.emac4.gaht3, p->u0.emac4.gaht4); + + printf(" IPCR = 0x%08x\n\n", p->u1.emac4.ipcr); + } else if (hdr->version == EMAC_VERSION) { + printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", + p->u0.emac4.iaht1, p->u0.emac4.iaht2, + p->u0.emac4.iaht3, p->u0.emac4.iaht4); + + printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", + p->u0.emac4.gaht1, p->u0.emac4.gaht2, + p->u0.emac4.gaht3, p->u0.emac4.gaht4); + } + return res; +} + +static void *print_mal_regs(void *buf) +{ + struct emac_ethtool_regs_subhdr *hdr = buf; + struct mal_regs *p = (struct mal_regs *)(hdr + 1); + unsigned int i; + + printf("MAL%d Registers\n", hdr->index); + printf("-----------------\n"); + printf("CFG = 0x%08x ESR = 0x%08x IER = 0x%08x\n" + "TX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n" + "RX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n", + p->cfg, p->esr, p->ier, + p->tx_casr, p->tx_carr, p->tx_eobisr, p->tx_deir, + p->rx_casr, p->rx_carr, p->rx_eobisr, p->rx_deir); + + printf("TX|"); + for (i = 0; i < p->tx_count; ++i) { + if (i && !(i % 4)) + printf("\n "); + printf("CTP%d = 0x%08x ", i, p->tx_ctpr[i]); + } + printf("\nRX|"); + for (i = 0; i < p->rx_count; ++i) { + if (i && !(i % 4)) + printf("\n "); + printf("CTP%d = 0x%08x ", i, p->rx_ctpr[i]); + } + printf("\n "); + for (i = 0; i < p->rx_count; ++i) { + u32 r = p->rcbs[i]; + if (i && !(i % 3)) + printf("\n "); + printf("RCBS%d = 0x%08x (%d) ", i, r, r * 16); + } + printf("\n\n"); + return p + 1; +} + +static void *print_zmii_regs(void *buf) +{ + struct emac_ethtool_regs_subhdr *hdr = buf; + struct zmii_regs *p = (struct zmii_regs *)(hdr + 1); + + printf("ZMII%d Registers\n", hdr->index); + printf("-----------------\n"); + printf("FER = %08x SSR = %08x\n" + "SMIISR = %08x\n\n", p->fer, p->ssr, p->smiisr); + + return p + 1; +} + +static void *print_rgmii_regs(void *buf) +{ + struct emac_ethtool_regs_subhdr *hdr = buf; + struct rgmii_regs *p = (struct rgmii_regs *)(hdr + 1); + + printf("RGMII%d Registers\n", hdr->index); + printf("-----------------\n"); + printf("FER = %08x SSR = %08x\n\n", p->fer, p->ssr); + + return p + 1; +} + +static void *print_tah_regs(void *buf) +{ + struct emac_ethtool_regs_subhdr *hdr = buf; + struct tah_regs *p = (struct tah_regs *)(hdr + 1); + + printf("TAH%d Registers\n", hdr->index); + printf("-----------------\n"); + + printf("REVID = %08x MR = %08x TSR = %08x\n" + "SSR0 = %08x SSR1 = %08x SSR2 = %08x\n" + "SSR3 = %08x SSR4 = %08x SSR5 = %08x\n\n", + p->revid, p->mr, p->tsr, + p->ssr0, p->ssr1, p->ssr2, p->ssr3, p->ssr4, p->ssr5); + + return p + 1; +} + +int ibm_emac_dump_regs(struct ethtool_drvinfo *info __maybe_unused, + struct ethtool_regs *regs) +{ + struct emac_ethtool_regs_hdr *hdr = + (struct emac_ethtool_regs_hdr *)regs->data; + void *buf = hdr + 1; + + buf = print_mal_regs(buf); + buf = print_emac_regs(buf); + if (hdr->components & EMAC_ETHTOOL_REGS_ZMII) + buf = print_zmii_regs(buf); + if (hdr->components & EMAC_ETHTOOL_REGS_RGMII) + buf = print_rgmii_regs(buf); + if (hdr->components & EMAC_ETHTOOL_REGS_TAH) + print_tah_regs(buf); + + return 0; +} |