From: robertkaiser Date: Thu, 13 Mar 2003 18:14:28 +0000 (+0000) Subject: Changes for Shannon (aka Tuxscreen) to run stand-alone X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=9a6b629681c7b45b28901b908ac9a54725b27b06;p=users%2Frw%2Farmboot.git Changes for Shannon (aka Tuxscreen) to run stand-alone --- diff --git a/board/shannon/README.Install b/board/shannon/README.Install index 18a594d..1c5d16c 100644 --- a/board/shannon/README.Install +++ b/board/shannon/README.Install @@ -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. diff --git a/board/shannon/memsetup.S b/board/shannon/memsetup.S index 2f7ab9b..bf08580 100644 --- a/board/shannon/memsetup.S +++ b/board/shannon/memsetup.S @@ -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 */ diff --git a/board/shannon/video.c b/board/shannon/video.c index cf4adc5..a96e6a4 100644 --- a/board/shannon/video.c +++ b/board/shannon/video.c @@ -28,6 +28,194 @@ #include "config.h" #include +#include +#include + +#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 */