Browse Source

[N9H30] Fix SDH dual ports.

Wayne Lin 4 years ago
parent
commit
978ea520d9

+ 11 - 4
bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sdh.h

@@ -376,6 +376,7 @@ typedef struct
     __IO uint32_t BLEN;                  /*!< [0x0838] SD Block Length Register                                         */
     __IO uint32_t TOUT;                  /*!< [0x083c] SD Response/Data-in Time-out Register                            */
 
+    __IO uint32_t ECTL;                  /*!< [0x0840] SD Host Extend Control Register                                  */
 } SDH_T;
 
 
@@ -450,8 +451,8 @@ typedef struct
 #define SDH_CTL_CLK8OEN_Pos              (6)                                               /*!< SDH_T::CTL: CLK8OEN Position           */
 #define SDH_CTL_CLK8OEN_Msk              (0x1ul << SDH_CTL_CLK8OEN_Pos)                    /*!< SDH_T::CTL: CLK8OEN Mask               */
 
-#define SDH_CTL_CLKKEEP_Pos              (7)                                               /*!< SDH_T::CTL: CLKKEEP Position          */
-#define SDH_CTL_CLKKEEP_Msk              (0x1ul << SDH_CTL_CLKKEEP_Pos)                    /*!< SDH_T::CTL: CLKKEEP Mask              */
+#define SDH_CTL_CLKKEEP0_Pos              (7)                                               /*!< SDH_T::CTL: CLKKEEP Position          */
+#define SDH_CTL_CLKKEEP0_Msk              (0x1ul << SDH_CTL_CLKKEEP0_Pos)                    /*!< SDH_T::CTL: CLKKEEP Mask              */
 
 #define SDH_CTL_CMDCODE_Pos              (8)                                               /*!< SDH_T::CTL: CMDCODE Position           */
 #define SDH_CTL_CMDCODE_Msk              (0x3ful << SDH_CTL_CMDCODE_Pos)                   /*!< SDH_T::CTL: CMDCODE Mask               */
@@ -567,6 +568,12 @@ typedef struct
 #define SDH_TOUT_TOUT_Pos                (0)                                               /*!< SDH_T::TOUT: TOUT Position             */
 #define SDH_TOUT_TOUT_Msk                (0xfffffful << SDH_TOUT_TOUT_Pos)                 /*!< SDH_T::TOUT: TOUT Mask                 */
 
+#define SDH_ECTL_POWEROFF0_Pos           (0)                                               /*!< SDH_T::ECTL: POWEROFF0 Position             */
+#define SDH_ECTL_POWEROFF0_Msk           (0x1ul << SDH_ECTL_POWEROFF0_Pos)                 /*!< SDH_T::ECTL: POWEROFF0 Mask                 */
+
+#define SDH_ECTL_POWEROFF1_Pos           (1)                                               /*!< SDH_T::ECTL: POWEROFF1 Position             */
+#define SDH_ECTL_POWEROFF1_Msk           (0x1ul << SDH_ECTL_POWEROFF1_Pos)                 /*!< SDH_T::ECTL: POWEROFF1 Mask                 */
+
 /**@}*/ /* SDH_CONST */
 /**@}*/ /* end of SDH register group */
 /**@}*/ /* end of REGISTER group */
@@ -740,11 +747,11 @@ void SDH_Open(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardDetSrc);
 uint32_t SDH_Probe(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t card_num);
 uint32_t SDH_Read(SDH_T *sdh, SDH_INFO_T *pSD, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount);
 uint32_t SDH_Write(SDH_T *sdh, SDH_INFO_T *pSD, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount);
-
-void SDH_CardSelect(SDH_T *sdh, uint32_t u32CardSrc);
+void SDH_CardSelect(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardSrc);
 uint32_t SDH_CardDetection(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t card_num);
 void SDH_Open_Disk(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardDetSrc);
 void SDH_Close_Disk(SDH_T *sdh, SDH_INFO_T *pSD);
+uint32_t SDH_WhichCardIsSelected(SDH_T *sdh);
 
 
 /*@}*/ /* end of group N9H30_SDH_EXPORTED_FUNCTIONS */

+ 82 - 15
bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c

@@ -43,6 +43,23 @@
     static uint8_t _SDH1_ucSDHCBuffer[512] __attribute__((aligned(32)));
 #endif
 
