Skip to content

Commit

Permalink
[board] bringup t536 sdc0
Browse files Browse the repository at this point in the history
  • Loading branch information
SamulKyull authored and SamulKyull committed Feb 23, 2025
1 parent 4e84441 commit b889bf7
Show file tree
Hide file tree
Showing 3 changed files with 310 additions and 13 deletions.
70 changes: 70 additions & 0 deletions board/tlt536-evm/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,76 @@ sunxi_serial_t uart_dbg = {
},
};

sunxi_sdhci_t sdhci0 = {
.name = "sdhci0",
.id = MMC_CONTROLLER_0,
.reg_base = SUNXI_SMHC0_BASE,
.sdhci_mmc_type = MMC_TYPE_SD,
.max_clk = 50000000,
.width = SMHC_WIDTH_4BIT,
.dma_des_addr = SDRAM_BASE + 0x30080000,
.pinctrl = {
.gpio_clk = {GPIO_PIN(GPIO_PORTF, 2), GPIO_PERIPH_MUX2},
.gpio_cmd = {GPIO_PIN(GPIO_PORTF, 3), GPIO_PERIPH_MUX2},
.gpio_d0 = {GPIO_PIN(GPIO_PORTF, 1), GPIO_PERIPH_MUX2},
.gpio_d1 = {GPIO_PIN(GPIO_PORTF, 0), GPIO_PERIPH_MUX2},
.gpio_d2 = {GPIO_PIN(GPIO_PORTF, 5), GPIO_PERIPH_MUX2},
.gpio_d3 = {GPIO_PIN(GPIO_PORTF, 4), GPIO_PERIPH_MUX2},
.gpio_cd = {GPIO_PIN(GPIO_PORTF, 6), GPIO_INPUT},
.cd_level = GPIO_LEVEL_LOW,
},
.clk_ctrl = {
.gate_reg_base = SUNXI_CCU_BASE + SMHC0_BGR_REG,
.gate_reg_offset = SDHCI_DEFAULT_CLK_GATE_OFFSET(0),
.rst_reg_base = SUNXI_CCU_BASE + SMHC0_BGR_REG,
.rst_reg_offset = SDHCI_DEFAULT_CLK_RST_OFFSET(0),
},
.sdhci_clk = {
.reg_base = SUNXI_CCU_BASE + SMHC0_CLK_REG,
.reg_factor_n_offset = SDHCI_DEFAULT_CLK_FACTOR_N_OFFSET,
.reg_factor_m_offset = SDHCI_DEFAULT_CLK_FACTOR_M_OFFSET,
.clk_sel = 0x1,
.parent_clk = 300000000,
},
};

sunxi_sdhci_t sdhci2 = {
.name = "sdhci2",
.id = MMC_CONTROLLER_2,
.reg_base = SUNXI_SMHC2_BASE,
.sdhci_mmc_type = MMC_TYPE_EMMC,
.max_clk = 5200000,
.width = SMHC_WIDTH_8BIT,
.dma_des_addr = SDRAM_BASE + 0x30080000,
.pinctrl = {
.gpio_clk = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX3},
.gpio_cmd = {GPIO_PIN(GPIO_PORTC, 6), GPIO_PERIPH_MUX3},
.gpio_d0 = {GPIO_PIN(GPIO_PORTC, 10), GPIO_PERIPH_MUX3},
.gpio_d1 = {GPIO_PIN(GPIO_PORTC, 13), GPIO_PERIPH_MUX3},
.gpio_d2 = {GPIO_PIN(GPIO_PORTC, 15), GPIO_PERIPH_MUX3},
.gpio_d3 = {GPIO_PIN(GPIO_PORTC, 8), GPIO_PERIPH_MUX3},
.gpio_d4 = {GPIO_PIN(GPIO_PORTC, 9), GPIO_PERIPH_MUX3},
.gpio_d5 = {GPIO_PIN(GPIO_PORTC, 11), GPIO_PERIPH_MUX3},
.gpio_d6 = {GPIO_PIN(GPIO_PORTC, 14), GPIO_PERIPH_MUX3},
.gpio_d7 = {GPIO_PIN(GPIO_PORTC, 16), GPIO_PERIPH_MUX3},
.gpio_ds = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX3},
.gpio_rst = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX3},
},
.clk_ctrl = {
.gate_reg_base = SUNXI_CCU_BASE + SMHC2_BGR_REG,
.gate_reg_offset = SDHCI_DEFAULT_CLK_GATE_OFFSET(2),
.rst_reg_base = SUNXI_CCU_BASE + SMHC2_BGR_REG,
.rst_reg_offset = SDHCI_DEFAULT_CLK_RST_OFFSET(2),
},
.sdhci_clk = {
.reg_base = SUNXI_CCU_BASE + SMHC2_CLK_REG,
.reg_factor_n_offset = SDHCI_DEFAULT_CLK_FACTOR_N_OFFSET,
.reg_factor_m_offset = SDHCI_DEFAULT_CLK_FACTOR_M_OFFSET,
.clk_sel = 0x1,
.parent_clk = 800000000,
},
};

