From 82cd557c24914db627c93ae2599068cf05429367 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 9 Aug 2019 09:26:41 +0200 Subject: [PATCH] software/bios: add Ethernet PHY MDIO read/write/dump commands --- litex/soc/software/bios/main.c | 140 +++++++++++++++++++++---- litex/soc/software/include/base/mdio.h | 13 +++ litex/soc/software/libbase/Makefile | 2 +- litex/soc/software/libbase/mdio.c | 91 ++++++++++++++++ 4 files changed, 224 insertions(+), 22 deletions(-) create mode 100644 litex/soc/software/include/base/mdio.h create mode 100644 litex/soc/software/libbase/mdio.c diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index a93b4e13..600819b5 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -1,12 +1,11 @@ // This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq +// This file is Copyright (c) 2014-2019 Florent Kermarrec // This file is Copyright (c) 2015 Yann Sionneau // This file is Copyright (c) 2015 whitequark // This file is Copyright (c) 2019 Ambroz Bizjak // This file is Copyright (c) 2019 Caleb Jamison // This file is Copyright (c) 2018 Dolu1990 // This file is Copyright (c) 2018 Felix Held -// This file is Copyright (c) 2014 Florent Kermarec -// This file is Copyright (c) 2014-2019 Florent Kermarrec // This file is Copyright (c) 2019 Gabriel L. Somlo // This file is Copyright (c) 2018 Jean-François Nguyen // This file is Copyright (c) 2018 Sergiusz Bazanski @@ -36,6 +35,10 @@ #include #endif +#ifdef CSR_ETHPHY_MDIO_W_ADDR +#include +#endif + #include "sdram.h" #include "boot.h" @@ -141,6 +144,40 @@ static void mw(char *addr, char *value, char *count) for (i=0;i [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 \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; + } + val2 = strtoul(val, &c, 0); + if(*c != 0) { + printf("incorrect val\n"); + return; + } + 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 \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 i; + unsigned int val; + int i; - if((*dstaddr == 0) || (*srcaddr == 0)) { - printf("mc [count]\n"); + if((*phyadr == 0) || (*count == 0)) { + printf("mdiod \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); + count2 = strtoul(count, &c, 0); if(*c != 0) { - printf("incorrect source address\n"); + printf("incorrect count\n"); return; } - if(*count == 0) { - count2 = 1; - } else { - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } + printf("MDIO dump @0x%x:\n", phyadr2); + for (i=0; i +#ifdef CSR_ETHPHY_MDIO_W_ADDR +#include "mdio.h" + +#include +#include + +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 \ No newline at end of file -- 2.30.2