123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018-02-08 RT-Thread the first version
- */
- #include <rtthread.h>
- #include <rthw.h>
- #include <rtdevice.h>
- #include <string.h>
- #include "drv_sdio.h"
- #include "interrupt.h"
- #include "mmu.h"
- #include "drv_gpio.h"
- #include "drv_clock.h"
- #define DBG_TAG "MMC"
- // #define DBG_LVL DBG_LOG
- // #define DBG_LVL DBG_INFO
- #define DBG_LVL DBG_WARNING
- // #define DBG_LVL DBG_ERROR
- #include <rtdbg.h>
- #ifdef RT_USING_SDIO
- #define CONFIG_MMC_USE_DMA
- #define DMA_ALIGN (32U)
- struct mmc_xfe_des
- {
- rt_uint32_t size; /* block size */
- rt_uint32_t num; /* block num */
- rt_uint8_t *buff; /* buff addr */
- rt_uint32_t flag; /* write or read or stream */
- #define MMC_DATA_WRITE (1 << 0)
- #define MMC_DATA_READ (1 << 1)
- #define MMC_DATA_STREAM (1 << 2)
- };
- struct mmc_flag
- {
- volatile rt_uint32_t risr;
- volatile rt_uint32_t idst;
- };
- struct sdio_drv
- {
- struct rt_mmcsd_host *host;
- struct rt_mmcsd_req *req;
- struct rt_semaphore rt_sem;
- struct mmc_xfe_des xfe;
- struct mmc_flag flag;
- tina_mmc_t mmc_des;
- rt_uint8_t *mmc_buf;
- rt_uint8_t usedma;
- };
- #ifdef CONFIG_MMC_USE_DMA
- #ifdef TINA_USING_SDIO0
- rt_align(32) static rt_uint8_t dma_buffer[64 * 1024];
- #endif
- #endif
- static void mmc_request_end(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req);
- static void mmc_delay_us(int us)
- {
- volatile unsigned int temp;
- while (us--)
- {
- temp = 0x2f;
- while (temp--)
- {
- temp = temp;
- };
- }
- }
- static void mmc_dump_errinfo(unsigned int err)
- {
- LOG_E("[err]:0x%08x, %s%s%s%s%s%s%s%s%s%s%s",
- err,
- err & SDXC_RespErr ? " RE" : "",
- err & SDXC_RespCRCErr ? " RCE" : "",
- err & SDXC_DataCRCErr ? " DCE" : "",
- err & SDXC_RespTimeout ? " RTO" : "",
- err & SDXC_DataTimeout ? " DTO" : "",
- err & SDXC_DataStarve ? " DS" : "",
- err & SDXC_FIFORunErr ? " FE" : "",
- err & SDXC_HardWLocked ? " HL" : "",
- err & SDXC_StartBitErr ? " SBE" : "",
- err & SDXC_EndBitErr ? " EBE" : "",
- err == 0 ? " STO" : ""
- );
- }
- static int mmc_update_clk(tina_mmc_t mmc)
- {
- rt_uint32_t cmd;
- rt_uint32_t timeout = 2000000;
- /* cmd load */
- cmd = SDXC_LOAD_CMD | SDXC_UPDATE_CLOCK_CMD | SDXC_WAIT_OVER_CMD;
- mmc->cmdr_reg = cmd;
- /* while load success */
- while ((mmc->cmdr_reg & SDXC_LOAD_CMD) && (--timeout))
- {
- mmc_delay_us(1);
- }
- if (!timeout)
- {
- LOG_E("mmc update clk failed");
- return -RT_ERROR;
- }
- /* clean interrupt */
- mmc->risr_reg = mmc->risr_reg;
- return RT_EOK;
- }
- static rt_err_t mmc_trans_data_by_dma(tina_mmc_t mmc, struct mmc_xfe_des *xfe)
- {
- rt_align(32) static struct mmc_des_v4p1 pdes[128];
- unsigned i, rval;
- unsigned des_idx;
- unsigned length = xfe->size * xfe->num;
- unsigned buff_frag_num = length >> SDXC_DES_NUM_SHIFT;
- unsigned remain = length & (SDXC_DES_BUFFER_MAX_LEN - 1);
- if (remain)
- {
- buff_frag_num ++;
- }
- else
- {
- remain = SDXC_DES_BUFFER_MAX_LEN;
- }
- memset(pdes, 0, sizeof(pdes));
- mmu_clean_dcache((rt_uint32_t)(xfe->buff), length);
- for (i = 0, des_idx = 0; i < buff_frag_num; i++, des_idx++)
- {
- // memset((void*)&pdes[des_idx], 0, sizeof(struct mmc_v4p1));
- pdes[des_idx].des_chain = 1;
- pdes[des_idx].own = 1;
- pdes[des_idx].dic = 1;
- if ((buff_frag_num > 1) && (i != buff_frag_num - 1))
- {
- pdes[des_idx].data_buf1_sz = SDXC_DES_BUFFER_MAX_LEN;
- }
- else
- {
- pdes[des_idx].data_buf1_sz = remain;
- }
- pdes[des_idx].buf_addr_ptr1 = (unsigned long)(xfe->buff) + i * SDXC_DES_BUFFER_MAX_LEN;
- if (i == 0)
- {
- pdes[des_idx].first_des = 1;
- }
- if (i == (buff_frag_num - 1))
- {
- pdes[des_idx].dic = 0;
- pdes[des_idx].last_des = 1;
- pdes[des_idx].end_of_ring = 1;
- pdes[des_idx].buf_addr_ptr2 = 0;
- }
- else
- {
- pdes[des_idx].buf_addr_ptr2 = (unsigned long)&pdes[des_idx+1];
- }
- LOG_D("frag %d, remain %d, des[%d](%08x): " \
- "[0] = %08x, [1] = %08x, [2] = %08x, [3] = %08x", \
- i, remain, des_idx, (unsigned int)&pdes[des_idx],
- (unsigned int)((unsigned int*)&pdes[des_idx])[0], (unsigned int)((unsigned int*)&pdes[des_idx])[1],
- (unsigned int)((unsigned int*)&pdes[des_idx])[2], (unsigned int)((unsigned int*)&pdes[des_idx])[3]);
- }
- mmu_clean_dcache((rt_uint32_t)pdes, sizeof(struct mmc_des_v4p1) * (des_idx + 1));
- /*
- * GCTRLREG
- * GCTRL[2] : DMA reset
- * GCTRL[5] : DMA enable
- *
- * IDMACREG
- * IDMAC[0] : IDMA soft reset
- * IDMAC[1] : IDMA fix burst flag
- * IDMAC[7] : IDMA on
- *
- * IDIECREG
- * IDIE[0] : IDMA transmit interrupt flag
- * IDIE[1] : IDMA receive interrupt flag
- */
- rval = mmc->gctl_reg;
- mmc->gctl_reg = rval | (1 << 5) | (1 << 2); /* dma enable */
- mmc->dmac_reg = (1 << 0); /* idma reset */
- while(mmc->dmac_reg & 0x1) {}; /* wait idma reset done */
- mmc->dmac_reg = (1 << 1) | (1 << 7); /* idma on */
- rval = mmc->idie_reg & (~3);
- if (xfe->flag == MMC_DATA_WRITE)
- rval |= (1 << 0);
- else
- rval |= (1 << 1);
- mmc->idie_reg = rval;
- mmc->dlba_reg = (unsigned long)pdes;
- mmc->fwlr_reg = (2U << 28) | (7U << 16) | 8;
- return 0;
- }
- static rt_err_t mmc_trans_data_by_cpu(tina_mmc_t mmc, struct mmc_xfe_des *xfe)
- {
- unsigned i;
- unsigned byte_cnt = xfe->size * xfe->num;
- unsigned *buff = (unsigned *)(xfe->buff);
- volatile unsigned timeout = 2000000;
- if (xfe->flag == MMC_DATA_WRITE)
- {
- for (i = 0; i < (byte_cnt >> 2); i++)
- {
- while(--timeout && (mmc->star_reg & (1 << 3)));
- if (timeout <= 0)
- {
- LOG_E("write data by cpu failed status:0x%08x", mmc->star_reg);
- return -RT_ERROR;
- }
- mmc->fifo_reg = buff[i];
- timeout = 2000000;
- }
- }
- else
- {
- for (i = 0; i < (byte_cnt >> 2); i++)
- {
- while(--timeout && (mmc->star_reg & (1 << 2)));
- if (timeout <= 0)
- {
- LOG_E("read data by cpu failed status:0x%08x", mmc->star_reg);
- return -RT_ERROR;
- }
- buff[i] = mmc->fifo_reg;
- timeout = 2000000;
- }
- }
- return RT_EOK;
- }
- static rt_err_t mmc_config_clock(tina_mmc_t mmc, int clk)
- {
- rt_uint32_t rval = 0;
- /* disable card clock */
- rval = mmc->ckcr_reg;
- rval &= ~(1 << 16);
- mmc->ckcr_reg = rval;
- if (mmc_update_clk(mmc) != RT_EOK)
- {
- LOG_E("clk update fail line:%d", __LINE__);
- return -RT_ERROR;
- }
- if (mmc == MMC0)
- {
- mmc_set_clk(SDMMC0, clk);
- }
- else
- {
- mmc_set_clk(SDMMC1, clk);
- }
- /* Re-enable card clock */
- rval = mmc->ckcr_reg;
- rval |= (0x1 << 16); //(3 << 16);
- mmc->ckcr_reg = rval;
- if(mmc_update_clk(mmc) != RT_EOK)
- {
- LOG_E("clk update fail line:%d", __LINE__);
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- static rt_err_t mmc_set_ios(tina_mmc_t mmc, int clk, int bus_width)
- {
- LOG_D("mmc set io bus width:%d clock:%d", \
- (bus_width == MMCSD_BUS_WIDTH_8 ? 8 : (bus_width == MMCSD_BUS_WIDTH_4 ? 4 : 1)), clk);
- /* change clock */
- if (clk && (mmc_config_clock(mmc, clk) != RT_EOK))
- {
- LOG_E("update clock failed");
- return -RT_ERROR;
- }
- /* Change bus width */
- if (bus_width == MMCSD_BUS_WIDTH_8)
- {
- mmc->bwdr_reg = 2;
- }
- else if (bus_width == MMCSD_BUS_WIDTH_4)
- {
- mmc->bwdr_reg = 1;
- }
- else
- {
- mmc->bwdr_reg = 0;
- }
- return RT_EOK;
- }
- static int mmc_send_cmd(struct rt_mmcsd_host *host, struct rt_mmcsd_cmd *cmd)
- {
- unsigned int cmdval = 0x80000000;
- signed int timeout = 0;
- int err = 0;
- unsigned int status = 0;
- struct rt_mmcsd_data *data = cmd->data;
- unsigned int bytecnt = 0;
- struct sdio_drv *sdio_des = (struct sdio_drv *)host->private_data;
- tina_mmc_t mmc = sdio_des->mmc_des;
- timeout = 5000 * 1000;
- status = mmc->star_reg;
- while (status & (1 << 9))
- {
- LOG_D("note: check card busy");
- status = mmc->star_reg;
- if (!timeout--)
- {
- err = -1;
- LOG_E("mmc cmd12 busy timeout data:0x%08x", status);
- return err;
- }
- mmc_delay_us(1);
- }
- /*
- * CMDREG
- * CMD[5:0] : Command index
- * CMD[6] : Has response
- * CMD[7] : Long response
- * CMD[8] : Check response CRC
- * CMD[9] : Has data
- * CMD[10] : Write
- * CMD[11] : Steam mode
- * CMD[12] : Auto stop
- * CMD[13] : Wait previous over
- * CMD[14] : About cmd
- * CMD[15] : Send initialization
- * CMD[21] : Update clock
- * CMD[31] : Load cmd
- */
- if (!cmd->cmd_code)
- cmdval |= (1 << 15);
- if (resp_type(cmd) != RESP_NONE)
- cmdval |= (1 << 6);
- if (resp_type(cmd) == RESP_R2)
- cmdval |= (1 << 7);
- if ((resp_type(cmd) != RESP_R3) && (resp_type(cmd) != RESP_R4))
- cmdval |= (1 << 8);
- if (data)
- {
- cmdval |= (1 << 9) | (1 << 13);
- if (data->flags & DATA_DIR_WRITE)
- cmdval |= (1 << 10);
- if (data->blks > 1)
- cmdval |= (1 << 12);
- mmc->bksr_reg = data->blksize;
- bytecnt = data->blksize * data->blks;
- mmc->bycr_reg = bytecnt;
- }
- LOG_D("cmd %d(0x%08x), arg 0x%08x", cmd->cmd_code, cmdval | cmd->cmd_code, cmd->arg);
- mmc->cagr_reg = cmd->arg;
- if (!data)
- {
- mmc->cmdr_reg = cmdval | cmd->cmd_code;
- mmc->imkr_reg |= 0x1 << 2;
- }
- /*
- * transfer data and check status
- * STATREG[2] : FIFO empty
- * STATREG[3] : FIFO full
- */
- if (data)
- {
- LOG_D("mmc trans data %d bytes addr:0x%08x", bytecnt, data);
- #ifdef CONFIG_MMC_USE_DMA
- if (bytecnt > 64)
- {
- #else
- if (0)
- {
- #endif
- sdio_des->usedma = 1;
- mmc->gctl_reg = mmc->gctl_reg & (~0x80000000);
- mmc_trans_data_by_dma(mmc, &sdio_des->xfe);
- mmc->cmdr_reg = cmdval | cmd->cmd_code;
- }
- else
- {
- sdio_des->usedma = 0;
- mmc->gctl_reg = mmc->gctl_reg | 0x80000000;
- mmc->cmdr_reg = cmdval | cmd->cmd_code;
- mmc_trans_data_by_cpu(mmc, &sdio_des->xfe);
- }
- if (data->blks > 1)
- {
- mmc->imkr_reg |= (0x1 << 14);
- }
- else
- {
- mmc->imkr_reg |= (0x1 << 3);
- }
- }
- mmc->imkr_reg |= 0xbfc2;
- if (data)
- {
- //TODO:2 * bytecnt * 4?
- timeout = sdio_des->usedma ? (2 * bytecnt * 4) : 100; //0.04us(25M)*2(4bit width)*25()
- if (timeout < 10)
- {
- timeout = 10;
- }
- }
- else
- {
- timeout = 200;
- }
- if (rt_sem_take(&sdio_des->rt_sem, timeout) != RT_EOK)
- {
- err = (mmc->risr_reg | sdio_des->flag.risr) & 0xbfc2;
- goto out;
- }
- err = (mmc->risr_reg | sdio_des->flag.risr) & 0xbfc2;
- if (err)
- {
- cmd->err = -RT_ETIMEOUT;
- goto out;
- }
- if (resp_type(cmd) == RESP_R2)
- {
- cmd->resp[3] = mmc->resp0_reg;
- cmd->resp[2] = mmc->resp1_reg;
- cmd->resp[1] = mmc->resp2_reg;
- cmd->resp[0] = mmc->resp3_reg;
- LOG_D("mmc resp 0x%08x 0x%08x 0x%08x 0x%08x",
- cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
- }
- else
- {
- cmd->resp[0] = mmc->resp0_reg;
- LOG_D("mmc resp 0x%08x", cmd->resp[0]);
- }
- out:
- if (err)
- {
- mmc_dump_errinfo(err & 0xbfc2);
- }
- if (data && sdio_des->usedma)
- {
- /* IDMASTAREG
- * IDST[0] : idma tx int
- * IDST[1] : idma rx int
- * IDST[2] : idma fatal bus error
- * IDST[4] : idma descriptor invalid
- * IDST[5] : idma error summary
- * IDST[8] : idma normal interrupt sumary
- * IDST[9] : idma abnormal interrupt sumary
- */
- status = mmc->idst_reg;
- mmc->idst_reg = status;
- mmc->idie_reg = 0;
- mmc->dmac_reg = 0;
- mmc->gctl_reg = mmc->gctl_reg & (~(1 << 5));
- }
- if (err)
- {
- if (data && (data->flags & DATA_DIR_READ) && (bytecnt == 512))
- {
- mmc->gctl_reg = mmc->gctl_reg | 0x80000000;
- mmc->dbgc_reg = 0xdeb;
- timeout = 1000;
- LOG_D("Read remain data");
- while (mmc->bbcr_reg < 512)
- {
- unsigned int tmp = mmc->fifo_reg;
- tmp = tmp;
- LOG_D("Read data 0x%08x, bbcr 0x%04x", tmp, mmc->bbcr_reg);
- mmc_delay_us(1);
- if (!(timeout--))
- {
- LOG_E("Read remain data timeout");
- break;
- }
- }
- }
- mmc->gctl_reg = 0x7;
- while (mmc->gctl_reg & 0x7) { };
- mmc_update_clk(mmc);
- cmd->err = -RT_ETIMEOUT;
- LOG_E("mmc cmd %d err", cmd->cmd_code);
- }
- mmc->gctl_reg &= ~(0x1 << 4);
- mmc->imkr_reg &= ~0xffff;
- mmc->risr_reg = 0xffffffff;
- mmc->gctl_reg |= 0x1 << 4;
- while (!rt_sem_take(&sdio_des->rt_sem, 0)) {}
- mmc_request_end(sdio_des->host, sdio_des->req);
- return err;
- }
- static void mmc_request_end(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
- {
- struct rt_mmcsd_data *data;
- unsigned byte_cnt;
- struct sdio_drv *sdio = (struct sdio_drv *)host->private_data;
- #ifdef CONFIG_MMC_USE_DMA
- data = req->cmd->data;
- if (data)
- {
- byte_cnt = data->blksize * data->blks;
- if ((byte_cnt > 64) && (data->flags & DATA_DIR_READ))
- {
- mmu_invalidate_dcache((rt_uint32_t)sdio->xfe.buff, (rt_uint32_t)byte_cnt);
- if (((rt_uint32_t)data->buf) & (DMA_ALIGN - 1))
- {
- memcpy(data->buf, sdio->xfe.buff, byte_cnt);
- }
- }
- }
- #endif
- mmcsd_req_complete(host);
- }
- static void sdio_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
- {
- struct rt_mmcsd_data *data;
- int byte_cnt;
- struct sdio_drv *sdio;
- sdio = (struct sdio_drv *)host->private_data;
- sdio->req = req;
- data = req->cmd->data;
- if (data)
- {
- sdio->xfe.size = data->blksize;
- sdio->xfe.num = data->blks;
- sdio->xfe.buff = (rt_uint8_t *)data->buf;
- sdio->xfe.flag = (data->flags & DATA_DIR_WRITE) ? \
- MMC_DATA_WRITE : MMC_DATA_READ;
- #ifdef CONFIG_MMC_USE_DMA
- byte_cnt = data->blksize * data->blks;
- if ((byte_cnt > 64) && (((rt_uint32_t)data->buf) & (DMA_ALIGN - 1)))
- {
- sdio->xfe.buff = (rt_uint8_t *)sdio->mmc_buf;
- if (data->flags & DATA_DIR_WRITE)
- {
- memcpy(sdio->mmc_buf, data->buf, byte_cnt);
- mmu_clean_dcache((rt_uint32_t)sdio->mmc_buf, (rt_uint32_t)byte_cnt);
- }
- }
- #endif
- }
- memset(&sdio->flag, 0, sizeof(struct mmc_flag));
- mmc_send_cmd(host, req->cmd);
- return;
- }
- static void sdio_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
- {
- int clk = io_cfg->clock;
- int width = io_cfg->bus_width;
- struct sdio_drv *sdio_des = (struct sdio_drv *)host->private_data;
- tina_mmc_t mmc = sdio_des->mmc_des;
- mmc_set_ios(mmc, clk, width);
- }
- static const struct rt_mmcsd_host_ops ops =
- {
- sdio_request_send,
- sdio_set_iocfg,
- RT_NULL,
- RT_NULL,
- };
- static void sdio_interrupt_handle(int irqno, void *param)
- {
- rt_uint32_t risr, idst;
- rt_uint32_t status;
- struct sdio_drv *sdio_des = (struct sdio_drv *)param;
- struct rt_mmcsd_data *data = sdio_des->req->cmd->data;
- tina_mmc_t mmc = sdio_des->mmc_des;
- risr = mmc->risr_reg;
- idst = mmc->idst_reg;
- mmc->risr_reg = risr & mmc->imkr_reg;
- mmc->idst_reg = idst & mmc->idie_reg;
- sdio_des->flag.risr |= risr;
- sdio_des->flag.idst |= idst;
- if (data)
- {
- int done = 0;
- status = sdio_des->flag.risr | mmc->risr_reg;
- if (data->blks > 1)//not wait auto stop when MMC_CMD_MANUAL is set
- {
- if (sdio_des->usedma)
- done = ((status & (1 << 14)) && (sdio_des->flag.idst & 0x3)) ? 1 : 0;
- else
- done = status & (1 << 14);
- }
- else
- {
- if (sdio_des->usedma)
- done = ((status & (1 << 3)) && (sdio_des->flag.idst & 0x3)) ? 1 : 0;
- else
- done = status & (1 << 3);
- }
- if (done)
- {
- rt_sem_release(&sdio_des->rt_sem);
- }
- }
- else
- {
- rt_sem_release(&sdio_des->rt_sem);
- }
- }
- static void sdio_gpio_init(struct sdio_drv *sdio_des)
- {
- int pin;
- if ((rt_uint32_t)sdio_des->mmc_des == MMC0_BASE_ADDR)
- {
- /* SDC0: PF0-PF5 */
- for (pin = GPIO_PIN_0; pin <= GPIO_PIN_5; pin++)
- {
- gpio_set_func(GPIO_PORT_F, pin, IO_FUN_1);
- gpio_set_pull_mode(GPIO_PORT_F, pin, PULL_UP);
- gpio_set_drive_level(GPIO_PORT_F, pin, DRV_LEVEL_2);
- }
- }
- else if ((rt_uint32_t)sdio_des->mmc_des == MMC1_BASE_ADDR)
- {
- //todo: config gpio port
- RT_ASSERT(0);
- }
- }
- static void sdio_clk_io_on(struct sdio_drv *sdio_des)
- {
- if ((rt_uint32_t)sdio_des->mmc_des == MMC0_BASE_ADDR)
- {
- CCU->bus_clk_gating0 |= 0x1 << 8;
- CCU->bus_soft_rst0 |= 0x1 << 8;
- }
- else if ((rt_uint32_t)sdio_des->mmc_des == MMC1_BASE_ADDR)
- {
- CCU->bus_clk_gating0 |= 0x1 << 9;
- CCU->bus_soft_rst0 |= 0x1 << 9;
- }
- mmc_set_clk(SDMMC0, 24000000);
- }
- static void sdio_irq_init(void *param)
- {
- struct sdio_drv *sdio_des = (struct sdio_drv *)param;
- if ((rt_uint32_t)sdio_des->mmc_des == MMC0_BASE_ADDR)
- {
- rt_hw_interrupt_install(SDC0_INTERRUPT, sdio_interrupt_handle, param, "mmc0_irq");
- rt_hw_interrupt_umask(SDC0_INTERRUPT);
- }
- else if ((rt_uint32_t)sdio_des->mmc_des == MMC1_BASE_ADDR)
- {
- rt_hw_interrupt_install(SDC1_INTERRUPT, sdio_interrupt_handle, param, "mmc1_irq");
- rt_hw_interrupt_umask(SDC1_INTERRUPT);
- }
- sdio_des->mmc_des->gctl_reg |= (0x1 << 4);
- }
- int tina_sdio_init(void)
- {
- struct rt_mmcsd_host *host;
- #ifdef TINA_USING_SDIO0
- {
- static struct sdio_drv _sdio_drv;
- host = mmcsd_alloc_host();
- if (!host)
- {
- LOG_E("alloc host failed");
- goto err;
- }
- if (rt_sem_init(&_sdio_drv.rt_sem, "sdio_sem", RT_NULL, RT_IPC_FLAG_FIFO))
- {
- LOG_E("sem init failed");
- goto err;
- }
- _sdio_drv.mmc_des = (tina_mmc_t)MMC0_BASE_ADDR;
- _sdio_drv.mmc_buf = dma_buffer;
- //init gpio pin
- sdio_gpio_init(&_sdio_drv);
- //clk is on
- sdio_clk_io_on(&_sdio_drv);
- //irq init
- sdio_irq_init(&_sdio_drv);
- host->ops = &ops;
- host->freq_min = 400 * 1000;
- host->freq_max = 50 * 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 | VDD_34_35 | VDD_35_36;
- host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ | MMCSD_SUP_HIGHSPEED;
- host->max_seg_size = 2048;
- host->max_dma_segs = 10;
- host->max_blk_size = 512;
- host->max_blk_count = 4096;
- host->private_data = &_sdio_drv;
- _sdio_drv.host = host;
- mmcsd_change(host);
- }
- #endif
- return RT_EOK;
- err:
- if (host)
- {
- rt_free(host);
- }
- return -RT_ERROR;
- }
- INIT_APP_EXPORT(tina_sdio_init);
- #endif
|