]> www.infradead.org Git - users/rw/armboot.git/commitdiff
Changes for Shannon (aka Tuxscreen) to run stand-alone
authorrobertkaiser <robertkaiser>
Thu, 13 Mar 2003 18:14:28 +0000 (18:14 +0000)
committerrobertkaiser <robertkaiser>
Thu, 13 Mar 2003 18:14:28 +0000 (18:14 +0000)
board/shannon/README.Install
board/shannon/memsetup.S
board/shannon/video.c

index 18a594d05bd7c3281ab550e485c7e80a1da05e00..1c5d16cd704bb827b9c8132919b5b6a82d2a4489 100644 (file)
@@ -69,13 +69,39 @@ contains only a single mapping.
 If you do not want IrDA keyboard support, undefine both CONFIG_KEYBOARD
 and CONFIG_KEYBOARD_IRDA.
 
+1.3 Standalone operation
+
+ARMboot can now be started directly from power on, i.e. you can
+toss the Inferno firmware once and for all. This is nice because:
+
+- You don't have to hit ESC, CTRL+P, B F!kern2 to get into ARMboot,
+  it will come up right away.
+
+- Only the first 128K of flash is occupied by ARMboot, the rest is
+  freely available
+
+- Inferno insists on turning on the SA-1100's watchdog, which can not
+  be turned off any more, so you have to service it in whatever experimental
+  program you want to run, or else you get a reset after two minutes or so.
+  This is not the case with ARMboot.
+
+So, quite a few reasons to do this. Be warned though that you can
+actually destroy your Tuxscreen if the installation fails (see below).
+
+To build ARMboot for standalone operation, change CONFIG_INFERNO
+to undefined and define CONFIG_INIT_CRITICAL.
+
+
 2. Installing ARMboot on the Shannon
 ------------------------------------
 
-ARMboot expects to be loaded by the Inferno bootloader. To make this
-happen, you must put the ARMboot binary in the board's flash and you
-must convert into a format suitable for Inferno. Specifically, the image
-must be preceeded by an Inferno-specific header and the whole image
+2.1 Invoking ARMboot from Inferno
+---------------------------------
+
+If ARMboot is configured to be loaded by the Inferno bootloader, you
+must put the ARMboot binary in the board's flash and you must convert
+into a format suitable for Inferno. Specifically, the image must be
+preceeded by an Inferno-specific header and the whole image
 (header + ARMboot) must be compressed with gzip. The Inferno header
 is distributed with ARMboot under board/shannon/inferno.header.
 Thus, to obtain an inferno-bootable ARMboot image, run a command like
@@ -118,4 +144,98 @@ Now, when you turn your Shannon back on, hit ESC when the spash screen
 comes up. Then enter CTRL+P. This will bring you into the Inferno monitor.
 From there, enter "B F!kern2" to invoke ARMboot.
 
