123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-4-21 Wayne First version
- *
- ******************************************************************************/
- #include "rtconfig.h"
- #if defined(BSP_USING_SDH)
- #include <rtdevice.h>
- #include <drivers/mmcsd_core.h>
- #include <drivers/sdio.h>
- #include "NuMicro.h"
- #define LOG_TAG "drv.sdh"
- #undef DBG_ENABLE
- #define DBG_SECTION_NAME LOG_TAG
- #define DBG_LEVEL LOG_LVL_ASSERT
- #define DBG_COLOR
- #include <rtdbg.h>
- #define SDH_ALIGN_LEN 4
- #define SDH_BUFF_SIZE 512
- #define SDH_BLOCK_SIZE 512
- enum
- {
- SDH_START = -1,
- #if defined(BSP_USING_SDH0)
- SDH0_IDX,
- #endif
- #if defined(BSP_USING_SDH1)
- SDH1_IDX,
- #endif
- SDH_CNT
- };
- struct nu_sdh
- {
- struct rt_mmcsd_host *host;
- char *name;
- SDH_T *base;
- IRQn_Type irqn;
- uint32_t rstidx;
- uint32_t modid;
- uint8_t *cachebuf;
- uint32_t u32CmdResp0;
- uint32_t u32CmdResp1;
- uint32_t u32CurClk;
- rt_tick_t LastNotice;
- };
- typedef struct nu_sdh *nu_sdh_t;
- /* Private variables ------------------------------------------------------------*/
- static struct nu_sdh nu_sdh_arr [] =
- {
- #if defined(BSP_USING_SDH0)
- {
- .name = "sdh0",
- .base = SDH0,
- .irqn = SDH0_IRQn,
- .rstidx = SDH0_RST,
- .modid = SDH0_MODULE,
- .cachebuf = RT_NULL,
- },
- #endif
- #if defined(BSP_USING_SDH1)
- {
- .name = "sdh1",
- .base = SDH1,
- .irqn = SDH1_IRQn,
- .rstidx = SDH1_RST,
- .modid = SDH1_MODULE,
- .cachebuf = RT_NULL,
- },
- #endif
- }; /* struct nu_sdh nu_sdh_arr [] */
- #define SDH_SetClock SDH_Set_clock
- static int SDH_SetBusWidth(SDH_T *sdh, uint32_t bw)
- {
- if (bw == 4)
- {
- sdh->CTL |= SDH_CTL_DBW_Msk;
- }
- else if (bw == 1)
- {
- sdh->CTL &= ~SDH_CTL_DBW_Msk;
- }
- else
- {
- goto exit_SDH_SetBusWidth;
- }
- return 0;
- exit_SDH_SetBusWidth:
- return -1;
- }
- static int SDH_GetBusStatus(SDH_T *sdh, uint32_t mask)
- {
- int cnt = 0x100000;
- while (cnt-- > 0)
- {
- sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
- while (sdh->CTL & SDH_CTL_CLK8OEN_Msk) { }
- if (SDH_GET_INT_FLAG(sdh, SDH_INTSTS_DAT0STS_Msk))
- break;
- }
- return (cnt == 0) ? -1 : 0 ;
- }
- static int SDH_GetCD(SDH_T *sdh)
- {
- int i32CD = 0;
- if ((sdh->GCTL & SDH_GCTL_SDEN_Msk) == SDH_GCTL_SDEN_Msk)
- {
- if ((sdh->INTEN & SDH_INTEN_CDSRC_Msk) == SDH_INTEN_CDSRC_Msk) /* Card detect pin from GPIO */
- {
- i32CD = (sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) ? 0 : 1;
- }
- else /* Card detect pin from DAT3 mode */
- {
- __IO uint32_t i;
- sdh->CTL |= SDH_CTL_CLKKEEP_Msk;
- for (i = 0ul; i < 5000ul; i++) { }
- i32CD = ((sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) == SDH_INTSTS_CDSTS_Msk) ? 1 : 0;
- sdh->CTL &= ~SDH_CTL_CLKKEEP_Msk;
- }
- }
- return i32CD;
- }
- static void SDH_Enable(SDH_T *sdh)
- {
- /* Reset sdh and its DMA engine at first. */
- sdh->DMACTL |= SDH_DMACTL_DMARST_Msk | SDH_DMACTL_DMAEN_Msk;
- while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == SDH_DMACTL_DMARST_Msk) { }
- sdh->DMACTL = SDH_DMACTL_DMAEN_Msk;
- sdh->DMAINTSTS = SDH_DMAINTSTS_ABORTIF_Msk | SDH_DMAINTSTS_WEOTIF_Msk; // clear all interrupt flag
- sdh->GCTL = SDH_GCTL_GCTLRST_Msk;
- while ((sdh->GCTL & SDH_GCTL_GCTLRST_Msk) == SDH_GCTL_GCTLRST_Msk) { }// clear all interrupt flag
- sdh->GINTSTS = SDH_GINTSTS_DTAIF_Msk;
- sdh->GCTL = SDH_GCTL_SDEN_Msk;
- sdh->CTL |= SDH_CTL_CTLRST_Msk;
- while ((sdh->CTL & SDH_CTL_CTLRST_Msk) == SDH_CTL_CTLRST_Msk) { }
- sdh->INTSTS = 0xFFFFFFFF; // clear all interrupt flag
- sdh->INTEN |= SDH_INTEN_CDSRC_Msk;
- sdh->INTEN |= SDH_INTEN_CDIEN_Msk;
- }
- /**
- * @brief This function get command responding.
- * @param sdh SDH instance
- * @param cmd rt_mmcsd_cmd
- * @retval none
- */
- static void nu_sdh_sendcmd_done(SDH_T *sdh, struct rt_mmcsd_cmd *cmd)
- {
- if (resp_type(cmd) == RESP_R2)
- {
- uint8_t *c = (uint8_t *)&sdh->FB[0];
- int i, j, tmp[5];
- for (i = 0, j = 0; j < 5; i += 4, j++)
- {
- tmp[j] = (*(c + i) << 24) | (*(c + i + 1) << 16) | (*(c + i + 2) << 8) | (*(c + i + 3));
- }
- for (i = 0; i < 4; i++)
- {
- cmd->resp[i] = ((tmp[i] & 0x00ffffff) << 8) |
- ((tmp[i + 1] & 0xff000000) >> 24);
- }
- }
- else
- {
- cmd->resp[0] = (sdh->RESP0 << 8) | (sdh->RESP1 & 0xff);
- cmd->resp[1] = cmd->resp[2] = cmd->resp[3] = 0;
- }
- }
- /**
- * @brief This function wait data-sending/receiving.
- * @param sdh SDH instance
- * @param data rt_mmcsd_data
- * @retval error code
- */
- static int nu_sdh_xfer_data(SDH_T *sdh, struct rt_mmcsd_data *data)
- {
- while (!SDH_GET_INT_FLAG(sdh, SDH_INTSTS_BLKDIF_Msk)) { }
- SDH_CLR_INT_FLAG(sdh, SDH_INTSTS_BLKDIF_Msk);
- if (data->flags & DATA_DIR_WRITE)
- {
- sdh->CTL |= SDH_CTL_CLKKEEP_Msk;
- while (!SDH_GET_INT_FLAG(sdh, SDH_INTSTS_DAT0STS_Msk)) { }
- sdh->CTL &= ~SDH_CTL_CLKKEEP_Msk;
- }
- return 0;
- }
- /**
- * @brief This function send command and wait its response.
- * @param host rt_mmcsd_host
- * @param cmd rt_mmcsd_cmd
- * @param data rt_mmcsd_data
- * @retval error code
- */
- static int nu_sdh_sendcmd(struct rt_mmcsd_host *host, struct rt_mmcsd_cmd *cmd, struct rt_mmcsd_data *data)
- {
- int ret;
- nu_sdh_t NuSdh = (nu_sdh_t)host->private_data;
- SDH_T *sdh = NuSdh->base;
- volatile uint32_t ctl = 0, tout = 0;
- switch (host->io_cfg.bus_width)
- {
- case MMCSD_BUS_WIDTH_1:
- ctl &= ~SDH_CTL_DBW_Msk;
- break;
- case MMCSD_BUS_WIDTH_4:
- ctl |= SDH_CTL_DBW_Msk;
- break;
- case MMCSD_BUS_WIDTH_8:
- default:
- return -1;
- }
- /* Reset sdh and its DMA engine at first. */
- sdh->DMACTL |= SDH_DMACTL_DMARST_Msk | SDH_DMACTL_DMAEN_Msk;
- while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == SDH_DMACTL_DMARST_Msk) { }
- sdh->DMACTL = SDH_DMACTL_DMAEN_Msk;
- sdh->DMAINTSTS = SDH_DMAINTSTS_ABORTIF_Msk | SDH_DMAINTSTS_WEOTIF_Msk; // clear all interrupt flag
- if (resp_type(cmd) != RESP_NONE)
- {
- if (resp_type(cmd) == RESP_R2)
- {
- ctl |= SDH_CTL_R2EN_Msk;
- }
- else
- {
- ctl |= SDH_CTL_RIEN_Msk;
- }
- tout = 0xFFFF;
- }
- /* Set SDNWR and BLK_CNT to 1 */
- ctl |= ((9 << SDH_CTL_SDNWR_Pos) | (1 << SDH_CTL_BLKCNT_Pos));
- ctl |= ((cmd->cmd_code << SDH_CTL_CMDCODE_Pos) | SDH_CTL_COEN_Msk);
- /* Set Transfer mode regarding to data flag */
- if (data != RT_NULL)
- {
- sdh->BLEN = data->blksize - 1;
- if (data->blksize <= 0x200)
- {
- if (data->blks < 256)
- {
- ctl = (ctl & ~SDH_CTL_BLKCNT_Msk) | (data->blks << SDH_CTL_BLKCNT_Pos);
- }
- else
- {
- LOG_E("SD Max block transfer is 255!!");
- }
- }
- if (data->flags & DATA_DIR_READ)
- {
- tout = 0xFFFFFF;
- ctl |= SDH_CTL_DIEN_Msk; // Data-in
- sdh->DMASA = (uint32_t)data->buf; // Read from dest
- }
- else if (data->flags & DATA_DIR_WRITE)
- {
- ctl |= SDH_CTL_DOEN_Msk; // Data-out
- sdh->DMASA = (uint32_t)data->buf; // Write to dest
- }
- }
- else if (resp_type(cmd) == RESP_R1B)
- {
- }
- /* Clear response-timeout flag first for safty and reset new timeout value. */
- SDH_CLR_INT_FLAG(sdh, SDH_INTSTS_RTOIF_Msk);
- sdh->TOUT = tout;
- /* Set argument and start a transaction. */
- sdh->CMDARG = cmd->arg;
- sdh->CTL = ctl;
- /* Wait a command done. */
- while ((sdh->CTL & (SDH_CTL_COEN_Msk)) == SDH_CTL_COEN_Msk) { }
- if (resp_type(cmd) != RESP_NONE)
- {
- if (resp_type(cmd) == RESP_R2)
- {
- /* Wait to receive a response R2 from SD card and store the response data into DMC's Flash buffer (exclude CRC7). */
- while (sdh->CTL & SDH_CTL_R2EN_Msk)
- {
- /* When get a Response timeout, break the polling. */
- if (SDH_GET_INT_FLAG(sdh, SDH_INTSTS_RTOIF_Msk))
- {
- ret = __LINE__;
- goto exit_nu_sdh_sendcmd;
- }
- }
- }
- else
- {
- /* Wait to receive a response from SD card. */
- while ((sdh->CTL & SDH_CTL_RIEN_Msk))
- {
- /* When get a Response timeout, break the polling. */
- if (SDH_GET_INT_FLAG(sdh, SDH_INTSTS_RTOIF_Msk))
- {
- ret = __LINE__;
- goto exit_nu_sdh_sendcmd;
- }
- }
- /* TOFIX: ISSUE: Sometimes, SDH's RIEN is cleared automatically by controller after host sending CMD5 to SD card. */
- /* Workaround: To check previous cmd's response with CMD's. */
- if (cmd->cmd_code == 5)
- {
- if ((NuSdh->u32CmdResp0 == sdh->RESP0) && (NuSdh->u32CmdResp1 == sdh->RESP1))
- {
- LOG_E("False CMD5-RESP issue occured.\n");
- ret = __LINE__;
- goto exit_nu_sdh_sendcmd;
- }
- }
- NuSdh->u32CmdResp0 = sdh->RESP0;
- NuSdh->u32CmdResp1 = sdh->RESP1;
- }
- /* Get response from FB or register */
- nu_sdh_sendcmd_done(sdh, cmd);
- }
- if (data != RT_NULL)
- {
- /* Wait data processing done */
- nu_sdh_xfer_data(sdh, data);
- ret = SDH_GetBusStatus(sdh, 0);
- if (ret)
- {
- LOG_E("ERROR: Busy %d\n", ret);
- ret = __LINE__;
- goto exit_nu_sdh_sendcmd;
- }
- }
- /* Handle CRC flag */
- if (SDH_GET_INT_FLAG(sdh, SDH_INTSTS_CRCIF_Msk)) // Fault
- {
- uint32_t u32INTSTS = sdh->INTSTS;
- SDH_CLR_INT_FLAG(sdh, SDH_INTSTS_CRCIF_Msk);
- ret = __LINE__;
- if ((resp_type(cmd) != RESP_R3) && (u32INTSTS & SDH_INTSTS_CRC7_Msk) == 0) //CRC7, Ignore R3
- {
- LOG_E("CRC7 error! (resp_type=%d)", resp_type(cmd));
- goto exit_nu_sdh_sendcmd;
- }
- if ((u32INTSTS & SDH_INTSTS_CRC16_Msk) == 0) //CRC16
- {
- LOG_E("CRC16 error! (resp_type=%d)", resp_type(cmd));
- goto exit_nu_sdh_sendcmd;
- }
- }
- return 0;
- exit_nu_sdh_sendcmd:
- LOG_D("[%s %d] cmdid=%d error line=%d", __func__, __LINE__, cmd->cmd_code, ret);
- cmd->resp[0] = cmd->resp[1] = cmd->resp[2] = cmd->resp[3] = 0;
- sdh->TOUT = 0;
- SDH_Enable(sdh);
- return -ret;
- }
- /**
- * @brief This function send request.
- * @param host rt_mmcsd_host
- * @param req request
- * @retval None
- */
- static void nu_sdh_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
- {
- nu_sdh_t NuSdh;
- SDH_T *sdh;
- RT_ASSERT(host);
- RT_ASSERT(req);
- NuSdh = (nu_sdh_t)host->private_data;
- sdh = NuSdh->base;
- if (!SDH_GetCD(sdh)) // card is not present
- {
- LOG_E("Card is not present");
- req->cmd->err = -RT_EIO;
- goto exit_nu_sdh_request;
- }
- if (req->cmd != RT_NULL)
- {
- struct rt_mmcsd_cmd *cmd = req->cmd;
- struct rt_mmcsd_data *data = req->data;
- LOG_D("[%s%s%s%s%s]REQ: CMD:%d ARG:0x%08x RESP_TYPE:%d rw:%c addr:%08x, blks:%d, blksize:%d datalen:%d",
- (host->card == RT_NULL) ? "Unknown" : "",
- (host->card) && (host->card->card_type == CARD_TYPE_MMC) ? "MMC" : "",
- (host->card) && (host->card->card_type == CARD_TYPE_SD) ? "SD" : "",
- (host->card) && (host->card->card_type == CARD_TYPE_SDIO) ? "SDIO" : "",
- (host->card) && (host->card->card_type == CARD_TYPE_SDIO_COMBO) ? "SDIO_COMBO" : "",
- cmd->cmd_code,
- cmd->arg,
- resp_type(cmd),
- data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-',
- data ? data->buf : 0,
- data ? data->blks : 0,
- data ? data->blksize : 0,
- data ? data->blks * data->blksize : 0);
- if (data != RT_NULL)
- {
- rt_uint32_t size;
- rt_int32_t IsNonaligned = 0;
- rt_uint32_t *org_data_buf = data->buf;
- size = data->blksize * data->blks;
- RT_ASSERT(org_data_buf);
- IsNonaligned = (((rt_uint32_t)data->buf & (SDH_ALIGN_LEN - 1)) > 0) ? 1 : 0;
- if (IsNonaligned)
- {
- /* Allocate memory temp buffer on demand. */
- RT_ASSERT(size <= SDH_BUFF_SIZE);
- if (NuSdh->cachebuf == RT_NULL)
- {
- NuSdh->cachebuf = rt_malloc_align(SDH_BUFF_SIZE, SDH_ALIGN_LEN);
- RT_ASSERT(NuSdh->cachebuf);
- }
- data->buf = (rt_uint32_t *)NuSdh->cachebuf;
- if (data->flags & DATA_DIR_WRITE)
- {
- LOG_D("Un-aligned, prepare into cache buf(%d)", size);
- rt_memcpy(data->buf, org_data_buf, size);
- }
- }
- cmd->err = nu_sdh_sendcmd(host, cmd, data);
- if (!cmd->err && IsNonaligned)
- {
- if (data->flags & DATA_DIR_READ)
- {
- LOG_D("Un-aligned, restore from cache buf(%d)", size);
- rt_memcpy(org_data_buf, data->buf, size);
- }
- }
- data->buf = org_data_buf;
- LOG_HEX("data.dest", 16, (void *)data->buf, size);
- }
- else
- {
- cmd->err = nu_sdh_sendcmd(host, cmd, NULL);
- }
- if (resp_type(cmd) != RESP_NONE)
- LOG_HEX("cmd->resp", 16, (void *)&cmd->resp[0], 16);
- }
- if (req->stop != RT_NULL)
- {
- struct rt_mmcsd_cmd *stop = req->stop;
- stop->err = nu_sdh_sendcmd(host, stop, NULL);
- if (resp_type(stop) != RESP_NONE)
- LOG_HEX("stop->resp", 16, (void *)&stop->resp[0], 16);
- }
- exit_nu_sdh_request:
- mmcsd_req_complete(host);
- }
- /**
- * @brief This function config.
- * @param host rt_mmcsd_host
- * @param io_cfg rt_mmcsd_io_cfg
- * @retval None
- */
- static void nu_sdh_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
- {
- nu_sdh_t NuSdh;
- rt_uint32_t clk;
- SDH_T *sdh;
- RT_ASSERT(host);
- RT_ASSERT(io_cfg);
- NuSdh = (nu_sdh_t)host->private_data;
- sdh = NuSdh->base;
- clk = io_cfg->clock;
- LOG_D("[%s]clk:%d width(%d):%s%s%s power:%s%s%s",
- NuSdh->name,
- clk,
- io_cfg->bus_width,
- (io_cfg->bus_width) == MMCSD_BUS_WIDTH_8 ? "8" : "",
- (io_cfg->bus_width) == MMCSD_BUS_WIDTH_4 ? "4" : "",
- (io_cfg->bus_width) == MMCSD_BUS_WIDTH_1 ? "1" : "",
- io_cfg->power_mode == MMCSD_POWER_OFF ? "OFF" : "",
- io_cfg->power_mode == MMCSD_POWER_UP ? "UP" : "",
- io_cfg->power_mode == MMCSD_POWER_ON ? "ON" : "");
- /* Clock */
- if (clk > host->freq_max)
- clk = host->freq_max;
- if (clk < host->freq_min)
- clk = host->freq_min;
- LOG_D("[%s] ExceptedFreq: %d kHz", NuSdh->name, clk / 1000);
- if (NuSdh->u32CurClk != (clk / 1000))
- {
- SDH_SetClock(sdh, clk / 1000);
- NuSdh->u32CurClk = (clk / 1000);
- }
- switch (io_cfg->power_mode)
- {
- case MMCSD_POWER_UP:
- if (clk <= 400000)
- {
- /* power ON 74 clock */
- sdh->CTL |= SDH_CTL_CLK74OEN_Msk;
- while ((sdh->CTL & SDH_CTL_CLK74OEN_Msk) == SDH_CTL_CLK74OEN_Msk)
- {
- }
- }
- break;
- case MMCSD_POWER_ON:
- break;
- case MMCSD_POWER_OFF:
- break;
- default:
- break;
- }
- /* Bus width */
- switch ((io_cfg->bus_width))
- {
- case MMCSD_BUS_WIDTH_1:
- SDH_SetBusWidth(sdh, 1);
- break;
- case MMCSD_BUS_WIDTH_4:
- SDH_SetBusWidth(sdh, 4);
- break;
- case MMCSD_BUS_WIDTH_8:
- default:
- break;
- }
- }
- /**
- * @brief This function detect sdcard.
- * @param host rt_mmcsd_host
- * @retval card detection status
- */
- static rt_int32_t nu_sdh_card_detect(struct rt_mmcsd_host *host)
- {
- nu_sdh_t NuSdh;
- RT_ASSERT(host);
- NuSdh = (nu_sdh_t)host->private_data;
- SDH_T *sdh = NuSdh->base;
- LOG_D("try to detect device");
- return SDH_GetCD(sdh);
- }
- static void nu_sdh_isr(nu_sdh_t NuSdh)
- {
- SDH_T *sdh = NuSdh->base;
- uint32_t isr = sdh->INTSTS;
- /* card detected */
- if (isr & SDH_INTSTS_CDIF_Msk)
- {
- rt_tick_t cur_tick = rt_tick_get();
- rt_tick_t diff_tick;
- /* ready to change */
- if (cur_tick >= NuSdh->LastNotice)
- diff_tick = (cur_tick - NuSdh->LastNotice);
- else
- diff_tick = ((rt_tick_t) -1) - NuSdh->LastNotice + cur_tick;
- if (!NuSdh->LastNotice || (diff_tick > (RT_TICK_PER_SECOND / 5))) // Debounce 200ms
- {
- NuSdh->LastNotice = cur_tick;
- mmcsd_change(NuSdh->host);
- }
- /* Clear CDIF interrupt flag */
- SDH_CLR_INT_FLAG(sdh, SDH_INTSTS_CDIF_Msk);
- }
- }
- #if defined(BSP_USING_SDH0)
- void SDH0_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_sdh_isr(&nu_sdh_arr[SDH0_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #if defined(BSP_USING_SDH1)
- void SDH1_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_sdh_isr(&nu_sdh_arr[SDH1_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- /**
- * @brief This function update sdh interrupt.
- * @param host rt_mmcsd_host
- * @param enable
- * @retval None
- */
- void nu_sdh_irq_update(struct rt_mmcsd_host *host, rt_int32_t enable)
- {
- nu_sdh_t NuSdh = (nu_sdh_t)host->private_data;
- SDH_T *sdh = NuSdh->base;
- if (enable)
- {
- LOG_D("Enable %s irq", NuSdh->name);
- SDH_ENABLE_INT(sdh, SDH_INTSTS_CDIF_Msk);
- }
- else
- {
- LOG_D("Disable %s irq", NuSdh->name);
- SDH_DISABLE_INT(sdh, SDH_INTSTS_CDIF_Msk);
- }
- }
- static const struct rt_mmcsd_host_ops ops =
- {
- nu_sdh_request,
- nu_sdh_iocfg,
- nu_sdh_card_detect,
- nu_sdh_irq_update,
- };
- /**
- * @brief This function create mmcsd host.
- * @param sdh nu_sdh_t
- * @retval nuvton
- */
- void nu_sdh_host_init(nu_sdh_t sdh)
- {
- struct rt_mmcsd_host *host = mmcsd_alloc_host();
- RT_ASSERT(host);
- /* set host default attributes */
- host->ops = &ops;
- host->freq_min = 300 * 1000;
- host->freq_max = 48 * 1000 * 1000;
- host->valid_ocr = VDD_26_27 | VDD_27_28 | VDD_28_29 | VDD_29_30 | VDD_30_31 | VDD_31_32 | VDD_32_33 | VDD_33_34;
- host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED;
- host->max_seg_size = SDH_BUFF_SIZE;
- host->max_dma_segs = 1;
- host->max_blk_size = SDH_BLOCK_SIZE;
- host->max_blk_count = (SDH_BUFF_SIZE / SDH_BLOCK_SIZE);
- /* link up host and sdio */
- host->private_data = sdh;
- sdh->host = host;
- /* Enable DMA engine at first. */
- SDH_Enable(sdh->base);
- /* Install ISR. */
- NVIC_EnableIRQ(sdh->irqn);
- /* ready to change */
- //mmcsd_change(host);
- }
- static int rt_hw_sdh_init(void)
- {
- int i;
- for (i = (SDH_START + 1); i < SDH_CNT; i++)
- {
- CLK_EnableModuleClock(nu_sdh_arr[i].modid);
- SYS_ResetModule(nu_sdh_arr[i].rstidx);
- nu_sdh_host_init(&nu_sdh_arr[i]);
- }
- return 0;
- }
- INIT_DEVICE_EXPORT(rt_hw_sdh_init);
- void nu_sd_attach(void)
- {
- int i;
- /* ready to change */
- for (i = (SDH_START + 1); i < SDH_CNT; i++)
- {
- if (nu_sdh_arr[i].host)
- mmcsd_change(nu_sdh_arr[i].host);
- }
- }
- MSH_CMD_EXPORT(nu_sd_attach, attach card);
- void nu_sd_regdump(void)
- {
- int i;
- for (i = (SDH_START + 1); i < SDH_CNT; i++)
- {
- if (nu_sdh_arr[i].host)
- LOG_HEX("sdh_reg", 16, (void *)nu_sdh_arr[i].base, sizeof(SDH_T));
- }
- }
- MSH_CMD_EXPORT(nu_sd_regdump, dump sdh registers);
- #endif
|