diff options
Diffstat (limited to 'arch/ppc/syslib')
79 files changed, 23351 insertions, 0 deletions
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile new file mode 100644 index 00000000000..dd418ea3426 --- /dev/null +++ b/arch/ppc/syslib/Makefile @@ -0,0 +1,115 @@ +# +# Makefile for the linux kernel. +# + +CFLAGS_prom_init.o += -fPIC +CFLAGS_btext.o += -fPIC + +wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o + +obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o +obj-$(CONFIG_PPC_OCP) += ocp.o +obj-$(CONFIG_IBM_OCP) += ibm_ocp.o +obj-$(CONFIG_44x) += ibm44x_common.o +obj-$(CONFIG_440GP) += ibm440gp_common.o +obj-$(CONFIG_440GX) += ibm440gx_common.o +obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o +ifeq ($(CONFIG_4xx),y) +ifeq ($(CONFIG_VIRTEX_II_PRO),y) +obj-$(CONFIG_40x) += xilinx_pic.o +else +ifeq ($(CONFIG_403),y) +obj-$(CONFIG_40x) += ppc403_pic.o +else +obj-$(CONFIG_40x) += ppc4xx_pic.o +endif +endif +obj-$(CONFIG_44x) += ppc4xx_pic.o +obj-$(CONFIG_40x) += ppc4xx_setup.o +obj-$(CONFIG_GEN_RTC) += todc_time.o +obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o +obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o +ifeq ($(CONFIG_40x),y) +obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o +endif +endif +obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) +ifeq ($(CONFIG_8xx),y) +obj-$(CONFIG_PCI) += qspan_pci.o i8259.o +endif +obj-$(CONFIG_PPC_OF) += prom_init.o prom.o of_device.o +obj-$(CONFIG_PPC_PMAC) += open_pic.o indirect_pci.o +obj-$(CONFIG_POWER4) += open_pic2.o +obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o +obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o todc_time.o +obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \ + todc_time.o +obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o +obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o +obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o +obj-$(CONFIG_CHESTNUT) += mv64360_pic.o pci_auto.o +obj-$(CONFIG_GEMINI) += open_pic.o indirect_pci.o +obj-$(CONFIG_GT64260) += gt64260_pic.o +obj-$(CONFIG_K2) += i8259.o indirect_pci.o todc_time.o \ + pci_auto.o +obj-$(CONFIG_LOPEC) += i8259.o pci_auto.o todc_time.o +obj-$(CONFIG_HDPU) += pci_auto.o +obj-$(CONFIG_LUAN) += indirect_pci.o pci_auto.o todc_time.o +obj-$(CONFIG_KATANA) += pci_auto.o +obj-$(CONFIG_MCPN765) += todc_time.o indirect_pci.o pci_auto.o \ + open_pic.o i8259.o hawk_common.o +obj-$(CONFIG_MENF1) += todc_time.o i8259.o mpc10x_common.o \ + pci_auto.o indirect_pci.o +obj-$(CONFIG_MV64360) += mv64360_pic.o +obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o indirect_pci.o +obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \ + pci_auto.o hawk_common.o +obj-$(CONFIG_MVME5100_IPMC761_PRESENT) += i8259.o +obj-$(CONFIG_OCOTEA) += indirect_pci.o pci_auto.o todc_time.o +obj-$(CONFIG_PAL4) += cpc700_pic.o +obj-$(CONFIG_PCORE) += todc_time.o i8259.o pci_auto.o +obj-$(CONFIG_POWERPMC250) += pci_auto.o +obj-$(CONFIG_PPLUS) += hawk_common.o open_pic.o i8259.o \ + indirect_pci.o todc_time.o pci_auto.o +obj-$(CONFIG_PRPMC750) += open_pic.o indirect_pci.o pci_auto.o \ + hawk_common.o +obj-$(CONFIG_HARRIER) += harrier.o +obj-$(CONFIG_PRPMC800) += open_pic.o indirect_pci.o pci_auto.o +obj-$(CONFIG_RADSTONE_PPC7D) += i8259.o pci_auto.o +obj-$(CONFIG_SANDPOINT) += i8259.o pci_auto.o todc_time.o +obj-$(CONFIG_SBC82xx) += todc_time.o +obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \ + todc_time.o +obj-$(CONFIG_8260) += m8260_setup.o +obj-$(CONFIG_PCI_8260) += m8260_pci.o indirect_pci.o +obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o +obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o +ifeq ($(CONFIG_PPC_GEN550),y) +obj-$(CONFIG_KGDB) += gen550_kgdb.o gen550_dbg.o +obj-$(CONFIG_SERIAL_TEXT_DEBUG) += gen550_dbg.o +endif +ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y) +obj-$(CONFIG_SERIAL_TEXT_DEBUG) += mv64x60_dbg.o +endif +obj-$(CONFIG_BOOTX_TEXT) += btext.o +obj-$(CONFIG_MPC10X_BRIDGE) += mpc10x_common.o indirect_pci.o +obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o +obj-$(CONFIG_40x) += dcr.o +obj-$(CONFIG_BOOKE) += dcr.o +obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \ + ppc_sys.o mpc85xx_sys.o \ + mpc85xx_devices.o +ifeq ($(CONFIG_85xx),y) +obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o +endif +obj-$(CONFIG_83xx) += ipic.o ppc83xx_setup.o ppc_sys.o \ + mpc83xx_sys.o mpc83xx_devices.o +ifeq ($(CONFIG_83xx),y) +obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o +endif +obj-$(CONFIG_MPC8555_CDS) += todc_time.o +obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o \ + mpc52xx_sys.o mpc52xx_devices.o ppc_sys.o +ifeq ($(CONFIG_PPC_MPC52xx),y) +obj-$(CONFIG_PCI) += mpc52xx_pci.o +endif diff --git a/arch/ppc/syslib/btext.c b/arch/ppc/syslib/btext.c new file mode 100644 index 00000000000..7734f683617 --- /dev/null +++ b/arch/ppc/syslib/btext.c @@ -0,0 +1,861 @@ +/* + * Procedures for drawing on the screen early on in the boot process. + * + * Benjamin Herrenschmidt <benh@kernel.crashing.org> + */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/version.h> + +#include <asm/sections.h> +#include <asm/bootx.h> +#include <asm/btext.h> +#include <asm/prom.h> +#include <asm/page.h> +#include <asm/mmu.h> +#include <asm/pgtable.h> +#include <asm/io.h> +#include <asm/reg.h> + +#define NO_SCROLL + +#ifndef NO_SCROLL +static void scrollscreen(void); +#endif + +static void draw_byte(unsigned char c, long locX, long locY); +static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb); +static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb); +static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb); + +static int g_loc_X; +static int g_loc_Y; +static int g_max_loc_X; +static int g_max_loc_Y; + +unsigned long disp_BAT[2] __initdata = {0, 0}; + +#define cmapsz (16*256) + +static unsigned char vga_font[cmapsz]; + +int boot_text_mapped; +int force_printk_to_btext = 0; + +boot_infos_t disp_bi; + +extern char *klimit; + +/* + * Powermac can use btext_* after boot for xmon, + * chrp only uses it during early boot. + */ +#ifdef CONFIG_XMON +#define BTEXT __pmac +#define BTDATA __pmacdata +#else +#define BTEXT __init +#define BTDATA __initdata +#endif /* CONFIG_XMON */ + +/* + * This is called only when we are booted via BootX. + */ +void __init +btext_init(boot_infos_t *bi) +{ + g_loc_X = 0; + g_loc_Y = 0; + g_max_loc_X = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8; + g_max_loc_Y = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16; + disp_bi = *bi; + boot_text_mapped = 1; +} + +void __init +btext_welcome(void) +{ + unsigned long flags; + unsigned long pvr; + boot_infos_t* bi = &disp_bi; + + btext_drawstring("Welcome to Linux, kernel " UTS_RELEASE "\n"); + btext_drawstring("\nlinked at : 0x"); + btext_drawhex(KERNELBASE); + btext_drawstring("\nframe buffer at : 0x"); + btext_drawhex((unsigned long)bi->dispDeviceBase); + btext_drawstring(" (phys), 0x"); + btext_drawhex((unsigned long)bi->logicalDisplayBase); + btext_drawstring(" (log)"); + btext_drawstring("\nklimit : 0x"); + btext_drawhex((unsigned long)klimit); + btext_drawstring("\nMSR : 0x"); + __asm__ __volatile__ ("mfmsr %0" : "=r" (flags)); + btext_drawhex(flags); + __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr)); + pvr >>= 16; + if (pvr > 1) { + btext_drawstring("\nHID0 : 0x"); + __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags)); + btext_drawhex(flags); + } + if (pvr == 8 || pvr == 12 || pvr == 0x800c) { + btext_drawstring("\nICTC : 0x"); + __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags)); + btext_drawhex(flags); + } + btext_drawstring("\n\n"); +} + +/* Calc BAT values for mapping the display and store them + * in disp_BAT. Those values are then used from head.S to map + * the display during identify_machine() and MMU_Init() + * + * The display is mapped to virtual address 0xD0000000, rather + * than 1:1, because some some CHRP machines put the frame buffer + * in the region starting at 0xC0000000 (KERNELBASE). + * This mapping is temporary and will disappear as soon as the + * setup done by MMU_Init() is applied. + * + * For now, we align the BAT and then map 8Mb on 601 and 16Mb + * on other PPCs. This may cause trouble if the framebuffer + * is really badly aligned, but I didn't encounter this case + * yet. + */ +void __init +btext_prepare_BAT(void) +{ + boot_infos_t* bi = &disp_bi; + unsigned long vaddr = KERNELBASE + 0x10000000; + unsigned long addr; + unsigned long lowbits; + + addr = (unsigned long)bi->dispDeviceBase; + if (!addr) { + boot_text_mapped = 0; + return; + } + if (PVR_VER(mfspr(SPRN_PVR)) != 1) { + /* 603, 604, G3, G4, ... */ + lowbits = addr & ~0xFF000000UL; + addr &= 0xFF000000UL; + disp_BAT[0] = vaddr | (BL_16M<<2) | 2; + disp_BAT[1] = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW); + } else { + /* 601 */ + lowbits = addr & ~0xFF800000UL; + addr &= 0xFF800000UL; + disp_BAT[0] = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4; + disp_BAT[1] = addr | BL_8M | 0x40; + } + bi->logicalDisplayBase = (void *) (vaddr + lowbits); +} + +/* This function will enable the early boot text when doing OF booting. This + * way, xmon output should work too + */ +void __init +btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address) +{ + boot_infos_t* bi = &disp_bi; + + g_loc_X = 0; + g_loc_Y = 0; + g_max_loc_X = width / 8; + g_max_loc_Y = height / 16; + bi->logicalDisplayBase = (unsigned char *)address; + bi->dispDeviceBase = (unsigned char *)address; + bi->dispDeviceRowBytes = pitch; + bi->dispDeviceDepth = depth; + bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; + boot_text_mapped = 1; +} + +/* Here's a small text engine to use during early boot + * or for debugging purposes + * + * todo: + * + * - build some kind of vgacon with it to enable early printk + * - move to a separate file + * - add a few video driver hooks to keep in sync with display + * changes. + */ + +void __openfirmware +map_boot_text(void) +{ + unsigned long base, offset, size; + boot_infos_t *bi = &disp_bi; + unsigned char *vbase; + + /* By default, we are no longer mapped */ + boot_text_mapped = 0; + if (bi->dispDeviceBase == 0) + return; + base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL; + offset = ((unsigned long) bi->dispDeviceBase) - base; + size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset + + bi->dispDeviceRect[0]; + vbase = ioremap(base, size); + if (vbase == 0) + return; + bi->logicalDisplayBase = vbase + offset; + boot_text_mapped = 1; +} + +/* Calc the base address of a given point (x,y) */ +static unsigned char * BTEXT +calc_base(boot_infos_t *bi, int x, int y) +{ + unsigned char *base; + + base = bi->logicalDisplayBase; + if (base == 0) + base = bi->dispDeviceBase; + base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); + base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; + return base; +} + +/* Adjust the display to a new resolution */ +void +btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch) +{ + boot_infos_t *bi = &disp_bi; + + if (bi->dispDeviceBase == 0) + return; + + /* check it's the same frame buffer (within 256MB) */ + if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000) + return; + + bi->dispDeviceBase = (__u8 *) phys; + bi->dispDeviceRect[0] = 0; + bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; + bi->dispDeviceDepth = depth; + bi->dispDeviceRowBytes = pitch; + if (boot_text_mapped) { + iounmap(bi->logicalDisplayBase); + boot_text_mapped = 0; + } + map_boot_text(); + g_loc_X = 0; + g_loc_Y = 0; + g_max_loc_X = width / 8; + g_max_loc_Y = height / 16; +} + +void BTEXT btext_clearscreen(void) +{ + boot_infos_t* bi = &disp_bi; + unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + { + unsigned long *ptr = base; + for(j=width; j; --j) + *(ptr++) = 0; + base += (bi->dispDeviceRowBytes >> 2); + } +} + +__inline__ void dcbst(const void* addr) +{ + __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr)); +} + +void BTEXT btext_flushscreen(void) +{ + boot_infos_t* bi = &disp_bi; + unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + { + unsigned long *ptr = base; + for(j=width; j>0; j-=8) { + dcbst(ptr); + ptr += 8; + } + base += (bi->dispDeviceRowBytes >> 2); + } +} + +#ifndef NO_SCROLL +static BTEXT void +scrollscreen(void) +{ + boot_infos_t* bi = &disp_bi; + unsigned long *src = (unsigned long *)calc_base(bi,0,16); + unsigned long *dst = (unsigned long *)calc_base(bi,0,0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + +#ifdef CONFIG_ADB_PMU + pmu_suspend(); /* PMU will not shut us down ! */ +#endif + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) + { + unsigned long *src_ptr = src; + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = *(src_ptr++); + src += (bi->dispDeviceRowBytes >> 2); + dst += (bi->dispDeviceRowBytes >> 2); + } + for (i=0; i<16; i++) + { + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = 0; + dst += (bi->dispDeviceRowBytes >> 2); + } +#ifdef CONFIG_ADB_PMU + pmu_resume(); /* PMU will not shut us down ! */ +#endif +} +#endif /* ndef NO_SCROLL */ + +void BTEXT btext_drawchar(char c) +{ + int cline = 0, x; + + if (!boot_text_mapped) + return; + + switch (c) { + case '\b': + if (g_loc_X > 0) + --g_loc_X; + break; + case '\t': + g_loc_X = (g_loc_X & -8) + 8; + break; + case '\r': + g_loc_X = 0; + break; + case '\n': + g_loc_X = 0; + g_loc_Y++; + cline = 1; + break; + default: + draw_byte(c, g_loc_X++, g_loc_Y); + } + if (g_loc_X >= g_max_loc_X) { + g_loc_X = 0; + g_loc_Y++; + cline = 1; + } +#ifndef NO_SCROLL + while (g_loc_Y >= g_max_loc_Y) { + scrollscreen(); + g_loc_Y--; + } +#else + /* wrap around from bottom to top of screen so we don't + waste time scrolling each line. -- paulus. */ + if (g_loc_Y >= g_max_loc_Y) + g_loc_Y = 0; + if (cline) { + for (x = 0; x < g_max_loc_X; ++x) + draw_byte(' ', x, g_loc_Y); + } +#endif +} + +void BTEXT +btext_drawstring(const char *c) +{ + if (!boot_text_mapped) + return; + while (*c) + btext_drawchar(*c++); +} + +void BTEXT +btext_drawhex(unsigned long v) +{ + static char hex_table[] = "012 |