+void dump_sdh_regs(SDH_T *sdh)
+{
+    rt_kprintf("\n+++++++++++++++++++++++\n");
+    rt_kprintf("    %s\n", sdh->CTL & SDH_CTL_SDPORT_Msk ? "SD1" : "SD0");
+    rt_kprintf("    DMACTL   = 0x%08x\n", sdh->DMACTL);
+    rt_kprintf("    GCTL   = 0x%08x\n", sdh->GCTL);
+    rt_kprintf("    GINTEN   = 0x%08x\n", sdh->GINTEN);
+    rt_kprintf("    GINTSTS   = 0x%08x\n", sdh->GINTSTS);
+    rt_kprintf("    CTL   = 0x%08x\n", sdh->CTL);
+    rt_kprintf("    INTEN   = 0x%08x\n", sdh->INTEN);
+    rt_kprintf("    INTSTS   = 0x%08x\n", sdh->INTSTS);
+    rt_kprintf("    BLEN   = 0x%08x\n", sdh->BLEN);
+    rt_kprintf("    TOUT   = 0x%08x\n", sdh->TOUT);
+    rt_kprintf("    ECTL   = 0x%08x\n", sdh->ECTL);
+    rt_kprintf("\n+++++++++++++++++++++++\n");
+}
+
 void SDH_CheckRB(SDH_T *sdh)
 {
     while (1)
@@ -271,18 +288,18 @@ uint32_t SDH_CardDetection(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t card_num)
     uint32_t u32INTSTS_CDSTS_Msk;
     uint32_t u32CTL_CLKKEEP_Msk;
 
-    if (card_num == SD_PORT1)
+    if (card_num & SD_PORT0)
+    {
+        u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC_Msk;
+        u32INTSTS_CDSTS_Msk = SDH_INTSTS_CDSTS_Msk;
+        u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP0_Msk;
+    }
+    else if (card_num & SD_PORT1)
     {
         u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC1_Msk;
         u32INTSTS_CDSTS_Msk = SDH_INTSTS_CDSTS1_Msk;
         u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP1_Msk;
     }
-    else
-    {
-        u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC_Msk;
-        u32INTSTS_CDSTS_Msk = SDH_INTSTS_CDSTS_Msk;
-        u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP_Msk;
-    }
 
     if ((sdh->INTEN & u32INTEN_CDSRC_Msk) == u32INTEN_CDSRC_Msk)   /* Card detect pin from GPIO */
     {
@@ -320,7 +337,12 @@ uint32_t SDH_CardDetection(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t card_num)
     return val;
 }
 
-void SDH_CardSelect(SDH_T *sdh, uint32_t u32CardSrc)
+uint32_t SDH_WhichCardIsSelected(SDH_T *sdh)
+{
+    return (sdh->CTL & SDH_CTL_SDPORT_Msk) ? SD_PORT1 : SD_PORT0;
+}
+
+void SDH_CardSelect(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardSrc)
 {
     if (u32CardSrc & SD_PORT0)
     {
@@ -331,6 +353,26 @@ void SDH_CardSelect(SDH_T *sdh, uint32_t u32CardSrc)
         sdh->CTL &= ~SDH_CTL_SDPORT_Msk;
         sdh->CTL |= (1 << SDH_CTL_SDPORT_Pos);
     }
+
+    switch (pSD->CardType)
+    {
+    case SDH_TYPE_MMC:
+        sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
+        SDH_Set_clock(sdh, MMC_FREQ);
+        break;
+    case SDH_TYPE_SD_LOW:
+    case SDH_TYPE_EMMC:
+        sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
+        SDH_Set_clock(sdh, SD_FREQ);
+        break;
+    case SDH_TYPE_SD_HIGH:
+        sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
+        SDH_Set_clock(sdh, SDHC_FREQ);
+        break;
+    case SDH_TYPE_UNKNOWN:
+    default:
+        break;
+    }
 }
 
 uint32_t SDH_Init(SDH_T *sdh, SDH_INFO_T *pSD)
@@ -363,6 +405,8 @@ uint32_t SDH_Init(SDH_T *sdh, SDH_INFO_T *pSD)
     pSD->R7Flag = 1ul;
     u32CmdTimeOut = 0xFFFFFul;
 
+    //dump_sdh_regs(sdh);
+
     i = SDH_SDCmdAndRsp(sdh, pSD, 8ul, 0x00000155ul, u32CmdTimeOut);
     if (i == Successful)
     {
@@ -451,6 +495,7 @@ uint32_t SDH_Init(SDH_T *sdh, SDH_INFO_T *pSD)
         else
         {
             pSD->CardType = SDH_TYPE_UNKNOWN;
+
             return SDH_INIT_ERROR;
         }
     }
@@ -743,33 +788,56 @@ void SDH_Open(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardDetSrc)
     uint32_t u32INTEN_CDSRC_Msk = 0;
     uint32_t u32INTSTS_CDIF_Msk = 0;
     uint32_t u32INTEN_CDIEN_Msk = 0;
+    uint32_t u32CTL_CLKKEEP_Msk = 0;
 
     if (u32CardDetSrc & SD_PORT0)
     {
         u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC_Msk;
         u32INTSTS_CDIF_Msk = SDH_INTSTS_CDIF_Msk;
         u32INTEN_CDIEN_Msk = SDH_INTEN_CDIEN_Msk;
+        u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP0_Msk;
     }
     else if (u32CardDetSrc & SD_PORT1)
     {
         u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC1_Msk;
         u32INTSTS_CDIF_Msk = SDH_INTSTS_CDIF1_Msk;
         u32INTEN_CDIEN_Msk = SDH_INTEN_CDIEN1_Msk;
+        u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP1_Msk;
     }
 
-    // enable DMAC
+    // Enable DMAC
     sdh->DMACTL = SDH_DMACTL_DMARST_Msk;
     while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == SDH_DMACTL_DMARST_Msk)
     {
     }
     sdh->DMACTL = SDH_DMACTL_DMAEN_Msk;
 
