added driver framework to prepare for driver unification, fixed USB driver, added...
authorchristinaa <kristinaa@tuta.io>
Sat, 7 Jan 2017 16:54:13 +0000 (16:54 +0000)
committerchristinaa <kristinaa@tuta.io>
Sat, 7 Jan 2017 16:54:13 +0000 (16:54 +0000)
16 files changed:
BCM2708PlatformStartup.cc [new file with mode: 0644]
Makefile
arm_chainloader/Makefile
arm_chainloader/start.s
arm_chainloader/trap.c [deleted file]
arm_chainloader/trap.cc [new file with mode: 0644]
arm_loader.cc
drivers/BCM2708ArmControl.cc [new file with mode: 0644]
drivers/BCM2708PowerManagement.cc [new file with mode: 0644]
drivers/BCM2708PowerManagement.hpp [new file with mode: 0644]
drivers/BCM2708UsbPhy.cc [new file with mode: 0644]
drivers/IODevice.cc [new file with mode: 0644]
drivers/IODevice.hpp [new file with mode: 0644]
lib/panic.h
linker.lds
romstage.c

diff --git a/BCM2708PlatformStartup.cc b/BCM2708PlatformStartup.cc
new file mode 100644 (file)
index 0000000..91dc609
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * VideoCore4_Drivers
+ * Copyright (c) 2017 Kristina Brooks
+ *
+ * BCM2708 power management driver.
+ */
+
+#include <drivers/IODevice.hpp>
+#include <drivers/BCM2708PowerManagement.hpp>
+
+extern "C" void PEStartPlatform() {
+       IODevice* imagePm = PowerManagementDomain::getDeviceForDomain(kCprPowerDomainImage);
+       assert(imagePm);
+       IODevice* usbPm = PowerManagementDomain::getDeviceForDomain(kCprPowerDomainUSB);
+       assert(usbPm);
+
+       /*
+        * all devices in the IMAGE domain have to be disabled before
+        * starting the domain itself.
+        */
+       usbPm->stop();
+       /*
+        * enable IMAGE power domain.
+        */
+       imagePm->start();
+       /*
+        * enable USB power domain.
+        */
+       usbPm->start();
+
+       /*
+        * start up USB PHY.
+        */
+       IODevice* usbPhy = IODevice::findByTag('USBP');
+       assert(usbPhy);
+       usbPhy->start();
+}
\ No newline at end of file
index cc6e4ef..3f79093 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,6 +17,10 @@ SRCS = \
        lib/udelay.c \
        lib/memcpy.c \
        lib/cxx_runtime.c \
+       drivers/IODevice.cc \
+       drivers/BCM2708PowerManagement.cc \
+       drivers/BCM2708UsbPhy.cc \
+       BCM2708PlatformStartup.cc \
        chainloader_inc.s
 
 ARCH = vc4
@@ -44,9 +48,9 @@ AS = $(CC)
 OBJCOPY = $(CROSS_COMPILE)objcopy
 LINKFLAGS = -nostdlib -nostartfiles -Wl,--build-id=none -T linker.lds
 
-CFLAGS = -c -nostdlib -std=c11 -fsingle-precision-constant -Wdouble-promotion -D__VIDEOCORE4__ -I./vc4_include/ -I./
+CFLAGS = -c -nostdlib -Wno-multichar -std=c11 -fsingle-precision-constant -Wdouble-promotion -D__VIDEOCORE4__ -I./vc4_include/ -I./
 ASFLAGS = -c -nostdlib -x assembler-with-cpp -D__VIDEOCORE4__ -I./vc4_include/ -I./
-CXXFLAGS = -c -nostdlib -std=c++11 -fno-exceptions -fno-rtti -D__VIDEOCORE4__ -I./vc4_include/ -I./
+CXXFLAGS = -c -nostdlib -Wno-multichar -std=c++11 -fno-exceptions -fno-rtti -D__VIDEOCORE4__ -I./vc4_include/ -I./
 
 HEADERS := \
        $(shell find . -type f -name '*.h') \
index 594403c..afcf192 100644 (file)
@@ -26,6 +26,7 @@ SRCS = \
        ../lib/cxx_runtime.c \
        ../lib/tlsf/tlsf.c \
        loader.cc \
+       trap.cc \
        main.c
 
 ARCH = armv6zk
index 124f9c9..a758c58 100644 (file)
@@ -31,13 +31,13 @@ the boot process.
 _start:\r
        /* vectors */\r
        b _common_start /* reset */\r
