software/bios: add Ethernet PHY MDIO read/write/dump commands

This commit is contained in:
Florent Kermarrec 2019-08-09 09:26:41 +02:00
parent 0ba9ab92b4
commit 82cd557c24
4 changed files with 225 additions and 23 deletions

View File

@ -1,12 +1,11 @@
// This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq <sb@m-labs.hk>
// This file is Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
// This file is Copyright (c) 2015 Yann Sionneau <ys@m-labs.hk>
// This file is Copyright (c) 2015 whitequark <whitequark@whitequark.org>
// This file is Copyright (c) 2019 Ambroz Bizjak <ambrop7@gmail.com>
// This file is Copyright (c) 2019 Caleb Jamison <cbjamo@gmail.com>
// This file is Copyright (c) 2018 Dolu1990 <charles.papon.90@gmail.com>
// This file is Copyright (c) 2018 Felix Held <felix-github@felixheld.de>
// This file is Copyright (c) 2014 Florent Kermarec <florent@enjoy-digital.fr>
// This file is Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
// This file is Copyright (c) 2019 Gabriel L. Somlo <gsomlo@gmail.com>
// This file is Copyright (c) 2018 Jean-François Nguyen <jf@lambdaconcept.fr>
// This file is Copyright (c) 2018 Sergiusz Bazanski <q3k@q3k.org>
@ -36,6 +35,10 @@
#include <spiflash.h>
#endif
#ifdef CSR_ETHPHY_MDIO_W_ADDR
#include <mdio.h>
#endif
#include "sdram.h"
#include "boot.h"
@ -141,6 +144,40 @@ static void mw(char *addr, char *value, char *count)
for (i=0;i<count2;i++) *addr2++ = value2;
}
static void mc(char *dstaddr, char *srcaddr, char *count)
{
char *c;
unsigned int *dstaddr2;
unsigned int *srcaddr2;
unsigned int count2;
unsigned int i;
if((*dstaddr == 0) || (*srcaddr == 0)) {
printf("mc <dst> <src> [count]\n");
return;
}
dstaddr2 = (unsigned int *)strtoul(dstaddr, &c, 0);
if(*c != 0) {
printf("incorrect destination address\n");
return;
}
srcaddr2 = (unsigned int *)strtoul(srcaddr, &c, 0);
if(*c != 0) {
printf("incorrect source address\n");
return;
}
if(*count == 0) {
count2 = 1;
} else {
count2 = strtoul(count, &c, 0);
if(*c != 0) {
printf("incorrect count\n");
return;
}
}
for (i=0;i<count2;i++) *dstaddr2++ = *srcaddr2++;
}
#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE)
static void fw(char *addr, char *value, char *count)
{
@ -177,40 +214,91 @@ static void fw(char *addr, char *value, char *count)
}
#endif
static void mc(char *dstaddr, char *srcaddr, char *count)
#ifdef CSR_ETHPHY_MDIO_W_ADDR
static void mdiow(char *phyadr, char *reg, char *val)
{
char *c;
unsigned int *dstaddr2;
unsigned int *srcaddr2;
unsigned int count2;
unsigned int i;
unsigned int phyadr2;
unsigned int reg2;
unsigned int val2;
if((*dstaddr == 0) || (*srcaddr == 0)) {
printf("mc <dst> <src> [count]\n");
if((*phyadr == 0) || (*reg == 0) || (*val == 0)) {
printf("mdiow <phyadr> <reg> <value>\n");
return;
}
dstaddr2 = (unsigned int *)strtoul(dstaddr, &c, 0);
phyadr2 = strtoul(phyadr, &c, 0);
if(*c != 0) {
printf("incorrect destination address\n");
printf("incorrect phyadr\n");
return;
}
srcaddr2 = (unsigned int *)strtoul(srcaddr, &c, 0);
reg2 = strtoul(reg, &c, 0);
if(*c != 0) {
printf("incorrect source address\n");
printf("incorrect reg\n");
return;
}
if(*count == 0) {
count2 = 1;
} else {
count2 = strtoul(count, &c, 0);
if(*c != 0) {
printf("incorrect count\n");
return;
}
val2 = strtoul(val, &c, 0);
if(*c != 0) {
printf("incorrect val\n");
return;
}
for (i=0;i<count2;i++) *dstaddr2++ = *srcaddr2++;
mdio_write(phyadr2, reg2, val2);
}
static void mdior(char *phyadr, char *reg)
{
char *c;
unsigned int phyadr2;
unsigned int reg2;
unsigned int val;
if((*phyadr == 0) || (*reg == 0)) {
printf("mdior <phyadr> <reg>\n");
return;
}
phyadr2 = strtoul(phyadr, &c, 0);
if(*c != 0) {
printf("incorrect phyadr\n");
return;
}
reg2 = strtoul(reg, &c, 0);
if(*c != 0) {
printf("incorrect reg\n");
return;
}
val = mdio_read(phyadr2, reg2);
printf("reg %d: 0x%04x\n", reg2, val);
}
static void mdiod(char *phyadr, char *count)
{
char *c;
unsigned int phyadr2;
unsigned int count2;
unsigned int val;
int i;
if((*phyadr == 0) || (*count == 0)) {
printf("mdiod <phyadr> <count>\n");
return;
}
phyadr2 = strtoul(phyadr, &c, 0);
if(*c != 0) {
printf("incorrect phyadr\n");
return;
}
count2 = strtoul(count, &c, 0);
if(*c != 0) {
printf("incorrect count\n");
return;
}
printf("MDIO dump @0x%x:\n", phyadr2);
for (i=0; i<count2; i++) {
val = mdio_read(phyadr2, i);
printf("reg %d: 0x%04x\n", i, val);
}
}
#endif
static void crc(char *startaddr, char *len)
{
char *c;
@ -253,6 +341,11 @@ static void help(void)
puts("mc - copy address space");
#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE)
puts("fw - write to flash");
#endif
#ifdef CSR_ETHPHY_MDIO_W_ADDR
puts("mdiow - write MDIO register");
puts("mdior - read MDIO register");
puts("mdiod - dump MDIO registers");
#endif
puts("");
puts("crc - compute CRC32 of a part of the address space");
@ -311,6 +404,11 @@ static void do_command(char *c)
else if(strcmp(token, "mc") == 0) mc(get_token(&c), get_token(&c), get_token(&c));
#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE)
else if(strcmp(token, "fw") == 0) fw(get_token(&c), get_token(&c), get_token(&c));
#endif
#ifdef CSR_ETHPHY_MDIO_W_ADDR
else if(strcmp(token, "mdiow") == 0) mdiow(get_token(&c), get_token(&c), get_token(&c));
else if(strcmp(token, "mdior") == 0) mdior(get_token(&c), get_token(&c));
else if(strcmp(token, "mdiod") == 0) mdiod(get_token(&c), get_token(&c));
#endif
else if(strcmp(token, "crc") == 0) crc(get_token(&c), get_token(&c));
else if(strcmp(token, "ident") == 0) ident();

View File

@ -0,0 +1,13 @@
#ifndef __MDIO_H
#define __MDIO_H
#define MDIO_CLK 0x01
#define MDIO_OE 0x02
#define MDIO_DO 0x04
#define MDIO_DI 0x01
void mdio_write(int phyadr, int reg, int val);
int mdio_read(int phyadr, int reg);
#endif /* __MDIO_H */

View File

@ -2,7 +2,7 @@ include ../include/generated/variables.mak
include $(SOC_DIRECTORY)/software/common.mak
OBJECTS=exception.o libc.o errno.o crc16.o crc32.o console.o \
system.o id.o uart.o time.o qsort.o strtod.o spiflash.o strcasecmp.o
system.o id.o uart.o time.o qsort.o strtod.o spiflash.o strcasecmp.o mdio.o
all: crt0-$(CPU)-ctr.o crt0-$(CPU)-xip.o libbase.a libbase-nofloat.a

View File

@ -0,0 +1,91 @@
#include <generated/csr.h>
#ifdef CSR_ETHPHY_MDIO_W_ADDR
#include "mdio.h"
#include <stdio.h>
#include <stdlib.h>
static void delay(void)
{
/* no delay FIXME */
}
static void raw_write(unsigned int word, int bitcount)
{
word <<= 32 - bitcount;
while(bitcount > 0) {
if(word & 0x80000000) {
ethphy_mdio_w_write(MDIO_CLK|MDIO_DO|MDIO_OE);
delay();
ethphy_mdio_w_write(MDIO_DO|MDIO_OE);
delay();
} else {
ethphy_mdio_w_write(MDIO_CLK|MDIO_OE);
delay();
ethphy_mdio_w_write(MDIO_OE);
delay();
}
word <<= 1;
bitcount--;
}
}
static unsigned int raw_read(void)
{
unsigned int word;
unsigned int i;
word = 0;
for(i=0;i<16;i++) {
word <<= 1;
ethphy_mdio_w_write(MDIO_CLK);
delay();
ethphy_mdio_w_write(0);
delay();
if(ethphy_mdio_r_read() & MDIO_DI)
word |= 1;
}
return word;
}
static void raw_turnaround(void)
{
ethphy_mdio_w_write(MDIO_CLK);
delay();
ethphy_mdio_w_write(0);
delay();
ethphy_mdio_w_write(MDIO_CLK);
delay();
ethphy_mdio_w_write(0);
delay();
}
void mdio_write(int phyadr, int reg, int val)
{
ethphy_mdio_w_write(MDIO_OE);
raw_write(0xffffffff, 32); /* < sync */
raw_write(0x05, 4); /* < start + write */
raw_write(phyadr, 5);
raw_write(reg, 5);
raw_write(0x02, 2); /* < turnaround */
raw_write(val, 16);
raw_turnaround();
}
int mdio_read(int phyadr, int reg)
{
int r;
ethphy_mdio_w_write(MDIO_OE);
raw_write(0xffffffff, 32); /* < sync */
raw_write(0x06, 4); /* < start + read */
raw_write(phyadr, 5);
raw_write(reg, 5);
raw_turnaround();
r = raw_read();
raw_turnaround();
return r;
}
#endif