From 209d46893b8a55f1bc2b9dd3db0d807d250e49de Mon Sep 17 00:00:00 2001
From: gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>
Date: Wed, 22 Feb 2012 15:29:44 +0000
Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3969
 35acf78f-673a-0410-8e92-d51de3d6d3f4

---
 os/hal/platforms/STM32/mac_lld.c | 107 ++++++++++++++++++++++++++++++++++-----
 os/hal/platforms/STM32/mac_lld.h |   4 ++
 testhal/STM32F1xx/MAC/Makefile   |   2 +-
 testhal/STM32F1xx/MAC/mcuconf.h  |  15 ++++--
 4 files changed, 110 insertions(+), 18 deletions(-)

diff --git a/os/hal/platforms/STM32/mac_lld.c b/os/hal/platforms/STM32/mac_lld.c
index 67f04f12e..ee08189bb 100644
--- a/os/hal/platforms/STM32/mac_lld.c
+++ b/os/hal/platforms/STM32/mac_lld.c
@@ -142,6 +142,7 @@ void mac_lld_init(void) {
   unsigned i;
 
   macObjectInit(&ETHD1);
+  ETHD1.link_up = FALSE;
 
   /* Descriptor tables are initialized in linked mode, note that the first
      word is not initialized here but in mac_lld_start().*/
@@ -205,23 +206,56 @@ void mac_lld_start(MACDriver *macp) {
   /* MAC clocks activation.*/
   rccEnableETH(FALSE);
 
-  /* Descriptor chains pointers.*/
-  ETH->DMARDLAR = (uint32_t)rd;
-  ETH->DMATDLAR = (uint32_t)rd;
-
   /* MAC configuration:
-       ETH_MACCR_TE     - Transmitter enable.
-       ETH_MACCR_RE     - Receiver enable.
-     Note that the complete setup of the MAC is performed when the link
-     status is detected.*/
-  ETH->MACCR = ETH_MACCR_TE | ETH_MACCR_TE;
-
-  ETH->MACFFR    = 0;
+     ETH_MACFFR_SAF     - Source address filter. Broadcast frames are not
+                          filtered.*/
+  ETH->MACFFR    = ETH_MACFFR_SAF;
+
+  /* MAC address configuration, only a single address comparator is used,
+     hash table not used.*/
+  ETH->MACA0HR   = ((uint32_t)macp->config->mac_address[0] << 8) |
+                   ((uint32_t)macp->config->mac_address[1] << 0);
+  ETH->MACA0LR   = ((uint32_t)macp->config->mac_address[2] << 24) |
+                   ((uint32_t)macp->config->mac_address[3] << 16) |
+                   ((uint32_t)macp->config->mac_address[4] << 8) |
+                   ((uint32_t)macp->config->mac_address[5] << 0);
+  ETH->MACA1HR   = 0x0000FFFF;
+  ETH->MACA1LR   = 0xFFFFFFFF;
+  ETH->MACA2HR   = 0x0000FFFF;
+  ETH->MACA2LR   = 0xFFFFFFFF;
+  ETH->MACA3HR   = 0x0000FFFF;
+  ETH->MACA3LR   = 0xFFFFFFFF;
   ETH->MACHTHR   = 0;
   ETH->MACHTLR   = 0;
-  ETH->MACHTLR   = 0;
+
+  /* MAC flow control not used, VLAN not used.*/
   ETH->MACFCR    = 0;
   ETH->MACVLANTR = 0;
+
+  /* Transmitter and receiver enabled.
+     Note that the complete setup of the MAC is performed when the link
+     status is detected.*/
+  ETH->MACCR = ETH_MACCR_TE | ETH_MACCR_TE;
+
+  /* DMA configuration:
+     Descriptor chains pointers.*/
+  ETH->DMARDLAR = (uint32_t)rd;
+  ETH->DMATDLAR = (uint32_t)td;
+
+  /* Enabling required interrupt sources.*/
+  ETH->DMASR    = 0xFFFFFFFF;                   /* Resetting pending flags. */
+
+  /* DMA general settings.*/
+  ETH->DMABMR   = ETH_DMABMR_AAB | ETH_DMABMR_RDP_1Beat | ETH_DMABMR_PBL_1Beat;
+
+  /* Transmit FIFO flush.*/
+  ETH->DMAOMR   = ETH_DMAOMR_FTF;
+  while (ETH->DMAOMR & ETH_DMAOMR_FTF)
+    ;
+
+  /* DMA final configuration and start.*/
+  ETH->DMAOMR   = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_TSF |
+                  ETH_DMAOMR_ST | ETH_DMAOMR_SR;
 }
 
 /**
@@ -350,7 +384,56 @@ void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) {
  * @notapi
  */
 bool_t mac_lld_poll_link_status(MACDriver *macp) {
+  uint32_t maccr, bmsr, bmcr;
+
+  /* Checks if the link is up, updates the status accordingly and returns.*/
+  bmsr = mii_read_phy(MII_BMSR);
+  if (!(bmsr & BMSR_LSTATUS))
+    return macp->link_up = FALSE;
+
+  maccr = ETH->MACCR;
+  bmcr = mii_read_phy(MII_BMCR);
+
+  /* Check on auto-negotiation mode.*/
+  if (bmcr & BMCR_ANENABLE) {
+    uint32_t lpa;
+
+    /* Auto-nogotiation enabled, checks the LPA register.*/
+    lpa = mii_read_phy(MII_LPA);
+
+    /* Check on link speed.*/
+    if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4))
+      maccr |= ETH_MACCR_FES;
+    else
+      maccr &= ~ETH_MACCR_FES;
+
+    /* Check on link mode.*/
+    if (lpa & (LPA_10FULL | LPA_100FULL))
+      maccr |= ETH_MACCR_DM;
+    else
+      maccr &= ~ETH_MACCR_DM;
+  }
+  else {
+    /* Auto-negotiation disabled, checks the current settings.*/
+
+    /* Check on link speed.*/
+    if (bmcr & BMCR_SPEED100)
+      maccr |= ETH_MACCR_FES;
+    else
+      maccr &= ~ETH_MACCR_FES;
+
+    /* Check on link mode.*/
+    if (bmcr & BMCR_FULLDPLX)
+      maccr |= ETH_MACCR_DM;
+    else
+      maccr &= ~ETH_MACCR_DM;
+  }
+
+  /* Changes the mode in the MAC.*/
+  ETH->MACCR = maccr;
 
