diff --git a/arch/vc4/timer.c b/arch/vc4/timer.c index 572f09083..0cfea8f64 100644 --- a/arch/vc4/timer.c +++ b/arch/vc4/timer.c @@ -10,11 +10,11 @@ static enum handler_return timer0_irq(void *arg); lk_bigtime_t current_time_hires(void) { //TODO, deal with rollover - return ( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO); + return (( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO)) / 1000; } lk_time_t current_time(void) { - return *REG32(ST_CLO); + return current_time_hires(); } static platform_timer_callback timer_cb = 0;; diff --git a/platform/bcm28xx/genet.c b/platform/bcm28xx/genet.c new file mode 100644 index 000000000..a49ab780a --- /dev/null +++ b/platform/bcm28xx/genet.c @@ -0,0 +1,27 @@ +// based on drivers/net/ethernet/broadcom/genet/bcmgenet.c from linux +// for PHY control, look at the cmd_bits variable in drivers/net/ethernet/broadcom/genet/bcmmii.c + +#include +#include +#include +#include +#include + +static int cmd_genet_dump(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("dump_genet", "print genet information", &cmd_genet_dump) +STATIC_COMMAND_END(genet); + +#define SYS_REV_CTRL (GENET_BASE + 0x0) + +static int cmd_genet_dump(int argc, const cmd_args *argv) { + uint32_t reg = *REG32(SYS_REV_CTRL); + uint8_t major = (reg >> 24 & 0x0f); + if (major == 6) major = 5; + else if (major == 5) major = 4; + else if (major == 0) major = 1; + + dprintf(INFO, "found GENET controller version %d\n", major); + return 0; +} diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index f5a3a6082..1ec3a1dfc 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -41,6 +41,7 @@ #define ARM_BASE (BCM_PERIPH_BASE_VIRT + 0xB000) #define PM_BASE (BCM_PERIPH_BASE_VIRT + 0x100000) #define CM_BASE (BCM_PERIPH_BASE_VIRT + 0x101000) +#define A2W_BASE (BCM_PERIPH_BASE_VIRT + 0x102000) #define PCM_CLOCK_BASE (BCM_PERIPH_BASE_VIRT + 0x101098) #define RNG_BASE (BCM_PERIPH_BASE_VIRT + 0x104000) #define GPIO_BASE (BCM_PERIPH_BASE_VIRT + 0x200000) @@ -55,6 +56,7 @@ #define SMI_BASE (BCM_PERIPH_BASE_VIRT + 0x600000) #define BSC1_BASE (BCM_PERIPH_BASE_VIRT + 0x804000) #define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000) +#define GENET_BASE (0x7d580000) // TODO, this is before the normal BCM_PERIPH_BASE_VIRT bank #define MCORE_BASE (BCM_PERIPH_BASE_VIRT + 0x0000) #define ST_CS (ST_BASE + 0x0) @@ -62,6 +64,8 @@ #define ST_CHI (ST_BASE + 0x8) #define ST_C0 (ST_BASE + 0xc) +#define CM_VPUCTL (CM_BASE + 0x008) +#define CM_VPUDIV (CM_BASE + 0x00c) #define CM_UARTCTL (CM_BASE + 0xf0) #define CM_UARTDIV (CM_BASE + 0xf4) @@ -70,12 +74,14 @@ #define IC0_SRC0 (IC0_BASE + 0x8) #define IC0_SRC1 (IC0_BASE + 0xc) #define IC0_VADDR (IC0_BASE + 0x30) +#define IC0_WAKEUP (IC0_BASE + 0x34) #define IC1_C (IC1_BASE + 0x0) #define IC1_S (IC1_BASE + 0x4) #define IC1_SRC0 (IC1_BASE + 0x8) #define IC1_SRC1 (IC1_BASE + 0xc) #define IC1_VADDR (IC1_BASE + 0x30) +#define IC1_WAKEUP (IC1_BASE + 0x34) #define PM_PASSWORD 0x5a000000 #define PM_RSTC (PM_BASE + 0x1c) @@ -83,6 +89,29 @@ #define PM_WDOG (PM_BASE + 0x24) #define PM_WDOG_MASK 0x00000fff +#define A2W_PASSWORD 0x5a000000 +#define A2W_PLLA_CTRL (A2W_BASE + 0x100) +#define A2W_PLLC_CTRL (A2W_BASE + 0x120) +#define A2W_PLLC_CTRL_PDIV_SET 0x00007000 +#define A2W_PLLC_CTRL_NDIV_SET 0x000003ff +#define A2W_PLLC_CTRL_PDIV_LSB 12 +#define A2W_PLLD_CTRL (A2W_BASE + 0x140) +#define A2W_PLLH_CTRL (A2W_BASE + 0x160) +#define A2W_PLLB_CTRL (A2W_BASE + 0x1e0) +#define A2W_PLLA_FRAC (A2W_BASE + 0x200) +#define A2W_PLLC_FRAC (A2W_BASE + 0x220) +#define A2W_PLLD_FRAC (A2W_BASE + 0x240) +#define A2W_PLLH_FRAC (A2W_BASE + 0x260) +#define A2W_PLLB_FRAC (A2W_BASE + 0x2e0) +#define A2W_PLLC_CORE1 (A2W_BASE + 0x420) +#define A2W_PLLC_CORE0 (A2W_BASE + 0x620) +#define A2W_PLLC_CORE0_DIV_SET 0x000000ff +#define A2W_PLLA_FRAC_MASK 0x000fffff +#define A2W_PLLB_FRAC_MASK 0x000fffff +#define A2W_PLLC_FRAC_MASK 0x000fffff +#define A2W_PLLD_FRAC_MASK 0x000fffff +#define A2W_PLLH_FRAC_MASK 0x000fffff + #define ARMCTRL_BASE (ARM_BASE + 0x000) #define ARMCTRL_INTC_BASE (ARM_BASE + 0x200) #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h index f7f95c9dc..3b28cd7fd 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h @@ -3,15 +3,15 @@ #ifdef __cplusplus extern "C" { #endif -uint32_t clk_get_input_freq(volatile uint32_t *ctlreg); -uint32_t clk_get_freq(volatile uint32_t *divreg, volatile uint32_t *ctlreg); -uint32_t get_vpu_per_freq(); -uint32_t get_uart_base_freq(); -uint32_t plla(); -uint32_t pllb(); -uint32_t pllc(); -uint32_t plld(); -uint32_t pllh(); +uint32_t clk_get_input_freq(uint32_t ctlreg); +uint32_t clk_get_freq(uint32_t divreg, uint32_t ctlreg); +uint32_t get_vpu_per_freq(void); +uint32_t get_uart_base_freq(void); +uint32_t plla(void); +uint32_t pllb(void); +uint32_t pllc(void); +uint32_t plld(void); +uint32_t pllh(void); extern uint32_t xtal_freq; #ifdef __cplusplus } diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 795a107ba..156b009cf 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -1,21 +1,31 @@ -#include #include #include +#include +#include +#include +#include uint32_t xtal_freq; -uint32_t get_vpu_per_freq() { - return clk_get_freq(&CM_VPUDIV, &CM_VPUCTL); +static int cmd_pll_dump(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("dump_pll_state", "print all pll state", &cmd_pll_dump) +STATIC_COMMAND_END(pll); + +uint32_t get_vpu_per_freq(void) { + return clk_get_freq(CM_VPUDIV, CM_VPUCTL); } uint32_t get_uart_base_freq() { - return clk_get_freq(&CM_UARTDIV, &CM_UARTCTL); + return clk_get_freq(CM_UARTDIV, CM_UARTCTL); } uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { - uint32_t ndiv = A2W_PLLC_CTRL & A2W_PLLC_CTRL_NDIV_SET; - uint32_t pdiv = (A2W_PLLC_CTRL & A2W_PLLC_CTRL_PDIV_SET) >> A2W_PLLC_CTRL_PDIV_LSB; - uint64_t mult1 = (ndiv << 20) | frac; + // FIXME, ignores the addr passed in + uint32_t ndiv = *REG32(ctrl) & A2W_PLLC_CTRL_NDIV_SET; + uint32_t pdiv = (*REG32(ctrl) & A2W_PLLC_CTRL_PDIV_SET) >> A2W_PLLC_CTRL_PDIV_LSB; + uint64_t mult1 = (ndiv << 20) | *REG32(frac); mult1 *= pdiv; // TODO, the optional /2 phase uint32_t freq = (xtal_freq * mult1) >> 20; @@ -23,44 +33,44 @@ uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { } uint32_t plla() { - return compute_pll_freq(A2W_PLLA_CTRL, A2W_PLLA_FRAC & A2W_PLLA_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLA_CTRL), *REG32(A2W_PLLA_FRAC) & A2W_PLLA_FRAC_MASK); } uint32_t pllb() { - return compute_pll_freq(A2W_PLLB_CTRL, A2W_PLLB_FRAC & A2W_PLLB_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLB_CTRL), *REG32(A2W_PLLB_FRAC) & A2W_PLLB_FRAC_MASK); } uint32_t pllc() { //uint32_t ana1 = A2W_PLLC_ANA1; - uint32_t ctrl = A2W_PLLC_CTRL; - uint32_t frac = A2W_PLLC_FRAC & A2W_PLLC_FRAC_MASK; + uint32_t ctrl = *REG32(A2W_PLLC_CTRL); + uint32_t frac = *REG32(A2W_PLLC_FRAC) & A2W_PLLC_FRAC_MASK; return compute_pll_freq(ctrl, frac); } uint32_t plld() { - return compute_pll_freq(A2W_PLLD_CTRL, A2W_PLLD_FRAC & A2W_PLLD_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLD_CTRL), *REG32(A2W_PLLD_FRAC) & A2W_PLLD_FRAC_MASK); } uint32_t pllh() { - return compute_pll_freq(A2W_PLLH_CTRL, A2W_PLLH_FRAC & A2W_PLLH_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLH_CTRL), *REG32(A2W_PLLH_FRAC) & A2W_PLLH_FRAC_MASK); } -uint32_t pllc_core0() { - uint32_t ctrl = A2W_PLLC_CORE0; +uint32_t pllc_core0(void) { + uint32_t ctrl = *REG32(A2W_PLLC_CORE0); uint32_t div = ctrl & A2W_PLLC_CORE0_DIV_SET; uint32_t pllc_freq = pllc(); return pllc_freq / div; } -uint32_t clk_get_freq(volatile uint32_t *divreg, volatile uint32_t *ctlreg) { - uint32_t div = *divreg; +uint32_t clk_get_freq(uint32_t divreg, uint32_t ctlreg) { + uint32_t div = *REG32(divreg); if (div == 0) return 0; uint64_t input_freq = clk_get_input_freq(ctlreg); - return ((input_freq << 12) / *divreg); + return ((input_freq << 12) / div); } -uint32_t clk_get_input_freq(volatile uint32_t *ctlreg) { - uint32_t ctl = *ctlreg; +uint32_t clk_get_input_freq(uint32_t ctlreg) { + uint32_t ctl = *REG32(ctlreg); switch (ctl & 0xf) { case 0: // GND clock source return 0; @@ -85,3 +95,44 @@ uint32_t clk_get_input_freq(volatile uint32_t *ctlreg) { return 0; } } + +static uint32_t dump_pll_state(const char *prefix, uint32_t ctrl, uint32_t frac) { + uint32_t ctrl_val = *REG32(ctrl); + uint32_t frac_value = *REG32(frac); + dprintf(INFO, "A2W_%s_CTRL: 0x%x\n", prefix, ctrl_val); + dprintf(INFO, "A2W_%s_FRAC: 0x%x\n", prefix, frac_value); + uint32_t freq = compute_pll_freq(ctrl, frac); + dprintf(INFO, "%s freq: %u\n", prefix, freq); + return freq; +} + +static void dump_plldiv_state(const char *prefix, uint32_t ctrl, uint32_t input) { + uint32_t ctrl_val = *REG32(ctrl); + dprintf(INFO, "\tA2W_%s: 0x%x\n", prefix, ctrl_val); + uint8_t div = ctrl_val & 0xff; + if (div == 0) return; + uint32_t freq = input / div; + dprintf(INFO, "\t%s freq: %u\n", prefix, freq); +} + +static void dump_plldiv2_state(const char *prefix, uint32_t ctrl, uint32_t div) { + uint32_t ctrl_val = *REG32(ctrl); + uint32_t div_val = *REG32(div); + dprintf(INFO, "CM_%sCTL: 0x%x\n", prefix, ctrl_val); + dprintf(INFO, "CM_%sDIV: 0x%x\n", prefix, div_val); +} + +static int cmd_pll_dump(int argc, const cmd_args *argv) { + dump_pll_state("PLLA", A2W_PLLA_CTRL, A2W_PLLA_FRAC); + dump_pll_state("PLLB", A2W_PLLB_CTRL, A2W_PLLB_FRAC); + uint32_t pllc_freq = dump_pll_state("PLLC", A2W_PLLC_CTRL, A2W_PLLC_FRAC); + if (pllc_freq > 0) { + dump_plldiv_state("PLLC_CORE0", A2W_PLLC_CORE0, pllc_freq); + dump_plldiv_state("PLLC_CORE1", A2W_PLLC_CORE1, pllc_freq); + } + dump_pll_state("PLLD", A2W_PLLD_CTRL, A2W_PLLD_FRAC); + dump_pll_state("PLLH", A2W_PLLH_CTRL, A2W_PLLH_FRAC); + + dump_plldiv2_state("VPU", CM_VPUCTL, CM_VPUDIV); + return 0; +} diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 8fd2216f5..5948f5de4 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -5,12 +5,28 @@ MODULE := $(LOCAL_DIR) WITH_SMP := 1 #LK_HEAP_IMPLEMENTATION ?= dlmalloc -ifeq ($(ARCJ),arm) -MODULE_DEPS := \ +# 1st pass to set arch +ifeq ($(TARGET),rpi2) + ARCH := arm + ARM_CPU := cortex-a7 + GLOBAL_DEFINES += CRYSTAL=19200000 +else ifeq ($(TARGET),rpi3) + ARCH := arm64 + ARM_CPU := cortex-a53 + GLOBAL_DEFINES += CRYSTAL=19200000 +else ifeq ($(TARGET),rpi4-vpu) + ARCH ?= vc4 + GLOBAL_DEFINES += CRYSTAL=54000000 +endif + + +ifeq ($(ARCH),arm) +MODULE_DEPS += \ dev/timer/arm_generic \ lib/cbuf -MODULE_SRCS += +MODULE_SRCS += \ $(LOCAL_DIR)/mailbox.c \ + $(LOCAL_DIR)/intc.c \ endif @@ -24,7 +40,7 @@ endif MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ $(LOCAL_DIR)/platform.c \ - #$(LOCAL_DIR)/intc.c \ + $(LOCAL_DIR)/pll_read.c \ MEMBASE := 0x00000000 @@ -36,8 +52,6 @@ LINKER_SCRIPT += \ $(BUILDDIR)/system-onesegment.ld ifeq ($(TARGET),rpi2) -ARCH := arm -ARM_CPU := cortex-a7 # put our kernel at 0x80000000 KERNEL_BASE = 0x80000000 KERNEL_LOAD_OFFSET := 0x00008000 @@ -50,8 +64,6 @@ MODULE_SRCS += \ $(LOCAL_DIR)/uart.c else ifeq ($(TARGET),rpi3) -ARCH := arm64 -ARM_CPU := cortex-a53 KERNEL_LOAD_OFFSET := 0x00080000 MEMSIZE ?= 0x40000000 # 1GB @@ -70,18 +82,16 @@ MODULE_DEPS += \ app/tests \ lib/fdt else ifeq ($(TARGET),rpi4-vpu) -ARCH ?= vc4 MEMSIZE ?= 0x1400000 # 20MB MEMBASE ?= 0 GLOBAL_DEFINES += \ BCM2XXX_VPU=1 SMP_MAX_CPUS=1 \ MEMSIZE=$(MEMSIZE) \ MEMBASE=$(MEMBASE) \ - CRYSTAL=54000000 \ MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ - $(LOCAL_DIR)/pll_read.c \ + $(LOCAL_DIR)/genet.c \ endif diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 9ff209fb3..6013a39d8 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -102,7 +102,6 @@ void uart_init(void) { // assumes interrupts are contiguous register_int_handler(INTERRUPT_VC_UART + i, &uart_irq, (void *)i); uint32_t divisor = calculate_baud_divisor(115200); - dprintf(INFO, "changing divisor to %d\n", divisor); uart_flush(i);