git subrepo pull emummc
subrepo: subdir: "emummc" merged: "817020a9" upstream: origin: "https://github.com/m4xw/emuMMC" branch: "develop" commit: "817020a9" git-subrepo: version: "0.4.0" origin: "https://github.com/ingydotnet/git-subrepo" commit: "5d6aba9"
This commit is contained in:
@@ -23,9 +23,13 @@
|
||||
#include "sd.h"
|
||||
#include "../utils/types.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../utils/fatal.h"
|
||||
|
||||
#define DPRINTF(...) //fprintf(stdout, __VA_ARGS__)
|
||||
|
||||
sdmmc_accessor_t *_current_accessor = NULL;
|
||||
bool sdmmc_memcpy_buf = false;
|
||||
|
||||
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||
{
|
||||
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
|
||||
@@ -41,6 +45,80 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||
* Common functions for SD and MMC.
|
||||
*/
|
||||
|
||||
// FS DMA calculations.
|
||||
intptr_t sdmmc_calculate_dma_addr(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors)
|
||||
{
|
||||
int dma_buf_idx = 0;
|
||||
char *_buf = (char *)buf;
|
||||
char *actual_buf_start = _buf;
|
||||
char *actual_buf_end = &_buf[512 * num_sectors];
|
||||
char *dma_buffer_start = _this->parent->dmaBuffers[FS_SDMMC_EMMC].device_addr_buffer;
|
||||
|
||||
if (dma_buffer_start <= _buf && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[FS_SDMMC_EMMC].device_addr_buffer_size])
|
||||
{
|
||||
dma_buf_idx = FS_SDMMC_EMMC;
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_buffer_start = _this->parent->dmaBuffers[FS_SDMMC_SD].device_addr_buffer;
|
||||
if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[FS_SDMMC_SD].device_addr_buffer_size])
|
||||
{
|
||||
dma_buf_idx = FS_SDMMC_SD;
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_buffer_start = _this->parent->dmaBuffers[FS_SDMMC_GC].device_addr_buffer;
|
||||
if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[FS_SDMMC_GC].device_addr_buffer_size])
|
||||
{
|
||||
dma_buf_idx = FS_SDMMC_GC;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If buffer is on a random heap
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sdmmc_memcpy_buf = false;
|
||||
|
||||
intptr_t admaaddr = (intptr_t)&_this->parent->dmaBuffers[dma_buf_idx].device_addr_buffer_masked[actual_buf_start - dma_buffer_start];
|
||||
return admaaddr;
|
||||
}
|
||||
|
||||
int sdmmc_get_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_sectors)
|
||||
{
|
||||
int dma_buf_idx = 0;
|
||||
int blkSize = num_sectors * 512;
|
||||
|
||||
if (_this->parent->dmaBuffers[FS_SDMMC_EMMC].device_addr_buffer_size >= blkSize)
|
||||
{
|
||||
dma_buf_idx = FS_SDMMC_EMMC;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_this->parent->dmaBuffers[FS_SDMMC_SD].device_addr_buffer_size >= blkSize)
|
||||
{
|
||||
dma_buf_idx = FS_SDMMC_SD;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_this->parent->dmaBuffers[FS_SDMMC_GC].device_addr_buffer_size >= blkSize)
|
||||
{
|
||||
dma_buf_idx = FS_SDMMC_GC;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If buffer is on a random heap
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sdmmc_memcpy_buf = true;
|
||||
return dma_buf_idx;
|
||||
}
|
||||
|
||||
static int _sdmmc_storage_check_result(u32 res)
|
||||
{
|
||||
//Error mask:
|
||||
@@ -129,9 +207,11 @@ static int _sdmmc_storage_check_status(sdmmc_storage_t *storage)
|
||||
static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_req_t reqbuf;
|
||||
u32 tmp = 0;
|
||||
|
||||
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
|
||||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.num_sectors = num_sectors;
|
||||
reqbuf.blksize = 512;
|
||||
@@ -140,12 +220,12 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
||||
reqbuf.is_auto_cmd12 = 1;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
|
||||
{
|
||||
u32 tmp = 0;
|
||||
{
|
||||
sdmmc_stop_transmission(storage->sdmmc, &tmp);
|
||||
_sdmmc_storage_get_status(storage, &tmp, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define _SDMMC_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
#include "../FS/FS.h"
|
||||
#include "sdmmc_driver.h"
|
||||
|
||||
typedef struct _mmc_cid
|
||||
@@ -102,6 +103,9 @@ typedef struct _sdmmc_storage_t
|
||||
sd_ssr_t ssr;
|
||||
} sdmmc_storage_t;
|
||||
|
||||
extern sdmmc_accessor_t *_current_accessor;
|
||||
extern bool sdmmc_memcpy_buf;
|
||||
|
||||
int sdmmc_storage_end(sdmmc_storage_t *storage);
|
||||
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
@@ -109,5 +113,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||
intptr_t sdmmc_calculate_dma_addr(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors);
|
||||
int sdmmc_get_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_sectors);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "../soc/pmc.h"
|
||||
#include "../soc/pinmux.h"
|
||||
#include "../soc/gpio.h"
|
||||
#include "../utils/fatal.h"
|
||||
|
||||
#define DPRINTF(...)
|
||||
|
||||
@@ -640,6 +641,23 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power)
|
||||
|
||||
static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
|
||||
{
|
||||
if(sdmmc->id == SDMMC_1)
|
||||
{
|
||||
static int last_power = SDMMC_POWER_3_3;
|
||||
if(power == SDMMC_POWER_1_8 && last_power == SDMMC_POWER_3_3)
|
||||
{
|
||||
last_power = power = SDMMC_POWER_1_8;
|
||||
if (!_sdmmc_autocal_config_offset(sdmmc, power))
|
||||
return;
|
||||
}
|
||||
else if(power == SDMMC_POWER_3_3 && last_power == SDMMC_POWER_1_8)
|
||||
{
|
||||
last_power = power = SDMMC_POWER_3_3;
|
||||
if (!_sdmmc_autocal_config_offset(sdmmc, power))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool should_enable_sd_clock = false;
|
||||
if (sdmmc->regs->clkcon & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)
|
||||
{
|
||||
@@ -788,7 +806,15 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
|
||||
u32 blkcnt = req->num_sectors;
|
||||
if (blkcnt >= 0xFFFF)
|
||||
blkcnt = 0xFFFF;
|
||||
u64 admaaddr = sdmmc->dma_addr_fs;
|
||||
|
||||
u64 admaaddr = (u64)sdmmc_calculate_dma_addr(_current_accessor, req->buf, blkcnt);
|
||||
if (!admaaddr)
|
||||
{
|
||||
// buf is on a heap
|
||||
int dma_idx = sdmmc_get_fitting_dma_index(_current_accessor, blkcnt);
|
||||
admaaddr = (u64)&_current_accessor->parent->dmaBuffers[dma_idx].device_addr_buffer_masked[0];
|
||||
sdmmc->last_dma_idx = dma_idx;
|
||||
}
|
||||
|
||||
//Check alignment.
|
||||
if (admaaddr & 7)
|
||||
@@ -870,7 +896,22 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
||||
if (req)
|
||||
{
|
||||
_sdmmc_config_dma(sdmmc, &blkcnt, req);
|
||||
armDCacheFlush(req->buf, req->blksize * blkcnt);
|
||||
if(!sdmmc_memcpy_buf)
|
||||
{
|
||||
// Flush from/to phys
|
||||
armDCacheFlush(req->buf, req->blksize * blkcnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(req->is_write)
|
||||
{
|
||||
void* dma_addr = &_current_accessor->parent->dmaBuffers[sdmmc->last_dma_idx].device_addr_buffer[0];
|
||||
memcpy(dma_addr, req->buf, req->blksize * blkcnt);
|
||||
|
||||
// Flush to phys
|
||||
armDCacheFlush(dma_addr, req->blksize * blkcnt);
|
||||
}
|
||||
}
|
||||
|
||||
_sdmmc_enable_interrupts(sdmmc);
|
||||
is_data_present = true;
|
||||
@@ -892,8 +933,15 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
||||
{
|
||||
sdmmc->expected_rsp_type = cmd->rsp_type;
|
||||
_sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type);
|
||||
|
||||
/*if(sdmmc->rsp[0] & 0xFDF9A080)
|
||||
{
|
||||
res = 0;
|
||||
sdmmc->rsp[0] = 0; // Reset error
|
||||
}*/
|
||||
}
|
||||
if (req)
|
||||
|
||||
if (res && req)
|
||||
_sdmmc_update_dma(sdmmc);
|
||||
}
|
||||
|
||||
@@ -903,7 +951,22 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
||||
{
|
||||
if (req)
|
||||
{
|
||||
armDCacheFlush(req->buf, req->blksize * blkcnt);
|
||||
if(!req->is_write)
|
||||
{
|
||||
if(!sdmmc_memcpy_buf)
|
||||
{
|
||||
// Flush from phys
|
||||
armDCacheFlush(req->buf, req->blksize * blkcnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
void* dma_addr = &_current_accessor->parent->dmaBuffers[sdmmc->last_dma_idx].device_addr_buffer[0];
|
||||
// Flush from phys
|
||||
armDCacheFlush(dma_addr, req->blksize * blkcnt);
|
||||
// Copy to buffer
|
||||
memcpy(req->buf, dma_addr, req->blksize * blkcnt);
|
||||
}
|
||||
}
|
||||
|
||||
if (blkcnt_out)
|
||||
*blkcnt_out = blkcnt;
|
||||
|
||||
@@ -83,7 +83,7 @@ typedef struct _sdmmc_t
|
||||
int venclkctl_set;
|
||||
u32 venclkctl_tap;
|
||||
u32 expected_rsp_type;
|
||||
u64 dma_addr_fs;
|
||||
u64 last_dma_idx;
|
||||
u64 dma_addr_next;
|
||||
u32 rsp[4];
|
||||
u32 rsp3;
|
||||
|
||||
Reference in New Issue
Block a user