-    //Reset Global
+    // Reset Global
     sdh->GCTL = SDH_GCTL_GCTLRST_Msk | SDH_GCTL_SDEN_Msk;
     while ((sdh->GCTL & SDH_GCTL_GCTLRST_Msk) == SDH_GCTL_GCTLRST_Msk)
     {
     }
 
+    if (sdh == SDH1)
+    {
+        /* Enable Power, 0: Enable, 1:Disable */
+        if (u32CardDetSrc & SD_PORT0)
+        {
+            sdh->ECTL &= ~SDH_ECTL_POWEROFF0_Msk;
+        }
+        else if (u32CardDetSrc & SD_PORT1)
+        {
+            sdh->ECTL &= ~SDH_ECTL_POWEROFF1_Msk;
+        }
+        /* disable SD clock output */
+        sdh->CTL &= ~(0xFF | u32CTL_CLKKEEP_Msk);
+    }
+
+    sdh->CTL |= SDH_CTL_CTLRST_Msk;
+    while ((sdh->CTL & SDH_CTL_CTLRST_Msk) == SDH_CTL_CTLRST_Msk)
+    {
+    }
+
     memset(pSD, 0, sizeof(SDH_INFO_T));
     if (sdh == SDH0)
     {
@@ -800,13 +868,10 @@ void SDH_Open(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardDetSrc)
 
     sdh->INTSTS = u32INTSTS_CDIF_Msk;
     sdh->INTEN |= u32INTEN_CDIEN_Msk;
-
-    sdh->CTL |= SDH_CTL_CTLRST_Msk;
-    while ((sdh->CTL & SDH_CTL_CTLRST_Msk) == SDH_CTL_CTLRST_Msk)
-    {
-    }
 }
 
+
+
 /**
  *  @brief  This function use to initial SD card.
  *
@@ -889,6 +954,7 @@ uint32_t SDH_Read(SDH_T *sdh, SDH_INFO_T *pSD, uint8_t *pu8BufAddr, uint32_t u32
     {
         return status;
     }
+
     SDH_CheckRB(sdh);
 
     sdh->BLEN = blksize - 1ul;       /* the actual byte count is equal to (SDBLEN+1) */
