[N9H30] Fix SDH dual ports.

This commit is contained in:
Wayne Lin 2021-06-29 00:37:32 +08:00
parent 84e5ec69a2
commit 978ea520d9
3 changed files with 106 additions and 28 deletions

View File

@ -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 */

View File

@ -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,21 +788,24 @@ 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)
{
@ -770,6 +818,26 @@ void SDH_Open(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardDetSrc)
{
}
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,12 +868,9 @@ 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);

View File

@ -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)