rk27xx: Implement dualboot capable bootloader

Change-Id: I399e10635f611bdf6f7c1bd5843fa132dc88bfb4
diff --git a/bootloader/rk27xx.c b/bootloader/rk27xx.c
index b74526f..c1c8110 100644
--- a/bootloader/rk27xx.c
+++ b/bootloader/rk27xx.c
@@ -1,184 +1,110 @@
-#include "config.h"
-#include <stdlib.h>
 #include <stdio.h>
-#include <string.h>
-#include "inttypes.h"
-#include "string.h"
-#include "cpu.h"
-#include "system.h"
+#include <system.h>
+#include <inttypes.h>
+#include "config.h"
+#include "gcc_extensions.h"
 #include "lcd.h"
-#include "kernel.h"
-#include "thread.h"
-#include "backlight.h"
-#include "backlight-target.h"
 #include "font.h"
+#include "backlight.h"
+#include "adc.h"
+#include "button-target.h"
+#include "button.h"
 #include "common.h"
-#include "version.h"
+#include "storage.h"
+#include "disk.h"
+#include "panic.h"
+#include "power.h"
+#include "string.h"
+#include "file.h"
+#include "crc32-rkw.h"
+#include "rkw.h"
 
-// 441 Hz samples table, 44100 Hz and 441 Hz -> 100 samples 
-const int16_t samples[] = {
-         0,   2057,   4106,   6139,   8148,  10125,  12062,  13951,  15785,  17557,
-     19259,  20886,  22430,  23886,  25247,  26509,  27666,  28713,  29648,  30465,
-     31163,  31737,  32186,  32508,  32702,  32767,  32702,  32508,  32186,  31737,
-     31163,  30465,  29648,  28713,  27666,  26509,  25247,  23886,  22430,  20886,
-     19259,  17557,  15785,  13951,  12062,  10125,   8148,   6139,   4106,   2057,
-         0,  -2057,  -4106,  -6139,  -8148, -10125, -12062, -13951, -15785, -17557,
-    -19259, -20886, -22430, -23886, -25247, -26509, -27666, -28713, -29648, -30465,
-    -31163, -31737, -32186, -32508, -32702, -32767, -32702, -32508, -32186, -31737,
-    -31163, -30465, -29648, -28713, -27666, -26509, -25247, -23886, -22430, -20886,
-    -19259, -17557, -15785, -13951, -12062, -10125,  -8148,  -6139,  -4106,  -2057 };
+#define DRAM_ORIG 0x60000000
+#define LOAD_SIZE 0x700000
 
 extern void show_logo( void );
 