sunxi_i2c_t i2c_pmu = {
.base = SUNXI_RTWI_BASE,
.id = SUNXI_R_I2C0,
Expand Down
140 changes: 127 additions & 13 deletions board/tlt536-evm/hello_world/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,133 @@

#include <log.h>
#include <mmu.h>
#include <ff.h>

#include <common.h>

#include <mmc/sys-sdhci.h>
#include <cli.h>
#include <cli_shell.h>
#include <cli_termesc.h>

#include <sys-dram.h>
#include <sys-gpio.h>
#include <sys-i2c.h>
#include <sys-sdcard.h>

#include <cli.h>
#include <cli_shell.h>
#include <cli_termesc.h>
#include <sys-sid.h>
#include <sys-spi.h>
#include <sys-uart.h>

extern sunxi_serial_t uart_dbg;
extern sunxi_i2c_t i2c_pmu;
extern sunxi_sdhci_t sdhci0;
extern sunxi_sdhci_t sdhci2;

#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors)

#define CHUNK_SIZE 0x20000

static int fatfs_loadimage_size(char *filename, BYTE *dest, uint32_t *file_size) {
FIL file;
UINT byte_to_read = CHUNK_SIZE;
UINT byte_read;
UINT total_read = 0;
FRESULT fret;
int ret = 1;
uint32_t start, time;

fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
if (fret != FR_OK) {
printk_warning("FATFS: open, filename: [%s]: error %d\n", filename, fret);
ret = -1;
goto open_fail;
}

start = time_ms();

do {
byte_read = 0;
fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read);
dest += byte_to_read;
total_read += byte_read;
} while (byte_read >= byte_to_read && fret == FR_OK);

time = time_ms() - start + 1;

if (fret != FR_OK) {
printk_error("FATFS: read: error %d\n", fret);
ret = -1;
goto read_fail;
}
ret = 0;
*file_size = total_read;

read_fail:
fret = f_close(&file);

printk_info("FATFS: read in %ums at %.2fMB/S\n", time,
(f32) (total_read / time) / 1024.0f);

open_fail:
return ret;
}

msh_declare_command(helloworld);
static int fatfs_loadimage(char *filename, BYTE *dest) {
return fatfs_loadimage_size(filename, dest, NULL);
}

msh_declare_command(reload);
msh_define_help(reload, "rescan TF Card and reload DTB, Kernel zImage", "Usage: reload\n");
int cmd_reload(int argc, const char **argv) {
if (sdmmc_init(&card0, &sdhci0) != 0) {
printk_error("SMHC: init failed\n");
return 0;
}
return 0;
}