@@ -984,6 +1050,7 @@ uint32_t SDH_Read(SDH_T *sdh, SDH_INFO_T *pSD, uint8_t *pu8BufAddr, uint32_t u32
     {
         return SDH_CRC7_ERROR;
     }
+
     SDH_CheckRB(sdh);
 
     SDH_SDCommand(sdh, pSD, 7ul, 0ul);

+ 13 - 9
bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c

@@ -225,6 +225,11 @@ static void SDH_IRQHandler(int vector, void *param)
     unsigned int volatile isr;
     SDH_INFO_T *pSD = sdh->info;
 
+#if defined(BSP_USING_SDH1)
+    if (SDH_WhichCardIsSelected(sdh_base) == SD_PORT1)
+        pSD = &SD1;
+#endif
+
     // FMI data abort interrupt
     if (sdh_base->GINTSTS & SDH_GINTSTS_DTAIF_Msk)
     {
@@ -252,9 +257,8 @@ static void SDH_IRQHandler(int vector, void *param)
     else if (isr & SDH_INTSTS_CDIF1_Msk)   // card number=1 detect
     {
 #if defined(NU_SDH_HOTPLUG)
-        rt_event_send(&sdh_event, sdh->card_detected_event);
+        rt_event_send(&sdh_event, NU_SDH_CARD_DETECTED_SD1);
 #endif
-
         /* Clear CDIF1 interrupt flag */
         SDH_CLR_INT_FLAG(sdh_base, SDH_INTSTS_CDIF1_Msk);
     }
@@ -301,7 +305,7 @@ static rt_err_t nu_sdh_init(rt_device_t dev)
 static rt_err_t nu_sdh_open(rt_device_t dev, rt_uint16_t oflag)
 {
     nu_sdh_t sdh = (nu_sdh_t)dev;
-    rt_err_t result;
+    rt_err_t result = RT_EOK;
 
     RT_ASSERT(dev != RT_NULL);
 
@@ -311,7 +315,7 @@ static rt_err_t nu_sdh_open(rt_device_t dev, rt_uint16_t oflag)
         result = rt_mutex_take(&g_shared_lock, RT_WAITING_FOREVER);
         RT_ASSERT(result == RT_EOK);
     }
-    SDH_CardSelect(sdh->base, sdh->card_num);
+    SDH_CardSelect(sdh->base, sdh->info, sdh->card_num);
 #endif
 
     if (SDH_Probe(sdh->base, sdh->info, sdh->card_num) == 0)
@@ -353,7 +357,7 @@ static rt_size_t nu_sdh_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_siz
         result = rt_mutex_take(&g_shared_lock, RT_WAITING_FOREVER);
         RT_ASSERT(result == RT_EOK);
     }
-    SDH_CardSelect(sdh->base, sdh->card_num);
+    SDH_CardSelect(sdh->base, sdh->info, sdh->card_num);
 #endif
 
     result = rt_sem_take(&sdh->lock, RT_WAITING_FOREVER);
@@ -435,7 +439,7 @@ static rt_size_t nu_sdh_write(rt_device_t dev, rt_off_t pos, const void *buffer,
         result = rt_mutex_take(&g_shared_lock, RT_WAITING_FOREVER);
         RT_ASSERT(result == RT_EOK);
     }
-    SDH_CardSelect(sdh->base, sdh->card_num);
+    SDH_CardSelect(sdh->base, sdh->info, sdh->card_num);
 #endif
 
     result = rt_sem_take(&sdh->lock, RT_WAITING_FOREVER);
@@ -724,7 +728,7 @@ static void nu_card_detector(nu_sdh_t sdh)
             rt_err_t result = rt_mutex_take(&g_shared_lock, RT_WAITING_FOREVER);
             RT_ASSERT(result == RT_EOK);
         }
-        SDH_CardSelect(sdh_base, sdh->card_num);
+        SDH_CardSelect(sdh->base, sdh->info, sdh->card_num);
 #endif
 
         SDH_Open(sdh_base, sdh->info, CardDetect_From_GPIO | sdh->card_num);
@@ -755,7 +759,7 @@ static void sdh_hotplugger(void *param)
             rt_err_t result = rt_mutex_take(&g_shared_lock, RT_WAITING_FOREVER);
             RT_ASSERT(result == RT_EOK);
         }
-        SDH_CardSelect(nu_sdh_arr[i].base, nu_sdh_arr[i].card_num);
+        SDH_CardSelect(nu_sdh_arr[i].base, nu_sdh_arr[i].info, nu_sdh_arr[i].card_num);
 #endif
 
         /* Try to detect SD card on selected port. */
@@ -781,7 +785,7 @@ static void sdh_hotplugger(void *param)
                           RT_WAITING_FOREVER, &e) == RT_EOK)
         {
             /* Debounce */
-            rt_thread_mdelay(200);
+            rt_thread_mdelay(500);
             switch (e)
             {
 #if defined(BSP_USING_EMMC)