+2.2 Invoking ARMboot from Power on
+----------------------------------
+
+!!!!!WARNING!!!!!!!!!!WARNING!!!!!!!!!!WARNING!!!!!!!!!!WARNING!!!!!
+
+    You can destroy your Tuxscreen doing this! More precisely,
+    you can bring it into a state where only the JFlash procedure
+    described at http://www.tuxscreen.net/wiki/view/JTAG can bring
+    it back to life. This recovery procedure involves soldering and
+    it requires a JTAG adapter (see above link for details), so it is
+    definitely not for the faint of heart.
+
+    I have successfully done this, so it definitely works. However,
+    it it is easy to get it wrong (it has happened to me), and you
+    have only one attempt.
+
+    Summary: I strongly suggest that you be able and prepared to
+             apply the JFlash procedure before you attempt this.
+
+!!!!!WARNING!!!!!!!!!!WARNING!!!!!!!!!!WARNING!!!!!!!!!!WARNING!!!!!
+
+- You should first install ARMboot for being invoked via Inferno
+  (see above).
+
+- Compile a new ARMboot binary for stand-alone operation.
+
+  .. edit config file, undef CONFIG_INFERNO, define CONFIG_INIT_CRITICAL
+  make clean;make
+
+- You must flash the resulting raw binary ("armboot.bin") into the
+  Tuxscreen's flash at offset zero. These flash sectors are write
+  locked for a standard Tuxscreeen, and you need to apply the 
+  FlashUnlock procedure described at:
+
+    http://www.tuxscreen.net/wiki/view//FlashUnlock
+
+  to remove the write locks.
+
+- After doing the FlashUnlock procedure, invoke ARMboot from Inferno.
+
+  power on, hit ESC, CTRL+P, enter "B F!kern2"
+
+- Download the new (stand-alone) ARMboot binary to RAM, for example
+  via serial line.
+
+   KERMIT>   set prefixing all
+   Tuxscreen # setenv baudrate 115200
+   KERMIT>   set speed 115200
+   ... switch baudrate ...
+   Tuxscreen # loadb d0000000
+   KERMIT>   send armboot.bin
+   ... takes awhile ... done!
+
+
+- [You may want to do a test wether this ARMBoot actually works before you
+  burn it into the low flash. You can not just invoke it from RAM (where it
+  is now) because it re-inititalizes the SDRAM controller, which will crash
+  if the code doing so resides in SDRAM. But you can copy it to some unused
+  place in high flash (e.g. to 0x3c0000 ) and invoke it there with "go 3c0000"
+  If this works, then there is a good chance that the same binary will work
+  from power on as well (however, this is not a 100% test).]
+
+- Unprotect the low flash sectors
+
+  Tuxscreen # protect off 0 1ffff
+
+- Cross your fingers, erase the low flash sectors.
+
+  Tuxscreen # erase 0 1ffff
+
+- Fingers still crossed, copy ARMboot from RAM to low flash.
+
+  cp.b d0000000 0 20000
+
+- Fingers *still* crossed, apply reset or power cycle the Tuxscreen.
+
+
+If everything works, ARMboot should come up on the screen.
+If the screen stays black, you have just converted your Tuxscreen
+into a paperweight :-(.
+
+Note 1: Theoretically, the procedure described at
+
+        http://www.tuxscreen.net/wiki/view/InstallingLinux
+
+      for installing the "Blob" loader should work for installing ARMboot
+      as well, i.e. the command "c D!armboot.bin F!all" should do. I tried
+      this once, it didn't work and I had to use the JFLash to revive my
+      Tuxscreen :-(. It is possible that my attempt only failed because
+      the flash had not been properly unlocked before. I have not bothered
+      to try it ever since...
 
+Note 2: If you have the ability to use JFlash anyway, you probably want
+        to use it right away to install ARMboot: Simply write the
+        armboot.bin to flash at offset zero.
index 2f7ab9b0bd9db5277d3cf670a034a21882256832..bf08580def23c5f819f5fa8878cded382bd72670 100644 (file)
@@ -39,16 +39,37 @@ MEM_START:  .long   0xc0000000
 #define MDCAS1 0x08
 #define MDCAS2 0x0c
 #define MSC0   0x10
-#define MSC1   0x14
 #define MECR   0x18
 
-mdcas0:                .long   0xc71c703f @ cccccccf
-mdcas1:                .long   0xffc71c71 @ fffffffc
-mdcas2:                .long   0xffffffff @ ffffffff
-mdcnfg:                .long   0x0334b21f @ 9326991f
-msc0:          .long   0xfff84458 @ 42304230
-msc1:          .long   0xffffffff @ 20182018 // war nicht drin
-mecr:          .long   0x7fff7fff @ 01000000
+#if (CFG_CPUSPEED == 0x03)
+/* RAM timing for 103 MHz */
+mdcas0:                .long   0xcccccccf
+mdcas1:                .long   0xfffffffc
+mdcas2:                .long   0xffffffff
+mdcnfg:                .long   0x0326991f
+msc0:          .long   0x42304230
+mecr:          .long   0x00c600c6
+#endif
+
+#if (CFG_CPUSPEED == 0x09)
+/* RAM timing for 190 MHz */
+mdcas0:                .long   0xc71c703f
+mdcas1:                .long   0xffc71c71
+mdcas2:                .long   0xffffffff
+mdcnfg:                .long   0x01b4b21f
+msc0:          .long   0x44584458
+mecr:          .long   0x016b016b
+#endif
+
+#if (CFG_CPUSPEED == 0x0a)
+/* RAM timing for 206 MHz */
+mdcas0:                .long   0xc71c703f
+mdcas1:                .long   0xffc71c71
+mdcas2:                .long   0xffffffff
+mdcnfg:                .long   0x0194b21f
+msc0:          .long   0x84c084c0
+mecr:          .long   0x018c018c
+#endif
 
 /* setting up the memory */
 
index cf4adc5ee1641abe63b78883bce326b775a775f9..a96e6a477d8fac2c5eee3f50d97e0633369aa28e 100644 (file)
 
 #include "config.h"
 #include <shannon_video.h>
+#include <SA-1100.h>
+#include <armboot.h>
+
+#if defined(CONFIG_CFB_CONSOLE) || defined(CONFIG_FRAMEBUFFER)
+
+#define SHANNON_UCB_GPIO_BACKLIGHT  9
+#define SHANNON_UCB_GPIO_BRIGHT_MASK    7
+#define SHANNON_UCB_GPIO_BRIGHT     6
+#define SHANNON_UCB_GPIO_CONTRAST_MASK  0x3f
+#define SHANNON_UCB_GPIO_CONTRAST   0
+
+#define UCB_IO_DATA 0x00
+#define UCB_IO_DIR  0x01
+
+
+static inline void ucb1x00_enable(void)
+{
+    Ser4MCSR = -1;
+    Ser4MCCR0 |= MCCR0_MCE;
+}
+
+
+static inline void ucb1x00_disable(void)
+{
+    Ser4MCCR0 &= ~MCCR0_MCE;
+}
+
+static inline void ucb1x00_reg_write(unsigned int reg, unsigned int val)
+{
+    int i;
+
+    Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
+
+    for (i = 0; i < 2; i++) {
+        udelay(10000);
+        if (Ser4MCSR & MCSR_CWC) {
+            break;
+        }
+    }
+}
+
+void ucb1x00_io_write(unsigned int set, unsigned int clear)
+{
+       static unsigned short io_out = 0;
+
+    io_out |= set;
+    io_out &= ~clear;
+
+    ucb1x00_reg_write(UCB_IO_DATA, io_out);
+}
+
+void ucb1x00_io_set_dir(unsigned int in, unsigned int out)
+{
+       static unsigned short io_dir = 0;
+
+    io_dir |= out;
+    io_dir &= ~in;
+
+    ucb1x00_reg_write(UCB_IO_DIR, io_dir);
+}
+
+int lcd_contrast(int arg)
+{
+       arg &= SHANNON_UCB_GPIO_CONTRAST_MASK;
+    ucb1x00_enable();
+    ucb1x00_io_write(arg << SHANNON_UCB_GPIO_CONTRAST,
+        (~arg & SHANNON_UCB_GPIO_CONTRAST_MASK) << SHANNON_UCB_GPIO_CONTRAST);
+    ucb1x00_disable();
+    return 0;
+}
+
+
+int lcd_brightness(int arg)
+{
+       arg &= SHANNON_UCB_GPIO_BRIGHT_MASK;
+    arg = SHANNON_UCB_GPIO_BRIGHT_MASK - arg;
+    ucb1x00_enable();
+    ucb1x00_io_write(arg << SHANNON_UCB_GPIO_BRIGHT,
+        (~arg & SHANNON_UCB_GPIO_BRIGHT_MASK) << SHANNON_UCB_GPIO_BRIGHT);
+    ucb1x00_disable();
+    return 0;
+}
+
+#if defined(CONFIG_INIT_CRITICAL) && (defined(CONFIG_CFB_CONSOLE) || defined(CONFIG_FRAMEBUFFER))
+
+static int lcd_power(int arg)
+{
+       arg = !!arg;
+    arg = 1 - arg;
+    ucb1x00_enable();
+    ucb1x00_io_write(arg << SHANNON_UCB_GPIO_BACKLIGHT,
+        (~arg & 1) << SHANNON_UCB_GPIO_BACKLIGHT);
+    ucb1x00_disable();
+    return 0;
+}
+
+static void lcd_backlight_init(void)
+{
+    unsigned long mask;
+    int retval = 0;
+
+    /*
+     * Setup the PPC unit correctly.
+     */
+    PPDR &= ~PPC_RXD4;
+    PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+    PSDR |= PPC_RXD4;
+    PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+    PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+    Ser4MCSR = -1;
+    Ser4MCCR1 = 0;
+    Ser4MCCR0 = 0x00047f7f;
+
+    ucb1x00_enable();
+    mask = (SHANNON_UCB_GPIO_CONTRAST_MASK << SHANNON_UCB_GPIO_CONTRAST) |
+           (SHANNON_UCB_GPIO_BRIGHT_MASK << SHANNON_UCB_GPIO_BRIGHT) |
+           (1 << SHANNON_UCB_GPIO_BACKLIGHT);
+    ucb1x00_io_set_dir(0, mask);
+    ucb1x00_disable();
+}
+#endif
+
+#endif
+
+/*
+************************************************************
+** Initialize video hardware
+************************************************************
+*/
+
+/*
+** This is only used if we run stand-alone (i.e. #ifdef CONFIG_INIT_CRITICAL).
+** Otherwise we rely on the Inferno firmware having done this already.
+*/
+
+#if defined(CONFIG_INIT_CRITICAL) && (defined(CONFIG_CFB_CONSOLE) || defined(CONFIG_FRAMEBUFFER))
+static void video_init_crit(void)
+{
+       /* lookup table to tell pixel clock setting from CPU clock */
+       static int pixclk[0x20] = 
+       {
+               5,      /* 59 MHz */
+               7,      /* 73 MHz */
+               7,      /* 88 MHz */
+               8,      /* 103 MHz */
+               9,      /* 118 MHz */
+               10,     /* 132 MHz */
+               11,     /* 147 MHz */
+               13,     /* 162 MHz */
+               14,     /* 176 MHz */
+               15,     /* 191 MHz */
+               16      /* 206 MHz */
+       };
+       int cpuclk;
+
+       /* disable LCD */
+       LCCR0 = 0x0001003c;
+
+       /* assign LCD GPIO pins */
+       GPDR = 0x004403fc;
+       GAFR = 0x000003fc;
+       GPSR = 0x00440000;
+
+       /* set up a mininimal, "inferno-compliant" color palette */
+       ((video_lut_entry*)LCD_LUT_ADDR)[0x00] = 0x1000;
+       ((video_lut_entry*)LCD_LUT_ADDR)[0xc9] = 0x1fff;
+
+       /* read CPU clock, set pixel clock divider accordingly */
+       cpuclk = PPCR & 0x1f;
+       if(cpuclk >= sizeof(pixclk)/sizeof(pixclk[0]))
+               cpuclk = sizeof(pixclk)/sizeof(pixclk[0]) - 1;
+       /* set up other LCD control registers */
+       LCCR3 = pixclk[cpuclk];
+       LCCR2 = 0x010000ef;
+       LCCR1 = 0x01010a70;
+
+       /* set DMA base address registers */
+       LCCR0 = 0x0001003c;
+       DBAR1 = LCD_LUT_ADDR;
+       DBAR2 = LCD_VIDEO_ADDR+LCD_VIDEO_COLS*LCD_VIDEO_ROWS/2;
+       LCCR0 = 0x0001003d;
+
+       lcd_backlight_init();
+       lcd_power(1);
+       lcd_brightness(7);
+       lcd_contrast(0x1f);
+}
+#endif
 
 /*
 ************************************************************
@@ -56,26 +244,20 @@ void video_set_lut(
        g &= COL_MASK;
        b &= COL_MASK;
 
-       /* set the entry, leave for MS bits intact */
+       /* set the entry, leave four MS bits intact */
        entry = (video_lut_entry*)LCD_LUT_ADDR + index;
-       *entry = (*entry & ~RGB_MASK) | (r << R_SHIFT) | (g << G_SHIFT) | (b << B_SHIFT);
+       *entry = (*entry & ~RGB_MASK) |
+ (r << R_SHIFT) | (g << G_SHIFT) | (b << B_SHIFT);
 }
 #endif
 
 
 /*
 ************************************************************
-** Initialize video hardware
+** Framebuffer driver init function
 ************************************************************
 */
 
-/*
-** Actually, we don't initialize hardware here -- We rely on
-** the Inferno firmware having done this already. All we do
-** here is to set the color lookup table such that we get
-** sane colors for black and white, and we clear the screen.
-*/
-
 #ifdef CONFIG_CFB_CONSOLE
 
 /*
@@ -86,6 +268,10 @@ void *video_hw_init(void)
        int   cnt;
        unsigned long *p = (unsigned long*)LCD_VIDEO_ADDR;
 
+#ifdef CONFIG_INIT_CRITICAL
+       video_init_crit();
+#endif
+
        /* set lookup table for black and white */
        video_set_lut(0, 0, 0, 0);
        video_set_lut(1, 0xff, 0xff, 0xff);
@@ -111,6 +297,9 @@ void *video_framebuffer_init(
        unsigned int *fcol,
        unsigned int *bcol)
 {
+#ifdef CONFIG_INIT_CRITICAL
+       video_init_crit();
+#endif
        /*
        ** just deliver the required infomation to the caller
        */