228 lines
7.2 KiB
C
228 lines
7.2 KiB
C
/* SDK drivers */
|
|
#include "hpm_clock_drv.h"
|
|
#include "hpm_femc_drv.h"
|
|
#include "hpm_i2c_drv.h"
|
|
#include "hpm_lcdc_drv.h"
|
|
#include "hpm_pcfg_drv.h"
|
|
#include "hpm_pllctl_drv.h"
|
|
#include "hpm_pmp_drv.h"
|
|
#include "hpm_sysctl_drv.h"
|
|
|
|
/* Board */
|
|
#include "board.h"
|
|
#include "pinmux.h"
|
|
|
|
typedef struct {
|
|
GPIO_Type *ctl;
|
|
uint8_t index;
|
|
uint8_t pin;
|
|
} board_led_t;
|
|
|
|
static const board_led_t s_board_led_table[BOARD_LED_COUNT] = {
|
|
{.ctl = BOARD_LED0_GPIO_CTRL, .index = BOARD_LED0_GPIO_INDEX, .pin = BOARD_LED0_GPIO_PIN},
|
|
{.ctl = BOARD_LED1_GPIO_CTRL, .index = BOARD_LED1_GPIO_INDEX, .pin = BOARD_LED1_GPIO_PIN},
|
|
{.ctl = BOARD_LED2_GPIO_CTRL, .index = BOARD_LED2_GPIO_INDEX, .pin = BOARD_LED2_GPIO_PIN},
|
|
};
|
|
|
|
void board_init(void) {
|
|
board_clock_init();
|
|
|
|
board_debug_console_init();
|
|
board_led_init();
|
|
|
|
board_sdram_init();
|
|
|
|
board_pmp_init();
|
|
|
|
board_lcd_init();
|
|
}
|
|
|
|
void board_clock_init(void) {
|
|
uint32_t cpu0_freq = clock_get_frequency(clock_cpu0);
|
|
if (cpu0_freq == PLLCTL_SOC_PLL_REFCLK_FREQ) {
|
|
/* Configure the External OSC ramp-up time: ~9ms */
|
|
pllctl_xtal_set_rampup_time(HPM_PLLCTL, 32UL * 1000UL * 9U);
|
|
|
|
/* Select clock setting preset1 */
|
|
sysctl_clock_set_preset(HPM_SYSCTL, sysctl_preset_1);
|
|
}
|
|
|
|
/* Update DCDC voltage */
|
|
pcfg_dcdc_set_voltage(HPM_PCFG, BOARD_CORE_VOLTAGE_MV);
|
|
|
|
if (pllctl_init_int_pll_with_freq(HPM_PLLCTL, PLLCTL_PLL_PLL0, BOARD_CPU_FREQ) != status_success) {
|
|
for (;;) {
|
|
WFI();
|
|
}
|
|
}
|
|
|
|
clock_set_source_divider(clock_cpu0, clk_src_pll0_clk0, 1);
|
|
clock_update_core_clock();
|
|
}
|
|
|
|
void board_debug_console_init(void) {
|
|
console_config_t cfg;
|
|
|
|
board_debug_uart_pins_init();
|
|
|
|
/* Configure the UART clock to 24MHz */
|
|
clock_add_to_group(clock_uart0, 0);
|
|
clock_set_source_divider(clock_uart0, clk_src_osc24m, 1U);
|
|
|
|
cfg.type = CONSOLE_TYPE_UART;
|
|
cfg.base = HPM_UART0_BASE;
|
|
cfg.src_freq_in_hz = clock_get_frequency(clock_uart0);
|
|
cfg.baudrate = BOARD_DEBUG_UART_BAUD;
|
|
|
|
console_init(&cfg);
|
|
}
|
|
|
|
void board_led_init(void) {
|
|
board_led_pins_init();
|
|
}
|
|
|
|
void board_led_set(uint8_t led_id, bool state) {
|
|
if (led_id < BOARD_LED_COUNT) {
|
|
const board_led_t *led = &s_board_led_table[led_id];
|
|
gpio_write_pin(led->ctl, led->index, led->pin, !state);
|
|
}
|
|
}
|
|
|
|
void board_sdram_init(void) {
|
|
femc_config_t cfg;
|
|
femc_sdram_config_t sdram_cfg;
|
|
|
|
board_sdram_pins_init();
|
|
|
|
clock_add_to_group(clock_femc, 0);
|
|
clock_set_source_divider(clock_femc, clk_src_pll2_clk0, 2U);
|
|
|
|
femc_default_config(HPM_FEMC, &cfg);
|
|
cfg.dqs = FEMC_DQS_INTERNAL;
|
|
|
|
femc_init(HPM_FEMC, &cfg);
|
|
|
|
sdram_cfg.bank_num = FEMC_SDRAM_BANK_NUM_4;
|
|
sdram_cfg.prescaler = 3;
|
|
sdram_cfg.burst_len_in_byte = 8;
|
|
sdram_cfg.auto_refresh_count_in_one_burst = 1;
|
|
sdram_cfg.col_addr_bits = FEMC_SDRAM_COLUMN_ADDR_9_BITS;
|
|
sdram_cfg.cas_latency = FEMC_SDRAM_CAS_LATENCY_3;
|
|
|
|
sdram_cfg.precharge_to_act_in_ns = 18;
|
|
sdram_cfg.act_to_rw_in_ns = 18;
|
|
sdram_cfg.refresh_recover_in_ns = 72;
|
|
sdram_cfg.write_recover_in_ns = 12;
|
|
sdram_cfg.cke_off_in_ns = 42;
|
|
sdram_cfg.act_to_precharge_in_ns = 42;
|
|
|
|
sdram_cfg.self_refresh_recover_in_ns = 72;
|
|
sdram_cfg.refresh_recover_in_ns = 72;
|
|
sdram_cfg.act_to_act_in_ns = 12;
|
|
sdram_cfg.idle_timeout_in_ns = 6;
|
|
sdram_cfg.cs_mux_pin = FEMC_IO_MUX_NOT_USED;
|
|
|
|
sdram_cfg.cs = FEMC_SDRAM_CS0;
|
|
sdram_cfg.base_address = BOARD_SDRAM_BASE;
|
|
sdram_cfg.size_in_byte = BOARD_SDRAM_SIZE;
|
|
sdram_cfg.port_size = FEMC_SDRAM_PORT_SIZE_16_BITS;
|
|
sdram_cfg.refresh_count = 8192;
|
|
sdram_cfg.refresh_in_ms = 64;
|
|
sdram_cfg.data_width_in_byte = 2;
|
|
sdram_cfg.delay_cell_value = 29;
|
|
|
|
femc_config_sdram(HPM_FEMC, clock_get_frequency(clock_femc), &sdram_cfg);
|
|
}
|
|
|
|
void board_lcd_init(void) {
|
|
lcdc_config_t cfg = {0};
|
|
/*
|
|
* Fire 5" LCD Parameters:
|
|
* Horizontal Resolution: 800
|
|
* HBP: 46
|
|
* HFP: 210 (16-354)
|
|
* Vertical Resolution: 480
|
|
* VBP: 23
|
|
* VFP: 22 (7-147)
|
|
* HSync Pulse Width: 1 (1-40) P-CLK
|
|
* VSync Pulse Width: 1 (1-20) HSD
|
|
*
|
|
* Pixel Clock Frequency: 33.264MHz (@60fps, Typ.)
|
|
*/
|
|
|
|
board_lcd_pins_init();
|
|
|
|
/* Backlight ON */
|
|
gpio_set_pin_output_with_initial(BOARD_LCD_BLK_GPIO_CTRL, BOARD_LCD_BLK_GPIO_INDEX, BOARD_LCD_BLK_GPIO_PIN, 1U);
|
|
|
|
clock_add_to_group(clock_display, 0);
|
|
clock_set_source_divider(clock_display, clk_src_pll4_clk0, 18U); /* 33.0MHz */
|
|
|
|
/* Bug workaround, seems clock not stable */
|
|
clock_cpu_delay_ms(10);
|
|
|
|
lcdc_get_default_config(HPM_LCDC, &cfg);
|
|
|
|
cfg.resolution_x = BOARD_LCD_RES_H;
|
|
cfg.resolution_y = BOARD_LCD_RES_V;
|
|
|
|
cfg.hsync.pulse_width = 10;
|
|
cfg.hsync.back_porch_pulse = 46;
|
|
cfg.hsync.front_porch_pulse = 210;
|
|
|
|
cfg.vsync.pulse_width = 3;
|
|
cfg.vsync.back_porch_pulse = 23;
|
|
cfg.vsync.front_porch_pulse = 22;
|
|
|
|
cfg.control.invert_hsync = false;
|
|
cfg.control.invert_vsync = false;
|
|
cfg.control.invert_href = false;
|
|
cfg.control.invert_pixel_data = false;
|
|
cfg.control.invert_pixel_clock = false;
|
|
|
|
lcdc_init(HPM_LCDC, &cfg);
|
|
}
|
|
|
|
void board_pmp_init(void) {
|
|
uint32_t start_addr;
|
|
uint32_t end_addr;
|
|
uint32_t length;
|
|
pmp_entry_t pmp_entry[16];
|
|
uint8_t index = 0;
|
|
|
|
/* Init noncachable memory */
|
|
extern uint32_t __noncacheable_start__[];
|
|
extern uint32_t __noncacheable_end__[];
|
|
start_addr = (uint32_t)__noncacheable_start__;
|
|
end_addr = (uint32_t)__noncacheable_end__;
|
|
length = end_addr - start_addr;
|
|
if (length > 0) {
|
|
/* Ensure the address and the length are power of 2 aligned */
|
|
assert((length & (length - 1U)) == 0U);
|
|
assert((start_addr & (length - 1U)) == 0U);
|
|
pmp_entry[index].pmp_addr = PMP_NAPOT_ADDR(start_addr, length);
|
|
pmp_entry[index].pmp_cfg.val = PMP_CFG(READ_EN, WRITE_EN, EXECUTE_EN, ADDR_MATCH_NAPOT, REG_UNLOCK);
|
|
pmp_entry[index].pma_addr = PMA_NAPOT_ADDR(start_addr, length);
|
|
pmp_entry[index].pma_cfg.val = PMA_CFG(ADDR_MATCH_NAPOT, MEM_TYPE_MEM_NON_CACHE_BUF, AMO_EN);
|
|
index++;
|
|
}
|
|
|
|
/* Init share memory */
|
|
extern uint32_t __share_mem_start__[];
|
|
extern uint32_t __share_mem_end__[];
|
|
start_addr = (uint32_t)__share_mem_start__;
|
|
end_addr = (uint32_t)__share_mem_end__;
|
|
length = end_addr - start_addr;
|
|
if (length > 0) {
|
|
/* Ensure the address and the length are power of 2 aligned */
|
|
assert((length & (length - 1U)) == 0U);
|
|
assert((start_addr & (length - 1U)) == 0U);
|
|
pmp_entry[index].pmp_addr = PMP_NAPOT_ADDR(start_addr, length);
|
|
pmp_entry[index].pmp_cfg.val = PMP_CFG(READ_EN, WRITE_EN, EXECUTE_EN, ADDR_MATCH_NAPOT, REG_UNLOCK);
|
|
pmp_entry[index].pma_addr = PMA_NAPOT_ADDR(start_addr, length);
|
|
pmp_entry[index].pma_cfg.val = PMA_CFG(ADDR_MATCH_NAPOT, MEM_TYPE_MEM_NON_CACHE_BUF, AMO_EN);
|
|
index++;
|
|
}
|
|
|
|
pmp_config(&pmp_entry[0], index);
|
|
} |