msh_define_help(helloworld, "display helloworld", "Usage: helloworld\n");
int cmd_helloworld(int argc, const char **argv) {
printk(LOG_LEVEL_MUTE, "Hello World!\n");
asm volatile("svc #0");
msh_declare_command(read);
msh_define_help(read, "test", "Usage: read\n");
int cmd_read(int argc, const char **argv) {
uint32_t start;
uint32_t test_time;

printk_debug("Clear Buffer data\n");
memset((void *) SDRAM_BASE, 0x00, 0x2000);
dump_hex(SDRAM_BASE, 0x100);

printk_debug("Read data to buffer data\n");

start = time_ms();
sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, 1024);
test_time = time_ms() - start;
printk_debug("SDMMC: speedtest %uKB in %ums at %uKB/S\n",
(CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time,
(CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time);
dump_hex(SDRAM_BASE, 0x100);
return 0;
}

msh_declare_command(write);
msh_define_help(write, "test", "Usage: write\n");
int cmd_write(int argc, const char **argv) {
uint32_t start;
uint32_t test_time;

printk_debug("Set Buffer data\n");
memset((void *) SDRAM_BASE, 0x00, 0x2000);
memcpy((void *) SDRAM_BASE, argv[1], strlen(argv[1]));

start = time_ms();
sdmmc_blk_write(&card0, (uint8_t *) (SDRAM_BASE), 0, 1024);
test_time = time_ms() - start;
printk_debug("SDMMC: speedtest %uKB in %ums at %uKB/S\n",
(CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time,
(CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time);
return 0;
}

const msh_command_entry commands[] = {
msh_define_command(helloworld),
msh_define_command(reload),
msh_define_command(read),
msh_define_command(write),
msh_command_end,
};

Expand All @@ -60,6 +160,20 @@ int main(void) {

printk_info("Hello World!\n");

/* Initialize the SD host controller. */
if (sunxi_sdhci_init(&sdhci0) != 0) {
printk_error("SMHC: %s controller init failed\n", sdhci0.name);
} else {
printk_info("SMHC: %s controller initialized\n", sdhci0.name);
}

/* Initialize the SD card and check if initialization is successful. */
if (sdmmc_init(&card0, &sdhci0) != 0) {
printk_warning("SMHC: init failed\n");
} else {
printk_debug("Card OK!\n");
}

syterkit_shell_attach(commands);

abort();
Expand Down
113 changes: 113 additions & 0 deletions src/drivers/chips/sun55iw6/sys-sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,116 @@

#include <mmc/sys-mmc.h>
#include <mmc/sys-sdhci.h>

/**
* @brief Set the SDHC controller's clock frequency.
*
* This function sets the clock frequency for the specified SDHC controller.
*
* @param sdhci Pointer to the SDHC controller structure.
* @param clk_hz Desired clock frequency in Hertz.
* @return Returns 0 on success, -1 on failure.
*/
int sunxi_sdhci_set_mclk(sunxi_sdhci_t *sdhci, uint32_t clk_hz) {
uint32_t reg_val = 0x0;
mmc_t *mmc = sdhci->mmc;
sunxi_sdhci_clk_t clk = sdhci->sdhci_clk;

// Determine the clock source based on the requested frequency
if (clk_hz <= 4000000) {
clk.clk_sel = 0;// SCLK = 24000000 OSC CLK
} else {
clk.clk_sel = 2;// SCLK = AHB PLL
}

if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (mmc->bus_width == SMHC_WIDTH_8BIT)) {
clk_hz /= 4;
} else {
clk_hz /= 2;
}

// Set the clock divider values based on the requested frequency
switch (clk_hz) {
case 0 ... 400000:
clk.factor_n = 1;
clk.factor_m = 0xe;
break;
case 400001 ... 26000000:
clk.factor_n = (sdhci->id == 2) ? 2 : 1;
clk.factor_m = (sdhci->id == 2) ? 3 : 2;
break;
case 26000001 ... 52000000:
clk.factor_n = (sdhci->id == 2) ? 1 : 0;
clk.factor_m = 2;
break;
case 52000001 ... 100000000:
clk.clk_sel = 1;// PERI0_800M
clk.factor_n = 0;
clk.factor_m = 3;
break;
case 100000001 ... 150000000:
clk.clk_sel = 1;// PERI0_800M
clk.factor_n = 0;
clk.factor_m = 2;
break;
case 150000001 ... 200000000:
clk.clk_sel = 1;// PERI0_800M
clk.factor_n = 0;
clk.factor_m = 1;
break;
default:
clk.factor_n = (sdhci->id == 2) ? 1 : 0;
clk.factor_m = 2;
printk_debug("SMHC: requested frequency does not match: freq=%d, default to 52000000\n", clk_hz);
break;
}

// Configure the clock register value
reg_val = (clk.clk_sel << 24) | (clk.factor_n << 8) | clk.factor_m;
writel(reg_val, clk.reg_base);

return 0;
}

/**
* @brief Get the current clock frequency of the SDHC controller.
*
* This function retrieves the current clock frequency of the specified SDHC controller.
*
* @param sdhci Pointer to the SDHC controller structure.
* @return Current clock frequency in Hertz.
*/
uint32_t sunxi_sdhci_get_mclk(sunxi_sdhci_t *sdhci) {
uint32_t clk_hz;
uint32_t reg_val = 0x0;
sunxi_sdhci_clk_t clk = sdhci->sdhci_clk;

// Read the clock register value
reg_val = readl(clk.reg_base);

// Extract the divider values and clock source from the register value
clk.factor_m = reg_val & 0xf;
clk.factor_n = (reg_val >> 8) & 0x3;
clk.clk_sel = (reg_val >> 24) & 0x3;

// Calculate the current clock frequency based on the source and divider values
switch (clk.clk_sel) {
case 0:
clk_hz = 24000000;
break;
case 1:
case 3:
clk_hz = (sdhci->id == 2) ? 800000000 : 400000000;
break;
case 2:
case 4:
clk_hz = (sdhci->id == 2) ? 600000000 : 300000000;
break;
default:
printk_debug("SMHC: wrong clock source %u\n", clk.clk_sel);
break;
}

// Calculate the actual clock frequency based on the divider values
return clk_hz / (clk.factor_n + 1) / (clk.factor_m + 1);
}

0 comments on commit b889bf7

Please # to comment.