-       nop /* undefined */\r
+       b _fleh_undef /* undefined */\r
        b _secure_monitor /* swi/smc */\r
-       nop /* prefetch abort */\r
-       nop /* data abort */\r
-       nop /* reserved */\r
-       nop /* irq */\r
-       nop /* fiq */\r
+       b _fleh_prefabt /* prefetch abort */\r
+       b _fleh_dataabt /* data abort */\r
+       b _fleh_addrexc /* reserved */\r
+       b _fleh_irq /* irq */\r
+       b _fleh_fiq /* fiq */\r
 \r
 .globl g_FirmwareData\r
 g_FirmwareData:\r
@@ -47,15 +47,46 @@ g_FirmwareData:
        .long 0 /* Reserved */\r
        .long 0 /* Reserved */\r
 \r
+#define SaveRegisters() \\r
+       mov sp, #(MEM_STACK_END); \\r
+       stmea sp, {r0-lr}^; \\r
+       str lr, [sp, #60]; \\r
+       mrs r0, spsr\r
+       str r0, [sp, #64];\r
+\r
+_fleh_undef:\r
+       SaveRegisters()\r
+       b sleh_undef\r
+\r
+_fleh_prefabt:\r
+       SaveRegisters()\r
+       b sleh_prefabt\r
+\r
+_fleh_dataabt:\r
+       SaveRegisters()\r
+       b sleh_dataabt\r
+\r
+_fleh_addrexc:\r
+       SaveRegisters()\r
+       b sleh_addrexc\r
+\r
+_fleh_irq:\r
+       SaveRegisters()\r
+       b sleh_irq\r
+\r
+_fleh_fiq:\r
+       SaveRegisters()\r
+       b sleh_fiq\r
+\r
 _secure_monitor:\r
        mrc p15, 0, r0, c1, c1, 0\r
-       bic     r0, r0, #0x4a /* clear IRQ, EA, nET */\r
+       //bic   r0, r0, #0x4a /* clear IRQ, EA, nET */\r
        orr r0, r0, #1 /* set NS */\r
        mcr p15, 0, r0, c1, c1, 0\r
 \r
-       mov r0, #((1 << 7) | (1 << 8) | (1 << 6)) /* mask IRQ, AA and FIQ */\r
-       orr r0, r0, #0x1a /* switch to hypervisor mode */\r
-       msr spsr_cxfs, r0 \r
+       //mov r0, #((1 << 7) | (1 << 8) | (1 << 6)) /* mask IRQ, AA and FIQ */\r
+       //orr r0, r0, #0x1a /* switch to hypervisor mode */\r
+       //msr spsr_cxfs, r0 \r
 \r
        movs pc, lr\r
 \r
@@ -84,17 +115,21 @@ L_armv7_or_higher:
 \r
 L_setup_monitor:\r
        adr     r1, _start\r
-       mcr     p15, 0, r1, c12, c0, 1 /* MVBAR */\r
-       mcr p15, 0, r1, c7, c5, 4 /* ISB (ARMv6 compatible way) */\r
+       //mcr   p15, 0, r1, c12, c0, 1 /* MVBAR */\r
+       //mcr p15, 0, r1, c7, c5, 4 /* ISB (ARMv6 compatible way) */\r
+\r
+       mrc p15, 0, r0, c1, c1, 0\r
+       orr r0, r0, #1 /* set NS */\r
+       mcr p15, 0, r0, c1, c1, 0\r
 \r
        mov r12, #1\r
-       smc 0\r
+       //smc 0\r
        \r
 L_finish_init:\r
        /* enable instruction cache */\r
-       mrc p15, 0, r0, c1, c0, 0\r
-       orr r0, r0, #(1<<12)\r
-       mcr p15, 0, r0, c1, c0, 0\r
+       //mrc p15, 0, r0, c1, c0, 0\r
+       //orr r0, r0, #(1<<12)\r
+       //mcr p15, 0, r0, c1, c0, 0\r
 \r
        mov sp, #(MEM_STACK_END)\r
        mov r0, r12\r
diff --git a/arm_chainloader/trap.c b/arm_chainloader/trap.c
deleted file mode 100644 (file)
index 2946448..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * trap.cc
- * Copyright (c) 2017 Kristina Brooks
- *
- * ARM trap handling code.
- */
\ No newline at end of file
diff --git a/arm_chainloader/trap.cc b/arm_chainloader/trap.cc
new file mode 100644 (file)
index 0000000..06c6643
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * trap.cc
+ * Copyright (c) 2017 Kristina Brooks
+ *
+ * ARM trap handling code.
+ */
+
+#include <lib/runtime.h>
+
+struct arm_saved_state {
+       uint32_t        r[13];          /* General purpose register r0-r12 */
+       uint32_t        sp;                     /* Stack pointer r13 */
+       uint32_t        lr;                     /* Link register r14 */
+       uint32_t        pc;                     /* Program counter r15 */
+       uint32_t        cpsr;           /* Current program status register */
+       uint32_t        fsr;            /* Fault status */
+       uint32_t        far;            /* Virtual Fault Address */
+       uint32_t        exception;      /* exception number */
+};
+typedef struct arm_saved_state arm_saved_state_t;
+
+#define REGISTER_FORMAT_STRING(prefix) \
+       prefix "  r0: 0x%08x  r1: 0x%08x  r2: 0x%08x  r3: 0x%08x\n" \
+       prefix "  r4: 0x%08x  r5: 0x%08x  r6: 0x%08x  r7: 0x%08x\n" \
+       prefix "  r8: 0x%08x  r9: 0x%08x r10: 0x%08x r11: 0x%08x\n" \
+       prefix " r12: 0x%08x  sp: 0x%08x  lr: 0x%08x  pc: 0x%08x\n" \
+       prefix "cpsr: 0x%08x\n"
+
+#define REGISTER_PRINTF_LIST(regs) regs->r[0], regs->r[1], regs->r[2], regs->r[3],\
+       regs->r[4], regs->r[5], regs->r[6], regs->r[7], \
+       regs->r[8], regs->r[9], regs->r[10], regs->r[11], \
+       regs->r[12], regs->sp, regs->lr, regs->pc, regs->cpsr
+
+extern "C" void fatal_exception(arm_saved_state_t* regs, const char* fmt, ...)
+{
+       va_list va;
+
+       printf("Fatal Exception: ");
+       va_start(va, fmt);
+       vprintf(fmt, va);
+       va_end(va);
+       printf("\n");
+
+       printf("ARM registers: \n");
+       printf(REGISTER_FORMAT_STRING("    "), REGISTER_PRINTF_LIST(regs));
+
+       panic("Fatal CPU exception!");
+}
+
+extern "C" void sleh_undef(arm_saved_state_t* regs) {
+       fatal_exception(regs, "Undefined instruction");
+}
+
+extern "C" void sleh_prefabt(arm_saved_state_t* regs) {
+       fatal_exception(regs, "Prefetch abort");
+}
+
+extern "C" void sleh_dataabt(arm_saved_state_t* regs) {
+       fatal_exception(regs, "Data abort");
+}
+extern "C" void sleh_addrexc(arm_saved_state_t* regs) {
+       fatal_exception(regs, "Address exception");
+}
+
+extern "C" void sleh_irq(arm_saved_state_t* regs) {
+       fatal_exception(regs, "IRQ");
+}
+
+extern "C" void sleh_fiq(arm_saved_state_t* regs) {
+       fatal_exception(regs, "FIQ");
+}
\ No newline at end of file
index e3281c8..552e693 100644 (file)
@@ -18,7 +18,7 @@ ARM initialization stuff.
 =============================================================================*/\r
 \r
 #include <lib/runtime.h>\r
-#include "hardware.h"\r
+#include <drivers/BCM2708PowerManagement.hpp>\r
 \r
 #define logf(fmt, ...) printf("[ARMLDR:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__);\r
 \r
@@ -44,72 +44,14 @@ extern uint8_t L_arm_code_end;
 /* XXX: What is this? */\r
 #define PM_UNK_CFG_CLR 0xFFFCFFFF\r
 \r
-static bool power_wait_bit(uint32_t bit) {\r
-       for (int i = 0; i < 20; i++) {\r
-               if (PM_PROC & bit) {\r
-                       return true;\r
-               }\r
-               udelay(100);\r
-       }\r
-       return false;\r
-}\r
-\r
 static inline void assert_global_reset() {\r
-       logf("RSTN ...\n");\r
-       PM_PROC |= PM_PASSWORD | PM_PROC_ARMRSTN_SET;\r
-       udelay(300);\r
+       PowerManagementDomain::getDeviceForDomain(kCprPowerDomainARM)->setReset();\r
 }\r
 \r
 static void enable_power() {\r
-       uint32_t pmv;\r
-\r
-       logf("INIT PM_PROC: 0x%X\n", PM_PROC);\r
-\r
-       logf("requesting power up ...\n");\r
-\r
-       /* deassert all reset lines */\r
-       pmv = ((PM_PROC & PM_PROC_ARMRSTN_CLR) & PM_UNK_CFG_CLR) | PM_PASSWORD;\r
-\r
-       PM_PROC = pmv;\r
-\r
-       pmv |= PM_PROC_POWUP_SET;\r
-       udelay(10);\r
-       PM_PROC = pmv;\r
-\r
-       logf("POWUP PM_PROC: 0x%X\n", PM_PROC);\r
-\r
-       /* wait for POWOK */\r
-       logf("waiting for power up ...\n");\r
-       for (int i = 1; i < 5; i++) {\r
-               if (!power_wait_bit(PM_PROC_POWOK_SET)) {\r
-                       /* only go up to 3 */\r
-                       if (i == 4) {\r
-                               panic("timed out waiting for power up, state of PM_PROC is: 0x%X", PM_PROC);\r
-                       }\r
-\r
-                       pmv = (pmv & PM_UNK_CFG_CLR) | (i << PM_PROC_CFG_LSB);\r
-                       logf("timed out, trying different CFG: 0x%X \n", pmv);\r
-                       PM_PROC = pmv;\r
-               }\r
-       }\r
-\r
-       pmv |= PM_PROC_ISPOW_SET;\r
-       PM_PROC = pmv;\r
-\r
-       pmv |= PM_PROC_MEMREP_SET;\r
-       PM_PROC = pmv;\r
-\r
-       logf("waiting for MRDONE ...\n");\r
-       if (!power_wait_bit(PM_PROC_MRDONE_SET)) {\r
-               panic("timed out waiting for MRDONE, state of PM_PROC is: 0x%X", PM_PROC);\r
-       }\r
-\r
-       logf("setting ISFUNC ...\n");\r
-\r
-       pmv |= PM_PROC_ISFUNC_SET;\r
-       PM_PROC = pmv;\r
-\r
-       logf("ARM power domain initialized succesfully, state of PM_PROC is: 0x%X!\n", PM_PROC);\r
+       PowerManagementDomain* armPm = PowerManagementDomain::getDeviceForDomain(kCprPowerDomainARM);\r
+       assert(armPm);\r
+       armPm->start();\r
 }\r
 \r
 static void bresp_cycle_write(uint32_t bits) {\r
diff --git a/drivers/BCM2708ArmControl.cc b/drivers/BCM2708ArmControl.cc
new file mode 100644 (file)
index 0000000..9ef7dff
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * VideoCore4_Drivers
+ * Copyright (c) 2017 Kristina Brooks
+ *
+ * ARM control driver.
+ */
+
+#include <drivers/IODevice.hpp>
+#include <drivers/BCM2708PowerManagement.hpp>
+
+#define FLAG_BUSY (1 << 31)
+
+struct BCM2708ArmControl : IODevice {
+       IODriverConstructor(BCM2708ArmControl);
+
+       virtual void start() override {
+               IODriverLog("starting ...");
+
+               IODevice::start();
+       }
+
+       virtual void init() override {
+               setName("BCM2708ArmControl");
+               setTag('ARMC');
+       }
+};
+
+IODriverCreateSingletonInstance(BCM2708ArmControl);
+
diff --git a/drivers/BCM2708PowerManagement.cc b/drivers/BCM2708PowerManagement.cc
new file mode 100644 (file)
index 0000000..3317140
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * VideoCore4_Drivers
+ * Copyright (c) 2017 Kristina Brooks
+ *
+ * BCM2708 power management driver.
+ */
+
+#include <drivers/BCM2708PowerManagement.hpp>
+
+#define PM_UNK_CFG_CLR 0xFFFCFFFF
+
+PowerManagementDomain* g_BCM2708PowerDomains[kCprPowerDomain_MAX];
+
+PowerManagementDomain* PowerManagementDomain::getDeviceForDomain(cpr_power_domain_t domain) {
+       if (domain > kCprPowerDomain_MAX-1) {
+               return nullptr;
+       }
+       PowerManagementDomain* pm = g_BCM2708PowerDomains[domain];
+}
+
+/***********************************************************************
+ * 
+ * Superclass for all power domains.
+ *
+ ***********************************************************************/
+
+struct BCM2708PowerDomain : PowerManagementDomain {
+       volatile uint32_t* pmReg;
+       uint32_t rstnMask;
+       cpr_power_domain_t powerDomain;
+
+       inline void pmvOr(uint32_t& pmv, uint32_t value) {
+               pmv |= value;
+               *pmReg = pmv;
+       }
+
+       inline void pmvAnd(uint32_t& pmv, uint32_t value) {
+               pmv &= value;
+               *pmReg = pmv;
+       }
+
+       bool waitForPmBit(uint32_t bit) {
+               for (int i = 0; i < 20; i++) {
+                       if (*pmReg & bit) {
+                               return true;
+                       }
+                       waitOscTicks();
+               }
+               return false;
+       }
+
+       cpr_power_result_t waitForPOWOK(uint32_t& pmv) {
+               IODriverLog("waiting for POWOK ...");
+
+               for (int i = 1; i < 5; i++) {
+                       if (!waitForPmBit(PM_GNRIC_POWOK_SET)) {
+                               /* only go up to 3 */
+                               if (i == 4) {
+                                       IODriverLog("timed out waiting for powok!");
+                                       return kCprPowOkTimeout;
+                               }
+
+                               pmv = (pmv & PM_UNK_CFG_CLR) | (i << PM_GNRIC_CFG_LSB);
+                               IODriverLog("timed out, trying a different cfg value: 0x%X", pmv);
+                               *pmReg = pmv;
+                       }
+               }
+
+               IODriverLog("got POWOK with CFG=0x%X", *pmReg & PM_GNRIC_CFG_SET);
+               return kCprSuccess;
+       }
+
+       cpr_power_result_t beginPowerUpSequence(uint32_t& pmv) {
+               IODriverLog("starting power up sequence ...");
+               pmvOr(pmv, PM_GNRIC_POWUP_SET);
+       }
+
+       cpr_power_result_t completePowerUpSequence(uint32_t& pmv, bool setPowup = true) {
+               pmvOr(pmv, PM_GNRIC_ISPOW_SET);
+               pmvOr(pmv, PM_GNRIC_MEMREP_SET);
+
+               IODriverLog("waiting for MRDONE ...");
+               if (!waitForPmBit(PM_GNRIC_MRDONE_SET)) {
+                       IODriverLog("timed out waiting for MRDONE: 0x%X", *pmReg);
+                       return kCprMrDoneTimeout;
+               }
+
+               pmvOr(pmv, PM_GNRIC_ISFUNC_SET);
+
+               return kCprSuccess;
+       }
+
+       virtual cpr_power_result_t powerOn() {
+               uint32_t pmv;
+               cpr_power_result_t res;
+
+               IODriverLog("powering on (rstnMask=0x%X) ...", rstnMask);
+
+               pmv = ((*pmReg & rstnMask) & PM_UNK_CFG_CLR) | PM_PASSWORD;
+               *pmReg = pmv;
+               udelay(15);
+
+               beginPowerUpSequence(pmv);
+
+               res = waitForPOWOK(pmv);
+               if (res != kCprSuccess)
+                       return res;
+
+               res = completePowerUpSequence(pmv);
+               if (res != kCprSuccess)
+                       return res;
+
+               IODriverLog("domain powered on succesfully");
+
+               return kCprSuccess;
+       }
+
+       virtual void setReset() override {
+               IODriverLog("setting RSTN bits to 0x%X ...", (~rstnMask));
+               *pmReg |= (~rstnMask) | PM_PASSWORD;
+               udelay(300);
+       }
+
+       void waitOscTicks(uint32_t ticks = 2) {
+               CM_OSCCOUNT = CM_PASSWORD | ticks;
+               while(CM_OSCCOUNT != 0);
+       }
+
+       template <typename T>
+       void setPmReg(T regAddr) {
+               pmReg = reinterpret_cast<volatile uint32_t*>(regAddr);
+       }
+
+       void registerPowerDomain(cpr_power_domain_t domain) {
+               g_BCM2708PowerDomains[domain] = this;
+       } 
+};
+
+/***********************************************************************
+ * 
+ * Image power domain.
+ * Contains: PERII (USB), H264, ISP
+ *
+ ***********************************************************************/
+
+struct BCM2708PowerDomainImage : BCM2708PowerDomain {
+       IODriverConstructor(BCM2708PowerDomainImage);
+
+       virtual void init() override {
+               setName("BCM2708PowerDomainImage");
+               setPmReg(0x7E100108);
+               registerPowerDomain(kCprPowerDomainImage);
+               rstnMask = ~(PM_IMAGE_ISPRSTN_SET | PM_IMAGE_H264RSTN_SET | PM_IMAGE_PERIRSTN_SET);
+       }
+
+       virtual cpr_power_result_t powerOn() {
+               uint32_t pmv;
+               cpr_power_result_t res;
+
+               IODriverLog("powering on, current PM_IMAGE state: 0x%X", PM_IMAGE);
+
+               pmv = *pmReg | 0x10000 | PM_PASSWORD;
+               *pmReg = pmv;
+
+               /*
+                * first sequence has to be done with this CFG.
+                */
+               beginPowerUpSequence(pmv);
+
+               res = waitForPOWOK(pmv);
+               if (res != kCprSuccess)
+                       return res;
+
+               IODriverLog("stopping power up sequence ...");
+               pmvAnd(pmv, ~PM_GNRIC_POWUP_SET);
+               pmvOr(pmv, 0x30000); /* CFG */
+
+               /*
+                * now do this all over again with the new CFG.
+                */
+               beginPowerUpSequence(pmv);
+
+               res = waitForPOWOK(pmv);
+               if (res != kCprSuccess)
+                       return res;
+
+               res = completePowerUpSequence(pmv);
+               if (res != kCprSuccess)
+                       return res;
+
+               BCM2708PowerDomain::stop();
+
+               return kCprSuccess;
+       }
+
+       void resetPeripheralsUngated() {
+               CM_PERIICTL = CM_PASSWORD | CM_PERIICTL_GATE_SET;
+
+               //IODriverLog("vector op call ...");
+               //vector_op_gated();
+
+               CM_PERIICTL = CM_PASSWORD;
+
+               waitOscTicks();
+
+               *pmReg |= CM_PASSWORD | PM_IMAGE_PERIRSTN_SET;
+
+               CM_PERIICTL = CM_PASSWORD | CM_PERIICTL_GATE_SET;
+
+               IODriverLog("done");
+       }
+
+       virtual void start() override {
+#if 1
+               cpr_power_result_t res = powerOn();
+
+               if (res != kCprSuccess)
+                       panic("%s failed to start the image power domain", driverName);
+
+               resetPeripheralsUngated();
+#else
+               IODriverLog("image_domain_peripherals_init returned: 0x%X", image_domain_peripherals_init());
+#endif
+
+               IODriverLog("CM_PERIICTL = 0x%X", CM_PERIICTL);
+               IODriverLog("CM_PERIIDIV = 0x%X", CM_PERIIDIV);
+               IODriverLog("PM_IMAGE    = 0x%X", PM_IMAGE);
+
+               IODriverLog("started");
+
+               BCM2708PowerDomain::start();
+       }
+};
+
+IODriverCreateSingletonInstance(BCM2708PowerDomainImage);
+
+/***********************************************************************
+ * 
+ * USB power domain.
+ *
+ ***********************************************************************/
+
+struct BCM2708PowerDomainUSB : BCM2708PowerDomain {
+       IODriverConstructor(BCM2708PowerDomainUSB);
+
+       virtual void init() override {
+               setName("BCM2708PowerDomainUSB");
+               setPmReg(&PM_USB);
+               registerPowerDomain(kCprPowerDomainUSB);
+       }
+
+       virtual void stop() override {
+               IODriverLog("stopping ...");
+
+               PM_USB = PM_PASSWORD;
+               udelay(200000);
+
+               IODriverLog("stopped");
+
+               BCM2708PowerDomain::stop();
+       }
+
+       virtual void start() override {
+               IODriverLog("starting ...");
+
+               PM_USB |= PM_PASSWORD | PM_USB_CTRLEN_SET;
+               udelay(600);
+
+               IODriverLog("started");
+
+               BCM2708PowerDomain::start();
+       }
+};
+
+IODriverCreateSingletonInstance(BCM2708PowerDomainUSB);
+
+/***********************************************************************
+ * 
+ * ARM power domain.
+ *
+ ***********************************************************************/
+
+struct BCM2708PowerDomainARM : BCM2708PowerDomain {
+       IODriverConstructor(BCM2708PowerDomainARM);
+
+       virtual void init() override {
+               setName("BCM2708PowerDomainARM");
+               setPmReg(&PM_PROC);
+               rstnMask = PM_PROC_ARMRSTN_CLR;
+               registerPowerDomain(kCprPowerDomainARM);
+       }
+
+       virtual void stop() override {
+               panic("this power domain cannot be stopped");
+       }
+
+       virtual void start() override {
+               IODriverLog("starting ...");
+
+               cpr_power_result_t res = powerOn();
+
+               if (res != kCprSuccess)
+                       panic("%s failed to start the ARM power domain", driverName);
+
+               IODriverLog("started");
+
+               BCM2708PowerDomain::start();
+       }
+};
+
+IODriverCreateSingletonInstance(BCM2708PowerDomainARM);
+
diff --git a/drivers/BCM2708PowerManagement.hpp b/drivers/BCM2708PowerManagement.hpp
new file mode 100644 (file)
index 0000000..a9a5d51
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * VideoCore4_Drivers
+ * Copyright (c) 2017 Kristina Brooks
+ *
+ * BCM2708 power management driver.
+ */
+
+#pragma once
+#include <drivers/IODevice.hpp>
+
+enum cpr_power_result_t {
+       kCprSuccess = 0,
+       kCprPowOkTimeout,
+       kCprMrDoneTimeout,
+       kCprOscCountTimeout
+};
+
+enum cpr_power_domain_t {
+       kCprPowerDomainImage = 0,
+       kCprPowerDomainARM,
+       kCprPowerDomainUSB,
+       kCprPowerDomainVPU1,
+
+       kCprPowerDomain_MAX
+};
+
+struct PowerManagementDomain : IODevice {
+       static PowerManagementDomain* getDeviceForDomain(cpr_power_domain_t domain);
+       virtual void setReset() = 0;
+};
\ No newline at end of file
diff --git a/drivers/BCM2708UsbPhy.cc b/drivers/BCM2708UsbPhy.cc
new file mode 100644 (file)
index 0000000..e57674b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * VideoCore4_Drivers
+ * Copyright (c) 2017 Authors of rpi-open-firmware
+ *
+ * USB PHY initialization driver.
+ */
+
+#include <drivers/IODevice.hpp>
+#include <drivers/BCM2708PowerManagement.hpp>
+
+#define FLAG_BUSY (1 << 31)
+
+struct BCM2708UsbPhy : IODevice {
+       IODriverConstructor(BCM2708UsbPhy);
+
+       void wait() {
+               while(USB_GMDIOCSR & FLAG_BUSY);
+       }
+
+       void write_bare(int reg, uint16_t value, int type) {
+               reg &= 0x1F;
+
+               /* precede MDIO access */
+               USB_GMDIOGEN = 0xFFFFFFFF;
+               wait();
+
+               /* write the actual value, with flags */
+               USB_GMDIOGEN = type | (reg << 18) | value;
+               wait();
+
+               /* dummy write due to errata; see BCM2835 peripheral manual */
+               USB_GMDIOGEN = 0; 
+               wait();
+       }
+
+       uint16_t usb_read(int reg) {
+               write_bare(reg, 0, 0x60020000);
+               return USB_MDIO_CSR & 0x3FF;
+       }
+
+       virtual void usb_write(int reg, uint16_t value) {
+               IODriverLog("Writing 0x%X to reg 0x%X", value, reg);
+               write_bare(reg, value, 0x50020000);
+       }
+
+       virtual void start() override {
+               IODriverLog("starting ...");
+
+               USB_GMDIOCSR = (1 << 18);
+
+               usb_write(0x15, 4369/*cond ? 4569 : 272*/);
+               usb_write(0x19, 0x4);
+               usb_write(0x18, 0x10);
+               usb_write(0x1D, 0x4);
+               usb_write(0x17, 5682);
+
+               while(!usb_read(0x1B) & 0x7);
+
+               usb_write(0x1E, 0x01);
+
+               usb_write(0x1D, 0x5000);
+               usb_write(0x19, 0xC004);
+               usb_write(0x32, 0x1C2F);
+               usb_write(34, 256);
+               usb_write(36, 0x10);
+               usb_write(0x19, 0x04);
+
+               IODriverLog("started");
+
+               IODevice::start();
+       }
+
+       virtual void init() override {
+               setName("BCM2708UsbPhy");
+               setTag('USBP');
+       }
+};
+
+IODriverCreateSingletonInstance(BCM2708UsbPhy);
+
diff --git a/drivers/IODevice.cc b/drivers/IODevice.cc
new file mode 100644 (file)
index 0000000..b9cb4fc
--- /dev/null
@@ -0,0 +1,60 @@
+#include <drivers/IODevice.hpp>
+
+static IODevice* g_DeviceRegistry[32] = { 0 };
+static unsigned int g_NewDriverIndex = 0;
+
+IODevice::IODevice() {
+
+}
+
+void IODevice::_beforeInit() {
+       tag = 0;
+       deviceState = kIODeviceUninitialized;
+}
+
+void IODevice::_afterInit() {
+       assert(driverName);
+       if (tag)
+               registerDriver();
+}
+
+void IODevice::registerDriver() {
+       g_DeviceRegistry[g_NewDriverIndex++] = this;
+       IODriverLog("driver registered on platform IO plane");
+}
+
+void IODevice::driverLog(const char* fnName, const char* fmt, ...)
+{
+       va_list va;
+
+       printf("%s::%s(): ", driverName, fnName);
+       va_start(va, fmt);
+       vprintf(fmt, va);
+       va_end(va);
+       printf("\n");
+}
+
+IODevice* IODevice::findByTag(uint32_t tag) {
+       for (int i = 0; i < (sizeof(g_DeviceRegistry) / sizeof(void*)); i++) {
+               IODevice* dev = g_DeviceRegistry[i];
+               if (dev && dev->tag == tag) {
+                       return dev;
+               }
+       }
+
+       return nullptr;
+}
+
+void IODevice::start() {
+       deviceState = kIODeviceStarted;
+}
+
+void IODevice::stop() {
+       deviceState = kIODeviceStopped;
+}
+
+void IODevice::init() {
+       panic("IODevice objects have to override init()");
+}
+
+
diff --git a/drivers/IODevice.hpp b/drivers/IODevice.hpp
new file mode 100644 (file)
index 0000000..240c7ff
--- /dev/null
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <lib/runtime.h>
+#include <hardware.h>
+
+enum IODeviceState {
+       kIODeviceUninitialized,
+       kIODeviceStarted,
+       kIODeviceStopped
+};
+
+struct IODevice {
+       const char* driverName;
+       IODeviceState deviceState;
+       uint32_t tag;
+       
+       IODevice();
+
+       void driverLog(const char* fnName, const char* fmt, ...);
+       void registerDriver();
+
+       void inline setName(const char* name) {
+               driverName = name;
+       }
+
+       void inline setTag(uint32_t tag) {
+               this->tag = tag;
+       }
+
+       virtual void start();
+       virtual void stop();
+       virtual void init();
+
+       void _afterInit();
+       void _beforeInit();
+
+       virtual inline IODeviceState getDeviceState() {
+               return deviceState;
+       }
+
+       static IODevice* findByTag(uint32_t tag);
+};
+
+#define IODriverLog(fmt, ...) driverLog(__FUNCTION__, fmt, ##__VA_ARGS__)
+#define IODriverCreateSingletonInstance(clazz) static clazz __IODriver_static_ ## clazz {}
+#define IODriverConstructor(clazz) clazz() { _beforeInit(); init(); _afterInit(); }
\ No newline at end of file
index 084bce8..89eccc5 100644 (file)
@@ -16,6 +16,8 @@ extern void panic(const char* fmt,  ...)
 #define panic(ex, ...) \\r
        (panic)(# ex "@" PANIC_LOCATION, ## __VA_ARGS__)\r
 \r
+#define assert(x) if (!(x)) { panic("assertion '%s' failed", #x); }\r
+\r
 #ifdef __cplusplus\r
 }\r
 #endif
\ No newline at end of file
index 6cebac7..740bf8a 100644 (file)
@@ -22,6 +22,8 @@ SECTIONS
        .init_array : {
                *(.init_array)
                *(.init_array.*)
+               *(.ctors)
+               *(.ctors.*)
        }
        PROVIDE (__init_array_end = .);
 
index b4899c4..310b5c1 100644 (file)
@@ -161,6 +161,7 @@ void switch_vpu_to_pllc() {
 extern void sdram_init();\r
 extern void arm_init();\r
 extern void monitor_start();\r
+extern void PEStartPlatform();\r
 \r
 void print_crap() {\r
        printf("TB_BOOT_OPT = 0x%X\n", TB_BOOT_OPT);\r
@@ -198,6 +199,8 @@ int _main(unsigned int cpuid, unsigned int load_address) {
        sdram_init();\r
        printf("SDRAM initialization completed successfully!\n");\r
 \r
+       PEStartPlatform();\r
+\r
        /* bring up ARM */\r
        arm_init();\r
 \r
This page took 0.080881 seconds and 4 git commands to generate.