diff options
43 files changed, 4166 insertions, 510 deletions
@@ -2354,6 +2354,46 @@ format!) to the "bootm" command: bash# +More About U-Boot Image Types: +------------------------------ + +U-Boot supports the following image types: + + "Standalone Programs" are directly runnable in the environment + provided by U-Boot; it is expected that (if they behave + well) you can continue to work in U-Boot after return from + the Standalone Program. + "OS Kernel Images" are usually images of some Embedded OS which + will take over control completely. Usually these programs + will install their own set of exception handlers, device + drivers, set up the MMU, etc. - this means, that you cannot + expect to re-enter U-Boot except by resetting the CPU. + "RAMDisk Images" are more or less just data blocks, and their + parameters (address, size) are passed to an OS kernel that is + being started. + "Multi-File Images" contain several images, typically an OS + (Linux) kernel image and one or more data images like + RAMDisks. This construct is useful for instance when you want + to boot over the network using BOOTP etc., where the boot + server provides just a single image file, but you want to get + for instance an OS kernel and a RAMDisk image. + + "Multi-File Images" start with a list of image sizes, each + image size (in bytes) specified by an "uint32_t" in network + byte order. This list is terminated by an "(uint32_t)0". + Immediately after the terminating 0 follow the images, one by + one, all aligned on "uint32_t" boundaries (size rounded up to + a multiple of 4 bytes). + + "Firmware Images" are binary images containing firmware (like + U-Boot or FPGA images) which usually will be programmed to + flash memory. + + "Script files" are command sequences that will be executed by + U-Boot's command interpreter; this feature is especially + useful when you configure U-Boot to use a real shell (hush) + as command interpreter. + Standalone HOWTO: ================= diff --git a/board/sc520_cdp/sc520_cdp.c b/board/sc520_cdp/sc520_cdp.c index ba6255f4eb..2809ff72af 100644 --- a/board/sc520_cdp/sc520_cdp.c +++ b/board/sc520_cdp/sc520_cdp.c @@ -31,35 +31,35 @@ static void irq_init(void) { - + /* disable global interrupt mode */ - write_mmcr_byte(SC520_PICICR, 0x40); - + write_mmcr_byte(SC520_PICICR, 0x40); + /* set irq0-7 to edge */ write_mmcr_byte(SC520_MPICMODE, 0x00); - + /* set irq9-12 to level, all the other (8, 13-15) are edge */ write_mmcr_byte(SC520_SL1PICMODE, 0x1e); - + /* set irq16-24 (unused slave pic2) to level */ write_mmcr_byte(SC520_SL2PICMODE, 0xff); - - /* active low polarity on PIC interrupt pins, + + /* active low polarity on PIC interrupt pins, active high polarity on all other irq pins */ write_mmcr_word(SC520_INTPINPOL, 0); /* set irq number mapping */ - write_mmcr_byte(SC520_GPTMR0MAP,0); /* disable GP timer 0 INT */ + write_mmcr_byte(SC520_GPTMR0MAP,0); /* disable GP timer 0 INT */ write_mmcr_byte(SC520_GPTMR1MAP,0); /* disable GP timer 1 INT */ write_mmcr_byte(SC520_GPTMR2MAP,0); /* disable GP timer 2 INT */ - write_mmcr_byte(SC520_PIT0MAP,0x1); /* Set PIT timer 0 INT to IRQ0 */ + write_mmcr_byte(SC520_PIT0MAP,0x1); /* Set PIT timer 0 INT to IRQ0 */ write_mmcr_byte(SC520_PIT1MAP,0); /* diable PIT timer 1 INT */ write_mmcr_byte(SC520_PIT2MAP,0); /* diable PIT timer 2 INT */ write_mmcr_byte(SC520_PCIINTAMAP,0x4); /* Set PCI INT A to IRQ9 */ write_mmcr_byte(SC520_PCIINTBMAP,0x5); /* Set PCI INT B to IRQ10 */ write_mmcr_byte(SC520_PCIINTCMAP,0x6); /* Set PCI INT C to IRQ11 */ write_mmcr_byte(SC520_PCIINTDMAP,0x7); /* Set PCI INT D to IRQ12 */ - write_mmcr_byte(SC520_DMABCINTMAP,0); /* disable DMA INT */ + write_mmcr_byte(SC520_DMABCINTMAP,0); /* disable DMA INT */ write_mmcr_byte(SC520_SSIMAP,0); /* disable Synchronius serial INT */ write_mmcr_byte(SC520_WDTMAP,0); /* disable Watchdor INT */ write_mmcr_byte(SC520_RTCMAP,0x3); /* Set RTC int to 8 */ @@ -69,28 +69,28 @@ static void irq_init(void) write_mmcr_byte(SC520_GP0IMAP,6); /* Set GPIRQ0 (ISA IRQ2) to IRQ9 */ write_mmcr_byte(SC520_GP1IMAP,2); /* Set GPIRQ1 (SIO IRQ1) to IRQ1 */ write_mmcr_byte(SC520_GP2IMAP,7); /* Set GPIRQ2 (ISA IRQ12) to IRQ12 */ - + if (CFG_USE_SIO_UART) { write_mmcr_byte(SC520_UART1MAP,0); /* disable internal UART1 INT */ write_mmcr_byte(SC520_UART2MAP,0); /* disable internal UART2 INT */ - write_mmcr_byte(SC520_GP3IMAP,11); /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */ + write_mmcr_byte(SC520_GP3IMAP,11); /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */ write_mmcr_byte(SC520_GP4IMAP,12); /* Set GPIRQ4 (ISA IRQ4) to IRQ4 */ } else { write_mmcr_byte(SC520_UART1MAP,12); /* Set internal UART2 INT to IRQ4 */ write_mmcr_byte(SC520_UART2MAP,11); /* Set internal UART2 INT to IRQ3 */ - write_mmcr_byte(SC520_GP3IMAP,0); /* disable GPIRQ3 (ISA IRQ3) */ + write_mmcr_byte(SC520_GP3IMAP,0); /* disable GPIRQ3 (ISA IRQ3) */ write_mmcr_byte(SC520_GP4IMAP,0); /* disable GPIRQ4 (ISA IRQ4) */ } - + write_mmcr_byte(SC520_GP5IMAP,13); /* Set GPIRQ5 (ISA IRQ5) to IRQ5 */ write_mmcr_byte(SC520_GP6IMAP,21); /* Set GPIRQ6 (ISA IRQ6) to IRQ6 */ write_mmcr_byte(SC520_GP7IMAP,22); /* Set GPIRQ7 (ISA IRQ7) to IRQ7 */ write_mmcr_byte(SC520_GP8IMAP,3); /* Set GPIRQ8 (SIO IRQ8) to IRQ8 */ write_mmcr_byte(SC520_GP9IMAP,4); /* Set GPIRQ9 (ISA IRQ9) to IRQ9 */ - write_mmcr_byte(SC520_GP10IMAP,9); /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */ + write_mmcr_byte(SC520_GP10IMAP,9); /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */ write_mmcr_word(SC520_PCIHOSTMAP,0x11f); /* Map PCI hostbridge INT to NMI */ write_mmcr_word(SC520_ECCMAP,0x100); /* Map SDRAM ECC failure INT to NMI */ - + } /* PCI stuff */ @@ -98,11 +98,11 @@ static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev) { char pin; int irq; - - + + pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin); irq = pin-1; - + switch (PCI_DEV(dev)) { case 20: break; @@ -115,20 +115,20 @@ static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev) case 17: irq+=3; break; - default: + default: return; } - + irq&=3; /* wrap around */ irq+=9; /* lowest IRQ is 9 */ - + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, irq); -#if 0 - printf("fixup_irq: device %d pin %c irq %d\n", +#if 0 + printf("fixup_irq: device %d pin %c irq %d\n", PCI_DEV(dev), 'A' + pin -1, irq); #endif } - + static struct pci_controller sc520_cdp_hose = { fixup_irq: pci_sc520_cdp_fixup_irq, }; @@ -147,7 +147,7 @@ static void silence_uart(int port) void setup_ali_sio(int uart_primary) { ali512x_init(); - + ali512x_set_fdc(ALI_ENABLED, 0x3f2, 6, 0); ali512x_set_pp(ALI_ENABLED, 0x278, 7, 3); ali512x_set_uart(ALI_ENABLED, ALI_UART1, uart_primary?0x3f8:0x3e8, 4); @@ -155,21 +155,21 @@ void setup_ali_sio(int uart_primary) ali512x_set_rtc(ALI_DISABLED, 0, 0); ali512x_set_kbc(ALI_ENABLED, 1, 12); ali512x_set_cio(ALI_ENABLED); - + /* IrDa pins */ ali512x_cio_function(12, 1, 0, 0); ali512x_cio_function(13, 1, 0, 0); - + /* SSI chip select pins */ ali512x_cio_function(14, 0, 0, 0); /* SSI_CS */ - ali512x_cio_function(15, 0, 0, 0); /* SSI_MV */ + ali512x_cio_function(15, 0, 0, 0); /* SSI_MV */ ali512x_cio_function(16, 0, 1, 0); /* SSI_SPI# (inverted) */ /* Board REV pins */ ali512x_cio_function(20, 0, 0, 1); ali512x_cio_function(21, 0, 0, 1); ali512x_cio_function(22, 0, 0, 1); - ali512x_cio_function(23, 0, 0, 1); + ali512x_cio_function(23, 0, 0, 1); } @@ -178,13 +178,13 @@ static void bus_init(void) { /* set up the GP IO pins */ - write_mmcr_word(SC520_PIOPFS31_16, 0xf7ff); /* set the GPIO pin function 31-16 reg */ + write_mmcr_word(SC520_PIOPFS31_16, 0xf7ff); /* set the GPIO pin function 31-16 reg */ write_mmcr_word(SC520_PIOPFS15_0, 0xffff); /* set the GPIO pin function 15-0 reg */ - write_mmcr_byte(SC520_CSPFS, 0xf8); /* set the CS pin function reg */ + write_mmcr_byte(SC520_CSPFS, 0xf8); /* set the CS pin function reg */ write_mmcr_byte(SC520_CLKSEL, 0x70); - - write_mmcr_byte(SC520_GPCSRT, 1); /* set the GP CS offset */ + + write_mmcr_byte(SC520_GPCSRT, 1); /* set the GP CS offset */ write_mmcr_byte(SC520_GPCSPW, 3); /* set the GP CS pulse width */ write_mmcr_byte(SC520_GPCSOFF, 1); /* set the GP CS offset */ write_mmcr_byte(SC520_GPRDW, 3); /* set the RD pulse width */ @@ -192,40 +192,40 @@ static void bus_init(void) write_mmcr_byte(SC520_GPWRW, 3); /* set the GP WR pulse width */ write_mmcr_byte(SC520_GPWROFF, 1); /* set the GP WR offset */ - write_mmcr_word(SC520_BOOTCSCTL, 0x1823); /* set up timing of BOOTCS */ + write_mmcr_word(SC520_BOOTCSCTL, 0x1823); /* set up timing of BOOTCS */ write_mmcr_word(SC520_ROMCS1CTL, 0x1823); /* set up timing of ROMCS1 */ - write_mmcr_word(SC520_ROMCS2CTL, 0x1823); /* set up timing of ROMCS2 */ - + write_mmcr_word(SC520_ROMCS2CTL, 0x1823); /* set up timing of ROMCS2 */ + /* adjust the memory map: * by default the first 256MB (0x00000000 - 0x0fffffff) is mapped to SDRAM * and 256MB to 1G-128k (0x1000000 - 0x37ffffff) is mapped to PCI mmio - * we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */ - - + * we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */ + + /* SRAM = GPCS3 128k @ d0000-effff*/ - write_mmcr_long(SC520_PAR2, 0x4e00400d); - + write_mmcr_long(SC520_PAR2, 0x4e00400d); + /* IDE0 = GPCS6 1f0-1f7 */ - write_mmcr_long(SC520_PAR3, 0x380801f0); + write_mmcr_long(SC520_PAR3, 0x380801f0); /* IDE1 = GPCS7 3f6 */ - write_mmcr_long(SC520_PAR4, 0x3c0003f6); + write_mmcr_long(SC520_PAR4, 0x3c0003f6); /* bootcs */ - write_mmcr_long(SC520_PAR12, 0x8bffe800); + write_mmcr_long(SC520_PAR12, 0x8bffe800); /* romcs2 */ - write_mmcr_long(SC520_PAR13, 0xcbfff000); + write_mmcr_long(SC520_PAR13, 0xcbfff000); /* romcs1 */ - write_mmcr_long(SC520_PAR14, 0xabfff800); + write_mmcr_long(SC520_PAR14, 0xabfff800); /* 680 LEDS */ - write_mmcr_long(SC520_PAR15, 0x30000640); - - asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */ + write_mmcr_long(SC520_PAR15, 0x30000640); + + asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */ if (CFG_USE_SIO_UART) { - write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS); + write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS); setup_ali_sio(1); } else { - write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS)); + write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS)); setup_ali_sio(0); silence_uart(0x3e8); silence_uart(0x2e8); @@ -242,21 +242,21 @@ static void bus_init(void) int board_init(void) { DECLARE_GLOBAL_DATA_PTR; - - init_sc520(); + + init_sc520(); bus_init(); irq_init(); - + /* max drive current on SDRAM */ write_mmcr_word(SC520_DSCTL, 0x0100); - + /* enter debug mode after next reset (only if jumper is also set) */ write_mmcr_byte(SC520_RESCFG, 0x08); - + /* configure the software timer to 33.333MHz */ write_mmcr_byte(SC520_SWTMRCFG, 0); gd->bus_clk = 33333000; - + return 0; } @@ -277,14 +277,14 @@ int last_stage_init(void) { int minor; int major; - + major = minor = 0; major |= ali512x_cio_in(23)?2:0; major |= ali512x_cio_in(22)?1:0; minor |= ali512x_cio_in(21)?2:0; minor |= ali512x_cio_in(20)?1:0; - + printf("AMD SC520 CDP revision %d.%d\n", major, minor); - + return 0; } diff --git a/board/smdk2400/flash.c b/board/smdk2400/flash.c index c4d6bae8f2..6882b88451 100644 --- a/board/smdk2400/flash.c +++ b/board/smdk2400/flash.c @@ -76,7 +76,7 @@ ulong flash_init (void) flash_info[i].sector_count = CFG_MAX_FLASH_SECT; memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); if (i == 0) - flashbase = PHYS_FLASH_1; + flashbase = CFG_FLASH_BASE; else panic ("configured too many flash banks!\n"); for (j = 0; j < flash_info[i].sector_count; j++) { diff --git a/board/trab/flash.c b/board/trab/flash.c index 2443777ae1..a4f164b469 100644 --- a/board/trab/flash.c +++ b/board/trab/flash.c @@ -26,12 +26,7 @@ #include <common.h> #include <environment.h> -ulong myflush (void); - - -#define FLASH_BANK_SIZE 0x800000 /* 8 MB */ -/* this varies depending on the sector */ -#define MAIN_SECT_SIZE 0x20000 /* 2 x 64 kB */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; @@ -43,6 +38,7 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; #define CMD_ERASE_CONFIRM 0x00300030 #define CMD_PROGRAM 0x00A000A0 #define CMD_UNLOCK_BYPASS 0x00200020 +#define CMD_READ_MANF_ID 0x00900090 #define MEM_FLASH_ADDR1 (*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2))) #define MEM_FLASH_ADDR2 (*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2))) @@ -64,27 +60,38 @@ ulong flash_init (void) int i, j; ulong size = 0; - for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { ulong flashbase = 0; + flash_info_t *info = &flash_info[i]; + + /* Init: no FLASHes known */ + info->flash_id = FLASH_UNKNOWN; + + size += flash_get_size (CFG_FLASH_BASE, info); - flash_info[i].flash_id = - (AMD_MANUFACT & FLASH_VENDMASK) | - (AMD_ID_LV320B & FLASH_TYPEMASK); - flash_info[i].size = FLASH_BANK_SIZE; - flash_info[i].sector_count = CFG_MAX_FLASH_SECT; - memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); if (i == 0) - flashbase = PHYS_FLASH_1; + flashbase = CFG_FLASH_BASE; else panic ("configured too many flash banks!\n"); - for (j = 0; j < flash_info[i].sector_count; j++) { - - flash_info[i].start[j] = flashbase; - - /* the first 8 sectors are 8 kB */ - flashbase += (j < 8) ? 0x4000 : MAIN_SECT_SIZE; + for (j = 0; j < info->sector_count; j++) { + + info->protect[j] = 0; + info->start[j] = flashbase; + + switch (info->flash_id & FLASH_TYPEMASK) { + case (FLASH_AM320B & FLASH_TYPEMASK): + /* Boot sector type: 8 x 8 + N x 128 kB */ + flashbase += (j < 8) ? 0x4000 : 0x20000; + break; + case (FLASH_AM640U & FLASH_TYPEMASK): + /* Uniform sector type: 128 kB */ + flashbase += 0x20000; + break; + default: + printf ("## Bad flash chip type 0x%04lX\n", + info->flash_id & FLASH_TYPEMASK); + } } - size += flash_info[i].size; } /* @@ -116,7 +123,7 @@ void flash_print_info (flash_info_t * info) int i; switch (info->flash_id & FLASH_VENDMASK) { - case (AMD_MANUFACT & FLASH_VENDMASK): + case (FLASH_MAN_AMD & FLASH_VENDMASK): printf ("AMD: "); break; default: @@ -125,9 +132,12 @@ void flash_print_info (flash_info_t * info) } switch (info->flash_id & FLASH_TYPEMASK) { - case (AMD_ID_LV320B & FLASH_TYPEMASK): + case (FLASH_AM320B & FLASH_TYPEMASK): printf ("2x Am29LV320DB (32Mbit)\n"); break; + case (FLASH_AM640U & FLASH_TYPEMASK): + printf ("2x Am29LV640D (64Mbit)\n"); + break; default: printf ("Unknown Chip Type\n"); goto Done; @@ -177,7 +187,7 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) } if ((info->flash_id & FLASH_VENDMASK) != - (AMD_MANUFACT & FLASH_VENDMASK)) { + (FLASH_MAN_AMD & FLASH_VENDMASK)) { return ERR_UNKNOWN_FLASH_VENDOR; } @@ -265,13 +275,6 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) rc = ERR_TIMOUT; goto outahere; } - -#if 0 - printf ("ok.\n"); - } else { /* it was protected */ - - printf ("protected!\n"); -#endif } } @@ -453,3 +456,71 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) return write_word (info, wp, data); } + +/*----------------------------------------------------------------------- + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + ulong value; + + /* Write auto select command sequence and read Manufacturer ID */ + addr[0x0555] = CMD_UNLOCK1; + addr[0x02AA] = CMD_UNLOCK2; + addr[0x0555] = CMD_READ_MANF_ID; + + value = addr[0]; + + debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value); + + switch (value) { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + addr[0] = 0x00FF00FF; /* restore read mode */ + debug ("## flash_init: unknown manufacturer\n"); + return (0); /* no or unknown flash */ + } + + value = addr[1]; /* device ID */ + + debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value); + + switch (value) { + case AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 71; + info->size = 0x00800000; + + addr[0] = 0x00FF00FF; /* restore read mode */ + break; /* => 8 MB */ + + case AMD_ID_LV640U: + info->flash_id += FLASH_AM640U; + info->sector_count = 128; + info->size = 0x01000000; + + addr[0] = 0x00F000F0; /* restore read mode */ + break; /* => 16 MB */ + + default: + debug ("## flash_init: unknown flash chip\n"); + info->flash_id = FLASH_UNKNOWN; + addr[0] = 0x00FF00FF; /* restore read mode */ + return (0); /* => no or unknown flash */ + + } + + if (info->sector_count > CFG_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CFG_MAX_FLASH_SECT); + info->sector_count = CFG_MAX_FLASH_SECT; + } + + return (info->size); +} diff --git a/board/trab/trab.c b/board/trab/trab.c index 32f27efaeb..111c861410 100644 --- a/board/trab/trab.c +++ b/board/trab/trab.c @@ -60,11 +60,8 @@ static void udelay_no_timer (int usec) int board_init () { -#if defined(CONFIG_MODEM_SUPPORT) && defined(CONFIG_VFD) - ulong size; - unsigned long addr; - extern void mem_malloc_init (ulong); - extern int drv_vfd_init(void); +#if defined(CONFIG_VFD) + extern int vfd_init_clocks(void); #endif DECLARE_GLOBAL_DATA_PTR; @@ -107,26 +104,11 @@ int board_init () /* adress of boot parameters */ gd->bd->bi_boot_params = 0x0c000100; -#ifdef CONFIG_MODEM_SUPPORT #ifdef CONFIG_VFD -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - /* - * reserve memory for VFD display (always full pages) - */ - /* armboot_real_end is defined in the board-specific linker script */ - addr = (_armboot_real_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); - size = vfd_setmem (addr); - gd->fb_base = addr; - /* round to the next page boundary */ - addr += size; - addr = (addr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); - mem_malloc_init (addr); - /* must do this after the framebuffer is allocated */ - drv_vfd_init(); + vfd_init_clocks(); #endif /* CONFIG_VFD */ +#ifdef CONFIG_MODEM_SUPPORT udelay_no_timer (KBD_MDELAY); if (key_pressed()) { diff --git a/board/trab/vfd.c b/board/trab/vfd.c index 234a9d4c02..fa1194ca7f 100644 --- a/board/trab/vfd.c +++ b/board/trab/vfd.c @@ -55,12 +55,16 @@ #define BLAU 0x0C #define VIOLETT 0X0D -ulong vfdbase; -ulong frame_buf_size; +ulong vfdbase; +ulong frame_buf_size; #define frame_buf_offs 4 +/* Supported VFD Types */ +#define VFD_TYPE_T119C 1 /* Noritake T119C VFD */ +#define VFD_TYPE_MN11236 2 + /* taken from armboot/common/vfd.c */ -ulong adr_vfd_table[112][18][2][4][2]; +unsigned long adr_vfd_table[112][18][2][4][2]; unsigned char bit_vfd_table[112][18][2][4][2]; /* @@ -68,26 +72,42 @@ unsigned char bit_vfd_table[112][18][2][4][2]; */ void init_grid_ctrl(void) { + DECLARE_GLOBAL_DATA_PTR; ulong adr, grid_cycle; unsigned int bit, display; unsigned char temp, bit_nr; + ulong val; - for (adr=vfdbase; adr<=(vfdbase+7168); adr+=4) /*clear frame buffer */ - (*(volatile ulong*)(adr))=0; + /* + * clear frame buffer (logical clear => set to "black") + */ + if (gd->vfd_inv_data == 0) + val = 0; + else + val = ~0; - for(display=0;display<=3;display++) - { - for(grid_cycle=0;grid_cycle<=55;grid_cycle++) - { - bit = grid_cycle*256*4+(grid_cycle+200)*4+frame_buf_offs+display; + for (adr = vfdbase; adr <= (vfdbase+7168); adr += 4) { + (*(volatile ulong*)(adr)) = val; + } + + switch (gd->vfd_type) { + case VFD_TYPE_T119C: + for (display=0; display<4; display++) { + for(grid_cycle=0; grid_cycle<56; grid_cycle++) { + bit = grid_cycle * 256 * 4 + + (grid_cycle + 200) * 4 + + frame_buf_offs + display; /* wrap arround if offset (see manual S3C2400) */ if (bit>=frame_buf_size*8) - bit = bit-(frame_buf_size*8); - adr = vfdbase+(bit/32)*4+(3-(bit%32)/8); - bit_nr = bit%8; - bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + bit = bit - (frame_buf_size * 8); + adr = vfdbase + (bit/32) * 4 + (3 - (bit%32) / 8); + bit_nr = bit % 8; + bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4; temp=(*(volatile unsigned char*)(adr)); - temp|=(1<<bit_nr); + if (gd->vfd_inv_data) + temp &= ~(1<<bit_nr); + else + temp |= (1<<bit_nr); (*(volatile unsigned char*)(adr))=temp; if(grid_cycle<55) @@ -101,9 +121,54 @@ void init_grid_ctrl(void) bit_nr = bit%8; bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; temp=(*(volatile unsigned char*)(adr)); - temp|=(1<<bit_nr); + if (gd->vfd_inv_data) + temp &= ~(1<<bit_nr); + else + temp |= (1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + } + } + break; + case VFD_TYPE_MN11236: + for (display=0; display<4; display++) { + for (grid_cycle=0; grid_cycle<38; grid_cycle++) { + bit = grid_cycle * 256 * 4 + + (253 - grid_cycle) * 4 + + frame_buf_offs + display; + /* wrap arround if offset (see manual S3C2400) */ + if (bit>=frame_buf_size*8) + bit = bit - (frame_buf_size * 8); + adr = vfdbase + (bit/32) * 4 + (3 - (bit%32) / 8); + bit_nr = bit % 8; + bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4; + temp=(*(volatile unsigned char*)(adr)); + if (gd->vfd_inv_data) + temp &= ~(1<<bit_nr); + else + temp |= (1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + + if(grid_cycle<37) + bit = grid_cycle*256*4+(252-grid_cycle)*4+frame_buf_offs+display; + + /* wrap arround if offset (see manual S3C2400) */ + if (bit>=frame_buf_size*8) + bit = bit-(frame_buf_size*8); + adr = vfdbase+(bit/32)*4+(3-(bit%32)/8); + bit_nr = bit%8; + bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + temp=(*(volatile unsigned char*)(adr)); + if (gd->vfd_inv_data) + temp &= ~(1<<bit_nr); + else + temp |= (1<<bit_nr); (*(volatile unsigned char*)(adr))=temp; } + } + break; + default: + printf ("Warning: unknown display type\n"); + break; } } @@ -113,175 +178,142 @@ void init_grid_ctrl(void) */ void create_vfd_table(void) { - unsigned int vfd_table[112][18][2][4][2]; - ulong adr; - unsigned int x, y, color, display, entry, pixel, bit_nr; - - /* - * Create translation table for Noritake-T119C-VFD-specific - * organized frame-buffer. - * Created is the number of the bit in the framebuffer (the - * first transferred pixel of each frame is bit 0). - */ - for(y=0;y<=17;y++) /* Zeile */ - { - for(x=0;x<=111;x++) /* Spalten */ - { - /*Display 0 blaue Pixel Eintrag 1 */ - vfd_table[x][y][0][0][0]=((x%4)*4+y*16+(x/4)*2048); - /*Display 0 rote Pixel Eintrag 1 */ - vfd_table[x][y][1][0][0]=((x%4)*4+y*16+(x/4)*2048+512); - if(x<=1) - { - /*Display 0 blaue Pixel Eintrag 2 */ - vfd_table[x][y][0][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1024); - /*Display 0 rote Pixel Eintrag 2 */ - vfd_table[x][y][1][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1024); - } - else - { - /*Display 0 blaue Pixel Eintrag 2 */ - vfd_table[x][y][0][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+1024); - /*Display 0 rote Pixel Eintrag 2 */ - vfd_table[x][y][1][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1024); - } - /*Display 1 blaue Pixel Eintrag 1 */ - vfd_table[x][y][0][1][0]=((x%4)*4+y*16+(x/4)*2048+1); - /*Display 1 rote Pixel Eintrag 1 */ - vfd_table[x][y][1][1][0]=((x%4)*4+y*16+(x/4)*2048+512+1); - if(x<=1) - { - /*Display 1 blaue Pixel Eintrag 2 */ - vfd_table[x][y][0][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1+1024); - /*Display 1 rote Pixel Eintrag 2 */ - vfd_table[x][y][1][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1+1024); - } - else - { - /*Display 1 blaue Pixel Eintrag 2 */ - vfd_table[x][y][0][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+1+1024); - /*Display 1 rote Pixel Eintrag 2 */ - vfd_table[x][y][1][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1+1024); - } - /*Display 2 blaue Pixel Eintrag 1 */ - vfd_table[x][y][0][2][0]=((x%4)*4+y*16+(x/4)*2048+2); - /*Display 2 rote Pixel Eintrag 1 */ - vfd_table[x][y][1][2][0]=((x%4)*4+y*16+(x/4)*2048+512+2); - if(x<=1) - { - /*Display 2 blaue Pixel Eintrag 2 */ - vfd_table[x][y][0][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+2+1024); - /*Display 2 rote Pixel Eintrag 2 */ - vfd_table[x][y][1][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+2+1024); - } - else - { - /*Display 2 blaue Pixel Eintrag 2 */ - vfd_table[x][y][0][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+2+1024); - /*Display 2 rote Pixel Eintrag 2 */ - vfd_table[x][y][1][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+2+1024); - } - /*Display 3 blaue Pixel Eintrag 1 */ - vfd_table[x][y][0][3][0]=((x%4)*4+y*16+(x/4)*2048+3); - /*Display 3 rote Pixel Eintrag 1 */ - vfd_table[x][y][1][3][0]=((x%4)*4+y*16+(x/4)*2048+512+3); - if(x<=1) - { - /*Display 3 blaue Pixel Eintrag 2 */ - vfd_table[x][y][0][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+3+1024); - /*Display 3 rote Pixel Eintrag 2 */ - vfd_table[x][y][1][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+3+1024); - } - else - { - /*Display 3 blaue Pixel Eintrag 2 */ - vfd_table[x][y][0][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+3+1024); - /*Display 3 rote Pixel Eintrag 2 */ - vfd_table[x][y][1][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+3+1024); - } + DECLARE_GLOBAL_DATA_PTR; + unsigned long vfd_table[112][18][2][4][2]; + unsigned int x, y, color, display, entry, pixel; + unsigned int x_abcdef = 0; + + switch (gd->vfd_type) { + case VFD_TYPE_T119C: + for(y=0; y<=17; y++) { /* Line */ + for(x=0; x<=111; x++) { /* Column */ + for(display=0; display <=3; display++) { + + /* Display 0 blue pixels */ + vfd_table[x][y][0][display][0] = + (x==0) ? y*16+display + : (x%4)*4+y*16+((x-1)/2)*1024+display; + /* Display 0 red pixels */ + vfd_table[x][y][1][display][0] = + (x==0) ? y*16+512+display + : (x%4)*4+y*16+((x-1)/2)*1024+512+display; + } + } + } + break; + case VFD_TYPE_MN11236: + for(y=0; y<=17; y++) { /* Line */ + for(x=0; x<=111; x++) { /* Column */ + for(display=0; display <=3; display++) { + + vfd_table[x][y][0][display][0]=0; + vfd_table[x][y][0][display][1]=0; + vfd_table[x][y][1][display][0]=0; + vfd_table[x][y][1][display][1]=0; + + switch (x%6) { + case 0: x_abcdef=0; break; /* a -> a */ + case 1: x_abcdef=2; break; /* b -> c */ + case 2: x_abcdef=4; break; /* c -> e */ + case 3: x_abcdef=5; break; /* d -> f */ + case 4: x_abcdef=3; break; /* e -> d */ + case 5: x_abcdef=1; break; /* f -> b */ + } + + /* blue pixels */ + vfd_table[x][y][0][display][0] = + (x>1) ? x_abcdef*4+((x-1)/3)*1024+y*48+display + : x_abcdef*4+ 0+y*48+display; + /* blue pixels */ + if (x>1 && (x-1)%3) + vfd_table[x][y][0][display][1] = x_abcdef*4+((x-1)/3+1)*1024+y*48+display; + + /* red pixels */ + vfd_table[x][y][1][display][0] = + (x>1) ? x_abcdef*4+24+((x-1)/3)*1024+y*48+display + : x_abcdef*4+24+ 0+y*48+display; + /* red pixels */ + if (x>1 && (x-1)%3) + vfd_table[x][y][1][display][1] = x_abcdef*4+24+((x-1)/3+1)*1024+y*48+display; + } } + } + break; + default: + /* do nothing */ + return; } /* - * Create translation table for Noritake-T119C-VFD-specific - * organized frame-buffer * Create table with entries for physical byte adresses and * bit-number within the byte * from table with bit-numbers within the total framebuffer */ - for(y=0;y<=17;y++) - { - for(x=0;x<=111;x++) - { - for(color=0;color<=1;color++) - { - for(display=0;display<=3;display++) - { - for(entry=0;entry<=1;entry++) - { - pixel = vfd_table[x][y][color][display][entry] + frame_buf_offs; - /* - * wrap arround if offset - * (see manual S3C2400) - */ - if (pixel>=frame_buf_size*8) - pixel = pixel-(frame_buf_size*8); - adr = vfdbase+(pixel/32)*4+(3-(pixel%32)/8); - bit_nr = pixel%8; - bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; - adr_vfd_table[x][y][color][display][entry] = adr; - bit_vfd_table[x][y][color][display][entry] = bit_nr; - } - } + for(y=0;y<18;y++) { + for(x=0;x<112;x++) { + for(color=0;color<2;color++) { + for(display=0;display<4;display++) { + for(entry=0;entry<2;entry++) { + unsigned long adr = vfdbase; + unsigned int bit_nr = 0; + + if (vfd_table[x][y][color][display][entry]) { + + pixel = vfd_table[x][y][color][display][entry] + frame_buf_offs; + /* + * wrap arround if offset + * (see manual S3C2400) + */ + if (pixel>=frame_buf_size*8) + pixel = pixel-(frame_buf_size*8); + adr = vfdbase+(pixel/32)*4+(3-(pixel%32)/8); + bit_nr = pixel%8; + bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + } + adr_vfd_table[x][y][color][display][entry] = adr; + bit_vfd_table[x][y][color][display][entry] = bit_nr; } + } } + } } } /* * Set/clear pixel of the VFDs */ -void set_vfd_pixel(unsigned char x, unsigned char y, unsigned char color, unsigned char display, unsigned char value) +void set_vfd_pixel(unsigned char x, unsigned char y, + unsigned char color, unsigned char display, + unsigned char value) { + DECLARE_GLOBAL_DATA_PTR; ulong adr; unsigned char bit_nr, temp; - if (value!=0) - { - /* Pixel-Eintrag Nr. 1 */ - adr = adr_vfd_table[x][y][color][display][0]; - /* Pixel-Eintrag Nr. 1 */ - bit_nr = bit_vfd_table[x][y][color][display][0]; - temp=(*(volatile unsigned char*)(adr)); - temp|=1<<bit_nr; - (*(volatile unsigned char*)(adr))=temp; - - /* Pixel-Eintrag Nr. 2 */ - adr = adr_vfd_table[x][y][color][display][1]; - /* Pixel-Eintrag Nr. 2 */ - bit_nr = bit_vfd_table[x][y][color][display][1]; - temp=(*(volatile unsigned char*)(adr)); - temp|=1<<bit_nr; - (*(volatile unsigned char*)(adr))=temp; + if (! gd->vfd_type) { + /* Unknown type. */ + return; } - else - { - /* Pixel-Eintrag Nr. 1 */ - adr = adr_vfd_table[x][y][color][display][0]; - /* Pixel-Eintrag Nr. 1 */ - bit_nr = bit_vfd_table[x][y][color][display][0]; - temp=(*(volatile unsigned char*)(adr)); - temp&=~(1<<bit_nr); - (*(volatile unsigned char*)(adr))=temp; - - /* Pixel-Eintrag Nr. 2 */ - adr = adr_vfd_table[x][y][color][display][1]; - /* Pixel-Eintrag Nr. 2 */ - bit_nr = bit_vfd_table[x][y][color][display][1]; - temp=(*(volatile unsigned char*)(adr)); - temp&=~(1<<bit_nr); - (*(volatile unsigned char*)(adr))=temp; + + /* Pixel-Eintrag Nr. 1 */ + adr = adr_vfd_table[x][y][color][display][0]; + /* Pixel-Eintrag Nr. 1 */ + bit_nr = bit_vfd_table[x][y][color][display][0]; + temp=(*(volatile unsigned char*)(adr)); + + if (gd->vfd_inv_data) { + if (value) + temp &= ~(1<<bit_nr); + else + temp |= (1<<bit_nr); + } else { + if (value) + temp |= (1<<bit_nr); + else + temp &= ~(1<<bit_nr); } + + (*(volatile unsigned char*)(adr))=temp; } /* @@ -334,12 +366,36 @@ void transfer_pic(int display, unsigned char *adr, int height, int width) } /* + * This function initializes VFD clock that is needed for the CPLD that + * manages the keyboard. + */ +int vfd_init_clocks(void) +{ + /* Port-Pins als LCD-Ausgang */ + rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA; + /* Port-Pins als LCD-Ausgang */ + rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8; +#ifdef WITH_VFRAME + /* mit VFRAME zum Messen */ + rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA; +#endif + + rLCDCON2 = 0x000DC000; + rLCDCON3 = 0x0051000A; + rLCDCON4 = 0x00000001; + rLCDCON5 = 0x00000440; + rLCDCON1 = 0x00000B75; +} + +/* * initialize LCD-Controller of the S3C2400 for using VFDs */ int drv_vfd_init(void) { + char *tmp; ulong palette; static int vfd_init_done = 0; + int vfd_id; DECLARE_GLOBAL_DATA_PTR; @@ -347,10 +403,58 @@ int drv_vfd_init(void) return (0); vfd_init_done = 1; + /* try to determine display type from the value + * defined by pull-ups + */ + rPCUP = (rPCUP | 0x000F); /* activate GPC0...GPC3 pullups */ + rPCCON = (rPCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as inputs */ + + vfd_id = (~rPCDAT) & 0x000F; /* read GPC0...GPC3 port pins */ + debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_id); + + switch (vfd_id) { + case 0: /* board revision <= Rev.100 */ +/*-----*/ + gd->vfd_inv_data = 0; + if (0) + gd->vfd_type = VFD_TYPE_MN11236; + else + gd->vfd_type = VFD_TYPE_T119C; +/*-----*/ + if ((tmp = getenv ("vfd_type")) == NULL) { + break; + } + if (strcmp(tmp, "T119C") == 0) { + gd->vfd_type = VFD_TYPE_T119C; + } else if (strcmp(tmp, "MN11236") == 0) { + gd->vfd_type = VFD_TYPE_MN11236; + } else { + /* cannot use printf for a warning here */ + gd->vfd_type = 0; /* unknown */ + } + gd->vfd_inv_data = 0; + + break; + default: /* default to MN11236, data inverted */ + gd->vfd_type = VFD_TYPE_MN11236; + gd->vfd_inv_data = 1; + setenv ("vfd_type", "MN11236"); + } + debug ("VFD type: %s%s\n", + (gd->vfd_type == VFD_TYPE_T119C) ? "T119C" : + (gd->vfd_type == VFD_TYPE_MN11236) ? "MN11236" : + "unknown", + gd->vfd_inv_data ? ", inverted data" : ""); + vfdbase = gd->fb_base; create_vfd_table(); init_grid_ctrl(); + for (palette=0; palette < 16; palette++) + (*(volatile unsigned int*)(PALETTE+(palette*4)))=palette; + for (palette=16; palette < 256; palette++) + (*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00; + /* * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt @@ -364,30 +468,10 @@ int drv_vfd_init(void) rLCDSADDR2 = (vfdbase + frame_buf_size) >> 1; rLCDSADDR3 = ((256/4)); - /* Port-Pins als LCD-Ausgang */ - rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA; - /* Port-Pins als LCD-Ausgang */ - rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8; -#ifdef WITH_VFRAME - /* mit VFRAME zum Messen */ - rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA; -#endif - - rLCDCON2 = 0x000DC000; - rLCDCON3 = 0x0051000A; - rLCDCON4 = 0x00000001; - rLCDCON5 = 0x00000440; - rLCDCON1 = 0x00000B75; - debug ("LCDSADDR1: %lX\n", rLCDSADDR1); debug ("LCDSADDR2: %lX\n", rLCDSADDR2); debug ("LCDSADDR3: %lX\n", rLCDSADDR3); - for(palette=0;palette<=15;palette++) - (*(volatile unsigned int*)(PALETTE+(palette*4)))=palette; - for(palette=16;palette<=255;palette++) - (*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00; - return 0; } diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index e138d78b9b..2ac5763071 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -192,6 +192,8 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (hdr->ih_arch != IH_CPU_ARM) #elif defined(__I386__) if (hdr->ih_arch != IH_CPU_I386) +#elif defined(__mips__) + if (hdr->ih_arch != IH_CPU_MIPS) #else # error Unknown CPU type #endif diff --git a/common/cmd_elf.c b/common/cmd_elf.c index 149ffa3daa..74957622b1 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -252,11 +252,13 @@ int valid_elf_image (unsigned long addr) return 0; } +#if 0 if (ehdr->e_machine != EM_PPC) { printf ("## Not a PowerPC elf image at address 0x%08lx\n", addr); return 0; } +#endif return 1; } diff --git a/common/cmd_ide.c b/common/cmd_ide.c index d082d5e9b3..94fc89b427 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -489,11 +489,14 @@ void ide_init (void) #ifdef CONFIG_IDE_8xx_PCCARD extern int pcmcia_on (void); + extern int ide_devices_found; /* Initialized in check_ide_device() */ WATCHDOG_RESET(); + ide_devices_found = 0; /* initialize the PCMCIA IDE adapter card */ - if (pcmcia_on()) + pcmcia_on(); + if (!ide_devices_found) return; udelay (1000000); /* 1 s */ #endif /* CONFIG_IDE_8xx_PCCARD */ @@ -550,6 +553,13 @@ void ide_init (void) int dev = bus * (CFG_IDE_MAXDEVICE / max_bus_scan); #endif +#ifdef CONFIG_IDE_8xx_PCCARD + /* Skip non-ide devices from probing */ + if ((ide_devices_found & (1 << bus)) == 0) { + ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + continue; + } +#endif printf ("Bus %d: ", bus); ide_bus_ok[bus] = 0; diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c index f9bd0ba89b..31abbaf72c 100644 --- a/common/cmd_pcmcia.c +++ b/common/cmd_pcmcia.c @@ -268,6 +268,7 @@ static int pcmcia_off (void) #define MAX_TUPEL_SZ 512 #define MAX_FEATURES 4 +int ide_devices_found; static int check_ide_device (int slot) { volatile uchar *ident = NULL; @@ -347,6 +348,8 @@ static int check_ide_device (int slot) return (1); } + ide_devices_found |= (1 << slot); + /* set I/O area in config reg -> only valid for ARGOSY D5!!! */ *((uchar *)(addr + config_base)) = 1; diff --git a/drivers/Makefile b/drivers/Makefile index afea752246..65de8b5c35 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -28,12 +28,13 @@ include $(TOPDIR)/config.mk LIB = libdrivers.a OBJS = 3c589.o 5701rls.o bcm570x.o bcm570x_autoneg.o \ - cfb_console.o cs8900.o dc2114x.o eepro100.o \ - i8042.o natsemi.o ns16550.o ns8382x.o ns87308.o \ + cfb_console.o cs8900.o ct69000.o dc2114x.o \ + eepro100.o i8042.o inca-ip_sw.o \ + natsemi.o ns16550.o ns8382x.o ns87308.o \ pci.o pci_auto.o pci_indirect.o \ pcnet.o sed13806.o serial.o \ smc91111.o smiLynxEM.o sym53c8xx.o \ - tigon3.o w83c553f.o ct69000.o + tigon3.o w83c553f.o all: $(LIB) diff --git a/drivers/cs8900.c b/drivers/cs8900.c index ecc7c13b1d..7165d60bdf 100644 --- a/drivers/cs8900.c +++ b/drivers/cs8900.c @@ -1,6 +1,10 @@ /* * Cirrus Logic CS8900A Ethernet * + * (C) 2003 Wolfgang Denk, wd@denx.de + * Extension to synchronize ethaddr environment variable + * against value in EEPROM + * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> @@ -48,188 +52,226 @@ /* we don't need 16 bit initialisation on 32 bit bus */ #define get_reg_init_bus(x) get_reg((x)) #else -static unsigned short get_reg_init_bus(int regno) +static unsigned short get_reg_init_bus (int regno) { - /* force 16 bit busmode */ - volatile unsigned char c; - c = CS8900_BUS16_0; - c = CS8900_BUS16_1; - c = CS8900_BUS16_0; - c = CS8900_BUS16_1; - c = CS8900_BUS16_0; - - CS8900_PPTR = regno; - return (unsigned short) CS8900_PDATA; + /* force 16 bit busmode */ + volatile unsigned char c; + + c = CS8900_BUS16_0; + c = CS8900_BUS16_1; + c = CS8900_BUS16_0; + c = CS8900_BUS16_1; + c = CS8900_BUS16_0; + + CS8900_PPTR = regno; + return (unsigned short) CS8900_PDATA; } #endif -static unsigned short -get_reg(int regno) +static unsigned short get_reg (int regno) { - CS8900_PPTR = regno; - return (unsigned short) CS8900_PDATA; + CS8900_PPTR = regno; + return (unsigned short) CS8900_PDATA; } -static void put_reg(int regno, unsigned short val) +static void put_reg (int regno, unsigned short val) { - CS8900_PPTR = regno; - CS8900_PDATA = val; + CS8900_PPTR = regno; + CS8900_PDATA = val; } -static void eth_reset(void) +static void eth_reset (void) { - int tmo; - unsigned short us; + int tmo; + unsigned short us; - /* reset NIC */ - put_reg(PP_SelfCTL, get_reg(PP_SelfCTL) | PP_SelfCTL_Reset ); + /* reset NIC */ + put_reg (PP_SelfCTL, get_reg (PP_SelfCTL) | PP_SelfCTL_Reset); - /* wait for 200ms */ - udelay(200000); - /* Wait until the chip is reset */ + /* wait for 200ms */ + udelay (200000); + /* Wait until the chip is reset */ - tmo = get_timer(0) + 1 * CFG_HZ; - while ((((us = get_reg_init_bus(PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0) - && tmo < get_timer(0)) - /*NOP*/; + tmo = get_timer (0) + 1 * CFG_HZ; + while ((((us = get_reg_init_bus (PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0) + && tmo < get_timer (0)) + /*NOP*/; } -void cs8900_get_enetaddr (uchar *addr) +void cs8900_get_enetaddr (uchar * addr) { - int i; - /* verify chip id */ - if (get_reg_init_bus(PP_ChipID) != 0x630e) - return; - eth_reset(); - if ((get_reg(PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == - (PP_SelfSTAT_EEPROM|PP_SelfSTAT_EEPROM_OK)) { - /* Load the MAC from EEPROM */ - for (i=0; i<6/2; i++) { - unsigned int Addr; - Addr = get_reg(PP_IA+i*2); - addr[i*2] = Addr & 0xFF; - addr[i*2+1] = Addr >> 8; + int i; + unsigned char env_enetaddr[6]; + char *tmp = getenv ("ethaddr"); + char *end; + + for (i=0; i<6; i++) { + env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; + if (tmp) + tmp = (*end) ? end+1 : end; + } + + /* verify chip id */ + if (get_reg_init_bus (PP_ChipID) != 0x630e) + return; + eth_reset (); + if ((get_reg (PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == + (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) { + + /* Load the MAC from EEPROM */ + for (i = 0; i < 6 / 2; i++) { + unsigned int Addr; + + Addr = get_reg (PP_IA + i * 2); + addr[i * 2] = Addr & 0xFF; + addr[i * 2 + 1] = Addr >> 8; + } + + if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6) != 0 && + memcmp(env_enetaddr, addr, 6) != 0) { + printf ("\nWarning: MAC addresses don't match:\n"); + printf ("\tHW MAC address: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + addr[0], addr[1], + addr[2], addr[3], + addr[4], addr[5] ); + printf ("\t\"ethaddr\" value: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + env_enetaddr[0], env_enetaddr[1], + env_enetaddr[2], env_enetaddr[3], + env_enetaddr[4], env_enetaddr[5]) ; + debug ("### Set MAC addr from environment\n"); + memcpy (addr, env_enetaddr, 6); + } + if (!tmp) { + char ethaddr[20]; + sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", + addr[0], addr[1], + addr[2], addr[3], + addr[4], addr[5]) ; + debug ("### Set environment from HW MAC addr = \"%s\"\n", ethaddr); + setenv ("ethaddr", ethaddr); + } + } - } } -void eth_halt( void ) +void eth_halt (void) { - /* disable transmitter/receiver mode */ - put_reg(PP_LineCTL, 0); + /* disable transmitter/receiver mode */ + put_reg (PP_LineCTL, 0); - /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ - get_reg_init_bus(PP_ChipID); + /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ + get_reg_init_bus (PP_ChipID); } -int eth_init( bd_t *bd ) +int eth_init (bd_t * bd) { - /* verify chip id */ - if (get_reg_init_bus(PP_ChipID) != 0x630e) - { - printf( "CS8900 Ethernet chip not found?!\n" ); - return 0; - } + /* verify chip id */ + if (get_reg_init_bus (PP_ChipID) != 0x630e) { + printf ("CS8900 Ethernet chip not found?!\n"); + return 0; + } - eth_reset(); - /* set the ethernet address */ - put_reg(PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8)); - put_reg(PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8)); - put_reg(PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8)); + eth_reset (); + /* set the ethernet address */ + put_reg (PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8)); + put_reg (PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8)); + put_reg (PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8)); - /* receive only error free packets addressed to this card */ - put_reg(PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); + /* receive only error free packets addressed to this card */ + put_reg (PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); - /* do not generate any interrupts on receive operations */ - put_reg(PP_RxCFG, 0); + /* do not generate any interrupts on receive operations */ + put_reg (PP_RxCFG, 0); - /* do not generate any interrupts on transmit operations */ - put_reg(PP_TxCFG, 0); + /* do not generate any interrupts on transmit operations */ + put_reg (PP_TxCFG, 0); - /* do not generate any interrupts on buffer operations */ - put_reg(PP_BufCFG, 0); + /* do not generate any interrupts on buffer operations */ + put_reg (PP_BufCFG, 0); - /* enable transmitter/receiver mode */ - put_reg(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); + /* enable transmitter/receiver mode */ + put_reg (PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); - return 0; + return 0; } /* Get a data block via Ethernet */ -extern int eth_rx(void) +extern int eth_rx (void) { - int i; - unsigned short rxlen; - unsigned short *addr; - unsigned short status; + int i; + unsigned short rxlen; + unsigned short *addr; + unsigned short status; - status = get_reg(PP_RER); + status = get_reg (PP_RER); - if ((status & PP_RER_RxOK) == 0) - return 0; + if ((status & PP_RER_RxOK) == 0) + return 0; - status = CS8900_RTDATA; /* stat */ - rxlen = CS8900_RTDATA; /* len */ + status = CS8900_RTDATA; /* stat */ + rxlen = CS8900_RTDATA; /* len */ - if(rxlen > PKTSIZE_ALIGN + PKTALIGN) - printf("packet too big!\n"); + if (rxlen > PKTSIZE_ALIGN + PKTALIGN) + printf ("packet too big!\n"); - for(addr = (unsigned short *)NetRxPackets[0], i = rxlen >> 1; i > 0; i-- ) - *addr++ = CS8900_RTDATA; - if(rxlen & 1) - *addr++ = CS8900_RTDATA; + for (addr = (unsigned short *) NetRxPackets[0], i = rxlen >> 1; i > 0; + i--) + *addr++ = CS8900_RTDATA; + if (rxlen & 1) + *addr++ = CS8900_RTDATA; - /* Pass the packet up to the protocol layers. */ - NetReceive(NetRxPackets[0], rxlen); + /* Pass the packet up to the protocol layers. */ + NetReceive (NetRxPackets[0], rxlen); - return rxlen; + return rxlen; } /* Send a data block via Ethernet. */ -extern int eth_send(volatile void *packet, int length) +extern int eth_send (volatile void *packet, int length) { - volatile unsigned short *addr; - int tmo; - unsigned short s; + volatile unsigned short *addr; + int tmo; + unsigned short s; retry: - /* initiate a transmit sequence */ - CS8900_TxCMD = PP_TxCmd_TxStart_Full; - CS8900_TxLEN = length; - - /* Test to see if the chip has allocated memory for the packet */ - if ((get_reg(PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { - /* Oops... this should not happen! */ - printf("cs: unable to send packet; retrying...\n"); - for (tmo = get_timer(0) + 5 * CFG_HZ; get_timer(0) < tmo; ) - /*NOP*/; - eth_reset(); - goto retry; - } - - /* Write the contents of the packet */ - /* assume even number of bytes */ - for(addr = packet; length > 0; length -= 2 ) - CS8900_RTDATA = *addr++; - - /* wait for transfer to succeed */ - tmo = get_timer(0) + 5 * CFG_HZ; - while((s = get_reg(PP_TER) & ~0x1F) == 0) - { - if (get_timer(0) >= tmo) - break; - } - - /* nothing */ ; - if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { - printf("\ntransmission error %#x\n", s); - } - - return 0; + /* initiate a transmit sequence */ + CS8900_TxCMD = PP_TxCmd_TxStart_Full; + CS8900_TxLEN = length; + + /* Test to see if the chip has allocated memory for the packet */ + if ((get_reg (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { + /* Oops... this should not happen! */ + printf ("cs: unable to send packet; retrying...\n"); + for (tmo = get_timer (0) + 5 * CFG_HZ; get_timer (0) < tmo;) + /*NOP*/; + eth_reset (); + goto retry; + } + + /* Write the contents of the packet */ + /* assume even number of bytes */ + for (addr = packet; length > 0; length -= 2) + CS8900_RTDATA = *addr++; + + /* wait for transfer to succeed */ + tmo = get_timer (0) + 5 * CFG_HZ; + while ((s = get_reg (PP_TER) & ~0x1F) == 0) { + if (get_timer (0) >= tmo) + break; + } + + /* nothing */ ; + if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { + printf ("\ntransmission error %#x\n", s); + } + + return 0; } -#endif /* COMMANDS & CFG_NET */ +#endif /* COMMANDS & CFG_NET */ -#endif /* CONFIG_DRIVER_CS8900 */ +#endif /* CONFIG_DRIVER_CS8900 */ diff --git a/drivers/tigon3.c b/drivers/tigon3.c index 5883744dbd..c20dbe5cd1 100644 --- a/drivers/tigon3.c +++ b/drivers/tigon3.c @@ -11,7 +11,6 @@ /* History: */ /******************************************************************************/ #include <common.h> -#include "bcm570x_mm.h" #include <asm/types.h> #if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \ defined(CONFIG_TIGON3) @@ -20,6 +19,7 @@ #endif #include <malloc.h> #include <linux/byteorder/big_endian.h> +#include "bcm570x_mm.h" #define EMBEDDED 1 /******************************************************************************/ diff --git a/examples/Makefile b/examples/Makefile index b7d6f94e40..e6a3023913 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -27,6 +27,10 @@ include $(TOPDIR)/config.mk SREC = hello_world.srec +ifeq ($(CPU),mips) +SREC = +endif + # The following example is pretty 8xx specific... ifeq ($(CPU),mpc8xx) SREC += timer.srec diff --git a/examples/syscall.S b/examples/syscall.S index a952fd7744..510807bc9a 100644 --- a/examples/syscall.S +++ b/examples/syscall.S @@ -37,7 +37,37 @@ mon_free: stmfd sp!, {fp, ip, lr, pc} sub fp, ip, #4 ldmea fp, {fp, sp, pc} -#else /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +#elif defined(CONFIG_MIPS)/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +#warning MIPS version not implemented yet + .global mon_getc + .type mon_getc,function +mon_getc: + .global mon_tstc + .type mon_tstc,function +mon_tstc: + .global mon_putc + .type mon_putc,function +mon_putc: + .global mon_puts + .type mon_puts,function +mon_puts: + .global mon_printf + .type mon_printf,function +mon_printf: + .global mon_install_hdlr + .type mon_install_hdlr,function +mon_install_hdlr: + .global mon_free_hdlr + .type mon_free_hdlr,function +mon_free_hdlr: + .global mon_malloc + .type mon_malloc,function +mon_malloc: + .global mon_free + .type mon_free,function +mon_free: + +#else #ifdef CONFIG_I386 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ #define SYMBOL_NAME(X) X diff --git a/include/asm-arm/global_data.h b/include/asm-arm/global_data.h index bf26d0b4ad..e0a95e081b 100644 --- a/include/asm-arm/global_data.h +++ b/include/asm-arm/global_data.h @@ -43,6 +43,8 @@ typedef struct global_data { unsigned long env_valid; /* Checksum of Environment valid? */ #ifdef CONFIG_VFD unsigned long fb_base; /* base address of frame buffer */ + unsigned char vfd_type; /* display type */ + unsigned char vfd_inv_data; /* inverted data lines ? */ #endif #if 0 unsigned long cpu_clk; /* CPU clock in Hz! */ diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h new file mode 100644 index 0000000000..0d1bf3246d --- /dev/null +++ b/include/asm-mips/addrspace.h @@ -0,0 +1,70 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 2000 by Maciej W. Rozycki + * + * Defitions for the address spaces of the MIPS CPUs. + */ +#ifndef __ASM_MIPS_ADDRSPACE_H +#define __ASM_MIPS_ADDRSPACE_H + +/* + * Memory segments (32bit kernel mode addresses) + */ +#define KUSEG 0x00000000 +#define KSEG0 0x80000000 +#define KSEG1 0xa0000000 +#define KSEG2 0xc0000000 +#define KSEG3 0xe0000000 + +#define K0BASE KSEG0 + +/* + * Returns the kernel segment base of a given address + */ +#ifndef __ASSEMBLY__ +#define KSEGX(a) (((unsigned long)(a)) & 0xe0000000) +#else +#define KSEGX(a) ((a) & 0xe0000000) +#endif + +/* + * Returns the physical address of a KSEG0/KSEG1 address + */ +#ifndef __ASSEMBLY__ +#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) +#else +#define PHYSADDR(a) ((a) & 0x1fffffff) +#endif + +/* + * Map an address to a certain kernel segment + */ +#ifndef __ASSEMBLY__ +#define KSEG0ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0)) +#define KSEG1ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1)) +#define KSEG2ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2)) +#define KSEG3ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3)) +#else +#define KSEG0ADDR(a) (((a) & 0x1fffffff) | KSEG0) +#define KSEG1ADDR(a) (((a) & 0x1fffffff) | KSEG1) +#define KSEG2ADDR(a) (((a) & 0x1fffffff) | KSEG2) +#define KSEG3ADDR(a) (((a) & 0x1fffffff) | KSEG3) +#endif + +/* + * Memory segments (64bit kernel mode addresses) + */ +#define XKUSEG 0x0000000000000000 +#define XKSSEG 0x4000000000000000 +#define XKPHYS 0x8000000000000000 +#define XKSEG 0xc000000000000000 +#define CKSEG0 0xffffffff80000000 +#define CKSEG1 0xffffffffa0000000 +#define CKSSEG 0xffffffffc0000000 +#define CKSEG3 0xffffffffe0000000 + +#endif /* __ASM_MIPS_ADDRSPACE_H */ diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h new file mode 100644 index 0000000000..edff4c0fe8 --- /dev/null +++ b/include/asm-mips/bitops.h @@ -0,0 +1,912 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1994 - 1997, 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (c) 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_BITOPS_H +#define _ASM_BITOPS_H + +#include <linux/types.h> +#include <asm/byteorder.h> /* sigh ... */ + +#ifdef __KERNEL__ + +#include <asm/sgidefs.h> +#include <asm/system.h> +#include <linux/config.h> + +/* + * clear_bit() doesn't provide any barrier for the compiler. + */ +#define smp_mb__before_clear_bit() barrier() +#define smp_mb__after_clear_bit() barrier() + +/* + * Only disable interrupt for kernel mode stuff to keep usermode stuff + * that dares to use kernel include files alive. + */ +#define __bi_flags unsigned long flags +#define __bi_cli() __cli() +#define __bi_save_flags(x) __save_flags(x) +#define __bi_save_and_cli(x) __save_and_cli(x) +#define __bi_restore_flags(x) __restore_flags(x) +#else +#define __bi_flags +#define __bi_cli() +#define __bi_save_flags(x) +#define __bi_save_and_cli(x) +#define __bi_restore_flags(x) +#endif /* __KERNEL__ */ + +#ifdef CONFIG_CPU_HAS_LLSC + +#include <asm/mipsregs.h> + +/* + * These functions for MIPS ISA > 1 are interrupt and SMP proof and + * interrupt friendly + */ + +/* + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void +set_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0, %1\t\t# set_bit\n\t" + "or\t%0, %2\n\t" + "sc\t%0, %1\n\t" + "beqz\t%0, 1b" + : "=&r" (temp), "=m" (*m) + : "ir" (1UL << (nr & 0x1f)), "m" (*m)); +} + +/* + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __set_bit(int nr, volatile void * addr) +{ + unsigned long * m = ((unsigned long *) addr) + (nr >> 5); + + *m |= 1UL << (nr & 31); +} + +/* + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +extern __inline__ void +clear_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0, %1\t\t# clear_bit\n\t" + "and\t%0, %2\n\t" + "sc\t%0, %1\n\t" + "beqz\t%0, 1b\n\t" + : "=&r" (temp), "=m" (*m) + : "ir" (~(1UL << (nr & 0x1f))), "m" (*m)); +} + +/* + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void +change_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0, %1\t\t# change_bit\n\t" + "xor\t%0, %2\n\t" + "sc\t%0, %1\n\t" + "beqz\t%0, 1b" + : "=&r" (temp), "=m" (*m) + : "ir" (1UL << (nr & 0x1f)), "m" (*m)); +} + +/* + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __change_bit(int nr, volatile void * addr) +{ + unsigned long * m = ((unsigned long *) addr) + (nr >> 5); + + *m ^= 1UL << (nr & 31); +} + +/* + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_set_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp, res; + + __asm__ __volatile__( + ".set\tnoreorder\t\t# test_and_set_bit\n" + "1:\tll\t%0, %1\n\t" + "or\t%2, %0, %3\n\t" + "sc\t%2, %1\n\t" + "beqz\t%2, 1b\n\t" + " and\t%2, %0, %3\n\t" + ".set\treorder" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << (nr & 0x1f)), "m" (*m) + : "memory"); + + return res != 0; +} + +/* + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a |= mask; + + return retval; +} + +/* + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_clear_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp, res; + + __asm__ __volatile__( + ".set\tnoreorder\t\t# test_and_clear_bit\n" + "1:\tll\t%0, %1\n\t" + "or\t%2, %0, %3\n\t" + "xor\t%2, %3\n\t" + "sc\t%2, %1\n\t" + "beqz\t%2, 1b\n\t" + " and\t%2, %0, %3\n\t" + ".set\treorder" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << (nr & 0x1f)), "m" (*m) + : "memory"); + + return res != 0; +} + +/* + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a &= ~mask; + + return retval; +} + +/* + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_change_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp, res; + + __asm__ __volatile__( + ".set\tnoreorder\t\t# test_and_change_bit\n" + "1:\tll\t%0, %1\n\t" + "xor\t%2, %0, %3\n\t" + "sc\t%2, %1\n\t" + "beqz\t%2, 1b\n\t" + " and\t%2, %0, %3\n\t" + ".set\treorder" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << (nr & 0x1f)), "m" (*m) + : "memory"); + + return res != 0; +} + +/* + * __test_and_change_bit - Change a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a ^= mask; + + return retval; +} + +#else /* MIPS I */ + +/* + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void set_bit(int nr, volatile void * addr) +{ + int mask; + volatile int *a = addr; + __bi_flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_and_cli(flags); + *a |= mask; + __bi_restore_flags(flags); +} + +/* + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __set_bit(int nr, volatile void * addr) +{ + int mask; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + *a |= mask; +} + +/* + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +extern __inline__ void clear_bit(int nr, volatile void * addr) +{ + int mask; + volatile int *a = addr; + __bi_flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_and_cli(flags); + *a &= ~mask; + __bi_restore_flags(flags); +} + +/* + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void change_bit(int nr, volatile void * addr) +{ + int mask; + volatile int *a = addr; + __bi_flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_and_cli(flags); + *a ^= mask; + __bi_restore_flags(flags); +} + +/* + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __change_bit(int nr, volatile void * addr) +{ + unsigned long * m = ((unsigned long *) addr) + (nr >> 5); + + *m ^= 1UL << (nr & 31); +} + +/* + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int test_and_set_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + __bi_flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_and_cli(flags); + retval = (mask & *a) != 0; + *a |= mask; + __bi_restore_flags(flags); + + return retval; +} + +/* + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a |= mask; + + return retval; +} + +/* + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int test_and_clear_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + __bi_flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_and_cli(flags); + retval = (mask & *a) != 0; + *a &= ~mask; + __bi_restore_flags(flags); + + return retval; +} + +/* + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a &= ~mask; + + return retval; +} + +/* + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int test_and_change_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + __bi_flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __bi_save_and_cli(flags); + retval = (mask & *a) != 0; + *a ^= mask; + __bi_restore_flags(flags); + + return retval; +} + +/* + * __test_and_change_bit - Change a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a ^= mask; + + return retval; +} + +#undef __bi_flags +#undef __bi_cli +#undef __bi_save_flags +#undef __bi_restore_flags + +#endif /* MIPS I */ + +/* + * test_bit - Determine whether a bit is set + * @nr: bit number to test + * @addr: Address to start counting from + */ +extern __inline__ int test_bit(int nr, volatile void *addr) +{ + return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0; +} + +#ifndef __MIPSEB__ + +/* Little endian versions. */ + +/* + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +extern __inline__ int find_first_zero_bit (void *addr, unsigned size) +{ + unsigned long dummy; + int res; + + if (!size) + return 0; + + __asm__ (".set\tnoreorder\n\t" + ".set\tnoat\n" + "1:\tsubu\t$1,%6,%0\n\t" + "blez\t$1,2f\n\t" + "lw\t$1,(%5)\n\t" + "addiu\t%5,4\n\t" +#if (_MIPS_ISA == _MIPS_ISA_MIPS2 ) || (_MIPS_ISA == _MIPS_ISA_MIPS3 ) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5 ) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) + "beql\t%1,$1,1b\n\t" + "addiu\t%0,32\n\t" +#else + "addiu\t%0,32\n\t" + "beq\t%1,$1,1b\n\t" + "nop\n\t" + "subu\t%0,32\n\t" +#endif +#ifdef __MIPSEB__ +#error "Fix this for big endian" +#endif /* __MIPSEB__ */ + "li\t%1,1\n" + "1:\tand\t%2,$1,%1\n\t" + "beqz\t%2,2f\n\t" + "sll\t%1,%1,1\n\t" + "bnez\t%1,1b\n\t" + "add\t%0,%0,1\n\t" + ".set\tat\n\t" + ".set\treorder\n" + "2:" + : "=r" (res), "=r" (dummy), "=r" (addr) + : "0" ((signed int) 0), "1" ((unsigned int) 0xffffffff), + "2" (addr), "r" (size) + : "$1"); + + return res; +} + +/* + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +extern __inline__ int find_next_zero_bit (void * addr, int size, int offset) +{ + unsigned int *p = ((unsigned int *) addr) + (offset >> 5); + int set = 0, bit = offset & 31, res; + unsigned long dummy; + + if (bit) { + /* + * Look for zero in first byte + */ +#ifdef __MIPSEB__ +#error "Fix this for big endian byte order" +#endif + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n" + "1:\tand\t$1,%4,%1\n\t" + "beqz\t$1,1f\n\t" + "sll\t%1,%1,1\n\t" + "bnez\t%1,1b\n\t" + "addiu\t%0,1\n\t" + ".set\tat\n\t" + ".set\treorder\n" + "1:" + : "=r" (set), "=r" (dummy) + : "0" (0), "1" (1 << bit), "r" (*p) + : "$1"); + if (set < (32 - bit)) + return set + offset; + set = 32 - bit; + p++; + } + /* + * No zero yet, search remaining full bytes for a zero + */ + res = find_first_zero_bit(p, size - 32 * (p - (unsigned int *) addr)); + return offset + set + res; +} + +#endif /* !(__MIPSEB__) */ + +/* + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +extern __inline__ unsigned long ffz(unsigned long word) +{ + unsigned int __res; + unsigned int mask = 1; + + __asm__ ( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "move\t%0,$0\n" + "1:\tand\t$1,%2,%1\n\t" + "beqz\t$1,2f\n\t" + "sll\t%1,1\n\t" + "bnez\t%1,1b\n\t" + "addiu\t%0,1\n\t" + ".set\tat\n\t" + ".set\treorder\n" + "2:\n\t" + : "=&r" (__res), "=r" (mask) + : "r" (word), "1" (mask) + : "$1"); + + return __res; +} + +#ifdef __KERNEL__ + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#endif /* __KERNEL__ */ + +#ifdef __MIPSEB__ +/* + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +extern __inline__ int find_next_zero_bit(void *addr, int size, int offset) +{ + unsigned long *p = ((unsigned long *) addr) + (offset >> 5); + unsigned long result = offset & ~31UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31UL; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (32-offset); + if (size < 32) + goto found_first; + if (~tmp) + goto found_middle; + size -= 32; + result += 32; + } + while (size & ~31UL) { + if (~(tmp = *(p++))) + goto found_middle; + result += 32; + size -= 32; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; +found_middle: + return result + ffz(tmp); +} + +/* Linus sez that gcc can optimize the following correctly, we'll see if this + * holds on the Sparc as it does for the ALPHA. + */ + +#if 0 /* Fool kernel-doc since it doesn't do macros yet */ +/* + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +extern int find_first_zero_bit (void *addr, unsigned size); +#endif + +#define find_first_zero_bit(addr, size) \ + find_next_zero_bit((addr), (size), 0) + +#endif /* (__MIPSEB__) */ + +/* Now for the ext2 filesystem bit operations and helper routines. */ + +#ifdef __MIPSEB__ +extern __inline__ int ext2_set_bit(int nr, void * addr) +{ + int mask, retval, flags; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + save_and_cli(flags); + retval = (mask & *ADDR) != 0; + *ADDR |= mask; + restore_flags(flags); + return retval; +} + +extern __inline__ int ext2_clear_bit(int nr, void * addr) +{ + int mask, retval, flags; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + save_and_cli(flags); + retval = (mask & *ADDR) != 0; + *ADDR &= ~mask; + restore_flags(flags); + return retval; +} + +extern __inline__ int ext2_test_bit(int nr, const void * addr) +{ + int mask; + const unsigned char *ADDR = (const unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + return ((mask & *ADDR) != 0); +} + +#define ext2_find_first_zero_bit(addr, size) \ + ext2_find_next_zero_bit((addr), (size), 0) + +extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) +{ + unsigned long *p = ((unsigned long *) addr) + (offset >> 5); + unsigned long result = offset & ~31UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31UL; + if(offset) { + /* We hold the little endian value in tmp, but then the + * shift is illegal. So we could keep a big endian value + * in tmp, like this: + * + * tmp = __swab32(*(p++)); + * tmp |= ~0UL >> (32-offset); + * + * but this would decrease preformance, so we change the + * shift: + */ + tmp = *(p++); + tmp |= __swab32(~0UL >> (32-offset)); + if(size < 32) + goto found_first; + if(~tmp) + goto found_middle; + size -= 32; + result += 32; + } + while(size & ~31UL) { + if(~(tmp = *(p++))) + goto found_middle; + result += 32; + size -= 32; + } + if(!size) + return result; + tmp = *p; + +found_first: + /* tmp is little endian, so we would have to swab the shift, + * see above. But then we have to swab tmp below for ffz, so + * we might as well do this here. + */ + return result + ffz(__swab32(tmp) | (~0UL << size)); +found_middle: + return result + ffz(__swab32(tmp)); +} +#else /* !(__MIPSEB__) */ + +/* Native ext2 byte ordering, just collapse using defines. */ +#define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr)) +#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr)) +#define ext2_test_bit(nr, addr) test_bit((nr), (addr)) +#define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size)) +#define ext2_find_next_zero_bit(addr, size, offset) \ + find_next_zero_bit((addr), (size), (offset)) + +#endif /* !(__MIPSEB__) */ + +/* + * Bitmap functions for the minix filesystem. + * FIXME: These assume that Minix uses the native byte/bitorder. + * This limits the Minix filesystem's value for data exchange very much. + */ +#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) +#define minix_set_bit(nr,addr) set_bit(nr,addr) +#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* _ASM_BITOPS_H */ diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h new file mode 100644 index 0000000000..b9604cf202 --- /dev/null +++ b/include/asm-mips/byteorder.h @@ -0,0 +1,31 @@ +/* $Id: byteorder.h,v 1.8 1998/11/02 09:29:32 ralf Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) by Ralf Baechle + */ +#ifndef _MIPS_BYTEORDER_H +#define _MIPS_BYTEORDER_H + +#include <asm/types.h> + +#ifdef __GNUC__ + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +# define __BYTEORDER_HAS_U64__ +# define __SWAB_64_THRU_32__ +#endif + +#endif /* __GNUC__ */ + +#if defined (__MIPSEB__) +# include <linux/byteorder/big_endian.h> +#elif defined (__MIPSEL__) +# include <linux/byteorder/little_endian.h> +#else +# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???" +#endif + +#endif /* _MIPS_BYTEORDER_H */ diff --git a/include/asm-mips/cachectl.h b/include/asm-mips/cachectl.h new file mode 100644 index 0000000000..9cc2b87215 --- /dev/null +++ b/include/asm-mips/cachectl.h @@ -0,0 +1,24 @@ +/* + * cachectl.h -- defines for MIPS cache control system calls + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle + */ +#ifndef __ASM_MIPS_CACHECTL +#define __ASM_MIPS_CACHECTL + +/* + * Options for cacheflush system call + */ +#define ICACHE (1<<0) /* flush instruction cache */ +#define DCACHE (1<<1) /* writeback and flush data cache */ +#define BCACHE (ICACHE|DCACHE) /* flush both caches */ + +/* + * Caching modes for the cachectl(2) call + * + * cachectl(2) is currently not supported and returns ENOSYS. + */ +#define CACHEABLE 0 /* make pages cacheable */ +#define UNCACHEABLE 1 /* make pages uncacheable */ + +#endif /* __ASM_MIPS_CACHECTL */ diff --git a/include/asm-mips/cacheops.h b/include/asm-mips/cacheops.h new file mode 100644 index 0000000000..66b0b361f0 --- /dev/null +++ b/include/asm-mips/cacheops.h @@ -0,0 +1,47 @@ +/* + * Cache operations for the cache instruction. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * (C) Copyright 1996, 1997 by Ralf Baechle + */ +#ifndef __ASM_MIPS_CACHEOPS_H +#define __ASM_MIPS_CACHEOPS_H + +/* + * Cache Operations + */ +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 +#define Index_Invalidate_SI 0x02 +#define Index_Writeback_Inv_SD 0x03 +#define Index_Load_Tag_I 0x04 +#define Index_Load_Tag_D 0x05 +#define Index_Load_Tag_SI 0x06 +#define Index_Load_Tag_SD 0x07 +#define Index_Store_Tag_I 0x08 +#define Index_Store_Tag_D 0x09 +#define Index_Store_Tag_SI 0x0A +#define Index_Store_Tag_SD 0x0B +#define Create_Dirty_Excl_D 0x0d +#define Create_Dirty_Excl_SD 0x0f +#define Hit_Invalidate_I 0x10 +#define Hit_Invalidate_D 0x11 +#define Hit_Invalidate_SI 0x12 +#define Hit_Invalidate_SD 0x13 +#define Fill 0x14 +#define Hit_Writeback_Inv_D 0x15 + /* 0x16 is unused */ +#define Hit_Writeback_Inv_SD 0x17 +#define Hit_Writeback_I 0x18 +#define Hit_Writeback_D 0x19 + /* 0x1a is unused */ +#define Hit_Writeback_SD 0x1b + /* 0x1c is unused */ + /* 0x1e is unused */ +#define Hit_Set_Virtual_SI 0x1e +#define Hit_Set_Virtual_SD 0x1f + +#endif /* __ASM_MIPS_CACHEOPS_H */ diff --git a/include/asm-mips/global_data.h b/include/asm-mips/global_data.h new file mode 100644 index 0000000000..72d0cb0749 --- /dev/null +++ b/include/asm-mips/global_data.h @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2002-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_GBL_DATA_H +#define __ASM_GBL_DATA_H + +#include <asm/regdef.h> + +/* + * The following data structure is placed in some memory wich is + * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or + * some locked parts of the data cache) to allow for a minimum set of + * global variables during system initialization (until we have set + * up the memory controller so that we can use RAM). + * + * Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t) + */ + +typedef struct global_data { + bd_t *bd; + unsigned long flags; + unsigned long baudrate; + unsigned long have_console; /* serial_init() was called */ + unsigned long ram_size; /* RAM size */ + unsigned long reloc_off; /* Relocation Offset */ + unsigned long env_addr; /* Address of Environment struct */ + unsigned long env_valid; /* Checksum of Environment valid? */ +} gd_t; + +/* + * Global Data Flags + */ +#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ +#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ + +#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("k0") + +#endif /* __ASM_GBL_DATA_H */ diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h new file mode 100644 index 0000000000..9a7aaf7f4b --- /dev/null +++ b/include/asm-mips/io.h @@ -0,0 +1,450 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995 Waldorf GmbH + * Copyright (C) 1994 - 2000 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 FSMLabs, Inc. + */ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include <linux/config.h> +#if 0 +#include <linux/pagemap.h> +#endif +#include <asm/addrspace.h> +#include <asm/byteorder.h> + +/* + * Slowdown I/O port space accesses for antique hardware. + */ +#undef CONF_SLOWDOWN_IO + +/* + * Sane hardware offers swapping of I/O space accesses in hardware; less + * sane hardware forces software to fiddle with this ... + */ +#if defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) + +#define __ioswab8(x) (x) +#define __ioswab16(x) swab16(x) +#define __ioswab32(x) swab32(x) + +#else + +#define __ioswab8(x) (x) +#define __ioswab16(x) (x) +#define __ioswab32(x) (x) + +#endif + +/* + * This file contains the definitions for the MIPS counterpart of the + * x86 in/out instructions. This heap of macros and C results in much + * better code than the approach of doing it in plain C. The macros + * result in code that is to fast for certain hardware. On the other + * side the performance of the string functions should be improved for + * sake of certain devices like EIDE disks that do highspeed polled I/O. + * + * Ralf + * + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + * + * This file is not meant to be obfuscating: it's just complicated + * to (a) handle it all in a way that makes gcc able to optimize it + * as well as possible and (b) trying to avoid writing the same thing + * over and over again with slight variations and possibly making a + * mistake somewhere. + */ + +/* + * On MIPS I/O ports are memory mapped, so we access them using normal + * load/store instructions. mips_io_port_base is the virtual address to + * which all ports are being mapped. For sake of efficiency some code + * assumes that this is an address that can be loaded with a single lui + * instruction, so the lower 16 bits must be zero. Should be true on + * on any sane architecture; generic code does not use this assumption. + */ +extern unsigned long mips_io_port_base; + +/* + * Thanks to James van Artsdalen for a better timing-fix than + * the two short jumps: using outb's to a nonexistent port seems + * to guarantee better timings even on fast machines. + * + * On the other hand, I'd like to be sure of a non-existent port: + * I feel a bit unsafe about using 0x80 (should be safe, though) + * + * Linus + * + */ + +#define __SLOW_DOWN_IO \ + __asm__ __volatile__( \ + "sb\t$0,0x80(%0)" \ + : : "r" (mips_io_port_base)); + +#ifdef CONF_SLOWDOWN_IO +#ifdef REALLY_SLOW_IO +#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } +#else +#define SLOW_DOWN_IO __SLOW_DOWN_IO +#endif +#else +#define SLOW_DOWN_IO +#endif + +/* + * Change virtual addresses to physical addresses and vv. + * These are trivial on the 1:1 Linux/MIPS mapping + */ +extern inline unsigned long virt_to_phys(volatile void * address) +{ + return PHYSADDR(address); +} + +extern inline void * phys_to_virt(unsigned long address) +{ + return (void *)KSEG0ADDR(address); +} + +/* + * IO bus memory addresses are also 1:1 with the physical address + */ +extern inline unsigned long virt_to_bus(volatile void * address) +{ + return PHYSADDR(address); +} + +extern inline void * bus_to_virt(unsigned long address) +{ + return (void *)KSEG0ADDR(address); +} + +/* + * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped + * for the processor. + */ +extern unsigned long isa_slot_offset; + +extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); + +#if 0 +extern inline void *ioremap(unsigned long offset, unsigned long size) +{ + return __ioremap(offset, size, _CACHE_UNCACHED); +} + +extern inline void *ioremap_nocache(unsigned long offset, unsigned long size) +{ + return __ioremap(offset, size, _CACHE_UNCACHED); +} + +extern void iounmap(void *addr); +#endif + +/* + * XXX We need system specific versions of these to handle EISA address bits + * 24-31 on SNI. + * XXX more SNI hacks. + */ +#define readb(addr) (*(volatile unsigned char *)(addr)) +#define readw(addr) __ioswab16((*(volatile unsigned short *)(addr))) +#define readl(addr) __ioswab32((*(volatile unsigned int *)(addr))) +#define __raw_readb readb +#define __raw_readw readw +#define __raw_readl readl + +#define writeb(b,addr) (*(volatile unsigned char *)(addr)) = (b) +#define writew(b,addr) (*(volatile unsigned short *)(addr)) = (__ioswab16(b)) +#define writel(b,addr) (*(volatile unsigned int *)(addr)) = (__ioswab32(b)) +#define __raw_writeb writeb +#define __raw_writew writew +#define __raw_writel writel + +#define memset_io(a,b,c) memset((void *)(a),(b),(c)) +#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) +#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) + +/* END SNI HACKS ... */ + +/* + * ISA space is 'always mapped' on currently supported MIPS systems, no need + * to explicitly ioremap() it. The fact that the ISA IO space is mapped + * to PAGE_OFFSET is pure coincidence - it does not mean ISA values + * are physical addresses. The following constant pointer can be + * used as the IO-area pointer (it can be iounmapped as well, so the + * analogy with PCI is quite large): + */ +#define __ISA_IO_base ((char *)(PAGE_OFFSET)) + +#define isa_readb(a) readb(a) +#define isa_readw(a) readw(a) +#define isa_readl(a) readl(a) +#define isa_writeb(b,a) writeb(b,a) +#define isa_writew(w,a) writew(w,a) +#define isa_writel(l,a) writel(l,a) + +#define isa_memset_io(a,b,c) memset_io((a),(b),(c)) +#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),(b),(c)) +#define isa_memcpy_toio(a,b,c) memcpy_toio((a),(b),(c)) + +/* + * We don't have csum_partial_copy_fromio() yet, so we cheat here and + * just copy it. The net code will then do the checksum later. + */ +#define eth_io_copy_and_sum(skb,src,len,unused) memcpy_fromio((skb)->data,(src),(len)) +#define isa_eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),(b),(c),(d)) + +static inline int check_signature(unsigned long io_addr, + const unsigned char *signature, int length) +{ + int retval = 0; + do { + if (readb(io_addr) != *signature) + goto out; + io_addr++; + signature++; + length--; + } while (length); + retval = 1; +out: + return retval; +} +#define isa_check_signature(io, s, l) check_signature(i,s,l) + +/* + * Talk about misusing macros.. + */ + +#define __OUT1(s) \ +extern inline void __out##s(unsigned int value, unsigned int port) { + +#define __OUT2(m) \ +__asm__ __volatile__ ("s" #m "\t%0,%1(%2)" + +#define __OUT(m,s,w) \ +__OUT1(s) __OUT2(m) : : "r" (__ioswab##w(value)), "i" (0), "r" (mips_io_port_base+port)); } \ +__OUT1(s##c) __OUT2(m) : : "r" (__ioswab##w(value)), "ir" (port), "r" (mips_io_port_base)); } \ +__OUT1(s##_p) __OUT2(m) : : "r" (__ioswab##w(value)), "i" (0), "r" (mips_io_port_base+port)); \ + SLOW_DOWN_IO; } \ +__OUT1(s##c_p) __OUT2(m) : : "r" (__ioswab##w(value)), "ir" (port), "r" (mips_io_port_base)); \ + SLOW_DOWN_IO; } + +#define __IN1(t,s) \ +extern __inline__ t __in##s(unsigned int port) { t _v; + +/* + * Required nops will be inserted by the assembler + */ +#define __IN2(m) \ +__asm__ __volatile__ ("l" #m "\t%0,%1(%2)" + +#define __IN(t,m,s,w) \ +__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); return __ioswab##w(_v); } \ +__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); return __ioswab##w(_v); } \ +__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SLOW_DOWN_IO; return __ioswab##w(_v); } \ +__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return __ioswab##w(_v); } + +#define __INS1(s) \ +extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) { + +#define __INS2(m) \ +if (count) \ +__asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + ".set\tnoat\n" \ + "1:\tl" #m "\t$1,%4(%5)\n\t" \ + "subu\t%1,1\n\t" \ + "s" #m "\t$1,(%0)\n\t" \ + "bne\t$0,%1,1b\n\t" \ + "addiu\t%0,%6\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" + +#define __INS(m,s,i) \ +__INS1(s) __INS2(m) \ + : "=r" (addr), "=r" (count) \ + : "0" (addr), "1" (count), "i" (0), \ + "r" (mips_io_port_base+port), "I" (i) \ + : "$1");} \ +__INS1(s##c) __INS2(m) \ + : "=r" (addr), "=r" (count) \ + : "0" (addr), "1" (count), "ir" (port), \ + "r" (mips_io_port_base), "I" (i) \ + : "$1");} + +#define __OUTS1(s) \ +extern inline void __outs##s(unsigned int port, const void * addr, unsigned long count) { + +#define __OUTS2(m) \ +if (count) \ +__asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + ".set\tnoat\n" \ + "1:\tl" #m "\t$1,(%0)\n\t" \ + "subu\t%1,1\n\t" \ + "s" #m "\t$1,%4(%5)\n\t" \ + "bne\t$0,%1,1b\n\t" \ + "addiu\t%0,%6\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" + +#define __OUTS(m,s,i) \ +__OUTS1(s) __OUTS2(m) \ + : "=r" (addr), "=r" (count) \ + : "0" (addr), "1" (count), "i" (0), "r" (mips_io_port_base+port), "I" (i) \ + : "$1");} \ +__OUTS1(s##c) __OUTS2(m) \ + : "=r" (addr), "=r" (count) \ + : "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), "I" (i) \ + : "$1");} + +__IN(unsigned char,b,b,8) +__IN(unsigned short,h,w,16) +__IN(unsigned int,w,l,32) + +__OUT(b,b,8) +__OUT(h,w,16) +__OUT(w,l,32) + +__INS(b,b,1) +__INS(h,w,2) +__INS(w,l,4) + +__OUTS(b,b,1) +__OUTS(h,w,2) +__OUTS(w,l,4) + + +/* + * Note that due to the way __builtin_constant_p() works, you + * - can't use it inside an inline function (it will never be true) + * - you don't have to worry about side effects within the __builtin.. + */ +#define outb(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outbc((val),(port)) : \ + __outb((val),(port))) + +#define inb(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __inbc(port) : \ + __inb(port)) + +#define outb_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outbc_p((val),(port)) : \ + __outb_p((val),(port))) + +#define inb_p(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __inbc_p(port) : \ + __inb_p(port)) + +#define outw(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outwc((val),(port)) : \ + __outw((val),(port))) + +#define inw(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __inwc(port) : \ + __inw(port)) + +#define outw_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outwc_p((val),(port)) : \ + __outw_p((val),(port))) + +#define inw_p(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __inwc_p(port) : \ + __inw_p(port)) + +#define outl(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outlc((val),(port)) : \ + __outl((val),(port))) + +#define inl(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __inlc(port) : \ + __inl(port)) + +#define outl_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outlc_p((val),(port)) : \ + __outl_p((val),(port))) + +#define inl_p(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __inlc_p(port) : \ + __inl_p(port)) + + +#define outsb(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outsbc((port),(addr),(count)) : \ + __outsb ((port),(addr),(count))) + +#define insb(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __insbc((port),(addr),(count)) : \ + __insb((port),(addr),(count))) + +#define outsw(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outswc((port),(addr),(count)) : \ + __outsw ((port),(addr),(count))) + +#define insw(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __inswc((port),(addr),(count)) : \ + __insw((port),(addr),(count))) + +#define outsl(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __outslc((port),(addr),(count)) : \ + __outsl ((port),(addr),(count))) + +#define insl(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ + __inslc((port),(addr),(count)) : \ + __insl((port),(addr),(count))) + +#define IO_SPACE_LIMIT 0xffff + +/* + * The caches on some architectures aren't dma-coherent and have need to + * handle this in software. There are three types of operations that + * can be applied to dma buffers. + * + * - dma_cache_wback_inv(start, size) makes caches and coherent by + * writing the content of the caches back to memory, if necessary. + * The function also invalidates the affected part of the caches as + * necessary before DMA transfers from outside to memory. + * - dma_cache_wback(start, size) makes caches and coherent by + * writing the content of the caches back to memory, if necessary. + * The function also invalidates the affected part of the caches as + * necessary before DMA transfers from outside to memory. + * - dma_cache_inv(start, size) invalidates the affected parts of the + * caches. Dirty lines of the caches may be written back or simply + * be discarded. This operation is necessary before dma operations + * to the memory. + */ +extern void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); +extern void (*_dma_cache_wback)(unsigned long start, unsigned long size); +extern void (*_dma_cache_inv)(unsigned long start, unsigned long size); + +#define dma_cache_wback_inv(start,size) _dma_cache_wback_inv(start,size) +#define dma_cache_wback(start,size) _dma_cache_wback(start,size) +#define dma_cache_inv(start,size) _dma_cache_inv(start,size) + +#endif /* _ASM_IO_H */ diff --git a/include/asm-mips/isadep.h b/include/asm-mips/isadep.h new file mode 100644 index 0000000000..3cd1eb8eb5 --- /dev/null +++ b/include/asm-mips/isadep.h @@ -0,0 +1,35 @@ +/* + * Various ISA level dependant constants. + * Most of the following constants reflect the different layout + * of Coprocessor 0 registers. + * + * Copyright (c) 1998 Harald Koerfgen + */ +#include <linux/config.h> + +#ifndef __ASM_ISADEP_H +#define __ASM_ISADEP_H + +#if defined(CONFIG_CPU_R3000) +/* + * R2000 or R3000 + */ + +/* + * kernel or user mode? (CP0_STATUS) + */ +#define KU_MASK 0x08 +#define KU_USER 0x08 +#define KU_KERN 0x00 + +#else +/* + * kernel or user mode? + */ +#define KU_MASK 0x18 +#define KU_USER 0x10 +#define KU_KERN 0x00 + +#endif + +#endif /* __ASM_ISADEP_H */ diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h new file mode 100644 index 0000000000..56fc3da785 --- /dev/null +++ b/include/asm-mips/mipsregs.h @@ -0,0 +1,540 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + * Modified for further R[236]000 support by Paul M. Antoine, 1996. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + */ +#ifndef _ASM_MIPSREGS_H +#define _ASM_MIPSREGS_H + +#if 0 +#include <linux/linkage.h> +#endif + +/* + * The following macros are especially useful for __asm__ + * inline assembler. + */ +#ifndef __STR +#define __STR(x) #x +#endif +#ifndef STR +#define STR(x) __STR(x) +#endif + +/* + * Coprocessor 0 register names + */ +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONF $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_INFO $7 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 + +/* + * R4640/R4650 cp0 register names. These registers are listed + * here only for completeness; without MMU these CPUs are not useable + * by Linux. A future ELKS port might take make Linux run on them + * though ... + */ +#define CP0_IBASE $0 +#define CP0_IBOUND $1 +#define CP0_DBASE $2 +#define CP0_DBOUND $3 +#define CP0_CALG $17 +#define CP0_IWATCH $18 +#define CP0_DWATCH $19 + +/* + * Coprocessor 0 Set 1 register names + */ +#define CP0_S1_DERRADDR0 $26 +#define CP0_S1_DERRADDR1 $27 +#define CP0_S1_INTCONTROL $20 +/* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION $0 +#define CP1_STATUS $31 + +/* + * FPU Status Register Values + */ +/* + * Status Register Values + */ + +#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ +#define FPU_CSR_COND 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ +#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ +#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ +#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ +#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ +#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ +#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPU_CSR_ALL_X 0x0003f000 +#define FPU_CSR_UNI_X 0x00020000 +#define FPU_CSR_INV_X 0x00010000 +#define FPU_CSR_DIV_X 0x00008000 +#define FPU_CSR_OVF_X 0x00004000 +#define FPU_CSR_UDF_X 0x00002000 +#define FPU_CSR_INE_X 0x00001000 + +#define FPU_CSR_ALL_E 0x00000f80 +#define FPU_CSR_INV_E 0x00000800 +#define FPU_CSR_DIV_E 0x00000400 +#define FPU_CSR_OVF_E 0x00000200 +#define FPU_CSR_UDF_E 0x00000100 +#define FPU_CSR_INE_E 0x00000080 + +#define FPU_CSR_ALL_S 0x0000007c +#define FPU_CSR_INV_S 0x00000040 +#define FPU_CSR_DIV_S 0x00000020 +#define FPU_CSR_OVF_S 0x00000010 +#define FPU_CSR_UDF_S 0x00000008 +#define FPU_CSR_INE_S 0x00000004 + +/* rounding mode */ +#define FPU_CSR_RN 0x0 /* nearest */ +#define FPU_CSR_RZ 0x1 /* towards zero */ +#define FPU_CSR_RU 0x2 /* towards +Infinity */ +#define FPU_CSR_RD 0x3 /* towards -Infinity */ + + +/* + * Values for PageMask register + */ +#include <linux/config.h> +#ifdef CONFIG_CPU_VR41XX +#define PM_1K 0x00000000 +#define PM_4K 0x00001800 +#define PM_16K 0x00007800 +#define PM_64K 0x0001f800 +#define PM_256K 0x0007f800 +#else +#define PM_4K 0x00000000 +#define PM_16K 0x00006000 +#define PM_64K 0x0001e000 +#define PM_256K 0x0007e000 +#define PM_1M 0x001fe000 +#define PM_4M 0x007fe000 +#define PM_16M 0x01ffe000 +#endif + +/* + * Values used for computation of new tlb entries + */ +#define PL_4K 12 +#define PL_16K 14 +#define PL_64K 16 +#define PL_256K 18 +#define PL_1M 20 +#define PL_4M 22 +#define PL_16M 24 + +/* + * Macros to access the system control coprocessor + */ +#define read_32bit_cp0_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "mfc0\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +#define read_32bit_cp0_set1_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "cfc0\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +/* + * For now use this only with interrupts disabled! + */ +#define read_64bit_cp0_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmfc0\t%0,"STR(source)"\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + __res;}) + +#define write_32bit_cp0_register(register,value) \ + __asm__ __volatile__( \ + "mtc0\t%0,"STR(register)"\n\t" \ + "nop" \ + : : "r" (value)); + +#define write_32bit_cp0_set1_register(register,value) \ + __asm__ __volatile__( \ + "ctc0\t%0,"STR(register)"\n\t" \ + "nop" \ + : : "r" (value)); + +#define write_64bit_cp0_register(register,value) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmtc0\t%0,"STR(register)"\n\t" \ + ".set\tmips0" \ + : : "r" (value)) + +/* + * This should be changed when we get a compiler that support the MIPS32 ISA. + */ +#define read_mips32_cp0_config1() \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tnoreorder\n\t" \ + ".set\tnoat\n\t" \ + ".word\t0x40018001\n\t" \ + "move\t%0,$1\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + :"=r" (__res)); \ + __res;}) + +/* + * R4x00 interrupt enable / cause bits + */ +#define IE_SW0 (1<< 8) +#define IE_SW1 (1<< 9) +#define IE_IRQ0 (1<<10) +#define IE_IRQ1 (1<<11) +#define IE_IRQ2 (1<<12) +#define IE_IRQ3 (1<<13) +#define IE_IRQ4 (1<<14) +#define IE_IRQ5 (1<<15) + +/* + * R4x00 interrupt cause bits + */ +#define C_SW0 (1<< 8) +#define C_SW1 (1<< 9) +#define C_IRQ0 (1<<10) +#define C_IRQ1 (1<<11) +#define C_IRQ2 (1<<12) +#define C_IRQ3 (1<<13) +#define C_IRQ4 (1<<14) +#define C_IRQ5 (1<<15) + +#ifndef _LANGUAGE_ASSEMBLY +/* + * Manipulate the status register. + * Mostly used to access the interrupt bits. + */ +#define __BUILD_SET_CP0(name,register) \ +extern __inline__ unsigned int \ +set_cp0_##name(unsigned int set) \ +{ \ + unsigned int res; \ + \ + res = read_32bit_cp0_register(register); \ + res |= set; \ + write_32bit_cp0_register(register, res); \ + \ + return res; \ +} \ + \ +extern __inline__ unsigned int \ +clear_cp0_##name(unsigned int clear) \ +{ \ + unsigned int res; \ + \ + res = read_32bit_cp0_register(register); \ + res &= ~clear; \ + write_32bit_cp0_register(register, res); \ + \ + return res; \ +} \ + \ +extern __inline__ unsigned int \ +change_cp0_##name(unsigned int change, unsigned int new) \ +{ \ + unsigned int res; \ + \ + res = read_32bit_cp0_register(register); \ + res &= ~change; \ + res |= (new & change); \ + if(change) \ + write_32bit_cp0_register(register, res); \ + \ + return res; \ +} + +__BUILD_SET_CP0(status,CP0_STATUS) +__BUILD_SET_CP0(cause,CP0_CAUSE) +__BUILD_SET_CP0(config,CP0_CONFIG) + +#endif /* defined (_LANGUAGE_ASSEMBLY) */ + +/* + * Bitfields in the R4xx0 cp0 status register + */ +#define ST0_IE 0x00000001 +#define ST0_EXL 0x00000002 +#define ST0_ERL 0x00000004 +#define ST0_KSU 0x00000018 +# define KSU_USER 0x00000010 +# define KSU_SUPERVISOR 0x00000008 +# define KSU_KERNEL 0x00000000 +#define ST0_UX 0x00000020 +#define ST0_SX 0x00000040 +#define ST0_KX 0x00000080 +#define ST0_DE 0x00010000 +#define ST0_CE 0x00020000 + +/* + * Bitfields in the R[23]000 cp0 status register. + */ +#define ST0_IEC 0x00000001 +#define ST0_KUC 0x00000002 +#define ST0_IEP 0x00000004 +#define ST0_KUP 0x00000008 +#define ST0_IEO 0x00000010 +#define ST0_KUO 0x00000020 +/* bits 6 & 7 are reserved on R[23]000 */ +#define ST0_ISC 0x00010000 +#define ST0_SWC 0x00020000 +#define ST0_CM 0x00080000 + +/* + * Bits specific to the R4640/R4650 + */ +#define ST0_UM (1 << 4) +#define ST0_IL (1 << 23) +#define ST0_DL (1 << 24) + +/* + * Bitfields in the TX39 family CP0 Configuration Register 3 + */ +#define TX39_CONF_ICS_SHIFT 19 +#define TX39_CONF_ICS_MASK 0x00380000 +#define TX39_CONF_ICS_1KB 0x00000000 +#define TX39_CONF_ICS_2KB 0x00080000 +#define TX39_CONF_ICS_4KB 0x00100000 +#define TX39_CONF_ICS_8KB 0x00180000 +#define TX39_CONF_ICS_16KB 0x00200000 + +#define TX39_CONF_DCS_SHIFT 16 +#define TX39_CONF_DCS_MASK 0x00070000 +#define TX39_CONF_DCS_1KB 0x00000000 +#define TX39_CONF_DCS_2KB 0x00010000 +#define TX39_CONF_DCS_4KB 0x00020000 +#define TX39_CONF_DCS_8KB 0x00030000 +#define TX39_CONF_DCS_16KB 0x00040000 + +#define TX39_CONF_CWFON 0x00004000 +#define TX39_CONF_WBON 0x00002000 +#define TX39_CONF_RF_SHIFT 10 +#define TX39_CONF_RF_MASK 0x00000c00 +#define TX39_CONF_DOZE 0x00000200 +#define TX39_CONF_HALT 0x00000100 +#define TX39_CONF_LOCK 0x00000080 +#define TX39_CONF_ICE 0x00000020 +#define TX39_CONF_DCE 0x00000010 +#define TX39_CONF_IRSIZE_SHIFT 2 +#define TX39_CONF_IRSIZE_MASK 0x0000000c +#define TX39_CONF_DRSIZE_SHIFT 0 +#define TX39_CONF_DRSIZE_MASK 0x00000003 + +/* + * Status register bits available in all MIPS CPUs. + */ +#define ST0_IM 0x0000ff00 +#define STATUSB_IP0 8 +#define STATUSF_IP0 (1 << 8) +#define STATUSB_IP1 9 +#define STATUSF_IP1 (1 << 9) +#define STATUSB_IP2 10 +#define STATUSF_IP2 (1 << 10) +#define STATUSB_IP3 11 +#define STATUSF_IP3 (1 << 11) +#define STATUSB_IP4 12 +#define STATUSF_IP4 (1 << 12) +#define STATUSB_IP5 13 +#define STATUSF_IP5 (1 << 13) +#define STATUSB_IP6 14 +#define STATUSF_IP6 (1 << 14) +#define STATUSB_IP7 15 +#define STATUSF_IP7 (1 << 15) +#define STATUSB_IP8 0 +#define STATUSF_IP8 (1 << 0) +#define STATUSB_IP9 1 +#define STATUSF_IP9 (1 << 1) +#define STATUSB_IP10 2 +#define STATUSF_IP10 (1 << 2) +#define STATUSB_IP11 3 +#define STATUSF_IP11 (1 << 3) +#define STATUSB_IP12 4 +#define STATUSF_IP12 (1 << 4) +#define STATUSB_IP13 5 +#define STATUSF_IP13 (1 << 5) +#define STATUSB_IP14 6 +#define STATUSF_IP14 (1 << 6) +#define STATUSB_IP15 7 +#define STATUSF_IP15 (1 << 7) +#define ST0_CH 0x00040000 +#define ST0_SR 0x00100000 +#define ST0_BEV 0x00400000 +#define ST0_RE 0x02000000 +#define ST0_FR 0x04000000 +#define ST0_CU 0xf0000000 +#define ST0_CU0 0x10000000 +#define ST0_CU1 0x20000000 +#define ST0_CU2 0x40000000 +#define ST0_CU3 0x80000000 +#define ST0_XX 0x80000000 /* MIPS IV naming */ + +/* + * Bitfields and bit numbers in the coprocessor 0 cause register. + * + * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. + */ +#define CAUSEB_EXCCODE 2 +#define CAUSEF_EXCCODE (31 << 2) +#define CAUSEB_IP 8 +#define CAUSEF_IP (255 << 8) +#define CAUSEB_IP0 8 +#define CAUSEF_IP0 (1 << 8) +#define CAUSEB_IP1 9 +#define CAUSEF_IP1 (1 << 9) +#define CAUSEB_IP2 10 +#define CAUSEF_IP2 (1 << 10) +#define CAUSEB_IP3 11 +#define CAUSEF_IP3 (1 << 11) +#define CAUSEB_IP4 12 +#define CAUSEF_IP4 (1 << 12) +#define CAUSEB_IP5 13 +#define CAUSEF_IP5 (1 << 13) +#define CAUSEB_IP6 14 +#define CAUSEF_IP6 (1 << 14) +#define CAUSEB_IP7 15 +#define CAUSEF_IP7 (1 << 15) +#define CAUSEB_IV 23 +#define CAUSEF_IV (1 << 23) +#define CAUSEB_CE 28 +#define CAUSEF_CE (3 << 28) +#define CAUSEB_BD 31 +#define CAUSEF_BD (1 << 31) + +/* + * Bits in the coprozessor 0 config register. + */ +#define CONF_CM_CACHABLE_NO_WA 0 +#define CONF_CM_CACHABLE_WA 1 +#define CONF_CM_UNCACHED 2 +#define CONF_CM_CACHABLE_NONCOHERENT 3 +#define CONF_CM_CACHABLE_CE 4 +#define CONF_CM_CACHABLE_COW 5 +#define CONF_CM_CACHABLE_CUW 6 +#define CONF_CM_CACHABLE_ACCELERATED 7 +#define CONF_CM_CMASK 7 +#define CONF_DB (1 << 4) +#define CONF_IB (1 << 5) +#define CONF_SC (1 << 17) +#define CONF_AC (1 << 23) +#define CONF_HALT (1 << 25) + +/* + * R10000 performance counter definitions. + * + * FIXME: The R10000 performance counter opens a nice way to implement CPU + * time accounting with a precission of one cycle. I don't have + * R10000 silicon but just a manual, so ... + */ + +/* + * Events counted by counter #0 + */ +#define CE0_CYCLES 0 +#define CE0_INSN_ISSUED 1 +#define CE0_LPSC_ISSUED 2 +#define CE0_S_ISSUED 3 +#define CE0_SC_ISSUED 4 +#define CE0_SC_FAILED 5 +#define CE0_BRANCH_DECODED 6 +#define CE0_QW_WB_SECONDARY 7 +#define CE0_CORRECTED_ECC_ERRORS 8 +#define CE0_ICACHE_MISSES 9 +#define CE0_SCACHE_I_MISSES 10 +#define CE0_SCACHE_I_WAY_MISSPREDICTED 11 +#define CE0_EXT_INTERVENTIONS_REQ 12 +#define CE0_EXT_INVALIDATE_REQ 13 +#define CE0_VIRTUAL_COHERENCY_COND 14 +#define CE0_INSN_GRADUATED 15 + +/* + * Events counted by counter #1 + */ +#define CE1_CYCLES 0 +#define CE1_INSN_GRADUATED 1 +#define CE1_LPSC_GRADUATED 2 +#define CE1_S_GRADUATED 3 +#define CE1_SC_GRADUATED 4 +#define CE1_FP_INSN_GRADUATED 5 +#define CE1_QW_WB_PRIMARY 6 +#define CE1_TLB_REFILL 7 +#define CE1_BRANCH_MISSPREDICTED 8 +#define CE1_DCACHE_MISS 9 +#define CE1_SCACHE_D_MISSES 10 +#define CE1_SCACHE_D_WAY_MISSPREDICTED 11 +#define CE1_EXT_INTERVENTION_HITS 12 +#define CE1_EXT_INVALIDATE_REQ 13 +#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14 +#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15 + +/* + * These flags define in which priviledge mode the counters count events + */ +#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */ +#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */ +#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */ +#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */ + +#endif /* _ASM_MIPSREGS_H */ diff --git a/include/asm-mips/posix_types.h b/include/asm-mips/posix_types.h new file mode 100644 index 0000000000..6c48b3f839 --- /dev/null +++ b/include/asm-mips/posix_types.h @@ -0,0 +1,123 @@ +/* $Id: posix_types.h,v 1.6 2000/02/04 23:32:54 ralf Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle + */ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef int __kernel_uid_t; +typedef int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef long __kernel_daddr_t; +typedef char * __kernel_caddr_t; + +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef int __kernel_uid32_t; +typedef int __kernel_gid32_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { + long val[2]; +} __kernel_fsid_t; + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + __fdsetp->fds_bits[__tmp] |= (1UL<<__rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *__p) +{ + unsigned long *__tmp = __p->fds_bits; + int __i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 16: + __tmp[ 0] = 0; __tmp[ 1] = 0; + __tmp[ 2] = 0; __tmp[ 3] = 0; + __tmp[ 4] = 0; __tmp[ 5] = 0; + __tmp[ 6] = 0; __tmp[ 7] = 0; + __tmp[ 8] = 0; __tmp[ 9] = 0; + __tmp[10] = 0; __tmp[11] = 0; + __tmp[12] = 0; __tmp[13] = 0; + __tmp[14] = 0; __tmp[15] = 0; + return; + + case 8: + __tmp[ 0] = 0; __tmp[ 1] = 0; + __tmp[ 2] = 0; __tmp[ 3] = 0; + __tmp[ 4] = 0; __tmp[ 5] = 0; + __tmp[ 6] = 0; __tmp[ 7] = 0; + return; + + case 4: + __tmp[ 0] = 0; __tmp[ 1] = 0; + __tmp[ 2] = 0; __tmp[ 3] = 0; + return; + } + } + __i = __FDSET_LONGS; + while (__i) { + __i--; + *__tmp = 0; + __tmp++; + } +} + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif /* _ASM_POSIX_TYPES_H */ diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h new file mode 100644 index 0000000000..8c3de908d5 --- /dev/null +++ b/include/asm-mips/processor.h @@ -0,0 +1,283 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 Waldorf GMBH + * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001 Ralf Baechle + * Copyright (C) 1996 Paul M. Antoine + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_PROCESSOR_H +#define _ASM_PROCESSOR_H + +#include <linux/config.h> + +#include <asm/isadep.h> + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l;}) + +#if !defined (_LANGUAGE_ASSEMBLY) +#if 0 +#include <linux/threads.h> +#endif +#include <asm/cachectl.h> +#include <asm/mipsregs.h> +#include <asm/reg.h> +#include <asm/system.h> + +struct mips_cpuinfo { + unsigned long udelay_val; + unsigned long *pgd_quick; + unsigned long *pte_quick; + unsigned long pgtable_cache_sz; +}; + +/* + * System setup and hardware flags.. + * XXX: Should go into mips_cpuinfo. + */ +extern void (*cpu_wait)(void); /* only available on R4[26]00 and R3081 */ +extern void r3081_wait(void); +extern void r4k_wait(void); +extern char cyclecounter_available; /* only available from R4000 upwards. */ + +extern struct mips_cpuinfo boot_cpu_data; +extern unsigned int vced_count, vcei_count; + +#ifdef CONFIG_SMP +extern struct mips_cpuinfo cpu_data[]; +#define current_cpu_data cpu_data[smp_processor_id()] +#else +#define cpu_data &boot_cpu_data +#define current_cpu_data boot_cpu_data +#endif + +/* + * Bus types (default is ISA, but people can check others with these..) + * MCA_bus hardcoded to 0 for now. + * + * This needs to be extended since MIPS systems are being delivered with + * numerous different types of bus systems. + */ +extern int EISA_bus; +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* + * MIPS has no problems with write protection + */ +#define wp_works_ok 1 +#define wp_works_ok__is_a_macro /* for versions in ksyms.c */ + +/* Lazy FPU handling on uni-processor */ +extern struct task_struct *last_task_used_math; + +/* + * User space process size: 2GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. TASK_SIZE + * for a 64 bit kernel expandable to 8192EB, of which the current MIPS + * implementations will "only" be able to use 1TB ... + */ +#define TASK_SIZE (0x7fff8000UL) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +/* + * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. + */ +#define IO_BITMAP_SIZE 32 + +#define NUM_FPU_REGS 32 + +struct mips_fpu_hard_struct { + double fp_regs[NUM_FPU_REGS]; + unsigned int control; +}; + +/* + * It would be nice to add some more fields for emulator statistics, but there + * are a number of fixed offsets in offset.h and elsewhere that would have to + * be recalculated by hand. So the additional information will be private to + * the FPU emulator for now. See asm-mips/fpu_emulator.h. + */ +typedef u64 fpureg_t; +struct mips_fpu_soft_struct { + fpureg_t regs[NUM_FPU_REGS]; + unsigned int sr; +}; + +union mips_fpu_union { + struct mips_fpu_hard_struct hard; + struct mips_fpu_soft_struct soft; +}; + +#define INIT_FPU { \ + {{0,},} \ +} + +typedef struct { + unsigned long seg; +} mm_segment_t; + +/* + * If you change thread_struct remember to change the #defines below too! + */ +struct thread_struct { + /* Saved main processor registers. */ + unsigned long reg16; + unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23; + unsigned long reg29, reg30, reg31; + + /* Saved cp0 stuff. */ + unsigned long cp0_status; + + /* Saved fpu/fpu emulator stuff. */ + union mips_fpu_union fpu; + + /* Other stuff associated with the thread. */ + unsigned long cp0_badvaddr; /* Last user fault */ + unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ + unsigned long error_code; + unsigned long trap_no; +#define MF_FIXADE 1 /* Fix address errors in software */ +#define MF_LOGADE 2 /* Log address errors to syslog */ + unsigned long mflags; + mm_segment_t current_ds; + unsigned long irix_trampoline; /* Wheee... */ + unsigned long irix_oldctx; + + /* + * These are really only needed if the full FPU emulator is configured. + * Would be made conditional on MIPS_FPU_EMULATOR if it weren't for the + * fact that having offset.h rebuilt differently for different config + * options would be asking for trouble. + * + * Saved EPC during delay-slot emulation (see math-emu/cp1emu.c) + */ + unsigned long dsemul_epc; + + /* + * Pointer to instruction used to induce address error + */ + unsigned long dsemul_aerpc; +}; + +#endif /* !defined (_LANGUAGE_ASSEMBLY) */ + +#define INIT_THREAD { \ + /* \ + * saved main processor registers \ + */ \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, \ + /* \ + * saved cp0 stuff \ + */ \ + 0, \ + /* \ + * saved fpu/fpu emulator stuff \ + */ \ + INIT_FPU, \ + /* \ + * Other stuff associated with the process \ + */ \ + 0, 0, 0, 0, \ + /* \ + * For now the default is to fix address errors \ + */ \ + MF_FIXADE, { 0 }, 0, 0, \ + /* \ + * dsemul_epc and dsemul_aerpc should never be used uninitialized, \ + * but... \ + */ \ + 0 ,0 \ +} + +#ifdef __KERNEL__ + +#define KERNEL_STACK_SIZE 8192 + +#if !defined (_LANGUAGE_ASSEMBLY) + +/* Free all resources held by a thread. */ +#define release_thread(thread) do { } while(0) + +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); + +/* Copy and release all segment info associated with a VM */ +#define copy_segments(p, mm) do { } while(0) +#define release_segments(mm) do { } while(0) + +/* + * Return saved PC of a blocked thread. + */ +extern inline unsigned long thread_saved_pc(struct thread_struct *t) +{ + extern void ret_from_fork(void); + + /* New born processes are a special case */ + if (t->reg31 == (unsigned long) ret_from_fork) + return t->reg31; + + return ((unsigned long *)t->reg29)[10]; +} + +/* + * Do necessary setup to start up a newly executed thread. + */ +#define start_thread(regs, new_pc, new_sp) do { \ + /* New thread looses kernel privileges. */ \ + regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KU_USER;\ + regs->cp0_epc = new_pc; \ + regs->regs[29] = new_sp; \ + current->thread.current_ds = USER_DS; \ +} while (0) + +unsigned long get_wchan(struct task_struct *p); + +#define __PT_REG(reg) ((long)&((struct pt_regs *)0)->reg - sizeof(struct pt_regs)) +#define __KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32) +#define KSTK_EIP(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(cp0_epc))) +#define KSTK_ESP(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(regs[29]))) + +/* Allocation and freeing of basic task resources. */ +/* + * NOTE! The task struct and the stack go together + */ +#define THREAD_SIZE (2*PAGE_SIZE) +#define alloc_task_struct() \ + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) +#define free_task_struct(p) free_pages((unsigned long)(p),1) +#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) + +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) + +#define cpu_relax() do { } while (0) + +#endif /* !defined (_LANGUAGE_ASSEMBLY) */ +#endif /* __KERNEL__ */ + +/* + * Return_address is a replacement for __builtin_return_address(count) + * which on certain architectures cannot reasonably be implemented in GCC + * (MIPS, Alpha) or is unuseable with -fomit-frame-pointer (i386). + * Note that __builtin_return_address(x>=1) is forbidden because GCC + * aborts compilation on some CPUs. It's simply not possible to unwind + * some CPU's stackframes. + * + * __builtin_return_address works only for non-leaf functions. We avoid the + * overhead of a function call by forcing the compiler to save the return + * address register on the stack. + */ +#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) + +#endif /* _ASM_PROCESSOR_H */ diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h new file mode 100644 index 0000000000..2517adb2a8 --- /dev/null +++ b/include/asm-mips/ptrace.h @@ -0,0 +1,86 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000 by Ralf Baechle + * + * Machine dependent structs and defines to help the user use + * the ptrace system call. + */ +#ifndef _ASM_PTRACE_H +#define _ASM_PTRACE_H + +#include <asm/isadep.h> +#include <linux/types.h> + +/* 0 - 31 are integer registers, 32 - 63 are fp registers. */ +#define FPR_BASE 32 +#define PC 64 +#define CAUSE 65 +#define BADVADDR 66 +#define MMHI 67 +#define MMLO 68 +#define FPC_CSR 69 +#define FPC_EIR 70 + +#ifndef _LANGUAGE_ASSEMBLY +/* + * This struct defines the way the registers are stored on the stack during a + * system call/exception. As usual the registers k0/k1 aren't being saved. + */ +struct pt_regs { + /* Pad bytes for argument save space on the stack. */ + unsigned long pad0[6]; + + /* Saved main processor registers. */ + unsigned long regs[32]; + + /* Other saved registers. */ + unsigned long lo; + unsigned long hi; + + /* + * saved cp0 registers + */ + unsigned long cp0_epc; + unsigned long cp0_badvaddr; + unsigned long cp0_status; + unsigned long cp0_cause; +}; + +#endif /* !(_LANGUAGE_ASSEMBLY) */ + +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +/* #define PTRACE_GETREGS 12 */ +/* #define PTRACE_SETREGS 13 */ +/* #define PTRACE_GETFPREGS 14 */ +/* #define PTRACE_SETFPREGS 15 */ +/* #define PTRACE_GETFPXREGS 18 */ +/* #define PTRACE_SETFPXREGS 19 */ + +#define PTRACE_SETOPTIONS 21 + +/* options set using PTRACE_SETOPTIONS */ +#define PTRACE_O_TRACESYSGOOD 0x00000001 + +#if 0 /* def _LANGUAGE_ASSEMBLY */ +#include <asm/offset.h> +#endif + +#ifdef __KERNEL__ + +#ifndef _LANGUAGE_ASSEMBLY +/* + * Does the process account for user or for system time? + */ +#define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER) + +#define instruction_pointer(regs) ((regs)->cp0_epc) + +extern void show_regs(struct pt_regs *); +#endif /* !(_LANGUAGE_ASSEMBLY) */ + +#endif + +#endif /* _ASM_PTRACE_H */ diff --git a/include/asm-mips/reg.h b/include/asm-mips/reg.h new file mode 100644 index 0000000000..35505b70f8 --- /dev/null +++ b/include/asm-mips/reg.h @@ -0,0 +1,66 @@ +/* + * Various register offset definitions for debuggers, core file + * examiners and whatnot. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 by Ralf Baechle + */ +#ifndef __ASM_MIPS_REG_H +#define __ASM_MIPS_REG_H + +/* + * This defines/structures correspond to the register layout on stack - + * if the order here is changed, it needs to be updated in + * include/asm-mips/stackframe.h + */ +#define EF_REG0 6 +#define EF_REG1 7 +#define EF_REG2 8 +#define EF_REG3 9 +#define EF_REG4 10 +#define EF_REG5 11 +#define EF_REG6 12 +#define EF_REG7 13 +#define EF_REG8 14 +#define EF_REG9 15 +#define EF_REG10 16 +#define EF_REG11 17 +#define EF_REG12 18 +#define EF_REG13 19 +#define EF_REG14 20 +#define EF_REG15 21 +#define EF_REG16 22 +#define EF_REG17 23 +#define EF_REG18 24 +#define EF_REG19 25 +#define EF_REG20 26 +#define EF_REG21 27 +#define EF_REG22 28 +#define EF_REG23 29 +#define EF_REG24 30 +#define EF_REG25 31 +/* + * k0/k1 unsaved + */ +#define EF_REG28 34 +#define EF_REG29 35 +#define EF_REG30 36 +#define EF_REG31 37 + +/* + * Saved special registers + */ +#define EF_LO 38 +#define EF_HI 39 + +#define EF_CP0_EPC 40 +#define EF_CP0_BADVADDR 41 +#define EF_CP0_STATUS 42 +#define EF_CP0_CAUSE 44 + +#define EF_SIZE 180 /* size in bytes */ + +#endif /* __ASM_MIPS_REG_H */ diff --git a/include/asm-mips/regdef.h b/include/asm-mips/regdef.h new file mode 100644 index 0000000000..691d047b67 --- /dev/null +++ b/include/asm-mips/regdef.h @@ -0,0 +1,52 @@ +/* + * include/asm-mips/regdefs.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995 by Ralf Baechle + */ + +#ifndef __ASM_MIPS_REGDEF_H +#define __ASM_MIPS_REGDEF_H + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + +#endif /* __ASM_MIPS_REGDEF_H */ diff --git a/include/asm-mips/sgidefs.h b/include/asm-mips/sgidefs.h new file mode 100644 index 0000000000..67f2658958 --- /dev/null +++ b/include/asm-mips/sgidefs.h @@ -0,0 +1,44 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1999, 2001 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef __ASM_SGIDEFS_H +#define __ASM_SGIDEFS_H + +/* + * Using a Linux compiler for building Linux seems logic but not to + * everybody. + */ +#if 0 /* ndef __linux__ */ +#error Use a Linux compiler or give up. +#endif + +/* + * Definitions for the ISA levels + * + * With the introduction of MIPS32 / MIPS64 instruction sets definitions + * MIPS ISAs are no longer subsets of each other. Therefore comparisons + * on these symbols except with == may result in unexpected results and + * are forbidden! + */ +#define _MIPS_ISA_MIPS1 1 +#define _MIPS_ISA_MIPS2 2 +#define _MIPS_ISA_MIPS3 3 +#define _MIPS_ISA_MIPS4 4 +#define _MIPS_ISA_MIPS5 5 +#define _MIPS_ISA_MIPS32 6 +#define _MIPS_ISA_MIPS64 7 + +/* + * Subprogram calling convention + */ +#define _MIPS_SIM_ABI32 1 +#define _MIPS_SIM_NABI32 2 +#define _MIPS_SIM_ABI64 3 + +#endif /* __ASM_SGIDEFS_H */ diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h new file mode 100644 index 0000000000..343b45eba3 --- /dev/null +++ b/include/asm-mips/string.h @@ -0,0 +1,157 @@ +/* $Id: string.h,v 1.13 2000/02/19 14:12:14 harald Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1994, 1995, 1996, 1997, 1998 by Ralf Baechle + */ +#ifndef __ASM_MIPS_STRING_H +#define __ASM_MIPS_STRING_H + +#include <linux/config.h> + +#define __HAVE_ARCH_STRCPY +extern __inline__ char *strcpy(char *__dest, __const__ char *__src) +{ + char *__xdest = __dest; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n" + "1:\tlbu\t$1,(%1)\n\t" + "addiu\t%1,1\n\t" + "sb\t$1,(%0)\n\t" + "bnez\t$1,1b\n\t" + "addiu\t%0,1\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (__dest), "=r" (__src) + : "0" (__dest), "1" (__src) + : "$1","memory"); + + return __xdest; +} + +#define __HAVE_ARCH_STRNCPY +extern __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n) +{ + char *__xdest = __dest; + + if (__n == 0) + return __xdest; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n" + "1:\tlbu\t$1,(%1)\n\t" + "subu\t%2,1\n\t" + "sb\t$1,(%0)\n\t" + "beqz\t$1,2f\n\t" + "addiu\t%0,1\n\t" + "bnez\t%2,1b\n\t" + "addiu\t%1,1\n" + "2:\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (__dest), "=r" (__src), "=r" (__n) + : "0" (__dest), "1" (__src), "2" (__n) + : "$1","memory"); + + return __dest; +} + +#define __HAVE_ARCH_STRCMP +extern __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct) +{ + int __res; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "lbu\t%2,(%0)\n" + "1:\tlbu\t$1,(%1)\n\t" + "addiu\t%0,1\n\t" + "bne\t$1,%2,2f\n\t" + "addiu\t%1,1\n\t" + "bnez\t%2,1b\n\t" + "lbu\t%2,(%0)\n\t" +#if defined(CONFIG_CPU_R3000) + "nop\n\t" +#endif + "move\t%2,$1\n" + "2:\tsubu\t%2,$1\n" + "3:\t.set\tat\n\t" + ".set\treorder" + : "=r" (__cs), "=r" (__ct), "=r" (__res) + : "0" (__cs), "1" (__ct) + : "$1"); + + return __res; +} + +#define __HAVE_ARCH_STRNCMP +extern __inline__ int +strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count) +{ + int __res; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n" + "1:\tlbu\t%3,(%0)\n\t" + "beqz\t%2,2f\n\t" + "lbu\t$1,(%1)\n\t" + "subu\t%2,1\n\t" + "bne\t$1,%3,3f\n\t" + "addiu\t%0,1\n\t" + "bnez\t%3,1b\n\t" + "addiu\t%1,1\n" + "2:\n\t" +#if defined(CONFIG_CPU_R3000) + "nop\n\t" +#endif + "move\t%3,$1\n" + "3:\tsubu\t%3,$1\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (__cs), "=r" (__ct), "=r" (__count), "=r" (__res) + : "0" (__cs), "1" (__ct), "2" (__count) + : "$1"); + + return __res; +} + +#undef __HAVE_ARCH_MEMSET +extern void *memset(void *__s, int __c, size_t __count); + +#undef __HAVE_ARCH_MEMCPY +extern void *memcpy(void *__to, __const__ void *__from, size_t __n); + +#undef __HAVE_ARCH_MEMMOVE +extern void *memmove(void *__dest, __const__ void *__src, size_t __n); + +/* Don't build bcopy at all ... */ +#define __HAVE_ARCH_BCOPY + +#define __HAVE_ARCH_MEMSCAN +extern __inline__ void *memscan(void *__addr, int __c, size_t __size) +{ + char *__end = (char *)__addr + __size; + + __asm__(".set\tpush\n\t" + ".set\tnoat\n\t" + ".set\treorder\n\t" + "1:\tbeq\t%0,%1,2f\n\t" + "addiu\t%0,1\n\t" + "lb\t$1,-1(%0)\n\t" + "bne\t$1,%4,1b\n" + "2:\t.set\tpop" + : "=r" (__addr), "=r" (__end) + : "0" (__addr), "1" (__end), "r" (__c) + : "$1"); + + return __addr; +} + +#endif /* __ASM_MIPS_STRING_H */ diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h new file mode 100644 index 0000000000..4b45847e96 --- /dev/null +++ b/include/asm-mips/system.h @@ -0,0 +1,268 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999 by Ralf Baechle + * Copyright (C) 1996 by Paul M. Antoine + * Copyright (C) 1994 - 1999 by Ralf Baechle + * + * Changed set_except_vector declaration to allow return of previous + * vector address value - necessary for "borrowing" vectors. + * + * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. + */ +#ifndef _ASM_SYSTEM_H +#define _ASM_SYSTEM_H + +#include <linux/config.h> +#include <asm/sgidefs.h> +#include <asm/ptrace.h> +#if 0 +#include <linux/kernel.h> +#endif + +extern __inline__ void +__sti(void) +{ + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\treorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "ori\t$1,0x1f\n\t" + "xori\t$1,0x1e\n\t" + "mtc0\t$1,$12\n\t" + ".set\tpop\n\t" + : /* no outputs */ + : /* no inputs */ + : "$1", "memory"); +} + +/* + * For cli() we have to insert nops to make shure that the new value + * has actually arrived in the status register before the end of this + * macro. + * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs + * no nops at all. + */ +extern __inline__ void +__cli(void) +{ + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\treorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "ori\t$1,1\n\t" + "xori\t$1,1\n\t" + ".set\tnoreorder\n\t" + "mtc0\t$1,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\tpop\n\t" + : /* no outputs */ + : /* no inputs */ + : "$1", "memory"); +} + +#define __save_flags(x) \ +__asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "mfc0\t%0,$12\n\t" \ + ".set\tpop\n\t" \ + : "=r" (x)) + +#define __save_and_cli(x) \ +__asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + ".set\tnoat\n\t" \ + "mfc0\t%0,$12\n\t" \ + "ori\t$1,%0,1\n\t" \ + "xori\t$1,1\n\t" \ + ".set\tnoreorder\n\t" \ + "mtc0\t$1,$12\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + ".set\tpop\n\t" \ + : "=r" (x) \ + : /* no inputs */ \ + : "$1", "memory") + +#define __restore_flags(flags) \ +do { \ + unsigned long __tmp1; \ + \ + __asm__ __volatile__( \ + ".set\tnoreorder\t\t\t# __restore_flags\n\t" \ + ".set\tnoat\n\t" \ + "mfc0\t$1, $12\n\t" \ + "andi\t%0, 1\n\t" \ + "ori\t$1, 1\n\t" \ + "xori\t$1, 1\n\t" \ + "or\t%0, $1\n\t" \ + "mtc0\t%0, $12\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + : "=r" (__tmp1) \ + : "0" (flags) \ + : "$1", "memory"); \ +} while(0) + +#ifdef CONFIG_SMP + +extern void __global_sti(void); +extern void __global_cli(void); +extern unsigned long __global_save_flags(void); +extern void __global_restore_flags(unsigned long); +# define sti() __global_sti() +# define cli() __global_cli() +# define save_flags(x) do { x = __global_save_flags(); } while (0) +# define restore_flags(x) __global_restore_flags(x) +# define save_and_cli(x) do { save_flags(x); cli(); } while(0) + +#else /* Single processor */ + +# define sti() __sti() +# define cli() __cli() +# define save_flags(x) __save_flags(x) +# define save_and_cli(x) __save_and_cli(x) +# define restore_flags(x) __restore_flags(x) + +#endif /* SMP */ + +/* For spinlocks etc */ +#define local_irq_save(x) __save_and_cli(x); +#define local_irq_restore(x) __restore_flags(x); +#define local_irq_disable() __cli(); +#define local_irq_enable() __sti(); + +/* + * These are probably defined overly paranoid ... + */ +#ifdef CONFIG_CPU_HAS_WB + +#include <asm/wbflush.h> +#define rmb() do { } while(0) +#define wmb() wbflush() +#define mb() wbflush() + +#else /* CONFIG_CPU_HAS_WB */ + +#define mb() \ +__asm__ __volatile__( \ + "# prevent instructions being moved around\n\t" \ + ".set\tnoreorder\n\t" \ + "# 8 nops to fool the R4400 pipeline\n\t" \ + "nop;nop;nop;nop;nop;nop;nop;nop\n\t" \ + ".set\treorder" \ + : /* no output */ \ + : /* no input */ \ + : "memory") +#define rmb() mb() +#define wmb() mb() + +#endif /* CONFIG_CPU_HAS_WB */ + +#ifdef CONFIG_SMP +#define smp_mb() mb() +#define smp_rmb() rmb() +#define smp_wmb() wmb() +#else +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() +#endif + +#define set_mb(var, value) \ +do { var = value; mb(); } while (0) + +#define set_wmb(var, value) \ +do { var = value; wmb(); } while (0) + +#if !defined (_LANGUAGE_ASSEMBLY) +/* + * switch_to(n) should switch tasks to task nr n, first + * checking that n isn't the current task, in which case it does nothing. + */ +#if 0 +extern asmlinkage void *resume(void *last, void *next); +#endif +#endif /* !defined (_LANGUAGE_ASSEMBLY) */ + +#define prepare_to_switch() do { } while(0) +#define switch_to(prev,next,last) \ +do { \ + (last) = resume(prev, next); \ +} while(0) + +/* + * For 32 and 64 bit operands we can take advantage of ll and sc. + * FIXME: This doesn't work for R3000 machines. + */ +extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val) +{ +#ifdef CONFIG_CPU_HAS_LLSC + unsigned long dummy; + + __asm__ __volatile__( + ".set\tnoreorder\t\t\t# xchg_u32\n\t" + ".set\tnoat\n\t" + "ll\t%0, %3\n" + "1:\tmove\t$1, %2\n\t" + "sc\t$1, %1\n\t" + "beqzl\t$1, 1b\n\t" + " ll\t%0, %3\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (val), "=o" (*m), "=r" (dummy) + : "o" (*m), "2" (val) + : "memory"); + + return val; +#else + unsigned long flags, retval; + + save_flags(flags); + cli(); + retval = *m; + *m = val; + restore_flags(flags); + return retval; +#endif /* Processor-dependent optimization */ +} + +#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) +#define tas(ptr) (xchg((ptr),1)) + +static __inline__ unsigned long +__xchg(unsigned long x, volatile void * ptr, int size) +{ + switch (size) { + case 4: + return xchg_u32(ptr, x); + } + return x; +} + +extern void *set_except_vector(int n, void *addr); + +extern void __die(const char *, struct pt_regs *, const char *where, + unsigned long line) __attribute__((noreturn)); +extern void __die_if_kernel(const char *, struct pt_regs *, const char *where, + unsigned long line); + +#define die(msg, regs) \ + __die(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) +#define die_if_kernel(msg, regs) \ + __die_if_kernel(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) + +#endif /* _ASM_SYSTEM_H */ diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h new file mode 100644 index 0000000000..638f75163c --- /dev/null +++ b/include/asm-mips/types.h @@ -0,0 +1,77 @@ +/* $Id: types.h,v 1.3 1999/08/18 23:37:50 ralf Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_TYPES_H +#define _ASM_TYPES_H + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if (_MIPS_SZLONG == 64) + +typedef __signed__ long __s64; +typedef unsigned long __u64; + +#else + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +typedef __signed char s8; +typedef unsigned char u8; + +typedef __signed short s16; +typedef unsigned short u16; + +typedef __signed int s32; +typedef unsigned int u32; + +#if (_MIPS_SZLONG == 64) + +typedef __signed__ long s64; +typedef unsigned long u64; + +#else + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long s64; +typedef unsigned long long u64; +#endif + +#endif + +#define BITS_PER_LONG _MIPS_SZLONG + +typedef unsigned long dma_addr_t; + +#endif /* __KERNEL__ */ + +#endif /* _ASM_TYPES_H */ diff --git a/include/asm-mips/u-boot.h b/include/asm-mips/u-boot.h new file mode 100644 index 0000000000..ff189d9367 --- /dev/null +++ b/include/asm-mips/u-boot.h @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _U_BOOT_H_ +#define _U_BOOT_H_ 1 + +typedef struct bd_info { + int bi_baudrate; /* serial console baudrate */ + unsigned long bi_ip_addr; /* IP Address */ + unsigned char bi_enetaddr[6]; /* Ethernet adress */ + struct environment_s *bi_env; + ulong bi_arch_number; /* unique id for this board */ + ulong bi_boot_params; /* where this board expects params */ + struct /* RAM configuration */ + { + ulong start; + ulong size; + } bi_dram[CONFIG_NR_DRAM_BANKS]; +} bd_t; + +#define bi_env_data bi_env->data +#define bi_env_crc bi_env->crc + +#endif /* _U_BOOT_H_ */ diff --git a/include/common.h b/include/common.h index 9f22b2f8d4..bce0132afc 100644 --- a/include/common.h +++ b/include/common.h @@ -149,7 +149,7 @@ void setenv (char *, char *); # include <asm/u-boot-arm.h> /* ARM version to be fixed! */ #endif /* CONFIG_ARM */ #ifdef CONFIG_I386 /* x86 version to be fixed! */ -# include <asm/ppcboot-i386.h> +# include <asm/ppcboot-i386.h> #endif /* CONFIG_I386 */ void pci_init (void); diff --git a/include/configs/smdk2400.h b/include/configs/smdk2400.h index c60e74607c..d0ad65ef2c 100644 --- a/include/configs/smdk2400.h +++ b/include/configs/smdk2400.h @@ -162,10 +162,7 @@ #define PHYS_SDRAM_1 0x0c000000 /* SDRAM Bank #1 */ #define PHYS_SDRAM_1_SIZE 0x02000000 /* 32 MB */ -#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ -#define PHYS_FLASH_SIZE 0x00800000 /* 8 MB */ - -#define CFG_FLASH_BASE PHYS_FLASH_1 +#define CFG_FLASH_BASE 0x00000000 /* Flash Bank #1 */ /*----------------------------------------------------------------------- * FLASH and environment organization @@ -180,7 +177,7 @@ #define CFG_ENV_IS_IN_FLASH 1 /* Address and size of Primary Environment Sector */ -#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x40000) +#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x40000) #define CFG_ENV_SIZE 0x40000 /* Address and size of Redundant Environment Sector */ diff --git a/include/configs/trab.h b/include/configs/trab.h index c6144119e6..086294e488 100644 --- a/include/configs/trab.h +++ b/include/configs/trab.h @@ -121,9 +121,8 @@ #define CONFIG_BOOTDELAY 5 #define CONFIG_PREBOOT "echo;echo *** booting ***;echo" #define CONFIG_BOOTARGS "console=ttyS0" -#define CONFIG_ETHADDR 00:D0:93:00:61:11 -#define CONFIG_NETMASK 255.255.255.0 -#define CONFIG_IPADDR 192.168.3.27 +#define CONFIG_NETMASK 255.255.0.0 +#define CONFIG_IPADDR 192.168.3.68 #define CONFIG_SERVERIP 192.168.3.1 #define CONFIG_BOOTCOMMAND "run flash_nfs" #define CONFIG_EXTRA_ENV_SETTINGS \ @@ -211,20 +210,17 @@ #define PHYS_SDRAM_1 0x0c000000 /* SDRAM Bank #1 */ #define PHYS_SDRAM_1_SIZE 0x01000000 /* 16 MB */ -#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ -#define PHYS_FLASH_SIZE 0x00800000 /* 8 MB */ +#define CFG_FLASH_BASE 0x00000000 /* Flash Bank #1 */ /* The following #defines are needed to get flash environment right */ -#define CFG_MONITOR_BASE PHYS_FLASH_1 +#define CFG_MONITOR_BASE CFG_FLASH_BASE #define CFG_MONITOR_LEN (256 << 10) -#define CFG_FLASH_BASE PHYS_FLASH_1 - /*----------------------------------------------------------------------- * FLASH and environment organization */ #define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ -#define CFG_MAX_FLASH_SECT (71) /* max number of sectors on one chip */ +#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */ /* timeout values are in ticks */ #define CFG_FLASH_ERASE_TOUT (2*CFG_HZ) /* Timeout for Flash Erase */ @@ -233,7 +229,7 @@ #define CFG_ENV_IS_IN_FLASH 1 /* Address and size of Primary Environment Sector */ -#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x4000) +#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x4000) #define CFG_ENV_SIZE 0x4000 /* Address and size of Redundant Environment Sector */ diff --git a/include/version.h b/include/version.h index 5249f2a598..042befe04a 100644 --- a/include/version.h +++ b/include/version.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2002 + * (C) Copyright 2000-2003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -24,6 +24,6 @@ #ifndef __VERSION_H__ #define __VERSION_H__ -#define U_BOOT_VERSION "U-Boot 0.2.2" +#define U_BOOT_VERSION "U-Boot 0.2.3" #endif /* __VERSION_H__ */ diff --git a/lib_arm/board.c b/lib_arm/board.c index b6b5cdb762..31cdd9ccde 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -46,9 +46,7 @@ static ulong mem_malloc_start = 0; static ulong mem_malloc_end = 0; static ulong mem_malloc_brk = 0; -#if !defined(CONFIG_MODEM_SUPPORT) static -#endif void mem_malloc_init (ulong dest_addr) { mem_malloc_start = dest_addr; @@ -187,7 +185,7 @@ void start_armboot (void) gd_t gd_data; bd_t bd_data; init_fnc_t **init_fnc_ptr; -#if defined(CONFIG_VFD) && !defined(CONFIG_MODEM_SUPPORT) +#if defined(CONFIG_VFD) unsigned long addr; #endif @@ -208,10 +206,9 @@ void start_armboot (void) display_flash_config (size); #ifdef CONFIG_VFD -#ifndef CONFIG_MODEM_SUPPORT -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif +# ifndef PAGE_SIZE +# define PAGE_SIZE 4096 +# endif /* * reserve memory for VFD display (always full pages) */ @@ -223,20 +220,18 @@ void start_armboot (void) addr += size; addr = (addr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); mem_malloc_init (addr); -#endif /* CONFIG_MODEM_SUPPORT */ #else /* armboot_real_end is defined in the board-specific linker script */ mem_malloc_init (_armboot_real_end); #endif /* CONFIG_VFD */ + /* initialize environment */ + env_relocate (); + #ifdef CONFIG_VFD -#ifndef CONFIG_MODEM_SUPPORT /* must do this after the framebuffer is allocated */ drv_vfd_init(); -#endif /* CONFIG_MODEM_SUPPORT */ #endif - /* initialize environment */ - env_relocate (); /* IP Address */ bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr"); @@ -267,15 +262,15 @@ void start_armboot (void) enable_interrupts (); #ifdef CONFIG_DRIVER_CS8900 - if (!getenv ("ethaddr")) { - cs8900_get_enetaddr (gd->bd->bi_enetaddr); - } + cs8900_get_enetaddr (gd->bd->bi_enetaddr); #endif #ifdef BOARD_POST_INIT board_post_init (); #endif +printf ("### vfd_type=0x%02X vfd_data_lines_inv=%d\n",gd->vfd_type,gd->vfd_inv_data); + /* main_loop() can return to retry autoboot, if so just run it again. */ for (;;) { main_loop (); diff --git a/mips_config.mk b/mips_config.mk new file mode 100644 index 0000000000..d8aa5fa777 --- /dev/null +++ b/mips_config.mk @@ -0,0 +1,24 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_CPPFLAGS += -DCONFIG_MIPS -D__MIPS__ @@ -39,6 +39,7 @@ extern int eth_3com_initialize(bd_t*); extern int pcnet_initialize(bd_t*); extern int fec_initialize(bd_t*); extern int scc_initialize(bd_t*); +extern int inca_switch_initialize(bd_t*); static struct eth_device *eth_devices, *eth_current; @@ -95,6 +96,9 @@ int eth_initialize(bd_t *bis) eth_devices = NULL; eth_current = NULL; +#ifdef CONFIG_INCA_IP_SWITCH + inca_switch_initialize(bis); +#endif #ifdef CONFIG_EEPRO100 eepro100_initialize(bis); #endif @@ -153,7 +157,7 @@ int eth_initialize(bd_t *bis) if (memcmp(dev->enetaddr, "\0\0\0\0\0\0", 6) && memcmp(dev->enetaddr, env_enetaddr, 6)) { - printf("\nWarning: %s HW address don't match:\n", dev->name); + printf("\nWarning: %s MAC addresses don't match:\n", dev->name); printf("Address in SROM is " "%02X:%02X:%02X:%02X:%02X:%02X\n", dev->enetaddr[0], dev->enetaddr[1], diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index de10b02ea4..b60395ecba 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -390,8 +390,8 @@ static int flash_io (int mode) char *data; if ((fd = open(DEVNAME(curdev), mode)) < 0) { - fprintf (stderr, - "Can't open %s: %s\n", + fprintf (stderr, + "Can't open %s: %s\n", DEVNAME(curdev), strerror(errno)); return (-1); } @@ -406,8 +406,8 @@ static int flash_io (int mode) /* switch to next partition for writing */ otherdev = !curdev; if ((fdr = open(DEVNAME(otherdev), mode)) < 0) { - fprintf (stderr, - "Can't open %s: %s\n", + fprintf (stderr, + "Can't open %s: %s\n", DEVNAME(otherdev), strerror(errno)); return (-1); } @@ -431,20 +431,20 @@ static int flash_io (int mode) resid = DEVESIZE(otherdev) - CFG_ENV_SIZE; if (resid) { if ((data = malloc(resid)) == NULL) { - fprintf(stderr, + fprintf(stderr, "Cannot malloc %d bytes: %s\n", resid, strerror(errno)); return (-1); } if (lseek (fdr, DEVOFFSET(otherdev) + CFG_ENV_SIZE, SEEK_SET) == -1) { fprintf (stderr, - "seek error on %s: %s\n", + "seek error on %s: %s\n", DEVNAME(otherdev), strerror(errno)); return (-1); } if ((rc = read (fdr, data, resid)) != resid) { fprintf (stderr, - "read error on %s: %s\n", + "read error on %s: %s\n", DEVNAME(otherdev), strerror(errno)); return (-1); } @@ -465,26 +465,26 @@ static int flash_io (int mode) printf("Writing environment to %s...\n",DEVNAME(otherdev)); if (lseek (fdr, DEVOFFSET(otherdev), SEEK_SET) == -1) { fprintf (stderr, - "seek error on %s: %s\n", + "seek error on %s: %s\n", DEVNAME(otherdev), strerror(errno)); return (-1); } if (write(fdr, &environment, len) != len) { fprintf (stderr, - "CRC write error on %s: %s\n", + "CRC write error on %s: %s\n", DEVNAME(otherdev), strerror(errno)); return (-1); } if (write(fdr, environment.data, ENV_SIZE) != ENV_SIZE) { fprintf (stderr, - "Write error on %s: %s\n", + "Write error on %s: %s\n", DEVNAME(otherdev), strerror(errno)); return (-1); } if (resid) { if (write (fdr, data, resid) != resid) { fprintf (stderr, - "write error on %s: %s\n", + "write error on %s: %s\n", DEVNAME(curdev), strerror(errno)); return (-1); } @@ -494,14 +494,14 @@ static int flash_io (int mode) /* change flag on current active env partition */ if (lseek (fd, DEVOFFSET(curdev) + sizeof(ulong), SEEK_SET) == -1) { fprintf (stderr, - "seek error on %s: %s\n", + "seek error on %s: %s\n", DEVNAME(curdev), strerror(errno)); return (-1); } - if (write (fd, &obsolete_flag, sizeof(obsolete_flag)) != + if (write (fd, &obsolete_flag, sizeof(obsolete_flag)) != sizeof(obsolete_flag)) { fprintf (stderr, - "Write error on %s: %s\n", + "Write error on %s: %s\n", DEVNAME(curdev), strerror(errno)); return (-1); } @@ -517,7 +517,7 @@ static int flash_io (int mode) ioctl (fd, MEMLOCK, &erase); if (close(fdr)) { fprintf (stderr, - "I/O error on %s: %s\n", + "I/O error on %s: %s\n", DEVNAME(otherdev), strerror(errno)); return (-1); } @@ -527,19 +527,19 @@ static int flash_io (int mode) if (lseek (fd, DEVOFFSET(curdev), SEEK_SET) == -1) { fprintf (stderr, - "seek error on %s: %s\n", + "seek error on %s: %s\n", DEVNAME(curdev), strerror(errno)); return (-1); } if (read (fd, &environment, len) != len) { fprintf (stderr, - "CRC read error on %s: %s\n", + "CRC read error on %s: %s\n", DEVNAME(curdev), strerror(errno)); return (-1); } if ((rc = read (fd, environment.data, ENV_SIZE)) != ENV_SIZE) { fprintf (stderr, - "Read error on %s: %s\n", + "Read error on %s: %s\n", DEVNAME(curdev), strerror(errno)); return (-1); } @@ -547,7 +547,7 @@ static int flash_io (int mode) if (close(fd)) { fprintf (stderr, - "I/O error on %s: %s\n", + "I/O error on %s: %s\n", DEVNAME(curdev), strerror(errno)); return (-1); } @@ -587,50 +587,50 @@ static int env_init(void) if (parse_config()) /* should fill envdevices */ return 1; - + if ((addr1 = calloc (1, ENV_SIZE)) == NULL) { - fprintf (stderr, + fprintf (stderr, "Not enough memory for environment (%ld bytes)\n", ENV_SIZE); return (errno); } - + /* read environment from FLASH to local buffer */ environment.data = addr1; curdev = 0; if (flash_io (O_RDONLY)) { return (errno); } - - crc1_ok = ((crc1 = crc32(0, environment.data, ENV_SIZE)) + + crc1_ok = ((crc1 = crc32(0, environment.data, ENV_SIZE)) == environment.crc); if (!HaveRedundEnv) { if (!crc1_ok) { - fprintf (stderr, + fprintf (stderr, "Warning: Bad CRC, using default environment\n"); environment.data = default_environment; free(addr1); } } else { flag1 = environment.flags; - + curdev = 1; if ((addr2 = calloc (1, ENV_SIZE)) == NULL) { - fprintf (stderr, + fprintf (stderr, "Not enough memory for environment (%ld bytes)\n", ENV_SIZE); return (errno); - } + } environment.data = addr2; - + if (flash_io (O_RDONLY)) { return (errno); } - - crc2_ok = ((crc2 = crc32(0, environment.data, ENV_SIZE)) + + crc2_ok = ((crc2 = crc32(0, environment.data, ENV_SIZE)) == environment.crc); flag2 = environment.flags; - + if (crc1_ok && ! crc2_ok) { environment.data = addr1; environment.flags = flag1; @@ -646,7 +646,7 @@ static int env_init(void) free(addr1); } else if (! crc1_ok && ! crc2_ok) { - fprintf (stderr, + fprintf (stderr, "Warning: Bad CRC, using default environment\n"); environment.data = default_environment; curdev = 0; @@ -720,15 +720,15 @@ static int parse_config() #endif #endif if (stat (DEVNAME(0), &st)) { - fprintf (stderr, - "Cannot access MTD device %s: %s\n", + fprintf (stderr, + "Cannot access MTD device %s: %s\n", DEVNAME(0), strerror(errno)); return 1; } - + if (HaveRedundEnv && stat (DEVNAME(1), &st)) { - fprintf (stderr, - "Cannot access MTD device %s: %s\n", + fprintf (stderr, + "Cannot access MTD device %s: %s\n", DEVNAME(2), strerror(errno)); return 1; } @@ -747,12 +747,12 @@ static int get_config (char *fname) return 1; } - while ((i < 2) && + while ((i < 2) && ((rc = fscanf (fp, "%s %lx %lx %lx", DEVNAME(i), &DEVOFFSET(i), &ENVSIZE(i), &DEVESIZE(i))) != EOF)) { /* Skip incomplete conversions and comment strings */ - if ((rc < 3) || (*DEVNAME(i) == '#')) { + if ((rc < 3) || (*DEVNAME(i) == '#')) { fgets (dump, sizeof(dump), fp); /* Consume till end */ continue; } @@ -760,7 +760,7 @@ static int get_config (char *fname) i++; } fclose(fp); - + HaveRedundEnv = i - 1; if (!i) { /* No valid entries found */ errno = EINVAL; |