liteeth/phy/gmii_mii: add clock counter and use it in bios to select mode
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Sun, 12 Apr 2015 15:33:38 +0000 (17:33 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Sun, 12 Apr 2015 16:42:52 +0000 (18:42 +0200)
misoclib/com/liteeth/phy/gmii_mii.py
software/bios/main.c
software/include/net/microudp.h
software/libnet/microudp.c

index 5cf8669d64e53482dcbb5559e53a0cd524fa4a64..91a122d5f794a582e7d9d9dc52e3b181d55b66c7 100644 (file)
@@ -1,10 +1,11 @@
 from migen.genlib.io import DDROutput
 from migen.flow.plumbing import Multiplexer, Demultiplexer
+from migen.genlib.cdc import MultiReg
 
 from misoclib.com.liteeth.common import *
 from misoclib.com.liteeth.generic import *
 
-from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMIIMIICRG
+from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMIICRG
 from misoclib.com.liteeth.phy.mii import LiteEthPHYMIITX, LiteEthPHYMIIRX
 from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMIITX, LiteEthPHYGMIIRX
 
@@ -67,6 +68,19 @@ class LiteEthPHYGMIIMIIRX(Module):
                        Record.connect(mux.source, source)
                ]
 
+class LiteEthGMIIMIIClockCounter(Module, AutoCSR):
+       def __init__(self):
+               self._reset = CSRStorage()
+               self._value = CSRStatus(32)
+               ###
+               counter = RenameClockDomains(Counter(32), "eth_rx")
+               self.submodules += counter
+               self.comb += [
+                       counter.reset.eq(self._reset.storage), #slow, don't need CDC
+                       counter.ce.eq(1),
+               ]
+               self.specials += MultiReg(counter.value, self._value.status)
+
 class LiteEthPHYGMIIMII(Module, AutoCSR):
        def __init__(self, clock_pads, pads, with_hw_init_reset=True):
                self.dw = 8
@@ -74,6 +88,7 @@ class LiteEthPHYGMIIMII(Module, AutoCSR):
                mode = self._mode.storage
                # Note: we can use GMII CRG since it also handles tx clock pad used for MII
                self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset)
+               self.submodules.clock_counter = LiteEthGMIIMIIClockCounter()
                self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx")
                self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx")
                self.sink, self.source = self.tx.sink, self.rx.source
index 5c92b93e8602d95ed6c569755ac1d567ad719da2..28f79dfc8e58cb3f762b63d6e27c26ab3fa5a91d 100644 (file)
@@ -502,6 +502,9 @@ static void boot_sequence(void)
                flashboot();
 #endif
                serialboot();
+#ifdef CSR_ETHPHY_MODE_ADDR
+               ethmode();
+#endif
 #ifdef CSR_ETHMAC_BASE
                netboot();
 #endif
index f9b33980048c82389406c0e90359db9dc016fb81..15c2a47dc4ef828af5a051e14f1d0323456b16c2 100644 (file)
@@ -15,5 +15,6 @@ void microudp_set_callback(udp_callback callback);
 void microudp_service(void);
 
 void ethreset(void);
+void ethmode(void);
 
 #endif /* __MICROUDP_H */
index 8720407e1c6b97ab578da226cb266144bf8c3349..2e6bceb235239b4db9a1070310d96921e9d033c6 100644 (file)
@@ -444,4 +444,27 @@ void ethreset(void)
        busy_wait(2);
 }
 
+void ethmode(void)
+{
+       ethphy_clock_counter_reset_write(1);
+       busy_wait(1);
+       ethphy_clock_counter_reset_write(0);
+       busy_wait(1);
+
+       printf("Ethernet phy mode: ");
+       /* if freq > 120 MHz, use GMII (5MHz margin)*/
+       if (ethphy_clock_counter_value_read() > 120000000/10) {
+               ethphy_mode_write(0);
+               printf("GMII");
+       /* else use MII */
+       } else {
+               ethphy_mode_write(1);
+               printf("MII");
+       }
+       printf("\n");
+
+       ethphy_clock_counter_reset_write(1);
+}
+
 #endif
+