+  /* Returns the link status.*/
+  return macp->link_up = TRUE;
 }
 
 #endif /* HAL_USE_MAC */
diff --git a/os/hal/platforms/STM32/mac_lld.h b/os/hal/platforms/STM32/mac_lld.h
index d3db90893..86d059d42 100644
--- a/os/hal/platforms/STM32/mac_lld.h
+++ b/os/hal/platforms/STM32/mac_lld.h
@@ -206,6 +206,10 @@ struct MACDriver {
   EventSource           rdevent;
 #endif
   /* End of the mandatory fields.*/
+  /**
+   * @brief Link status flag.
+   */
+  bool_t                link_up;
 };
 
 /**
diff --git a/testhal/STM32F1xx/MAC/Makefile b/testhal/STM32F1xx/MAC/Makefile
index 626ff0b9d..42966ebc8 100644
--- a/testhal/STM32F1xx/MAC/Makefile
+++ b/testhal/STM32F1xx/MAC/Makefile
@@ -66,7 +66,7 @@ include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk
 include $(CHIBIOS)/os/kernel/kernel.mk
 
 # Define linker script file here
-LDSCRIPT= $(PORTLD)/STM32F103xB.ld
+LDSCRIPT= $(PORTLD)/STM32F107xC.ld
 
 # C sources that can be compiled in ARM or THUMB mode depending on the global
 # setting.
diff --git a/testhal/STM32F1xx/MAC/mcuconf.h b/testhal/STM32F1xx/MAC/mcuconf.h
index e87bba983..7c7486270 100644
--- a/testhal/STM32F1xx/MAC/mcuconf.h
+++ b/testhal/STM32F1xx/MAC/mcuconf.h
@@ -41,16 +41,21 @@
 #define STM32_HSE_ENABLED                   TRUE
 #define STM32_LSE_ENABLED                   FALSE
 #define STM32_SW                            STM32_SW_PLL
-#define STM32_PLLSRC                        STM32_PLLSRC_HSE
-#define STM32_PLLXTPRE                      STM32_PLLXTPRE_DIV1
+#define STM32_PLLSRC                        STM32_PLLSRC_PREDIV1
+#define STM32_PREDIV1SRC                    STM32_PREDIV1SRC_PLL2
+#define STM32_PREDIV1_VALUE                 5
 #define STM32_PLLMUL_VALUE                  9
+#define STM32_PREDIV2_VALUE                 5
+#define STM32_PLL2MUL_VALUE                 8
+#define STM32_PLL3MUL_VALUE                 10
 #define STM32_HPRE                          STM32_HPRE_DIV1
 #define STM32_PPRE1                         STM32_PPRE1_DIV2
 #define STM32_PPRE2                         STM32_PPRE2_DIV2
 #define STM32_ADCPRE                        STM32_ADCPRE_DIV4
-#define STM32_USB_CLOCK_REQUIRED            TRUE
-#define STM32_USBPRE                        STM32_USBPRE_DIV1P5
-#define STM32_MCOSEL                        STM32_MCOSEL_NOCLOCK
+#define STM32_OTG_CLOCK_REQUIRED            TRUE
+#define STM32_OTGFSPRE                      STM32_OTGFSPRE_DIV3
+#define STM32_I2S_CLOCK_REQUIRED            FALSE
+#define STM32_MCOSEL                        STM32_MCOSEL_PLL2
 #define STM32_RTCSEL                        STM32_RTCSEL_HSEDIV
 #define STM32_PVD_ENABLE                    FALSE
 #define STM32_PLS                           STM32_PLS_LEV0
-- 
cgit v1.2.3