-void INT_HDMA(void)
-{
-#if 0
-//    static uint32_t i;
-//    printf("hdma int: %d", i++);
-
-    HDMA_ISRC0 = (uint32_t)&samples;
-    HDMA_IDST0 = (uint32_t)&I2S_TXR;
-    HDMA_ICNT0 = (sizeof(samples)/4) - 1;
-    HDMA_CON0 = (1<<22)|  // slice mode
-                (1<<21)|  // channel enable
-                (1<<18)|  // interrupt mode
-                (5<<13)|  // transfer mode inc8
-                (6<<9) |  // hdreq from i2s tx
-                (0<<7) |  // source address increment
-                (1<<5) |  // destination address fixed
-                (2<<3) |  // data size word
-                (1<<0);   // enable hardware triggered dma
-
-    HDMA_ISR = (1<<13) | // mask ch1 page overflow
-               (1<<11) | // mask ch1 page count down
-               (1<<9);   // mask ch1 interrupts
-#endif
-return;
-}
-
-static int codec_write(uint8_t reg, uint8_t data)
-{
-    uint8_t tmp = data;
-    return i2c_write(0x27<<1, reg<<1, 1, &tmp);
-}
-
+void main(void) NORETURN_ATTR;
 void main(void)
 {
-    int i;
+    char filename[MAX_PATH];
+    unsigned char* loadbuffer;
+    void(*kernel_entry)(void);
+    int ret;
+    enum {rb, of} boot = rb;
 
-    _backlight_init();
-
+    power_init();
     system_init();
     kernel_init();
     enable_irq();
 
-    lcd_init_device();
-    _backlight_on();
+    adc_init();
+    lcd_init();
+    backlight_init();
+    button_init_device();
+
     font_init();
     lcd_setfont(FONT_SYSFIXED);
 
     show_logo();
-    sleep(HZ*2);
 
-printf("show logo passed");
-    // I2S init
-    SCU_CLKCFG &= ~((1<<17) | (1<<16)); // enable i2s, i2c pclk
-//SCU_CLKCFG |= ((1<<17) | (1<<16));
-    I2S_OPR = (1<<17) |    // reset Tx
-              (1<<16) |    // reset Rx
-              (1<<6)  |    // disable HDMA Req1
-              (1<<5);      // disable HDMA Req2
+    int btn = button_read_device();
 
-    I2S_TXCTL = (1<<16) |  // LRCK/SCLK = 64
-                (4<<8)  |  // MCLK/SCK = 4
-                (1<<4)  |  // 16bit samples
-                (0<<3)  |  // stereo mode
-                (0<<1);    // I2S
- 
-    I2S_RXCTL = (1<<16) |  // LRCK/SCLK = 64
-                (4<<8)  |  // MCLK/SCK = 4
-                (1<<4)  |  // 16bit samples
-                (0<<3)  |  // stereo mode
-                (0<<1);    // I2S
+    /* if there is some other button pressed
+     * besides POWER/PLAY we boot into OF
+     */
+    if ((btn & ~POWEROFF_BUTTON))
+        boot = of;
 
-    I2S_FIFOSTS = (1<<18) |  // Tx int trigger half full
-                  (1<<16);   // Rx int trigger half full
+    /* if we are woken up by USB insert boot into OF */
+    if (DEV_INFO & (1<<20))
+        boot = of;
 
-    // I2S start
-    I2S_OPR = (1<<17) | (1<<16);
-    sleep(HZ/100);
+    lcd_clear_display();
 
-    I2S_OPR = (0<<6) | // req channel 1 enable                               
-              (1<<5) | // req channel 2 disable
-              (0<<4) | // HDMA req channel 1 Tx
-              (0<<2) | // normal I2S operation (no loopback)
-              (1<<1);  // Tx start
+    ret = storage_init();
+    if(ret < 0)
+        error(EATA, ret, true);
 
-printf("I2S config passed");
+    while(!disk_init(IF_MV(0)))
+        panicf("disk_init failed!");
 
-    HDMA_ISRC0 = (uint32_t)&samples;
-    HDMA_IDST0 = (uint32_t)&I2S_TXR;
-    HDMA_ICNT0 = (sizeof(samples)/4) - 1;
-    HDMA_ISCNT0 = 7;
-    HDMA_IPNCNTD0 = 1;
-    HDMA_CON0 = (1<<22)|  // slice mode
-                (1<<21)|  // channel enable
-                (1<<18)|  // interrupt mode
-                (5<<13)|  // transfer mode inc8
-                (6<<9) |  // hdreq from i2s tx
-                (0<<7) |  // source address increment
-                (1<<5) |  // destination address fixed
-                (2<<3) |  // data size word
-                (1<<0);   // enable hardware triggered dma
+    while((ret = disk_mount_all()) <= 0)
+        error(EDISK, ret, true);
 
-    HDMA_ISR = (1<<13) | // mask ch1 page overflow
-               (1<<11) | // mask ch1 page count down
-               (1<<9);   // mask ch1 interrupts
+    loadbuffer = (unsigned char*)DRAM_ORIG; /* DRAM */
+   
+    if (boot == rb)
+        snprintf(filename,sizeof(filename), BOOTDIR "/%s", BOOTFILE);    
+    else if (boot == of)
+        snprintf(filename,sizeof(filename), BOOTDIR "/%s", "BASE.RKW");
 
-    INTC_IMR |= (1<<12);
-    INTC_IECR |= (1<<12);
+    printf("Loading: %s", filename);
 
-printf("HDMA config passed");
-
-    i2c_init();
-
-printf("I2C config passed");
-
-    // codec init
-    codec_write(0x00, (1<<3)|(1<<2)|(1<<1)|(1<<0)); // AICR
-    codec_write(0x01, (1<<7)|(1<<5)|(1<<3));        // CR1
-    codec_write(0x02, (1<<2));                      // CR2
-    codec_write(0x03, 0);                           // CCR1
-    codec_write(0x04, (2<<4)|(2<<0));               // CCR2
-    codec_write(0x07, (3<<5)|(3<<0));               // CCR
-
-
-    codec_write(0x0f, 0x1f|(2<<6));                 // CGR6
-    codec_write(0x14, (1<<1));                      // TR1
-    codec_write(0x05, (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0)); // PMR1
-    sleep(HZ/100);
-
-    codec_write(0x06, (1<<3)|(1<<2)|(1<<0));               // PMR2
-
-
-    codec_write(0x05, (1<<6)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0));        // PMR1
-    codec_write(0x05, (1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0));               // PMR1
-
-
-    // DACout mode
-    codec_write(0x01, (1<<7)|(1<<3)|(1<<5)|(1<<4));  // CR1
-    codec_write(0x05, (1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0)); //PMR1
-//    codec_write(0x06, (1<<3)|(1<<2));                // PMR2
-
-printf("codec init passed");
-
-    codec_write(0x01, (1<<7)|(1<<3));         // CR1
-
-    codec_write(0x0a, 0); // 0dB digital gain
-    codec_write(0x11, 15|(2<<6)); // 
-
-    while(1)
+    ret = load_rkw(loadbuffer, filename, LOAD_SIZE);
+    if (ret < 0)
     {
-        printf("HDMA_CCNT0: 0x%0x FIFOSTS: 0x%0x", HDMA_CCNT0, I2S_FIFOSTS);
+        printf(rkw_strerror(ret));
+        lcd_update();
+        sleep(5*HZ);
+        power_off();
     }
+    else
+    {
+        printf(rkw_strerror(0));
+        sleep(HZ);
+    }
+
+    kernel_entry = (void*) loadbuffer;
+    commit_discard_idcache();
+
+    printf("Executing");
+    kernel_entry();
+
+    printf("ERR: Failed to boot");
+    sleep(5*HZ);
+    power_off();
+
+    /* hang */
+    while(1);
 }