add raspi4 sdio driver
This commit is contained in:
parent
8cf83694ae
commit
74812c0f2d
|
@ -112,7 +112,23 @@ CONFIG_DFS_FILESYSTEMS_MAX=2
|
||||||
CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
|
CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
|
||||||
CONFIG_DFS_FD_MAX=16
|
CONFIG_DFS_FD_MAX=16
|
||||||
# CONFIG_RT_USING_DFS_MNTTABLE is not set
|
# CONFIG_RT_USING_DFS_MNTTABLE is not set
|
||||||
# CONFIG_RT_USING_DFS_ELMFAT is not set
|
CONFIG_RT_USING_DFS_ELMFAT=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# elm-chan's FatFs, Generic FAT Filesystem Module
|
||||||
|
#
|
||||||
|
CONFIG_RT_DFS_ELM_CODE_PAGE=437
|
||||||
|
CONFIG_RT_DFS_ELM_WORD_ACCESS=y
|
||||||
|
# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set
|
||||||
|
# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set
|
||||||
|
# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
|
||||||
|
CONFIG_RT_DFS_ELM_USE_LFN_3=y
|
||||||
|
CONFIG_RT_DFS_ELM_USE_LFN=3
|
||||||
|
CONFIG_RT_DFS_ELM_MAX_LFN=255
|
||||||
|
CONFIG_RT_DFS_ELM_DRIVES=2
|
||||||
|
CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
|
||||||
|
# CONFIG_RT_DFS_ELM_USE_ERASE is not set
|
||||||
|
CONFIG_RT_DFS_ELM_REENTRANT=y
|
||||||
CONFIG_RT_USING_DFS_DEVFS=y
|
CONFIG_RT_USING_DFS_DEVFS=y
|
||||||
# CONFIG_RT_USING_DFS_ROMFS is not set
|
# CONFIG_RT_USING_DFS_ROMFS is not set
|
||||||
# CONFIG_RT_USING_DFS_RAMFS is not set
|
# CONFIG_RT_USING_DFS_RAMFS is not set
|
||||||
|
@ -140,7 +156,13 @@ CONFIG_RT_USING_PIN=y
|
||||||
# CONFIG_RT_USING_MTD_NAND is not set
|
# CONFIG_RT_USING_MTD_NAND is not set
|
||||||
# CONFIG_RT_USING_PM is not set
|
# CONFIG_RT_USING_PM is not set
|
||||||
# CONFIG_RT_USING_RTC is not set
|
# CONFIG_RT_USING_RTC is not set
|
||||||
# CONFIG_RT_USING_SDIO is not set
|
CONFIG_RT_USING_SDIO=y
|
||||||
|
CONFIG_RT_SDIO_STACK_SIZE=512
|
||||||
|
CONFIG_RT_SDIO_THREAD_PRIORITY=15
|
||||||
|
CONFIG_RT_MMCSD_STACK_SIZE=1024
|
||||||
|
CONFIG_RT_MMCSD_THREAD_PREORITY=22
|
||||||
|
CONFIG_RT_MMCSD_MAX_PARTITION=16
|
||||||
|
# CONFIG_RT_SDIO_DEBUG is not set
|
||||||
CONFIG_RT_USING_SPI=y
|
CONFIG_RT_USING_SPI=y
|
||||||
# CONFIG_RT_USING_QSPI is not set
|
# CONFIG_RT_USING_QSPI is not set
|
||||||
# CONFIG_RT_USING_SPI_MSD is not set
|
# CONFIG_RT_USING_SPI_MSD is not set
|
||||||
|
@ -525,7 +547,8 @@ CONFIG_BSP_USING_CORETIMER=y
|
||||||
# CONFIG_BSP_USING_SYSTIMER is not set
|
# CONFIG_BSP_USING_SYSTIMER is not set
|
||||||
CONFIG_BSP_USING_WDT=y
|
CONFIG_BSP_USING_WDT=y
|
||||||
# CONFIG_BSP_USING_RTC is not set
|
# CONFIG_BSP_USING_RTC is not set
|
||||||
# CONFIG_BSP_USING_SDIO is not set
|
CONFIG_BSP_USING_SDIO=y
|
||||||
|
CONFIG_BSP_USING_SDIO0=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Board Peripheral Drivers
|
# Board Peripheral Drivers
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2017-5-30 bernard the first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
|
||||||
|
#ifdef BSP_USING_SDIO0
|
||||||
|
#include <dfs_fs.h>
|
||||||
|
|
||||||
|
int mnt_init(void)
|
||||||
|
{
|
||||||
|
rt_thread_delay(RT_TICK_PER_SECOND);
|
||||||
|
if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("file system initialization done!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
INIT_ENV_EXPORT(mnt_init);
|
||||||
|
#endif
|
|
@ -0,0 +1,656 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2020-10-27 bigmagic first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mbox.h"
|
||||||
|
#include "raspi4.h"
|
||||||
|
#include "drv_sdio.h"
|
||||||
|
|
||||||
|
static rt_uint32_t mmc_base_clock = 0;
|
||||||
|
|
||||||
|
static rt_uint32_t sdCommandTable[] = {
|
||||||
|
SD_CMD_INDEX(0),
|
||||||
|
SD_CMD_RESERVED(1),
|
||||||
|
SD_CMD_INDEX(2) | SD_RESP_R2,
|
||||||
|
SD_CMD_INDEX(3) | SD_RESP_R1,
|
||||||
|
SD_CMD_INDEX(4),
|
||||||
|
SD_CMD_RESERVED(5), //SD_CMD_INDEX(5) | SD_RESP_R4,
|
||||||
|
SD_CMD_INDEX(6) | SD_RESP_R1,
|
||||||
|
SD_CMD_INDEX(7) | SD_RESP_R1b,
|
||||||
|
SD_CMD_INDEX(8) | SD_RESP_R1,
|
||||||
|
SD_CMD_INDEX(9) | SD_RESP_R2,
|
||||||
|
SD_CMD_INDEX(10) | SD_RESP_R2,
|
||||||
|
SD_CMD_INDEX(11) | SD_RESP_R1,
|
||||||
|
SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT,
|
||||||
|
SD_CMD_INDEX(13) | SD_RESP_R1,
|
||||||
|
SD_CMD_RESERVED(14),
|
||||||
|
SD_CMD_INDEX(15),
|
||||||
|
SD_CMD_INDEX(16) | SD_RESP_R1,
|
||||||
|
SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ,
|
||||||
|
SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
|
||||||
|
SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ,
|
||||||
|
SD_CMD_INDEX(20) | SD_RESP_R1b,
|
||||||
|
SD_CMD_RESERVED(21),
|
||||||
|
SD_CMD_RESERVED(22),
|
||||||
|
SD_CMD_INDEX(23) | SD_RESP_R1,
|
||||||
|
SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE,
|
||||||
|
SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
|
||||||
|
SD_CMD_INDEX(26) | SD_RESP_R1 | SD_DATA_WRITE, //add
|
||||||
|
SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE,
|
||||||
|
SD_CMD_INDEX(28) | SD_RESP_R1b,
|
||||||
|
SD_CMD_INDEX(29) | SD_RESP_R1b,
|
||||||
|
SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ,
|
||||||
|
SD_CMD_RESERVED(31),
|
||||||
|
SD_CMD_INDEX(32) | SD_RESP_R1,
|
||||||
|
SD_CMD_INDEX(33) | SD_RESP_R1,
|
||||||
|
SD_CMD_RESERVED(34),
|
||||||
|
SD_CMD_INDEX(35) | SD_RESP_R1, //add
|
||||||
|
SD_CMD_INDEX(36) | SD_RESP_R1, //add
|
||||||
|
SD_CMD_RESERVED(37),
|
||||||
|
SD_CMD_INDEX(38) | SD_RESP_R1b,
|
||||||
|
SD_CMD_INDEX(39) | SD_RESP_R4, //add
|
||||||
|
SD_CMD_INDEX(40) | SD_RESP_R5, //add
|
||||||
|
SD_CMD_INDEX(41) | SD_RESP_R3, //add, mov from harbote
|
||||||
|
SD_CMD_RESERVED(42) | SD_RESP_R1,
|
||||||
|
SD_CMD_RESERVED(43),
|
||||||
|
SD_CMD_RESERVED(44),
|
||||||
|
SD_CMD_RESERVED(45),
|
||||||
|
SD_CMD_RESERVED(46),
|
||||||
|
SD_CMD_RESERVED(47),
|
||||||
|
SD_CMD_RESERVED(48),
|
||||||
|
SD_CMD_RESERVED(49),
|
||||||
|
SD_CMD_RESERVED(50),
|
||||||
|
SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ,
|
||||||
|
SD_CMD_RESERVED(52),
|
||||||
|
SD_CMD_RESERVED(53),
|
||||||
|
SD_CMD_RESERVED(54),
|
||||||
|
SD_CMD_INDEX(55) | SD_RESP_R3,
|
||||||
|
SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA,
|
||||||
|
SD_CMD_RESERVED(57),
|
||||||
|
SD_CMD_RESERVED(58),
|
||||||
|
SD_CMD_RESERVED(59),
|
||||||
|
SD_CMD_RESERVED(60),
|
||||||
|
SD_CMD_RESERVED(61),
|
||||||
|
SD_CMD_RESERVED(62),
|
||||||
|
SD_CMD_RESERVED(63)
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline rt_uint32_t read32(rt_uint32_t addr)
|
||||||
|
{
|
||||||
|
return (*((volatile unsigned int*)(addr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void write32(rt_uint32_t addr, rt_uint32_t value)
|
||||||
|
{
|
||||||
|
(*((volatile unsigned int*)(addr))) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_err_t sd_int(struct sdhci_pdata_t * pdat, rt_uint32_t mask)
|
||||||
|
{
|
||||||
|
rt_uint32_t r;
|
||||||
|
rt_uint32_t m = mask | INT_ERROR_MASK;
|
||||||
|
int cnt = 1000000;
|
||||||
|
while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--)
|
||||||
|
DELAY_MICROS(1);
|
||||||
|
r = read32(pdat->virt + EMMC_INTERRUPT);
|
||||||
|
if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT))
|
||||||
|
{
|
||||||
|
write32(pdat->virt + EMMC_INTERRUPT, r);
|
||||||
|
//qemu maybe can not use sdcard
|
||||||
|
//rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n",mask, r, read32(pdat->virt + EMMC_STATUS));
|
||||||
|
//return -RT_ETIMEOUT;
|
||||||
|
}
|
||||||
|
else if (r & INT_ERROR_MASK)
|
||||||
|
{
|
||||||
|
write32(pdat->virt + EMMC_INTERRUPT, r);
|
||||||
|
rt_kprintf("send cmd/data error %x -> %x\n",r, read32(pdat->virt + EMMC_INTERRUPT));
|
||||||
|
return -RT_ERROR;
|
||||||
|
}
|
||||||
|
write32(pdat->virt + EMMC_INTERRUPT, mask);
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_err_t sd_status(struct sdhci_pdata_t * pdat, unsigned int mask)
|
||||||
|
{
|
||||||
|
int cnt = 500000;
|
||||||
|
while ((read32(pdat->virt + EMMC_STATUS) & mask) && !(read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) && cnt--)
|
||||||
|
DELAY_MICROS(1);
|
||||||
|
if (cnt <= 0)
|
||||||
|
{
|
||||||
|
return -RT_ETIMEOUT;
|
||||||
|
}
|
||||||
|
else if (read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK)
|
||||||
|
{
|
||||||
|
return -RT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd)
|
||||||
|
{
|
||||||
|
rt_uint32_t cmdidx;
|
||||||
|
rt_err_t ret = RT_EOK;
|
||||||
|
ret = sd_status(pdat, SR_CMD_INHIBIT);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
rt_kprintf("ERROR: EMMC busy %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdidx = sdCommandTable[cmd->cmdidx];
|
||||||
|
if (cmdidx == 0xFFFFFFFF)
|
||||||
|
return -RT_EINVAL;
|
||||||
|
if (cmd->datarw == DATA_READ)
|
||||||
|
cmdidx |= SD_DATA_READ;
|
||||||
|
if (cmd->datarw == DATA_WRITE)
|
||||||
|
cmdidx |= SD_DATA_WRITE;
|
||||||
|
mmcsd_dbg("transfer cmd %x(%d) %x %x\n", cmdidx, cmd->cmdidx, cmd->cmdarg, read32(pdat->virt + EMMC_INTERRUPT));
|
||||||
|
write32(pdat->virt + EMMC_INTERRUPT,read32(pdat->virt + EMMC_INTERRUPT));
|
||||||
|
write32(pdat->virt + EMMC_ARG1, cmd->cmdarg);
|
||||||
|
write32(pdat->virt + EMMC_CMDTM, cmdidx);
|
||||||
|
if (cmd->cmdidx == SD_APP_OP_COND)
|
||||||
|
DELAY_MICROS(1000);
|
||||||
|
else if ((cmd->cmdidx == SD_SEND_IF_COND) || (cmd->cmdidx == APP_CMD))
|
||||||
|
DELAY_MICROS(100);
|
||||||
|
|
||||||
|
ret = sd_int(pdat, INT_CMD_DONE);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (cmd->resptype & RESP_MASK)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (cmd->resptype & RESP_R2)
|
||||||
|
{
|
||||||
|
rt_uint32_t resp[4];
|
||||||
|
resp[0] = read32(pdat->virt + EMMC_RESP0);
|
||||||
|
resp[1] = read32(pdat->virt + EMMC_RESP1);
|
||||||
|
resp[2] = read32(pdat->virt + EMMC_RESP2);
|
||||||
|
resp[3] = read32(pdat->virt + EMMC_RESP3);
|
||||||
|
if (cmd->resptype == RESP_R2)
|
||||||
|
{
|
||||||
|
cmd->response[0] = resp[3]<<8 |((resp[2]>>24)&0xff);
|
||||||
|
cmd->response[1] = resp[2]<<8 |((resp[1]>>24)&0xff);
|
||||||
|
cmd->response[2] = resp[1]<<8 |((resp[0]>>24)&0xff);
|
||||||
|
cmd->response[3] = resp[0]<<8 ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd->response[0] = resp[0];
|
||||||
|
cmd->response[1] = resp[1];
|
||||||
|
cmd->response[2] = resp[2];
|
||||||
|
cmd->response[3] = resp[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cmd->response[0] = read32(pdat->virt + EMMC_RESP0);
|
||||||
|
}
|
||||||
|
mmcsd_dbg("response: %x: %x %x %x %x (%x, %x)\n", cmd->resptype, cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3], read32(pdat->virt + EMMC_STATUS),read32(pdat->virt + EMMC_INTERRUPT));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
rt_err_t ret;
|
||||||
|
int d;
|
||||||
|
while (c < blkcount)
|
||||||
|
{
|
||||||
|
if ((ret = sd_int(pdat, INT_READ_RDY)))
|
||||||
|
{
|
||||||
|
rt_kprintf("timeout happens when reading block %d\n",c);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
for (d=0; d < blksize / 4; d++)
|
||||||
|
if (read32(pdat->virt + EMMC_STATUS) & SR_READ_AVAILABLE)
|
||||||
|
buf[d] = read32(pdat->virt + EMMC_DATA);
|
||||||
|
c++;
|
||||||
|
buf += blksize / 4;
|
||||||
|
}
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
rt_err_t ret;
|
||||||
|
int d;
|
||||||
|
while (c < blkcount)
|
||||||
|
{
|
||||||
|
if ((ret = sd_int(pdat, INT_WRITE_RDY)))
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
for (d=0; d < blksize / 4; d++)
|
||||||
|
write32(pdat->virt + EMMC_DATA, buf[d]);
|
||||||
|
c++;
|
||||||
|
buf += blksize / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = sd_int(pdat, INT_DATA_DONE)))
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
|
||||||
|
{
|
||||||
|
rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
|
||||||
|
rt_err_t ret = sd_status(pdat, SR_DAT_INHIBIT);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
rt_kprintf("ERROR: EMMC busy\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (dat->blkcnt > 1)
|
||||||
|
{
|
||||||
|
struct sdhci_cmd_t newcmd;
|
||||||
|
newcmd.cmdidx = SET_BLOCK_COUNT;
|
||||||
|
newcmd.cmdarg = dat->blkcnt;
|
||||||
|
newcmd.resptype = RESP_R1;
|
||||||
|
ret = raspi_transfer_command(pdat, &newcmd);
|
||||||
|
if (ret) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dlen < 512)
|
||||||
|
{
|
||||||
|
write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write32(pdat->virt + EMMC_BLKSIZECNT, 512 | (dat->blkcnt) << 16);
|
||||||
|
}
|
||||||
|
if (dat->flag & DATA_DIR_READ)
|
||||||
|
{
|
||||||
|
cmd->datarw = DATA_READ;
|
||||||
|
ret = raspi_transfer_command(pdat, cmd);
|
||||||
|
if (ret) return ret;
|
||||||
|
mmcsd_dbg("read_block %d, %d\n", dat->blkcnt, dat->blksz );
|
||||||
|
ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
|
||||||
|
}
|
||||||
|
else if (dat->flag & DATA_DIR_WRITE)
|
||||||
|
{
|
||||||
|
cmd->datarw = DATA_WRITE;
|
||||||
|
ret = raspi_transfer_command(pdat, cmd);
|
||||||
|
if (ret) return ret;
|
||||||
|
mmcsd_dbg("write_block %d, %d", dat->blkcnt, dat->blksz );
|
||||||
|
ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
|
||||||
|
{
|
||||||
|
struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
|
||||||
|
if (!dat)
|
||||||
|
return raspi_transfer_command(pdat, cmd);
|
||||||
|
|
||||||
|
return raspi_transfer_data(pdat, cmd, dat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
|
||||||
|
{
|
||||||
|
struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
|
||||||
|
struct sdhci_cmd_t cmd;
|
||||||
|
struct sdhci_cmd_t stop;
|
||||||
|
struct sdhci_data_t dat;
|
||||||
|
rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
|
||||||
|
rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
|
||||||
|
rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
|
||||||
|
|
||||||
|
cmd.cmdidx = req->cmd->cmd_code;
|
||||||
|
cmd.cmdarg = req->cmd->arg;
|
||||||
|
cmd.resptype =resp_type(req->cmd);
|
||||||
|
if (req->data)
|
||||||
|
{
|
||||||
|
dat.buf = (rt_uint8_t *)req->data->buf;
|
||||||
|
dat.flag = req->data->flags;
|
||||||
|
dat.blksz = req->data->blksize;
|
||||||
|
dat.blkcnt = req->data->blks;
|
||||||
|
|
||||||
|
req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
req->cmd->resp[3] = cmd.response[3];
|
||||||
|
req->cmd->resp[2] = cmd.response[2];
|
||||||
|
req->cmd->resp[1] = cmd.response[1];
|
||||||
|
req->cmd->resp[0] = cmd.response[0];
|
||||||
|
|
||||||
|
if (req->stop)
|
||||||
|
{
|
||||||
|
stop.cmdidx = req->stop->cmd_code;
|
||||||
|
stop.cmdarg = req->stop->arg;
|
||||||
|
cmd.resptype =resp_type(req->stop);
|
||||||
|
req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
mmcsd_req_complete(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_int32_t mmc_card_status(struct rt_mmcsd_host *host)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_detect(struct sdhci_t * sdhci)
|
||||||
|
{
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width)
|
||||||
|
{
|
||||||
|
rt_uint32_t temp = 0;
|
||||||
|
struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
|
||||||
|
if (width == MMCSD_BUS_WIDTH_4)
|
||||||
|
{
|
||||||
|
temp = read32((pdat->virt + EMMC_CONTROL0));
|
||||||
|
temp |= C0_HCTL_HS_EN;
|
||||||
|
temp |= C0_HCTL_DWITDH; // always use 4 data lines:
|
||||||
|
write32((pdat->virt + EMMC_CONTROL0), temp);
|
||||||
|
}
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer ,rt_uint32_t base_clock, rt_uint32_t target_rate)
|
||||||
|
{
|
||||||
|
rt_uint32_t targetted_divisor = 0;
|
||||||
|
rt_uint32_t freq_select = 0;
|
||||||
|
rt_uint32_t upper_bits = 0;
|
||||||
|
rt_uint32_t ret = 0;
|
||||||
|
|
||||||
|
if(target_rate > base_clock)
|
||||||
|
targetted_divisor = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetted_divisor = base_clock / target_rate;
|
||||||
|
rt_uint32_t mod = base_clock % target_rate;
|
||||||
|
if(mod)
|
||||||
|
targetted_divisor--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decide on the clock mode to use
|
||||||
|
|
||||||
|
// Currently only 10-bit divided clock mode is supported
|
||||||
|
|
||||||
|
// HCI version 3 or greater supports 10-bit divided clock mode
|
||||||
|
// This requires a power-of-two divider
|
||||||
|
|
||||||
|
// Find the first bit set
|
||||||
|
int divisor = -1;
|
||||||
|
for(int first_bit = 31; first_bit >= 0; first_bit--)
|
||||||
|
{
|
||||||
|
rt_uint32_t bit_test = (1 << first_bit);
|
||||||
|
if(targetted_divisor & bit_test)
|
||||||
|
{
|
||||||
|
divisor = first_bit;
|
||||||
|
targetted_divisor &= ~bit_test;
|
||||||
|
if(targetted_divisor)
|
||||||
|
{
|
||||||
|
// The divisor is not a power-of-two, increase it
|
||||||
|
divisor++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(divisor == -1)
|
||||||
|
divisor = 31;
|
||||||
|
if(divisor >= 32)
|
||||||
|
divisor = 31;
|
||||||
|
|
||||||
|
if(divisor != 0)
|
||||||
|
divisor = (1 << (divisor - 1));
|
||||||
|
|
||||||
|
if(divisor >= 0x400)
|
||||||
|
divisor = 0x3ff;
|
||||||
|
|
||||||
|
freq_select = divisor & 0xff;
|
||||||
|
upper_bits = (divisor >> 8) & 0x3;
|
||||||
|
ret = (freq_select << 8) | (upper_bits << 6) | (0 << 5);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock)
|
||||||
|
{
|
||||||
|
rt_uint32_t temp = 0;
|
||||||
|
rt_uint32_t sdHostVer = 0;
|
||||||
|
int count = 100000;
|
||||||
|
struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)(sdhci->priv);
|
||||||
|
|
||||||
|
while ((read32(pdat->virt + EMMC_STATUS) & (SR_CMD_INHIBIT | SR_DAT_INHIBIT)) && (--count))
|
||||||
|
DELAY_MICROS(1);
|
||||||
|
if (count <= 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n",read32(pdat->virt + EMMC_STATUS));
|
||||||
|
return RT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch clock off.
|
||||||
|
temp = read32((pdat->virt + EMMC_CONTROL1));
|
||||||
|
temp &= ~C1_CLK_EN;
|
||||||
|
write32((pdat->virt + EMMC_CONTROL1),temp);
|
||||||
|
DELAY_MICROS(10);
|
||||||
|
// Request the new clock setting and enable the clock
|
||||||
|
temp = read32(pdat->virt + EMMC_SLOTISR_VER);
|
||||||
|
sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT;
|
||||||
|
int cdiv = sd_get_clock_divider(sdHostVer, mmc_base_clock, clock);
|
||||||
|
temp = read32((pdat->virt + EMMC_CONTROL1));
|
||||||
|
temp |= 1;
|
||||||
|
temp |= cdiv;
|
||||||
|
temp |= (7 << 16);
|
||||||
|
|
||||||
|
temp = (temp & 0xffff003f) | cdiv;
|
||||||
|
write32((pdat->virt + EMMC_CONTROL1),temp);
|
||||||
|
DELAY_MICROS(10);
|
||||||
|
|
||||||
|
// Enable the clock.
|
||||||
|
temp = read32(pdat->virt + EMMC_CONTROL1);
|
||||||
|
temp |= C1_CLK_EN;
|
||||||
|
write32((pdat->virt + EMMC_CONTROL1),temp);
|
||||||
|
DELAY_MICROS(10);
|
||||||
|
|
||||||
|
// Wait for clock to be stable.
|
||||||
|
count = 10000;
|
||||||
|
while (!(read32(pdat->virt + EMMC_CONTROL1) & C1_CLK_STABLE) && count--)
|
||||||
|
DELAY_MICROS(10);
|
||||||
|
if (count <= 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("EMMC: ERROR: failed to get stable clock %d.\n", clock);
|
||||||
|
return RT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
mmcsd_dbg("set stable clock %d.\n", clock);
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
|
||||||
|
{
|
||||||
|
struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data;
|
||||||
|
sdhci_setclock(sdhci, io_cfg->clock);
|
||||||
|
sdhci_setwidth(sdhci, io_cfg->bus_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rt_mmcsd_host_ops ops =
|
||||||
|
{
|
||||||
|
mmc_request_send,
|
||||||
|
mmc_set_iocfg,
|
||||||
|
RT_NULL,
|
||||||
|
RT_NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static rt_err_t reset_emmc(struct sdhci_pdata_t * pdat)
|
||||||
|
{
|
||||||
|
rt_uint32_t control1;
|
||||||
|
|
||||||
|
//Reset the controller
|
||||||
|
control1 = read32((pdat->virt + EMMC_CONTROL1));
|
||||||
|
control1 |= (1 << 24);
|
||||||
|
// Disable clock
|
||||||
|
control1 &= ~(1 << 2);
|
||||||
|
control1 &= ~(1 << 0);
|
||||||
|
//temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX;
|
||||||
|
write32((pdat->virt + EMMC_CONTROL1),control1);
|
||||||
|
int cnt = 10000;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DELAY_MICROS(10);
|
||||||
|
cnt = cnt - 1;
|
||||||
|
if(cnt == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((read32(pdat->virt + EMMC_CONTROL1) & (0x7 << 24)) != 0);
|
||||||
|
|
||||||
|
// Enable SD Bus Power VDD1 at 3.3V
|
||||||
|
rt_uint32_t control0 = read32(pdat->virt + EMMC_CONTROL0);
|
||||||
|
control0 |= 0x0F << 8;
|
||||||
|
write32(pdat->virt + EMMC_CONTROL0, control0);
|
||||||
|
|
||||||
|
rt_thread_delay(100);
|
||||||
|
//usleep(2000);
|
||||||
|
|
||||||
|
|
||||||
|
// Check for a valid card
|
||||||
|
mmcsd_dbg("EMMC: checking for an inserted card\n");
|
||||||
|
cnt = 10000;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DELAY_MICROS(10);
|
||||||
|
cnt = cnt - 1;
|
||||||
|
if(cnt == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((read32(pdat->virt + EMMC_STATUS) & (0x1 << 16)) == 0);
|
||||||
|
|
||||||
|
rt_uint32_t status_reg = read32(pdat->virt + EMMC_STATUS);
|
||||||
|
|
||||||
|
if((status_reg & (1 << 16)) == 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("EMMC: no card inserted\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mmcsd_dbg("EMMC: status: %08x\n", status_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear control2
|
||||||
|
write32(pdat->virt + EMMC_CONTROL2, 0);
|
||||||
|
|
||||||
|
// Get the base clock rate
|
||||||
|
mmc_base_clock = bcm271x_mbox_clock_get_rate(12);
|
||||||
|
if(mmc_base_clock == 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("EMMC: assuming clock rate to be 100MHz\n");
|
||||||
|
mmc_base_clock = 100000000;
|
||||||
|
}
|
||||||
|
mmcsd_dbg("EMMC: setting clock rate is %d\n", mmc_base_clock);
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RT_MMCSD_DBG
|
||||||
|
void dump_registers(struct sdhci_pdata_t * pdat)
|
||||||
|
{
|
||||||
|
rt_kprintf("EMMC registers:");
|
||||||
|
int i = EMMC_ARG2;
|
||||||
|
for (; i <= EMMC_CONTROL2; i += 4)
|
||||||
|
rt_kprintf("\t%x:%x\n", i, read32(pdat->virt + i));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0x50, read32(pdat->virt + 0x50));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0x70, read32(pdat->virt + 0x70));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0x74, read32(pdat->virt + 0x74));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0x80, read32(pdat->virt + 0x80));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0x84, read32(pdat->virt + 0x84));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0x88, read32(pdat->virt + 0x88));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0x8c, read32(pdat->virt + 0x8c));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0x90, read32(pdat->virt + 0x90));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0xf0, read32(pdat->virt + 0xf0));
|
||||||
|
rt_kprintf("\t%x:%x\n", 0xfc, read32(pdat->virt + 0xfc));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int raspi_sdmmc_init(void)
|
||||||
|
{
|
||||||
|
rt_uint32_t virt;
|
||||||
|
struct rt_mmcsd_host * host = RT_NULL;
|
||||||
|
struct sdhci_pdata_t * pdat = RT_NULL;
|
||||||
|
struct sdhci_t * sdhci = RT_NULL;
|
||||||
|
|
||||||
|
#ifdef BSP_USING_SDIO0
|
||||||
|
host = mmcsd_alloc_host();
|
||||||
|
if (!host)
|
||||||
|
{
|
||||||
|
rt_kprintf("alloc host failed");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdhci = rt_malloc(sizeof(struct sdhci_t));
|
||||||
|
if (!sdhci)
|
||||||
|
{
|
||||||
|
rt_kprintf("alloc sdhci failed");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
rt_memset(sdhci, 0, sizeof(struct sdhci_t));
|
||||||
|
|
||||||
|
virt = MMC2_BASE_ADDR;
|
||||||
|
|
||||||
|
pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t));
|
||||||
|
RT_ASSERT(pdat != RT_NULL);
|
||||||
|
|
||||||
|
pdat->virt = (rt_uint32_t)virt;
|
||||||
|
reset_emmc(pdat);
|
||||||
|
|
||||||
|
sdhci->name = "sd0";
|
||||||
|
sdhci->voltages = VDD_33_34;
|
||||||
|
sdhci->width = MMCSD_BUSWIDTH_4;
|
||||||
|
sdhci->clock = 250 * 1000 * 1000;
|
||||||
|
sdhci->removeable = RT_TRUE;
|
||||||
|
|
||||||
|
sdhci->detect = sdhci_detect;
|
||||||
|
sdhci->setwidth = sdhci_setwidth;
|
||||||
|
sdhci->setclock = sdhci_setclock;
|
||||||
|
sdhci->transfer = sdhci_transfer;
|
||||||
|
sdhci->priv = pdat;
|
||||||
|
host->ops = &ops;
|
||||||
|
host->freq_min = 400000;
|
||||||
|
host->freq_max = 50000000;
|
||||||
|
host->valid_ocr = VDD_32_33 | VDD_33_34;
|
||||||
|
host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
|
||||||
|
host->max_seg_size = 2048;
|
||||||
|
host->max_dma_segs = 10;
|
||||||
|
host->max_blk_size = 512;
|
||||||
|
host->max_blk_count = 4096;
|
||||||
|
|
||||||
|
host->private_data = sdhci;
|
||||||
|
|
||||||
|
write32((pdat->virt + EMMC_IRPT_EN),0xffffffff);
|
||||||
|
write32((pdat->virt + EMMC_IRPT_MASK),0xffffffff);
|
||||||
|
#ifdef RT_MMCSD_DBG
|
||||||
|
dump_registers(pdat);
|
||||||
|
#endif
|
||||||
|
mmcsd_change(host);
|
||||||
|
#endif
|
||||||
|
return RT_EOK;
|
||||||
|
err:
|
||||||
|
if (host) rt_free(host);
|
||||||
|
if (sdhci) rt_free(sdhci);
|
||||||
|
|
||||||
|
return -RT_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_DEVICE_EXPORT(raspi_sdmmc_init);
|
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2020-10-27 bigmagic first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DRV_SDIO_H__
|
||||||
|
#define __DRV_SDIO_H__
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
#include <drivers/mmcsd_core.h>
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "raspi4.h"
|
||||||
|
|
||||||
|
/* Struct for Intrrrupt Information */
|
||||||
|
#define SDXC_CmdDone BIT(0)
|
||||||
|
#define SDXC_DataDone BIT(1)
|
||||||
|
#define SDXC_BlockGap BIT(2)
|
||||||
|
#define SDXC_WriteRdy BIT(4)
|
||||||
|
#define SDXC_ReadRdy BIT(5)
|
||||||
|
#define SDXC_Card BIT(8)
|
||||||
|
#define SDXC_Retune BIT(12)
|
||||||
|
#define SDXC_BootAck BIT(13)
|
||||||
|
#define SDXC_EndBoot BIT(14)
|
||||||
|
#define SDXC_Err BIT(15)
|
||||||
|
#define SDXC_CTOErr BIT(16)
|
||||||
|
#define SDXC_CCRCErr BIT(17)
|
||||||
|
#define SDXC_CENDErr BIT(18)
|
||||||
|
#define SDXC_CBADErr BIT(19)
|
||||||
|
#define SDXC_DTOErr BIT(20)
|
||||||
|
#define SDXC_DCRCErr BIT(21)
|
||||||
|
#define SDXC_DENDErr BIT(22)
|
||||||
|
#define SDXC_ACMDErr BIT(24)
|
||||||
|
|
||||||
|
#define SDXC_BLKCNT_EN BIT(1)
|
||||||
|
#define SDXC_AUTO_CMD12_EN BIT(2)
|
||||||
|
#define SDXC_AUTO_CMD23_EN BIT(3)
|
||||||
|
#define SDXC_DAT_DIR BIT(4) //from card to host
|
||||||
|
#define SDXC_MULTI_BLOCK BIT(5)
|
||||||
|
#define SDXC_CMD_RSPNS_136 BIT(16)
|
||||||
|
#define SDXC_CMD_RSPNS_48 BIT(17)
|
||||||
|
#define SDXC_CMD_RSPNS_48busy BIT(16)|BIT(17)
|
||||||
|
#define SDXC_CHECK_CRC_CMD BIT(19)
|
||||||
|
#define SDXC_CMD_IXCHK_EN BIT(20)
|
||||||
|
#define SDXC_CMD_ISDATA BIT(21)
|
||||||
|
#define SDXC_CMD_SUSPEND BIT(22)
|
||||||
|
#define SDXC_CMD_RESUME BIT(23)
|
||||||
|
#define SDXC_CMD_ABORT BIT(23)|BIT(22)
|
||||||
|
|
||||||
|
#define SDXC_CMD_INHIBIT BIT(0)
|
||||||
|
#define SDXC_DAT_INHIBIT BIT(1)
|
||||||
|
#define SDXC_DAT_ACTIVE BIT(2)
|
||||||
|
#define SDXC_WRITE_TRANSFER BIT(8)
|
||||||
|
#define SDXC_READ_TRANSFER BIT(9)
|
||||||
|
|
||||||
|
struct sdhci_cmd_t
|
||||||
|
{
|
||||||
|
rt_uint32_t cmdidx;
|
||||||
|
rt_uint32_t cmdarg;
|
||||||
|
rt_uint32_t resptype;
|
||||||
|
rt_uint32_t datarw;
|
||||||
|
#define DATA_READ 1
|
||||||
|
#define DATA_WRITE 2
|
||||||
|
rt_uint32_t response[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sdhci_data_t
|
||||||
|
{
|
||||||
|
rt_uint8_t * buf;
|
||||||
|
rt_uint32_t flag;
|
||||||
|
rt_uint32_t blksz;
|
||||||
|
rt_uint32_t blkcnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sdhci_t
|
||||||
|
{
|
||||||
|
char * name;
|
||||||
|
rt_uint32_t voltages;
|
||||||
|
rt_uint32_t width;
|
||||||
|
rt_uint32_t clock;
|
||||||
|
rt_err_t removeable;
|
||||||
|
void * sdcard;
|
||||||
|
|
||||||
|
rt_err_t (*detect)(struct sdhci_t * sdhci);
|
||||||
|
rt_err_t (*setwidth)(struct sdhci_t * sdhci, rt_uint32_t width);
|
||||||
|
rt_err_t (*setclock)(struct sdhci_t * sdhci, rt_uint32_t clock);
|
||||||
|
rt_err_t (*transfer)(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat);
|
||||||
|
void * priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sdhci_pdata_t
|
||||||
|
{
|
||||||
|
rt_uint32_t virt;
|
||||||
|
};
|
||||||
|
|
||||||
|
// EMMC command flags
|
||||||
|
#define CMD_TYPE_NORMAL (0x00000000)
|
||||||
|
#define CMD_TYPE_SUSPEND (0x00400000)
|
||||||
|
#define CMD_TYPE_RESUME (0x00800000)
|
||||||
|
#define CMD_TYPE_ABORT (0x00c00000)
|
||||||
|
#define CMD_IS_DATA (0x00200000)
|
||||||
|
#define CMD_IXCHK_EN (0x00100000)
|
||||||
|
#define CMD_CRCCHK_EN (0x00080000)
|
||||||
|
#define CMD_RSPNS_NO (0x00000000)
|
||||||
|
#define CMD_RSPNS_136 (0x00010000)
|
||||||
|
#define CMD_RSPNS_48 (0x00020000)
|
||||||
|
#define CMD_RSPNS_48B (0x00030000)
|
||||||
|
#define TM_MULTI_BLOCK (0x00000020)
|
||||||
|
#define TM_DAT_DIR_HC (0x00000000)
|
||||||
|
#define TM_DAT_DIR_CH (0x00000010)
|
||||||
|
#define TM_AUTO_CMD23 (0x00000008)
|
||||||
|
#define TM_AUTO_CMD12 (0x00000004)
|
||||||
|
#define TM_BLKCNT_EN (0x00000002)
|
||||||
|
#define TM_MULTI_DATA (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN)
|
||||||
|
|
||||||
|
#define RCA_NO (1)
|
||||||
|
#define RCA_YES (2)
|
||||||
|
|
||||||
|
// INTERRUPT register settings
|
||||||
|
#define INT_AUTO_ERROR (0x01000000)
|
||||||
|
#define INT_DATA_END_ERR (0x00400000)
|
||||||
|
#define INT_DATA_CRC_ERR (0x00200000)
|
||||||
|
#define INT_DATA_TIMEOUT (0x00100000)
|
||||||
|
#define INT_INDEX_ERROR (0x00080000)
|
||||||
|
#define INT_END_ERROR (0x00040000)
|
||||||
|
#define INT_CRC_ERROR (0x00020000)
|
||||||
|
#define INT_CMD_TIMEOUT (0x00010000)
|
||||||
|
#define INT_ERR (0x00008000)
|
||||||
|
#define INT_ENDBOOT (0x00004000)
|
||||||
|
#define INT_BOOTACK (0x00002000)
|
||||||
|
#define INT_RETUNE (0x00001000)
|
||||||
|
#define INT_CARD (0x00000100)
|
||||||
|
#define INT_READ_RDY (0x00000020)
|
||||||
|
#define INT_WRITE_RDY (0x00000010)
|
||||||
|
#define INT_BLOCK_GAP (0x00000004)
|
||||||
|
#define INT_DATA_DONE (0x00000002)
|
||||||
|
#define INT_CMD_DONE (0x00000001)
|
||||||
|
#define INT_ERROR_MASK (INT_CRC_ERROR|INT_END_ERROR|INT_INDEX_ERROR| \
|
||||||
|
INT_DATA_TIMEOUT|INT_DATA_CRC_ERR|INT_DATA_END_ERR| \
|
||||||
|
INT_ERR|INT_AUTO_ERROR)
|
||||||
|
#define INT_ALL_MASK (INT_CMD_DONE|INT_DATA_DONE|INT_READ_RDY|INT_WRITE_RDY|INT_ERROR_MASK)
|
||||||
|
|
||||||
|
#define EMMC_ARG2 (0x00)
|
||||||
|
#define EMMC_BLKSIZECNT (0x04)
|
||||||
|
#define EMMC_ARG1 (0x08)
|
||||||
|
#define EMMC_CMDTM (0x0c)
|
||||||
|
#define EMMC_RESP0 (0x10)
|
||||||
|
#define EMMC_RESP1 (0x14)
|
||||||
|
#define EMMC_RESP2 (0x18)
|
||||||
|
#define EMMC_RESP3 (0x1c)
|
||||||
|
#define EMMC_DATA (0x20)
|
||||||
|
#define EMMC_STATUS (0x24)
|
||||||
|
#define EMMC_CONTROL0 (0x28)
|
||||||
|
#define EMMC_CONTROL1 (0x2c)
|
||||||
|
#define EMMC_INTERRUPT (0x30)
|
||||||
|
#define EMMC_IRPT_MASK (0x34)
|
||||||
|
#define EMMC_IRPT_EN (0x38)
|
||||||
|
#define EMMC_CONTROL2 (0x3c)
|
||||||
|
#define EMMC_CAPABILITIES_0 (0x40)
|
||||||
|
#define EMMC_CAPABILITIES_1 (0x44)
|
||||||
|
#define EMMC_BOOT_TIMEOUT (0x70)
|
||||||
|
#define EMMC_EXRDFIFO_EN (0x84)
|
||||||
|
#define EMMC_SPI_INT_SPT (0xf0)
|
||||||
|
#define EMMC_SLOTISR_VER (0xfc)
|
||||||
|
|
||||||
|
// CONTROL register settings
|
||||||
|
#define C0_SPI_MODE_EN (0x00100000)
|
||||||
|
#define C0_HCTL_HS_EN (0x00000004)
|
||||||
|
#define C0_HCTL_DWITDH (0x00000002)
|
||||||
|
|
||||||
|
#define C1_SRST_DATA (0x04000000)
|
||||||
|
#define C1_SRST_CMD (0x02000000)
|
||||||
|
#define C1_SRST_HC (0x01000000)
|
||||||
|
#define C1_TOUNIT_DIS (0x000f0000)
|
||||||
|
#define C1_TOUNIT_MAX (0x000e0000)
|
||||||
|
#define C1_CLK_GENSEL (0x00000020)
|
||||||
|
#define C1_CLK_EN (0x00000004)
|
||||||
|
#define C1_CLK_STABLE (0x00000002)
|
||||||
|
#define C1_CLK_INTLEN (0x00000001)
|
||||||
|
|
||||||
|
#define FREQ_SETUP (400000) // 400 Khz
|
||||||
|
#define FREQ_NORMAL (25000000) // 25 Mhz
|
||||||
|
|
||||||
|
// SLOTISR_VER values
|
||||||
|
#define HOST_SPEC_NUM 0x00ff0000
|
||||||
|
#define HOST_SPEC_NUM_SHIFT 16
|
||||||
|
#define HOST_SPEC_V3 2
|
||||||
|
#define HOST_SPEC_V2 1
|
||||||
|
#define HOST_SPEC_V1 0
|
||||||
|
|
||||||
|
// STATUS register settings
|
||||||
|
#define SR_DAT_LEVEL1 (0x1e000000)
|
||||||
|
#define SR_CMD_LEVEL (0x01000000)
|
||||||
|
#define SR_DAT_LEVEL0 (0x00f00000)
|
||||||
|
#define SR_DAT3 (0x00800000)
|
||||||
|
#define SR_DAT2 (0x00400000)
|
||||||
|
#define SR_DAT1 (0x00200000)
|
||||||
|
#define SR_DAT0 (0x00100000)
|
||||||
|
#define SR_WRITE_PROT (0x00080000) // From SDHC spec v2, BCM says reserved
|
||||||
|
#define SR_READ_AVAILABLE (0x00000800) // ???? undocumented
|
||||||
|
#define SR_WRITE_AVAILABLE (0x00000400) // ???? undocumented
|
||||||
|
#define SR_READ_TRANSFER (0x00000200)
|
||||||
|
#define SR_WRITE_TRANSFER (0x00000100)
|
||||||
|
#define SR_DAT_ACTIVE (0x00000004)
|
||||||
|
#define SR_DAT_INHIBIT (0x00000002)
|
||||||
|
#define SR_CMD_INHIBIT (0x00000001)
|
||||||
|
|
||||||
|
#define CONFIG_MMC_USE_DMA
|
||||||
|
#define DMA_ALIGN (32U)
|
||||||
|
|
||||||
|
#define SD_CMD_INDEX(a) ((a) << 24)
|
||||||
|
#define SD_CMD_RESERVED(a) (0xffffffff)
|
||||||
|
#define SD_CMD_INDEX(a) ((a) << 24)
|
||||||
|
#define SD_CMD_TYPE_NORMAL (0x0)
|
||||||
|
#define SD_CMD_TYPE_SUSPEND (1 << 22)
|
||||||
|
#define SD_CMD_TYPE_RESUME (2 << 22)
|
||||||
|
#define SD_CMD_TYPE_ABORT (3 << 22)
|
||||||
|
#define SD_CMD_TYPE_MASK (3 << 22)
|
||||||
|
#define SD_CMD_ISDATA (1 << 21)
|
||||||
|
#define SD_CMD_IXCHK_EN (1 << 20)
|
||||||
|
#define SD_CMD_CRCCHK_EN (1 << 19)
|
||||||
|
#define SD_CMD_RSPNS_TYPE_NONE (0) // For no response
|
||||||
|
#define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC)
|
||||||
|
#define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC)
|
||||||
|
#define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC)
|
||||||
|
#define SD_CMD_RSPNS_TYPE_MASK (3 << 16)
|
||||||
|
#define SD_CMD_MULTI_BLOCK (1 << 5)
|
||||||
|
#define SD_CMD_DAT_DIR_HC (0)
|
||||||
|
#define SD_CMD_DAT_DIR_CH (1 << 4)
|
||||||
|
#define SD_CMD_AUTO_CMD_EN_NONE (0)
|
||||||
|
#define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2)
|
||||||
|
#define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2)
|
||||||
|
#define SD_CMD_BLKCNT_EN (1 << 1)
|
||||||
|
#define SD_CMD_DMA (1)
|
||||||
|
#define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE
|
||||||
|
#define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48) // | SD_CMD_CRCCHK_EN)
|
||||||
|
#define SD_RESP_R1b (SD_CMD_RSPNS_TYPE_48B) // | SD_CMD_CRCCHK_EN)
|
||||||
|
#define SD_RESP_R2 (SD_CMD_RSPNS_TYPE_136) // | SD_CMD_CRCCHK_EN)
|
||||||
|
#define SD_RESP_R3 SD_CMD_RSPNS_TYPE_48
|
||||||
|
#define SD_RESP_R4 SD_CMD_RSPNS_TYPE_136
|
||||||
|
#define SD_RESP_R5 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
|
||||||
|
#define SD_RESP_R5b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN)
|
||||||
|
#define SD_RESP_R6 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
|
||||||
|
#define SD_RESP_R7 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
|
||||||
|
#define SD_DATA_READ (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH)
|
||||||
|
#define SD_DATA_WRITE (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC)
|
||||||
|
#endif
|
|
@ -131,6 +131,27 @@ typedef enum {
|
||||||
#define PM_RSTC_WRCFG_CLR (0xffffffcf)
|
#define PM_RSTC_WRCFG_CLR (0xffffffcf)
|
||||||
#define PM_RSTC_RESET (0x00000102)
|
#define PM_RSTC_RESET (0x00000102)
|
||||||
|
|
||||||
|
//timer
|
||||||
|
#define ST_BASE_OFFSET (0x003000)
|
||||||
|
#define STIMER_BASE (PER_BASE + ST_BASE_OFFSET)
|
||||||
|
#define STIMER_CS __REG32(STIMER_BASE + 0x0000)
|
||||||
|
#define STIMER_CLO __REG32(STIMER_BASE + 0x0004)
|
||||||
|
#define STIMER_CHI __REG32(STIMER_BASE + 0x0008)
|
||||||
|
#define STIMER_C0 __REG32(STIMER_BASE + 0x000C)
|
||||||
|
#define STIMER_C1 __REG32(STIMER_BASE + 0x0010)
|
||||||
|
#define STIMER_C2 __REG32(STIMER_BASE + 0x0014)
|
||||||
|
#define STIMER_C3 __REG32(STIMER_BASE + 0x0018)
|
||||||
|
|
||||||
|
#define DELAY_MICROS(micros) \
|
||||||
|
do{ \
|
||||||
|
rt_uint32_t compare = STIMER_CLO + micros * 25; \
|
||||||
|
while (STIMER_CLO < compare); \
|
||||||
|
} while (0) \
|
||||||
|
|
||||||
|
//External Mass Media Controller (SD Card)
|
||||||
|
#define MMC0_BASE_ADDR (PER_BASE+0x300000)
|
||||||
|
#define MMC2_BASE_ADDR (PER_BASE+0x340000)
|
||||||
|
|
||||||
/* the basic constants and interfaces needed by gic */
|
/* the basic constants and interfaces needed by gic */
|
||||||
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,6 +76,18 @@
|
||||||
#define DFS_FILESYSTEMS_MAX 2
|
#define DFS_FILESYSTEMS_MAX 2
|
||||||
#define DFS_FILESYSTEM_TYPES_MAX 2
|
#define DFS_FILESYSTEM_TYPES_MAX 2
|
||||||
#define DFS_FD_MAX 16
|
#define DFS_FD_MAX 16
|
||||||
|
#define RT_USING_DFS_ELMFAT
|
||||||
|
|
||||||
|
/* elm-chan's FatFs, Generic FAT Filesystem Module */
|
||||||
|
|
||||||
|
#define RT_DFS_ELM_CODE_PAGE 437
|
||||||
|
#define RT_DFS_ELM_WORD_ACCESS
|
||||||
|
#define RT_DFS_ELM_USE_LFN_3
|
||||||
|
#define RT_DFS_ELM_USE_LFN 3
|
||||||
|
#define RT_DFS_ELM_MAX_LFN 255
|
||||||
|
#define RT_DFS_ELM_DRIVES 2
|
||||||
|
#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
|
||||||
|
#define RT_DFS_ELM_REENTRANT
|
||||||
#define RT_USING_DFS_DEVFS
|
#define RT_USING_DFS_DEVFS
|
||||||
|
|
||||||
/* Device Drivers */
|
/* Device Drivers */
|
||||||
|
@ -86,6 +98,12 @@
|
||||||
#define RT_SERIAL_USING_DMA
|
#define RT_SERIAL_USING_DMA
|
||||||
#define RT_SERIAL_RB_BUFSZ 64
|
#define RT_SERIAL_RB_BUFSZ 64
|
||||||
#define RT_USING_PIN
|
#define RT_USING_PIN
|
||||||
|
#define RT_USING_SDIO
|
||||||
|
#define RT_SDIO_STACK_SIZE 512
|
||||||
|
#define RT_SDIO_THREAD_PRIORITY 15
|
||||||
|
#define RT_MMCSD_STACK_SIZE 1024
|
||||||
|
#define RT_MMCSD_THREAD_PREORITY 22
|
||||||
|
#define RT_MMCSD_MAX_PARTITION 16
|
||||||
#define RT_USING_SPI
|
#define RT_USING_SPI
|
||||||
#define RT_USING_WDT
|
#define RT_USING_WDT
|
||||||
|
|
||||||
|
@ -180,6 +198,8 @@
|
||||||
#define BSP_USING_SPI0_DEVICE0
|
#define BSP_USING_SPI0_DEVICE0
|
||||||
#define BSP_USING_CORETIMER
|
#define BSP_USING_CORETIMER
|
||||||
#define BSP_USING_WDT
|
#define BSP_USING_WDT
|
||||||
|
#define BSP_USING_SDIO
|
||||||
|
#define BSP_USING_SDIO0
|
||||||
|
|
||||||
/* Board Peripheral Drivers */
|
/* Board Peripheral Drivers */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue