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
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.
#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 */
#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
/*
************************************************************
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
/*
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);
unsigned int *fcol,
unsigned int *bcol)
{
+#ifdef CONFIG_INIT_CRITICAL
+ video_init_crit();
+#endif
/*
** just deliver the required infomation to the caller
*/