184 lines
5.6 KiB
C
Executable File
184 lines
5.6 KiB
C
Executable File
/*=============================================================================
|
|
Copyright (C) 2016 Kristina Brooks
|
|
All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
FILE DESCRIPTION
|
|
VideoCoreIV first stage bootloader.
|
|
|
|
=============================================================================*/
|
|
|
|
#include "lib/common.h"
|
|
#include "hardware.h"
|
|
|
|
uint32_t g_CPUID;
|
|
|
|
void uart_putc(unsigned int ch)
|
|
{
|
|
while(1) {
|
|
if (mmio_read32(AUX_MU_LSR_REG) & 0x20)
|
|
break;
|
|
}
|
|
mmio_write32(AUX_MU_IO_REG, ch);
|
|
}
|
|
|
|
void uart_init(void) {
|
|
unsigned int ra = GP_FSEL1;
|
|
ra &= ~(7 << 12);
|
|
ra |= 2 << 12;
|
|
GP_FSEL1 = ra;
|
|
|
|
GP_PUD = 0;
|
|
|
|
udelay(150);
|
|
GP_PUDCLK0 = (1 << 14) | (1 << 15);
|
|
udelay(150);
|
|
GP_PUDCLK0 = 0;
|
|
|
|
mmio_write32(AUX_ENABLES, 1);
|
|
mmio_write32(AUX_MU_IER_REG, 0);
|
|
mmio_write32(AUX_MU_CNTL_REG, 0);
|
|
mmio_write32(AUX_MU_LCR_REG, 3);
|
|
mmio_write32(AUX_MU_MCR_REG, 0);
|
|
mmio_write32(AUX_MU_IER_REG, 0);
|
|
mmio_write32(AUX_MU_IIR_REG, 0xC6);
|
|
|
|
mmio_write32(AUX_MU_BAUD_REG, 270);
|
|
|
|
mmio_write32(AUX_MU_LCR_REG, 3);
|
|
mmio_write32(AUX_MU_CNTL_REG, 3);
|
|
}
|
|
|
|
void led_init(void) {
|
|
unsigned int ra;
|
|
|
|
ra = GP_FSEL1;
|
|
ra &= ~(7 << 18);
|
|
ra |= 1 << 18;
|
|
|
|
GP_FSEL1 = ra;
|
|
}
|
|
|
|
/*
|
|
#define CM_PLLC_DIGRST_BITS 9:9
|
|
#define CM_PLLC_DIGRST_SET 0x00000200
|
|
#define CM_PLLC_ANARST_BITS 8:8
|
|
#define CM_PLLC_ANARST_SET 0x00000100
|
|
#define CM_PLLC_HOLDPER_BITS 7:7
|
|
#define CM_PLLC_HOLDPER_SET 0x00000080
|
|
#define CM_PLLC_LOADPER_BITS 6:6
|
|
#define CM_PLLC_LOADPER_SET 0x00000040
|
|
#define CM_PLLC_HOLDCORE2_BITS 5:5
|
|
#define CM_PLLC_HOLDCORE2_SET 0x00000020
|
|
#define CM_PLLC_LOADCORE2_BITS 4:4
|
|
#define CM_PLLC_LOADCORE2_SET 0x00000010
|
|
#define CM_PLLC_HOLDCORE1_BITS 3:3
|
|
#define CM_PLLC_HOLDCORE1_SET 0x00000008
|
|
#define CM_PLLC_LOADCORE1_BITS 2:2
|
|
#define CM_PLLC_LOADCORE1_SET 0x00000004
|
|
#define CM_PLLC_HOLDCORE0_BITS 1:1
|
|
#define CM_PLLC_HOLDCORE0_SET 0x00000002
|
|
#define CM_PLLC_LOADCORE0_BITS 0:0
|
|
#define CM_PLLC_LOADCORE0_SET 0x00000001
|
|
*/
|
|
|
|
void switch_vpu_to_pllc() {
|
|
A2W_XOSC_CTRL |= A2W_PASSWORD | A2W_XOSC_CTRL_PLLCEN_SET;
|
|
|
|
A2W_PLLC_FRAC = A2W_PASSWORD | 87380;
|
|
A2W_PLLC_CTRL = A2W_PASSWORD | 52 | 0x1000;
|
|
|
|
A2W_PLLC_ANA3 = A2W_PASSWORD | 0x100;
|
|
A2W_PLLC_ANA2 = A2W_PASSWORD | 0x0;
|
|
A2W_PLLC_ANA1 = A2W_PASSWORD | 0x144000;
|
|
A2W_PLLC_ANA0 = A2W_PASSWORD | 0x0;
|
|
|
|
CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET;
|
|
|
|
/* hold all */
|
|
CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
|
|
CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
|
|
CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET;
|
|
|
|
A2W_PLLC_DIG3 = A2W_PASSWORD | 0x0;
|
|
A2W_PLLC_DIG2 = A2W_PASSWORD | 0x400000;
|
|
A2W_PLLC_DIG1 = A2W_PASSWORD | 0x5;
|
|
A2W_PLLC_DIG0 = A2W_PASSWORD | 52 | 0x555000;
|
|
|
|
A2W_PLLC_CTRL = A2W_PASSWORD | 52 | 0x1000 | A2W_PLLC_CTRL_PRSTN_SET;
|
|
|
|
A2W_PLLC_DIG3 = A2W_PASSWORD | 0x42;
|
|
A2W_PLLC_DIG2 = A2W_PASSWORD | 0x500401;
|
|
A2W_PLLC_DIG1 = A2W_PASSWORD | 0x4005;
|
|
A2W_PLLC_DIG0 = A2W_PASSWORD | 52 | 0x555000;
|
|
|
|
A2W_PLLC_CORE0 = A2W_PASSWORD | 2;
|
|
|
|
CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
|
|
CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
|
|
CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET | CM_PLLC_LOADCORE0_SET;
|
|
|
|
CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
|
|
CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
|
|
CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET;
|
|
|
|
CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
|
|
CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
|
|
CM_PLLC_HOLDCORE1_SET;
|
|
|
|
CM_VPUCTL = CM_PASSWORD | CM_VPUCTL_FRAC_SET | CM_SRC_OSC | CM_VPUCTL_GATE_SET;
|
|
CM_VPUDIV = CM_PASSWORD | (4 << 12);
|
|
CM_VPUCTL = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET;
|
|
CM_VPUCTL = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET | 0x10; /* ENAB */
|
|
|
|
CM_TIMERDIV = CM_PASSWORD | (19 << 12) | 819;
|
|
CM_TIMERCTL = CM_PASSWORD | CM_SRC_OSC | 0x10;
|
|
}
|
|
|
|
extern void sdram_init();
|
|
extern void arm_init();
|
|
|
|
int _main(unsigned int cpuid, unsigned int load_address) {
|
|
switch_vpu_to_pllc();
|
|
|
|
led_init();
|
|
uart_init();
|
|
|
|
printf(
|
|
"=========================================================\n"
|
|
"::\n"
|
|
":: kFW for bcm2708, Copyright 2016, Kristina Brooks. \n"
|
|
"::\n"
|
|
":: BUILDATE : %s %s \n"
|
|
":: BUILDSTYLE: %s \n"
|
|
"::\n"
|
|
"=========================================================\n",
|
|
__DATE__, __TIME__,
|
|
"OPENSOURCE"
|
|
);
|
|
|
|
printf("CPUID = 0x%X\n", cpuid);
|
|
printf("LoadAddr = 0x%X\n", load_address);
|
|
|
|
g_CPUID = cpuid;
|
|
|
|
/* bring up SDRAM */
|
|
sdram_init();
|
|
printf("SDRAM initialization completed successfully!\n");
|
|
|
|
/* bring up ARM */
|
|
arm_init();
|
|
|
|
panic("main exiting!");
|
|
}
|
|
|