From: wdenk Date: Mon, 20 Nov 2000 17:19:27 +0000 (+0000) Subject: * Added support for MBX860T (thanks to Rob Taylor) X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=f7666189481b2e703285e4c5e7d318ddf802e101;p=users%2Frw%2Fppcboot.git * Added support for MBX860T (thanks to Rob Taylor) * Added support for Sandpoint8240 (thanks to Rob Taylor); this is Work In Progress (TM); current status: boots to command line input. EPIC code non-functional (interrupts disabled), No net, No IDE. * Add support for Status LED * Optionally panic() to reboot instead of hanging * Misc bug fixes * All frequencies in HZ now (internally) * Add support for BOOTP Domain Name Server Option --- diff --git a/CHANGELOG b/CHANGELOG index eb1656c..294e31e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,11 @@ Open Issues: ====================================================================== +* Enabling too many BOOTP Vendor Extensions easily overflows the 64 + byte limit imposed by the BOOTP header definition. While this is + not a problem on our side, some DHCP servers will complain. Should + we break up long BOOTP requests into several shorter ones? + * Boot with RAMDisk: No need to copy ramdisk image when it's already in RAM ??? Or do we @@ -56,6 +61,16 @@ To do: Modifications for 0.6.3: ====================================================================== +* Added support for MBX860T (thanks to Rob Taylor) + +* Added support for Sandpoint8240 (thanks to Rob Taylor); this is + Work In Progress (TM); current status: boots to command line input. + EPIC code non-functional (interrupts disabled), No net, No IDE. + +* Add support for Status LED + +* Optionally panic() to reboot instead of hanging + * Misc bug fixes * All frequencies in HZ now (internally) diff --git a/CREDITS b/CREDITS index fbf7034..3c1a80c 100644 --- a/CREDITS +++ b/CREDITS @@ -66,7 +66,11 @@ D: Author of LiMon-1.4.2, which contributed some ideas N: Paolo Scaffardi E: arsenio@tin.it -D: FADS823 configuration, MPC823 video support, I2C, wireless keyboard +D: FADS823 configuration, MPC823 video support, I2C, wireless keyboard, lots more + +N: Rob Taylor +E: robt@flyingpig.com +D: Port to MBX860T and Sandpoint8240 N: Christian Vejlbo E: christian.vejlbo@tellabs.com diff --git a/MAKEALL b/MAKEALL index 0778e90..31d7ad9 100755 --- a/MAKEALL +++ b/MAKEALL @@ -10,7 +10,8 @@ for i in TQM823L TQM850L TQM855L TQM860L FPS850L SM850 \ CPCI405 ADCIOP \ cogent_mpc8xx \ GENIETV \ - cogent_mpc8260 hymod + cogent_mpc8260 hymod \ + Sandpoint8240 do make distclean >/dev/null make ${i}_config diff --git a/Makefile b/Makefile index 61c8a9f..abc308b 100644 --- a/Makefile +++ b/Makefile @@ -191,6 +191,22 @@ MBX_config: unconfig echo "CPU = mpc8xx" >>config.mk ; \ echo "#include " >config.h +MBX860T_config: unconfig + @echo "Configuring for $(@:_config=) Board..." ; \ + cd include ; \ + echo "ARCH = ppc" > config.mk ; \ + echo "BOARD = mbx" >>config.mk ; \ + echo "CPU = mpc8xx" >>config.mk ; \ + echo "#include " >config.h + +Sandpoint8240_config: unconfig + @echo "Configuring for $(@:_config=) Board..." ; \ + cd include ; \ + echo "ARCH = ppc" > config.mk ; \ + echo "BOARD = sandpoint" >>config.mk ; \ + echo "CPU = mpc8240" >>config.mk ; \ + echo "#include " >config.h + hymod_config: unconfig @echo "Configuring for $(@:_config=) Board..." ; \ cd include ; \ diff --git a/README b/README index 6afb402..afbd368 100644 --- a/README +++ b/README @@ -67,20 +67,23 @@ Directory Hierarchy: - ppc Files generic to PowerPC architecture - tools Tools to build S-Record or PPCBoot images, etc. -- mpc8xx Files specific to Motorola MPC8xx CPUs -- ppc4xx Files specific to IBM 4xx CPUs +- mpc8xx Files specific to Motorola MPC8xx CPUs +- mpc8240 Files specific to Motorola MPC8240 CPU +- mpc8260 Files specific to Motorola MPC8260 CPU +- ppc4xx Files specific to IBM 4xx CPUs - adciop Files specific to ADCIOP boards - cogent Files specific to Cogent boards (need further configuration) - cpci405 Files specific to CPCI405 boards - etx094 Files specific to ETX_094 boards -- fads Files specific to Motorola FADS boards +- fads Files specific to FADS boards - genietv Files specific to GENIETV boards - hymod Files specific to HYMOD boards - ivms8 Files specific to IVMS8 boards -- mbx8xx Files specific to Motorola MBX boards +- mbx8xx Files specific to MBX boards - spd8xx Files specific to SPD8xxTS boards +- sandpoint Files specific to Sandpoint boards - tqm8xx Files specific to TQM8xxL boards diff --git a/common/board.c b/common/board.c index 1b37779..6540fca 100644 --- a/common/board.c +++ b/common/board.c @@ -31,6 +31,9 @@ #if (CONFIG_COMMANDS & CFG_CMD_KGDB) #include #endif +#ifdef CONFIG_STATUS_LED +#include +#endif #include static char *failed = "*** failed ***\n"; @@ -470,6 +473,9 @@ void board_init_r (bd_t *bd, ulong dest_addr) * Enable Interrupts */ interrupt_init (bd); +#ifdef CONFIG_STATUS_LED + status_led_set (STATUS_LED_BLINKING); +#endif udelay(20); diff --git a/common/cmd_ide.c b/common/cmd_ide.c index 167cdd1..693034a 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -27,7 +27,7 @@ */ #include #include -#include /* for PIO mode selection */ +#include #include #include #ifdef CONFIG_IDE_PCMCIA @@ -49,7 +49,9 @@ extern ldiv_t ldiv (long int __numer, long int __denom); # define __ldiv_t_defined 1 #endif -#ifdef DEBUG +#undef IDE_DEBUG + +#ifdef IDE_DEBUG #define PRINTF(fmt,args...) do { \ printf (fmt ,##args); \ } while (0) @@ -97,107 +99,6 @@ static int pio_mode = CFG_PIO_MODE; /* ------------------------------------------------------------------------- */ -#ifdef CONFIG_IDE_PCMCIA -/* - * Allow configuration to select PCMCIA slot, - * or try to generate a useful default - */ -#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) - - /* The RPX series use SLOT_B */ -#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE) -# define CONFIG_PCMCIA_SLOT_B -#elif defined(CONFIG_ADS) /* The ADS board use SLOT_A */ -# define CONFIG_PCMCIA_SLOT_A -#elif defined(CONFIG_FADS) /* The FADS series are a mess */ -# if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821) -# define CONFIG_PCMCIA_SLOT_A -# else -# define CONFIG_PCMCIA_SLOT_B -# endif -#elif defined(CONFIG_TQM860L) || defined(CONFIG_TQM855L) /* The TQM8xxL modules */ -# define CONFIG_PCMCIA_SLOT_A /* ... use SLOT_A on MPC860/855 */ -#elif defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) -# define CONFIG_PCMCIA_SLOT_B /* ... and SLOT_B else */ -#elif defined(CONFIG_SPD823TS) /* The SPD8xx use SLOT_B */ -# define CONFIG_PCMCIA_SLOT_B -#else -# error "PCMCIA Slot not configured" -#endif - -#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */ - -/* Make sure exactly one slot is defined - we support only one for now */ -#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) -#error Neither CONFIG_PCMCIA_SLOT_A nor CONFIG_PCMCIA_SLOT_B configured -#endif -#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B) -#error Both CONFIG_PCMCIA_SLOT_A and CONFIG_PCMCIA_SLOT_B configured -#endif - -#define PCMCIA_SOCKETS_NO 1 -#define PCMCIA_MEM_WIN_NO 4 -#define PCMCIA_IO_WIN_NO 2 - -/* define _slot_ to be able to optimize macros */ -#ifdef CONFIG_PCMCIA_SLOT_A -# define _slot_ 0 -# define PCMCIA_SLOT_MSG "SLOT_A" -#else -# define _slot_ 1 -# define PCMCIA_SLOT_MSG "SLOT_B" -#endif - -/* - * The TQM850L hardware has two pins swapped! Grrrrgh! - */ -#ifdef CONFIG_TQM850L -#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXOE -#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXRESET -#else -#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXRESET -#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXOE -#endif - -/* look up table for pgcrx registers */ - -#if 0 -static u_int *pcmcia_pgcrx[2] = { - &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra, - &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb, -}; - -#define PCMCIA_PGCRX(slot) (*pcmcia_pgcrx[slot]) -#endif - -/* - * This structure is used to address each window in the PCMCIA controller. - * - * Keep in mind that we assume that pcmcia_win_t[n+1] is mapped directly - * after pcmcia_win_t[n]... - */ - -typedef struct { - ulong br; - ulong or; -} pcmcia_win_t; - -/* ------------------------------------------------------------------------- */ - -/* - * Memory Map Information: - * - * BR0 / OR0: EPROM1 Base 0xFF000000 Size 512KB - * BR1 / OR1: EPROM2 Base 0xFF080000 Size 512KB - * BR2 / OR2: SRAM Base 0xFE200000 Size 2MB - * BR3 / OR3: SDRAM Base 0x00000000 Size 16MB (max. 64 MB used) - * BR4 / OR4: PER-8 Base 0xFE000000 Size 1MB - * BR5 / OR5: SHARC Base 0xFE400000 Size 4MB - */ -/* ------------------------------------------------------------------------- */ - -#endif /* CONFIG_IDE_PCMCIA */ - /* Current I/O Device */ static int curr_device = -1; @@ -572,7 +473,6 @@ void ide_init (bd_t *bd) udelay (10000); /* 10 ms */ c = inb (dev, ATA_STATUS); - ++i; if (i > (ATA_RESET_TIME * 100)) { puts ("** Timeout **\n"); ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */ @@ -640,6 +540,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; + PRINTF ("PBR0: %08x POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0); pcmp->pcmc_pbr1 = CFG_PCMCIA_PBR1; pcmp->pcmc_por1 = CFG_PCMCIA_POR1 @@ -647,6 +548,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; + PRINTF ("PBR1: %08x POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1); pcmp->pcmc_pbr2 = CFG_PCMCIA_PBR2; pcmp->pcmc_por2 = CFG_PCMCIA_POR2 @@ -654,6 +556,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; + PRINTF ("PBR2: %08x POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2); pcmp->pcmc_pbr3 = CFG_PCMCIA_PBR3; pcmp->pcmc_por3 = CFG_PCMCIA_POR3 @@ -661,6 +564,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; + PRINTF ("PBR3: %08x POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3); /* IDE 1 */ @@ -670,6 +574,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; + PRINTF ("PBR4: %08x POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4); pcmp->pcmc_pbr5 = CFG_PCMCIA_PBR5; pcmp->pcmc_por5 = CFG_PCMCIA_POR5 @@ -677,6 +582,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; + PRINTF ("PBR5: %08x POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5); pcmp->pcmc_pbr6 = CFG_PCMCIA_PBR6; pcmp->pcmc_por6 = CFG_PCMCIA_POR6 @@ -684,6 +590,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; + PRINTF ("PBR6: %08x POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6); pcmp->pcmc_pbr7 = CFG_PCMCIA_PBR7; pcmp->pcmc_por7 = CFG_PCMCIA_POR7 @@ -691,6 +598,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; + PRINTF ("PBR7: %08x POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7); } @@ -848,6 +756,7 @@ static void ide_print (int device) { ldiv_t mb, gb; ide_dev_id_t *idp = &(ide_device[device]); + char *mod, *ser; if (idp->size == 0) { puts ("not available\n"); @@ -864,7 +773,10 @@ static void ide_print (int device) gb.rem += 512; gb.rem /= 1024; - printf ("Model: %s Serial #: %s ", idp->model, idp->serial_no); + mod = idp->model; while (*mod && (*mod==' ')) ++mod; + ser = idp->serial_no; while (*ser && (*ser==' ')) ++ser; + + printf ("Model: %s Serial #: %s ", mod, ser); printf ("Capacity: %ld.%ld MB = %ld.%ld GB\n", mb.quot, mb.rem, gb.quot, gb.rem); } @@ -1030,14 +942,32 @@ static void ide_reset (void) immr->im_ioport.iop_pcso &= ~(CFG_PC_IDE_RESET); immr->im_ioport.iop_pcdir |= CFG_PC_IDE_RESET; /* Make output */ +#if 1 /* assert IDE RESET signal */ immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET); udelay (20000); /* de-assert RESET signal of IDE */ immr->im_ioport.iop_pcdat |= CFG_PC_IDE_RESET; +#else + /* assert IDE RESET signal */ + immr->im_ioport.iop_pcdat |= CFG_PC_IDE_RESET; + udelay (20000); + /* de-assert RESET signal of IDE */ + immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET); +#endif #else #error IDE reset pin not configured #endif + +#ifdef CFG_PB_IDE_MOTOR + immr->im_cpm.cp_pbpar &= ~(CFG_PB_IDE_MOTOR); /* IDE Motor in pin */ + immr->im_cpm.cp_pbodr &= ~(CFG_PB_IDE_MOTOR); + immr->im_cpm.cp_pbdir &= ~(CFG_PB_IDE_MOTOR); /* input */ + if ((immr->im_cpm.cp_pbdat & CFG_PB_IDE_MOTOR) == 0) { + printf ("\nWarning: 5V for IDE Motor missing\n"); + } +#endif /* CFG_PB_IDE_MOTOR */ + udelay (100000); } diff --git a/common/main.c b/common/main.c index b7ac76c..b4f0383 100644 --- a/common/main.c +++ b/common/main.c @@ -405,6 +405,7 @@ static int process_separators (char *s, int len, return 0; } +#if (CONFIG_COMMANDS & CFG_CMD_BOOTD) /* avoid "bootd" recursion */ if ((len < 0) && (cmdtp->cmd == do_bootd)) { #ifdef DEBUG_PARSER @@ -413,7 +414,7 @@ static int process_separators (char *s, int len, printf ("'bootd' recursion detected\n"); return 0; } - +#endif /* CFG_CMD_BOOTD */ /* OK - call function */ (cmdtp->cmd) (cmdtp, bd, flag, argc, argv); diff --git a/config.mk b/config.mk index 3e34010..0596d9b 100644 --- a/config.mk +++ b/config.mk @@ -68,7 +68,7 @@ OPTFLAGS= -Os -fomit-frame-pointer LDSCRIPT := $(BOARD)/ppcboot.lds CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \ - -D__KERNEL__ \ + -D__KERNEL__ -D__powerpc__ \ -I$(TOPDIR)/include \ -fno-builtin \ -pipe $(PLATFORM_CPPFLAGS) diff --git a/etx094/flash.c b/etx094/flash.c index 6c1cb12..5d8560a 100644 --- a/etx094/flash.c +++ b/etx094/flash.c @@ -480,7 +480,7 @@ void flash_erase (flash_info_t *info, int s_first, int s_last) { vu_long *addr = (vu_long*)(info->start[0]); int flag, prot, sect; - ulong start, now, last; + ulong type, start, now, last; if ((s_first < 0) || (s_first > s_last)) { if (info->flash_id == FLASH_UNKNOWN) { @@ -491,9 +491,10 @@ void flash_erase (flash_info_t *info, int s_first, int s_last) return; } - if ((info->flash_id == FLASH_UNKNOWN) || - (info->flash_id > FLASH_AMD_COMP)) { - printf ("Can't erase unknown flash type - aborted\n"); + type = (info->flash_id & FLASH_VENDMASK); + if ((type != FLASH_MAN_SST) && (type != FLASH_MAN_STM)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); return; } diff --git a/include/asm/8xx_immap.h b/include/asm/8xx_immap.h index e616ac6..af2a3de 100644 --- a/include/asm/8xx_immap.h +++ b/include/asm/8xx_immap.h @@ -335,38 +335,39 @@ typedef struct smc { /* Serial management channels */ /* MPC860T Fast Ethernet Controller. It isn't part of the CPM, but * it fits within the address space. */ + typedef struct fec { - uint fec_addr_low; /* LS 32 bits of station address */ - ushort fec_addr_high; /* MS 16 bits of address */ - ushort res1; - uint fec_hash_table_high; - uint fec_hash_table_low; - uint fec_r_des_start; - uint fec_x_des_start; - uint fec_r_buff_size; - uint res2[9]; - uint fec_ecntrl; - uint fec_ievent; - uint fec_imask; - uint fec_ivec; - uint fec_r_des_active; - uint fec_x_des_active; - uint res3[10]; - uint fec_mii_data; - uint fec_mii_speed; - uint res4[17]; - uint fec_r_bound; - uint fec_r_fstart; - uint res5[6]; - uint fec_x_fstart; - uint res6[17]; - uint fec_fun_code; - uint res7[3]; - uint fec_r_cntrl; - uint fec_r_hash; - uint res8[14]; - uint fec_x_cntrl; - uint res9[0x1e]; + uint fec_addr_low; /* lower 32 bits of station address */ + ushort fec_addr_high; /* upper 16 bits of station address */ + ushort res1; /* reserved */ + uint fec_hash_table_high; /* upper 32-bits of hash table */ + uint fec_hash_table_low; /* lower 32-bits of hash table */ + uint fec_r_des_start; /* beginning of Rx descriptor ring */ + uint fec_x_des_start; /* beginning of Tx descriptor ring */ + uint fec_r_buff_size; /* Rx buffer size */ + uint res2[9]; /* reserved */ + uint fec_ecntrl; /* ethernet control register */ + uint fec_ievent; /* interrupt event register */ + uint fec_imask; /* interrupt mask register */ + uint fec_ivec; /* interrupt level and vector status */ + uint fec_r_des_active; /* Rx ring updated flag */ + uint fec_x_des_active; /* Tx ring updated flag */ + uint res3[10]; /* reserved */ + uint fec_mii_data; /* MII data register */ + uint fec_mii_speed; /* MII speed control register */ + uint res4[17]; /* reserved */ + uint fec_r_bound; /* end of RAM (read-only) */ + uint fec_r_fstart; /* Rx FIFO start address */ + uint res5[6]; /* reserved */ + uint fec_x_fstart; /* Tx FIFO start address */ + uint res6[17]; /* reserved */ + uint fec_fun_code; /* fec SDMA function code */ + uint res7[3]; /* reserved */ + uint fec_r_cntrl; /* Rx control register */ + uint fec_r_hash; /* Rx hash register */ + uint res8[14]; /* reserved */ + uint fec_x_cntrl; /* Tx control register */ + uint res9[0x1e]; /* reserved */ } fec_t; /* The FEC and LCD color map share the same address space.... diff --git a/include/asm/io.h b/include/asm/io.h new file mode 100755 index 0000000..426f926 --- /dev/null +++ b/include/asm/io.h @@ -0,0 +1,180 @@ +/* originally from linux source. + * removed the dependacies on CONFIG_ values + * removed virt_to_phys stuff (and in fact everything surrounded by #if __KERNEL__) + * Modified By Rob Taylor, Flying Pig Systems, 2000 + */ + +#ifndef _PPC_IO_H +#define _PPC_IO_H + +#include +#include + +#define SIO_CONFIG_RA 0x398 +#define SIO_CONFIG_RD 0x399 + + +#define readb(addr) in_8((volatile u8 *)(addr)) +#define writeb(b,addr) out_8((volatile u8 *)(addr), (b)) +#if !defined(__BIG_ENDIAN) +#define readw(addr) (*(volatile u16 *) (addr)) +#define readl(addr) (*(volatile u32 *) (addr)) +#define writew(b,addr) ((*(volatile u16 *) (addr)) = (b)) +#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b)) +#else +#define readw(addr) in_le16((volatile u16 *)(addr)) +#define readl(addr) in_le32((volatile u32 *)(addr)) +#define writew(b,addr) out_le16((volatile u16 *)(addr),(b)) +#define writel(b,addr) out_le32((volatile u32 *)(addr),(b)) +#endif + +/* + * The insw/outsw/insl/outsl macros don't do byte-swapping. + * They are only used in practice for transferring buffers which + * are arrays of bytes, and byte-swapping is not appropriate in + * that case. - paulus + */ +#define insb(port, buf, ns) _insb((u8 *)((port)+_IO_BASE), (buf), (ns)) +#define outsb(port, buf, ns) _outsb((u8 *)((port)+_IO_BASE), (buf), (ns)) +#define insw(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns)) +#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns)) +#define insl(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl)) +#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl)) + +#define inb(port) in_8((u8 *)((port)+_IO_BASE)) +#define outb(val, port) out_8((u8 *)((port)+_IO_BASE), (val)) +#if !defined(__BIG_ENDIAN) +#define inw(port) in_be16((u16 *)((port)+_IO_BASE)) +#define outw(val, port) out_be16((u16 *)((port)+_IO_BASE), (val)) +#define inl(port) in_be32((u32 *)((port)+_IO_BASE)) +#define outl(val, port) out_be32((u32 *)((port)+_IO_BASE), (val)) +#else +#define inw(port) in_le16((u16 *)((port)+_IO_BASE)) +#define outw(val, port) out_le16((u16 *)((port)+_IO_BASE), (val)) +#define inl(port) in_le32((u32 *)((port)+_IO_BASE)) +#define outl(val, port) out_le32((u32 *)((port)+_IO_BASE), (val)) +#endif + +#define inb_p(port) in_8((u8 *)((port)+_IO_BASE)) +#define outb_p(val, port) out_8((u8 *)((port)+_IO_BASE), (val)) +#define inw_p(port) in_le16((u16 *)((port)+_IO_BASE)) +#define outw_p(val, port) out_le16((u16 *)((port)+_IO_BASE), (val)) +#define inl_p(port) in_le32((u32 *)((port)+_IO_BASE)) +#define outl_p(val, port) out_le32((u32 *)((port)+_IO_BASE), (val)) + +extern void _insb(volatile u8 *port, void *buf, int ns); +extern void _outsb(volatile u8 *port, const void *buf, int ns); +extern void _insw(volatile u16 *port, void *buf, int ns); +extern void _outsw(volatile u16 *port, const void *buf, int ns); +extern void _insl(volatile u32 *port, void *buf, int nl); +extern void _outsl(volatile u32 *port, const void *buf, int nl); +extern void _insw_ns(volatile u16 *port, void *buf, int ns); +extern void _outsw_ns(volatile u16 *port, const void *buf, int ns); +extern void _insl_ns(volatile u32 *port, void *buf, int nl); +extern void _outsl_ns(volatile u32 *port, const void *buf, int nl); + +/* + * The *_ns versions below don't do byte-swapping. + * Neither do the standard versions now, these are just here + * for older code. + */ +#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns)) +#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns)) +#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl)) +#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl)) + + +#define IO_SPACE_LIMIT ~0 + +#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)) + +/* + * Enforce In-order Execution of I/O: + * Acts as a barrier to ensure all previous I/O accesses have + * completed before any further ones are issued. + */ +#define eieio() __asm__ __volatile__ ("eieio" : : : "memory"); +#define sync() __asm__ __volatile__ ("sync" : : : "memory"); + +/* Enforce in-order execution of data I/O. + * No distinction between read/write on PPC; use eieio for all three. + */ +#define iobarrier_rw() eieio() +#define iobarrier_r() eieio() +#define iobarrier_w() eieio() + +/* + * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. + */ +extern inline int in_8(volatile u8 *addr) +{ + int ret; + + __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); + return ret; +} + +extern inline void out_8(volatile u8 *addr, int val) +{ + __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} + +extern inline int in_le16(volatile u16 *addr) +{ + int ret; + + __asm__ __volatile__("lhbrx %0,0,%1; eieio" : "=r" (ret) : + "r" (addr), "m" (*addr)); + return ret; +} + +extern inline int in_be16(volatile u16 *addr) +{ + int ret; + + __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); + return ret; +} + +extern inline void out_le16(volatile u16 *addr, int val) +{ + __asm__ __volatile__("sthbrx %1,0,%2; eieio" : "=m" (*addr) : + "r" (val), "r" (addr)); +} + +extern inline void out_be16(volatile u16 *addr, int val) +{ + __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} + +extern inline unsigned in_le32(volatile u32 *addr) +{ + unsigned ret; + + __asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) : + "r" (addr), "m" (*addr)); + return ret; +} + +extern inline unsigned in_be32(volatile u32 *addr) +{ + unsigned ret; + + __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); + return ret; +} + +extern inline void out_le32(volatile unsigned *addr, int val) +{ + __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) : + "r" (val), "r" (addr)); +} + +extern inline void out_be32(volatile unsigned *addr, int val) +{ + __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} + +#endif diff --git a/include/asm/mc146818rtc.h b/include/asm/mc146818rtc.h new file mode 100755 index 0000000..5f806c4 --- /dev/null +++ b/include/asm/mc146818rtc.h @@ -0,0 +1,27 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef __ASM_PPC_MC146818RTC_H +#define __ASM_PPC_MC146818RTC_H + +#include + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* __ASM_PPC_MC146818RTC_H */ diff --git a/include/asm/pci_io.h b/include/asm/pci_io.h new file mode 100755 index 0000000..0f57b53 --- /dev/null +++ b/include/asm/pci_io.h @@ -0,0 +1,43 @@ +/* originally from linux source (asm-ppc/io.h). + * Sanity added by Rob Taylor, Flying Pig Systems, 2000 + */ +#ifndef _PCI_IO_H_ +#define _PCI_IO_H_ + +#include "io.h" + + +#define pci_read_le16(addr, dest) \ + __asm__ __volatile__("lhbrx %0,0,%1" : "=r" (dest) : \ + "r" (addr), "m" (*addr)); + +#define pci_write_le16(addr, val) \ + __asm__ __volatile__("sthbrx %1,0,%2" : "=m" (*addr) : \ + "r" (val), "r" (addr)); + + +#define pci_read_le32(addr, dest) \ + __asm__ __volatile__("lwbrx %0,0,%1" : "=r" (dest) : \ + "r" (addr), "m" (*addr)); + +#define pci_write_le32(addr, val) \ +__asm__ __volatile__("stwbrx %1,0,%2" : "=m" (*addr) : \ + "r" (val), "r" (addr)); + +#define pci_readb(addr,b) ((b) = *(volatile u8 *) (addr)) +#define pci_writeb(b,addr) ((*(volatile u8 *) (addr)) = (b)) + +#if !defined(__BIG_ENDIAN) +#define pci_readw(addr,b) ((b) = *(volatile u16 *) (addr)) +#define pci_readl(addr,b) ((b) = *(volatile u32 *) (addr)) +#define pci_writew(b,addr) ((*(volatile u16 *) (addr)) = (b)) +#define pci_writel(b,addr) ((*(volatile u32 *) (addr)) = (b)) +#else +#define pci_readw(addr,b) pci_read_le16((volatile u16 *)(addr),(b)) +#define pci_readl(addr,b) pci_read_le32((volatile u32 *)(addr),(b)) +#define pci_writew(b,addr) pci_write_le16((volatile u16 *)(addr),(b)) +#define pci_writel(b,addr) pci_write_le32((volatile u32 *)(addr),(b)) +#endif + + +#endif /* _PCI_IO_H_ */ diff --git a/include/asm/processor.h b/include/asm/processor.h index 7f8d7bf..cbc5f90 100644 --- a/include/asm/processor.h +++ b/include/asm/processor.h @@ -507,8 +507,9 @@ #define _MACH_oak 0x00000800 /* IBM "Oak" 403 eval. board */ #define _MACH_walnut 0x00001000 /* IBM "Walnut" 405GP eval. board */ #define _MACH_8260 0x00002000 /* Generic 8260 */ -#define _MACH_tqm860 0x00004000 /* TQM860/L */ -#define _MACH_tqm8xxL 0x00008000 /* TQM8xxL */ +#define _MACH_sandpoint 0x00004000 /* Motorola SPS Processor eval board */ +#define _MACH_tqm860 0x00008000 /* TQM860/L */ +#define _MACH_tqm8xxL 0x00010000 /* TQM8xxL */ /* see residual.h for these */ @@ -556,6 +557,8 @@ n: : "=r" (rval)); rval;}) #define mtspr(rn, v) asm volatile("mtspr " stringify(rn) ",%0" : : "r" (v)) +#define tlbie(v) asm volatile("tlbie %0 \n sync" : : "r" (v)) + /* Segment Registers */ #define SR0 0 @@ -723,6 +726,9 @@ void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); #elif defined(CONFIG_8260) #define _machine _MACH_8260 #define have_of 0 +#elif defined(CONFIG_SANDPOINT) +#define _machine _MACH_sandpoint +#define have_of 0 #else #error "Machine not defined correctly" #endif diff --git a/include/commproc.h b/include/commproc.h index e1a2d59..e6ba1fc 100644 --- a/include/commproc.h +++ b/include/commproc.h @@ -382,6 +382,15 @@ typedef struct scc_enet { ushort sen_taddrl; /* temp address (LSB) */ } scc_enet_t; +/********************************************************************** + * + * Board specific configuration settings. + * + * Please note that we use the presence of a #define SCC_ENET and/or + * #define FEC_ENET to enable the SCC resp. FEC ethernet drivers. + **********************************************************************/ + + /*** MBX ************************************************************/ #ifdef CONFIG_MBX @@ -733,6 +742,37 @@ typedef struct scc_enet { #define SICR_ENET_CLKRT ((uint)0x00260000) #endif /* CONFIG_SM850 */ +/*** IVMS8 **********************************************************/ + +/* The IVMS8 uses the FEC on a MPC860T for Ethernet */ + +#ifdef CONFIG_IVMS8 + +#define FEC_ENET /* use FEC for EThernet */ +#undef SCC_ENET + +#define PB_ENET_POWER ((uint)0x00010000) /* PB 15 */ + +#define PC_ENET_RESET ((ushort)0x0010) /* PC 11 */ + +#define PD_MII_TXD1 ((ushort)0x1000) /* PD 3 */ +#define PD_MII_TXD2 ((ushort)0x0800) /* PD 4 */ +#define PD_MII_TXD3 ((ushort)0x0400) /* PD 5 */ +#define PD_MII_RX_DV ((ushort)0x0200) /* PD 6 */ +#define PD_MII_RX_ERR ((ushort)0x0100) /* PD 7 */ +#define PD_MII_RX_CLK ((ushort)0x0080) /* PD 8 */ +#define PD_MII_TXD0 ((ushort)0x0040) /* PD 9 */ +#define PD_MII_RXD0 ((ushort)0x0020) /* PD 10 */ +#define PD_MII_TX_ERR ((ushort)0x0010) /* PD 11 */ +#define PD_MII_MDC ((ushort)0x0008) /* PD 12 */ +#define PD_MII_RXD1 ((ushort)0x0004) /* PD 13 */ +#define PD_MII_RXD2 ((ushort)0x0002) /* PD 14 */ +#define PD_MII_RXD3 ((ushort)0x0001) /* PD 15 */ + +#define PD_MII_MASK ((ushort)0x1FFF) /* PD 3...15 */ + +#endif /* CONFIG_IVMS8 */ + /*********************************************************************/ /* SCC Event register as used by Ethernet. diff --git a/include/config_ETX094.h b/include/config_ETX094.h index 91d06fe..5324169 100644 --- a/include/config_ETX094.h +++ b/include/config_ETX094.h @@ -56,6 +56,8 @@ #undef CONFIG_WATCHDOG /* watchdog disabled */ +#define CONFIG_STATUS_LED 1 /* Status LED enabled */ + #define CONFIG_BOOTP_MASK CONFIG_BOOTP_ALL /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ diff --git a/include/config_IVMS8.h b/include/config_IVMS8.h index c9297bb..b038861 100644 --- a/include/config_IVMS8.h +++ b/include/config_IVMS8.h @@ -60,9 +60,9 @@ #if 0 #define CONFIG_COMMANDS \ ((CONFIG_CMD_DFL & ~(CFG_CMD_FLASH)) | CFG_CMD_IDE) /* no Flash, but IDE */ +#define CONFIG_COMMANDS ((CONFIG_CMD_DFL | CFG_CMD_IDE) & ~(CFG_CMD_NET)) #else -#define CONFIG_COMMANDS \ - (CONFIG_CMD_DFL & ~(CFG_CMD_NET)) +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_IDE) #endif /* 0 */ #define CONFIG_BOOTP_MASK CONFIG_BOOTP_DEFAULT @@ -101,6 +101,7 @@ #define CFG_PB_SDRAM_CLKE 0x00008000 /* PB 16 */ #define CFG_PB_ETH_POWERDOWN 0x00010000 /* PB 15 */ +#define CFG_PB_IDE_MOTOR 0x00020000 /* PB 14 */ #define CFG_PC_ETH_RESET ((ushort)0x0010) /* PC 11 */ #define CFG_PC_IDE_RESET ((ushort)0x0020) /* PC 10 */ @@ -226,7 +227,7 @@ */ #define SCCR_MASK SCCR_EBDF11 /* 0x01800014 */ -#define CFG_SCCR (SCCR_COM00 | /*SCCR_TBS|*/ \ +#define CFG_SCCR (SCCR_COM01 | /*SCCR_TBS|*/ \ SCCR_RTDIV | SCCR_RTSEL | \ /*SCCR_CRQEN|*/ /*SCCR_PRQEN|*/ \ SCCR_EBDF00 | SCCR_DFSYNC00 | \ @@ -276,6 +277,27 @@ #define CFG_PCMCIA_IO_ADDR (0xEC000000) #define CFG_PCMCIA_IO_SIZE ( 64 << 20 ) +/*----------------------------------------------------------------------- + * IDE/ATA stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_IDE_PCMCIA 1 /* PCMCIA interface required */ +#if 0 +#define CONFIG_IDE_LED 1 /* LED for ide supported */ +#endif +#define CONFIG_IDE_RESET 1 /* reset for ide supported */ + +#define CFG_IDE_MAXBUS 1 /* The IVMS8 has only 1 IDE bus */ +#define CFG_IDE_MAXDEVICE 1 /* ... and only 1 IDE device */ + +#define CFG_ATA_BASE_ADDR 0xFE100000 +#define CFG_ATA_IDE0_OFFSET 0x0000 +#undef CFG_ATA_IDE1_OFFSET /* only one IDE bus available */ + +#define CFG_ATA_DATA_OFFSET 0x0000 /* Offset for data I/O */ +#define CFG_ATA_REG_OFFSET 0x0080 /* Offset for normal register accesses */ +#define CFG_ATA_ALT_OFFSET 0x0100 /* Offset for alternate registers */ + /*----------------------------------------------------------------------- * *----------------------------------------------------------------------- diff --git a/include/config_Sandpoint8240.h b/include/config_Sandpoint8240.h new file mode 100644 index 0000000..ba950f6 --- /dev/null +++ b/include/config_Sandpoint8240.h @@ -0,0 +1,222 @@ + + + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC8240 1 +#define CONFIG_SANDPOINT 1 + +#define CONFIG_BAUDRATE 9600 +#define CONFIG_DRAM_SPEED 100 /* MHz */ +#define CONFIG_BOOTCOMMAND "bootm FE020000" /* autoboot command */ +#define CONFIG_BOOTARGS " " + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL & ~CFG_CMD_NET) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + + +/* + * Miscellaneous configurable options + */ +#undef CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT ":>" /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 8 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFF00000 +#define CFG_FLASH_SIZE ((uint)(512 * 1024)) /* sandpoint has tiny eeprom */ + +#ifdef DEBUG + #define CFG_MONITOR_BASE CFG_SDRAM_BASE +#else + #define CFG_MONITOR_BASE CFG_FLASH_BASE +#endif + +#ifdef DEBUG +#define CFG_MONITOR_LEN (4 <<20) /* if we're running in ram, give us plenty of space for debug info*/ +#else +#define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ +#endif +#define CFG_MALLOC_LEN (512 << 10) /* Reserve 512 kB for malloc() */ + +#define CFG_TFTP_LOADADDR 0x00100000 /* default load address */ + +#define CFG_MEMTEST_START 0x00000000 /* memtest works on */ +#define CFG_MEMTEST_END 0x02000000 /* 0 ... 32 MB in DRAM */ + +#define CFG_EUMB_ADDR 0xFC000000 + +#define CFG_ISA_MEM 0xFD000000 +#define CFG_ISA_IO 0xFE000000 + +#define FLASH_BASE0_PRELIM 0xFFF00000 /* sandpoint flash */ +#define FLASH_BASE1_PRELIM 0xFF000000 /* PMC onboard flash*/ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR CFG_SDRAM_BASE + CFG_MONITOR_LEN +#define CFG_INIT_RAM_END 0x3000 /* End of used area in DPRAM */ +#define CFG_INIT_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_INIT_DATA_OFFSET (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_INIT_DATA_OFFSET + + +#define CFG_WINBOND_83C553 1 /*has a winbond bridge */ +#define CFG_USE_WINBOND_IDE 0 /*use winbond 83c553 internal ide controller */ +#define CFG_WINBOND_ISA_CFG_ADDR 0x80005800 /*pci-isa bridge config addr */ +#define CFG_WINBOND_IDE_CFG_ADDR 0x80005900 /*ide config addr */ +#define CFG_NS87308_BADDR_10 1 + + +#define CFG_NS_PC87308UL 1 /* Nat Semi super-io controller on ISA bus */ + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + + +#define CFG_ROMNAL 8 /*rom/flash next access time*/ +#define CFG_ROMFAL 16 /*rom/flash access time*/ + +#define CFG_REFINT 430 /* no of clock cycles between CBR refresh cycles*/ +/* the following are for SDRAM only*/ +#define CFG_BSTOPRE 604 /* Burst To Precharge, sets open page interval */ +#define CFG_REFREC 8 /* Refresh to activate interval */ +#define CFG_RDLAT 4 /* data latancy from read command*/ +#define CFG_PRETOACT 3 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 5 /* Activate to Precharge interval */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latancy */ +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type */ +#define CFG_SDMODE_BURSTLEN 2 /* SDMODE Burst length 2=4, 3=8 */ + +#define CFG_REGISTERD_TYPE_BUFFER 1 + +/* memory bank settings*/ +/* only bits 20-29 are actually used from these vales to set the stare/end address + the upper two bits will be 0, and the lower 20 bits will be set to + 0x00000 for a start address, or 0xfffff for an end address*/ + +#define CFG_BANK0_START 0x00000000 + +#define CFG_BANK0_END 0x01ffffff +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x01000000 +#define CFG_BANK1_END 0x00ffffff +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x02000000 +#define CFG_BANK2_END 0x02ffffff +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x03000000 +#define CFG_BANK3_END 0x03ffffff +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x04000000 +#define CFG_BANK4_END 0x04ffffff +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x05000000 +#define CFG_BANK5_END 0x05ffffff +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x06000000 +#define CFG_BANK6_END 0x06ffffff +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x07000000 +#define CFG_BANK7_END 0x07ffffff +#define CFG_BANK7_ENABLE 0 + +#define CFG_ODCR 0xff /* configures line driver impedances, + see 8240 book for bit definitions */ +#define CFG_PGMAX 0x32 /* how long the 8240 reatins the currently accessed page in memory + see 8240 book for details*/ +#define CFG_IBAT0L FLASH_BASE0_PRELIM | BATL_CACHEINHIBIT | BATL_PP_10 +#define CFG_IBAT0U FLASH_BASE0_PRELIM | BATU_BL_16M | BATU_VS | BATU_VP +#define CFG_IBAT1L 0x00000000 | BATL_CACHEINHIBIT | BATL_PP_10 +#define CFG_IBAT1U 0x00000000 | BATU_BL_128M | BATU_VS | BATU_VP +#define CFG_IBAT2L CFG_ISA_MEM | BATL_MEMCOHERENCE | BATL_PP_10 +#define CFG_IBAT2U CFG_ISA_MEM | BATU_BL_16M | BATU_VS | BATU_VP +#define CFG_IBAT3L CFG_ISA_IO | BATL_MEMCOHERENCE | BATL_PP_10 +#define CFG_IBAT3U CFG_ISA_IO | BATU_BL_16M | BATU_VS | BATU_VP +#define CFG_DBAT0L FLASH_BASE0_PRELIM | BATL_MEMCOHERENCE | BATL_WRITETHROUGH | BATL_PP_10 +#define CFG_DBAT0U FLASH_BASE0_PRELIM | BATU_BL_16M | BATU_VS | BATU_VP +#define CFG_DBAT1L 0x00000000 | BATL_MEMCOHERENCE | BATL_WRITETHROUGH | BATL_PP_10 +#define CFG_DBAT1U 0x00000000 | BATU_BL_128M | BATU_VS | BATU_VP +#define CFG_DBAT2L CFG_ISA_MEM | BATL_MEMCOHERENCE | BATL_PP_10 +#define CFG_DBAT2U CFG_ISA_MEM | BATU_BL_16M | BATU_VS | BATU_VP +#define CFG_DBAT3L CFG_ISA_IO | BATL_MEMCOHERENCE | BATL_PP_10 +#define CFG_DBAT3U CFG_ISA_IO | BATU_BL_16M | BATU_VS | BATU_VP + + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 8 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_ENV_ALIGN 15 /* Bitshift for Environment Sector */ +#define CFG_FLASH_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ +/* the other CS:s are determined by looking at parameters in BCSRx */ + +/* values according to the manual */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 16 /* For all MPC8xx CPUs */ + + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +/* values according to the manual */ + +#define CONFIG_DRAM_50MHZ 1 +#define CONFIG_SDRAM_50MHZ + +#undef NR_8259_INTS +#define NR_8259_INTS 1 + + +#define CONFIG_DISK_SPINUP_TIME 1000000 + + +#endif /* __CONFIG_H */ diff --git a/include/config_TQM850L.h b/include/config_TQM850L.h index 3770d5f..9f01771 100644 --- a/include/config_TQM850L.h +++ b/include/config_TQM850L.h @@ -60,6 +60,8 @@ #undef CONFIG_WATCHDOG /* watchdog disabled */ +#define CONFIG_STATUS_LED 1 /* Status LED enabled */ + #define CONFIG_BOOTP_MASK CONFIG_BOOTP_DEFAULT /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h new file mode 100755 index 0000000..227feeb --- /dev/null +++ b/include/linux/mc146818rtc.h @@ -0,0 +1,98 @@ +/* mc146818rtc.h - register definitions for the Real-Time-Clock / CMOS RAM + * Copyright Torsten Duwe 1993 + * derived from Data Sheet, Copyright Motorola 1984 (!). + * It was written to be part of the Linux operating system. + */ +/* permission is hereby granted to copy, modify and redistribute this code + * in terms of the GNU Library General Public License, Version 2 or later, + * at your option. + */ + +#ifndef _MC146818RTC_H +#define _MC146818RTC_H + +#include +#include /* get the user-level API */ +#include /* register access macros */ + +/********************************************************************** + * register summary + **********************************************************************/ +#define RTC_SECONDS 0 +#define RTC_SECONDS_ALARM 1 +#define RTC_MINUTES 2 +#define RTC_MINUTES_ALARM 3 +#define RTC_HOURS 4 +#define RTC_HOURS_ALARM 5 +/* RTC_*_alarm is always true if 2 MSBs are set */ +# define RTC_ALARM_DONT_CARE 0xC0 + +#define RTC_DAY_OF_WEEK 6 +#define RTC_DAY_OF_MONTH 7 +#define RTC_MONTH 8 +#define RTC_YEAR 9 + +/* control registers - Moto names + */ +#define RTC_REG_A 10 +#define RTC_REG_B 11 +#define RTC_REG_C 12 +#define RTC_REG_D 13 + +/********************************************************************** + * register details + **********************************************************************/ +#define RTC_FREQ_SELECT RTC_REG_A + +/* update-in-progress - set to "1" 244 microsecs before RTC goes off the bus, + * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete, + * totalling to a max high interval of 2.228 ms. + */ +# define RTC_UIP 0x80 +# define RTC_DIV_CTL 0x70 + /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */ +# define RTC_REF_CLCK_4MHZ 0x00 +# define RTC_REF_CLCK_1MHZ 0x10 +# define RTC_REF_CLCK_32KHZ 0x20 + /* 2 values for divider stage reset, others for "testing purposes only" */ +# define RTC_DIV_RESET1 0x60 +# define RTC_DIV_RESET2 0x70 + /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */ +# define RTC_RATE_SELECT 0x0F + +/**********************************************************************/ +#define RTC_CONTROL RTC_REG_B +# define RTC_SET 0x80 /* disable updates for clock setting */ +# define RTC_PIE 0x40 /* periodic interrupt enable */ +# define RTC_AIE 0x20 /* alarm interrupt enable */ +# define RTC_UIE 0x10 /* update-finished interrupt enable */ +# define RTC_SQWE 0x08 /* enable square-wave output */ +# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ +# define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ +# define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ + +/**********************************************************************/ +#define RTC_INTR_FLAGS RTC_REG_C +/* caution - cleared by read */ +# define RTC_IRQF 0x80 /* any of the following 3 is active */ +# define RTC_PF 0x40 +# define RTC_AF 0x20 +# define RTC_UF 0x10 + +/**********************************************************************/ +#define RTC_VALID RTC_REG_D +# define RTC_VRT 0x80 /* valid RAM and time */ +/**********************************************************************/ + +/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) + * determines if the following two #defines are needed + */ +#ifndef BCD_TO_BIN +#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) +#endif + +#ifndef BIN_TO_BCD +#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) +#endif + +#endif /* _MC146818RTC_H */ diff --git a/include/mpc8240.h b/include/mpc8240.h new file mode 100755 index 0000000..f1b8f3a --- /dev/null +++ b/include/mpc8240.h @@ -0,0 +1,392 @@ +/* + * Copyright Rob Taylor, Flying Pig Systems Ltd. 2000. + * + * 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 __MPC8240_H__ +#define __MPC8240_H__ + +/*----------------------------------------------------------------------- + * Exception offsets (PowerPC standard) + */ +#define EXC_OFF_RESERVED0 0x0000 /* Reserved */ +#define EXC_OFF_SYS_RESET 0x0100 /* System reset */ +#define EXC_OFF_MACH_CHCK 0x0200 /* Machine Check */ +#define EXC_OFF_DATA_STOR 0x0300 /* Data Storage */ +#define EXC_OFF_INS_STOR 0x0400 /* Instruction Storage */ +#define EXC_OFF_EXTERNAL 0x0500 /* External */ +#define EXC_OFF_ALIGN 0x0600 /* Alignment */ +#define EXC_OFF_PROGRAM 0x0700 /* Program */ +#define EXC_OFF_FPUNAVAIL 0x0800 /* Floating-point Unavailable */ +#define EXC_OFF_DECR 0x0900 /* Decrementer */ +#define EXC_OFF_RESERVED1 0x0A00 /* Reserved */ +#define EXC_OFF_RESERVED2 0x0B00 /* Reserved */ +#define EXC_OFF_SYS_CALL 0x0C00 /* System Call */ +#define EXC_OFF_TRACE 0x0D00 /* Trace */ +#define EXC_OFF_FPUNASSIST 0x0E00 /* Floating-point Assist */ + + /* 0x0E10 - 0x0FFF are marked reserved in The PowerPC Architecture book */ + /* these found in DINK code - may not apply to 8240*/ +#define EXC_OFF_PMI 0x0F00 /* Performance Monitoring Interrupt */ +#define EXC_OFF_VMXUI 0x0F20 /* VMX (AltiVec) Unavailable Interrupt */ + + /* 0x1000 - 0x2FFF are implementation specific */ + /* these found in DINK code - may not apply to 8240 */ +#define EXC_OFF_ITME 0x1000 /* Instruction Translation Miss Exception */ +#define EXC_OFF_DLTME 0x1100 /* Data Load Translation Miss Exception */ +#define EXC_OFF_DSTME 0x1200 /* Data Store Translation Miss Exception */ +#define EXC_OFF_IABE 0x1300 /* Instruction Address Breakpoint Exception */ +#define EXC_OFF_SMIE 0x1400 /* System Management Interrupt Exception */ +#define EXC_OFF_JMDDI 0x1600 /* Java Mode denorm detection Interrupt -- WTF??*/ +#define EXC_OFF_RMTE 0x2000 /* Run Mode or Trace Exception */ + +#define MAP_A_CONFIG_ADDR_HIGH 0x8000 /* Upper half of CONFIG_ADDR for Map A */ +#define MAP_A_CONFIG_ADDR_LOW 0x0CF8 /* Lower half of CONFIG_ADDR for Map A */ +#define MAP_A_CONFIG_DATA_HIGH 0x8000 /* Upper half of CONFIG_DAT for Map A */ +#define MAP_A_CONFIG_DATA_LOW 0x0CFC /* Lower half of CONFIG_DAT for Map A */ +#define MAP_B_CONFIG_ADDR_HIGH 0xfec0 /* Upper half of CONFIG_ADDR for Map B */ +#define MAP_B_CONFIG_ADDR_LOW 0x0000 /* Lower half of CONFIG_ADDR for Map B */ +#define MAP_B_CONFIG_DATA_HIGH 0xfee0 /* Upper half of CONFIG_DAT for Map B */ +#define MAP_B_CONFIG_DATA_LOW 0x0000 /* Lower half of CONFIG_DAT for Map B */ + + +#if defined(CFG_ADDR_MAP_A) +#define CONFIG_ADDR_HIGH MAP_A_CONFIG_ADDR_HIGH /* Upper half of CONFIG_ADDR */ +#define CONFIG_ADDR_LOW MAP_A_CONFIG_ADDR_LOW /* Lower half of CONFIG_ADDR */ +#define CONFIG_DATA_HIGH MAP_A_CONFIG_DATA_HIGH /* Upper half of CONFIG_DAT */ +#define CONFIG_DATA_LOW MAP_A_CONFIG_DATA_LOW /* Lower half of CONFIG_DAT */ +#else /* Assume Map B, default */ +#define CONFIG_ADDR_HIGH MAP_B_CONFIG_ADDR_HIGH /* Upper half of CONFIG_ADDR */ +#define CONFIG_ADDR_LOW MAP_B_CONFIG_ADDR_LOW /* Lower half of CONFIG_ADDR */ +#define CONFIG_DATA_HIGH MAP_B_CONFIG_DATA_HIGH /* Upper half of CONFIG_DAT */ +#define CONFIG_DATA_LOW MAP_B_CONFIG_DATA_LOW /* Lower half of CONFIG_DAT */ +#endif + +#define CONFIG_ADDR (CONFIG_ADDR_HIGH << 16 | CONFIG_ADDR_LOW) + +#define CONFIG_DATA (CONFIG_DATA_HIGH << 16 | CONFIG_DATA_LOW) + +/*macros to wite to conif registers. addr should be a constant in all cases */ + +#define CONFIG_WRITE_BYTE( addr, data ) \ + __asm__ ( \ + " stwbrx %1, 0, %0\n \ + sync\n \ + stb %3, %4(%2)\n \ + sync " \ + : /* no output */ \ + : "r" (CONFIG_ADDR), "r" ((addr) & ~3), \ + "r" (CONFIG_DATA), "r" (data), \ + "n" ((addr) & 3)); + +#define CONFIG_WRITE_HALFWORD( addr, data ) \ + __asm__ ( \ + " stwbrx %1, 0, %0\n \ + sync\n \ + stwbrx %3, %4, %2\n \ + sync " \ + : /* no output */ \ + : "r" (CONFIG_ADDR), "r" (addr), \ + "r" (CONFIG_DATA), "r" (data), \ + "n" ((addr) & 3)); + +/* this assumes it's writeing on word boundaries*/ +#define CONFIG_WRITE_WORD( addr, data ) \ + __asm__ ( \ + " stwbrx %1, 0, %0\n \ + sync\n \ + stwbrx %3, 0, %2\n \ + sync " \ + : /* no output */ \ + : "r" (CONFIG_ADDR), "r" (addr), \ + "r" (CONFIG_DATA), "r" (data)); + +/* Configuration register reads*/ + +#define CONFIG_READ_BYTE( addr , reg ) \ + __asm__ ( \ + " stwbrx %1, 0, %2\n \ + sync\n \ + lbz %0, %4(%3)\n \ + sync " \ + : "=r" (reg) \ + : "r" ((addr) & ~3), "r" (CONFIG_ADDR), \ + "r" (CONFIG_DATA), "n" ((addr) & 3)); + + +#define CONFIG_READ_HALFWORD( addr , reg ) \ + __asm__ ( \ + " stwbrx %1, 0, %2\n \ + sync\n \ + lhbrx %0, %4, %3\n \ + sync " \ + : "=r" (reg) \ + : "r" (addr), "r" (CONFIG_ADDR), \ + "r" (CONFIG_DATA), \ + "n" ((addr)&3)); + +/* this assumes it's reading on word boundaries*/ +#define CONFIG_READ_WORD( addr , reg ) \ + __asm__ ( \ + " stwbrx %1, 0, %2\n \ + sync\n \ + lwbrx %0, 0, %3\n \ + sync " \ + : "=r" (reg) \ + : "r" (addr), "r" (CONFIG_ADDR),\ + "r" (CONFIG_DATA)); + +/* + configuration register 'addresses'. + These are described in chaper 5 of the 8240 users manual. + Where the register has an abreviation in the manual, this has been usaed here, + otherwise a name in keeping with the norm has been invented, + Note that some of these registers aren't documented in the manual +*/ + +#define PCICR 0x80000004 /* PCI Command Register */ +#define PCISR 0x80000006 /* PCI Status Register */ +#define PIR 0x80000009 /* PCI Programming Interface Register */ +#define PBCCR 0x8000000b /* PCI Base Class Code Register */ +#define PCLSR 0x8000000c /* Processor Cache Line Size Register */ +#define PLTR 0x8000000d /* PCI Latancy Timer Register */ +#define PHTR 0x8000000e /* PCI Header Type Register */ +#define BISTCTRL 0x8000000f /* BIST Control */ +#define LMBAR 0x80000010 /* Local Base Addres Register */ +#define PCSRBAR 0x80000014 /* PCSR Base Address Register */ +#define ILR 0x8000003c /* PCI Interrupt Line Register */ +#define IPR 0x8000003d /* Interrupt Pin Register */ +#define MINGNT 0x8000003e /* MIN GNI */ +#define MAXLAT 0x8000003f /* MAX LAT */ +#define PCIACR 0x80000046 /* PCI Arbiter Control Register */ +#define PMCR1 0x80000070 /* Power management config. 1 */ +#define PMCR2 0x80000072 /* Power management config. 2 */ +#define ODCR 0x80000073 /* Output Driver Control Register */ +#define CLKDCR 0x80000074 /* CLK Driver Control Register */ +#define EUMBBAR 0x80000078 /* Embedded Utilities Memory Block Base Address Register */ +#define MSAR1 0x80000080 /* Memory Starting Address Register 1 */ +#define MSAR2 0x80000084 /* Memory Starting Address Register 2 */ +#define EMSAR1 0x80000088 /* Extended Memory Starting Address Register 1*/ +#define EMSAR2 0x8000008c /* Extended Memory Starting Address Register 2*/ +#define MEAR1 0x80000090 /* Memory Ending Address Register 1 */ +#define MEAR2 0x80000094 /* Memory Ending Address Register 2 */ +#define EMEAR1 0x80000098 /* Extended Memory Ending Address Register 1 */ +#define EMEAR2 0x8000009c /* Extended Memory Ending Address Register 2 */ +#define MBER 0x800000a0 /* Memory bank Enable Register*/ +#define MPMR 0x800000a3 /* Memory Page Mode Register (stores PGMAX) */ +#define PICR1 0x800000a8 /* Processor Interface Configuration Register 1 */ +#define PICR2 0x800000ac /* Processor Interface Configuration Register 2 */ +#define ECCSBECR 0x800000b8 /* ECC Single-Bit Error Counter Register */ +#define ECCSBETR 0x800000b8 /* ECC Single-Bit Error Trigger Register */ +#define ERRENR1 0x800000c0 /* Error Enableing Register 1 */ +#define ERRENR2 0x800000c0 /* Error Enableing Register 2 */ +#define ERRDR1 0x800000c1 /* Error Detection Register 1 */ +#define IPBESR 0x800000c3 /* Internal Processor Error Status Register */ +#define ERRDR2 0x800000c5 /* Error Detection Register 2 */ +#define PBESR 0x800000c7 /* PCI Bus Error Status Register */ +#define PBEAR 0x800000c8 /* Processor/PCI Bus Error Status Register */ +#define AMBOR 0x800000e0 /* Address Map B Options Register */ +#define MCCR1 0x800000f0 /* Memory Control Configuration Register 1 */ +#define MCCR2 0x800000f4 /* Memory Control Configuration Register 2 */ +#define MCCR3 0x800000f8 /* Memory Control Configuration Register 3 */ +#define MCCR4 0x800000fc /* Memory Control Configuration Register 4 */ + +/* some values for soem of the above */ + +#define PICR1_CF_APARK 0x00000008 +#define PICR1_LE_MODE 0x00000020 +#define PICR1_ST_GATH_EN 0x00000040 +#define PICR1_EN_PCS 0x00000080 /* according to dink code, sets the 8240 to handle pci config space */ +#define PICR1_CF_DPARK 0x00000200 +#define PICR1_MCP_EN 0x00000800 +#define PICR1_FLASH_WR_EN 0x00001000 +#define PICR1_ADDRESS_NAP 0x00010000 +#define PICR1_PROC_TYPE_MSK 0x00060000 +#define PICR1_PROC_TYPE_603E 0x00040000 +#define PICR1_RCS0 0x00100000 +#define PIRC1_MSK 0xff000000 + +#define PICR2_CF_SNOOP_WS_MASK 0x000c0000 +#define PICR2_CF_SNOOP_WS_0WS 0x00000000 +#define PICR2_CF_SNOOP_WS_1WS 0x00040000 +#define PICR2_CF_SNOOP_WS_2WS 0x00080000 +#define PICR2_CF_SNOOP_WS_3WS 0x000c0000 +#define PICR2_CF_APHASE_WS_MASK 0x0000000c +#define PICR2_CF_APHASE_WS_0WS 0x00000000 +#define PICR2_CF_APHASE_WS_1WS 0x00000004 +#define PICR2_CF_APHASE_WS_2WS 0x00000008 +#define PICR2_CF_APHASE_WS_3WS 0x0000000c + +#define MCCR1_ROMNAL_SHIFT 28 +#define MCCR1_ROMNAL_MSK 0xf0000000 +#define MCCR1_ROMFAL_SHIFT 23 +#define MCCR1_ROMFAL_MSK 0x0f800000 +#define MCCR1_BURST 0x00100000 +#define MCCR1_MEMGO 0x00080000 +#define MCCR1_SREN 0x00040000 +#define MCCR1_RAM_TYPE 0x00020000 +#define MCCR1_PCKEN 0x00010000 + +#define MCCR2_TS_WAIT_TIMER_MSK 0xe0000000 +#define MCCR2_TS_WAIT_TIMER_SHIFT 29 +#define MCCR2_ASRISE_MSK 0x1e000000 +#define MCCR2_ASRISE_SHIFT 25 +#define MCCR2_ASFALL_MSK 0x01e00000 +#define MCCR2_ASFALL_SHIFT 21 + +#define MCCR2_INLINE_PAR_NOT_ECC 0x00100000 +#define MCCR2_WRITE_PARITY_CHK 0x00080000 +#define MCCR2_INLFRD_PARECC_CHK_EN 0x00040000 +#define MCCR2_ECC_EN 0x00020000 +#define MCCR2_EDO 0x00010000 +#define MCCR2_REFINT_MSK 0x0000fffc +#define MCCR2_REFINT_SHIFT 2 +#define MCCR2_RSV_PG 0x00000002 +#define MCCR2_PMW_PAR 0x00000001 + +#define MCCR3_BSTOPRE2TO5_MSK 0xf0000000 /*BSTOPRE[2-5]*/ +#define MCCR3_BSTOPRE2TO5_SHIFT 28 +#define MCCR3_REFREC_MSK 0x0f000000 +#define MCCR3_REFREC_SHIFT 24 +#define MCCR3_RDLAT_MSK 0x00f00000 +#define MCCR3_RDLAT_SHIFT 20 +#define MCCR3_CPX 0x00010000 +#define MCCR3_RAS6P_MSK 0x00078000 +#define MCCR3_RAS6P_SHIFT 15 +#define MCCR3_CAS5_MSK 0x00007000 +#define MCCR3_CAS5_SHIFT 12 +#define MCCR3_CP4_MSK 0x00000e00 +#define MCCR3_CP4_SHIFT 9 +#define MCCR3_CAS3_MSK 0x000001c0 +#define MCCR3_CAS3_SHIFT 6 +#define MCCR3_RCD2_MSK 0x00000038 +#define MCCR3_RCD2_SHIFT 3 +#define MCCR3_RP1_MSK 0x00000007 +#define MCCR3_RP1_SHIFT 0 + +#define MCCR4_PRETOACT_MSK 0xf0000000 +#define MCCR4_PRETOACT_SHIFT 28 +#define MCCR4_ACTTOPRE_MSK 0x0f000000 +#define MCCR4_ACTTOPRE_SHIFT 24 +#define MCCR4_WMODE 0x00800000 +#define MCCR4_INLINE 0x00400000 +#define MCCR4_BIT21 0x00200000 /* this include cos DINK code sets it- unknown function*/ +#define MCCR4_REGISTERED 0x00100000 +#define MCCR4_BSTOPRE0TO1_MSK 0x000c0000 /*BSTOPRE[0-1]*/ +#define MCCR4_BSTOPRE0TO1_SHIFT 18 +#define MCCR4_REGDIMM 0x00008000 +#define MCCR4_SDMODE_MSK 0x00007f00 +#define MCCR4_SDMODE_SHIFT 8 +#define MCCR4_ACTTORW_MSK 0x000000f0 +#define MCCR4_ACTTORW_SHIFT 4 +#define MCCR4_BSTOPRE6TO9_MSK 0x0000000f /*BSTOPRE[0-1]*/ +#define MCCR4_BSTOPRE6TO9_SHIFT 0 + +#define MICR_ADDR_MASK 0x0ff00000 +#define MICR_EADDR_MASK 0x30000000 + +#define BATU_BEPI_MSK 0xfffe0000 +#define BATU_BL_MSK 0x00001ffc + +#define BATU_BL_128K 0x00000000 +#define BATU_BL_256K 0x00000004 +#define BATU_BL_512K 0x0000000c +#define BATU_BL_1M 0x0000001c +#define BATU_BL_2M 0x0000003c +#define BATU_BL_4M 0x0000007c +#define BATU_BL_8M 0x000000fc +#define BATU_BL_16M 0x000001fc +#define BATU_BL_32M 0x000003fc +#define BATU_BL_64M 0x000007fc +#define BATU_BL_128M 0x00000ffc +#define BATU_BL_256M 0x00001ffc + +#define BATU_VS 0x00000002 +#define BATU_VP 0x00000001 + +#define BATL_BRPN_MSK 0xfffe0000 +#define BATL_WIMG_MSK 0x00000078 +#define BATL_WRITETHROUGH 0x00000008 +#define BATL_CACHEINHIBIT 0x00000010 +#define BATL_MEMCOHERENCE 0x00000020 +#define BATL_GUARDEDSTORAGE 0x00000040 +#define BATL_PP_MSK 0x00000003 +#define BATL_PP_00 0x00000000 +#define BATL_PP_01 0x00000001 +#define BATL_PP_10 0x00000002 +#define BATL_PP_11 0x00000003 + +/* I'd attempt to do defines for the PP bits, but it's use is a bit too complex, + * see the PowerPC Operating Environment Architecture section in the PowerPc arch book. + * chapter 4 + */ + +/*eumb and epic config*/ + +#define EPIC_FPR 0x00041000 +#define EPIC_GCR 0x00041020 +#define EPIC_EICR 0x00041030 +#define EPIC_EVI 0x00041080 +#define EPIC_PI 0x00041090 +#define EPIC_SVR 0x000410E0 +#define EPIC_TFRR 0x000410F0 + +/*note the information for these is rather mangled in the 8240 manual. these are guesses*/ +#define EPIC_GTCCR0 0x00041100 +#define EPIC_GTCCR1 0x00041140 +#define EPIC_GTCCR2 0x00041180 +#define EPIC_GTCCR3 0x000411C0 +#define EPIC_GTBCR0 0x00041110 +#define EPIC_GTBCR1 0x00041150 +#define EPIC_GTBCR2 0x00041190 +#define EPIC_GTBCR3 0x000411D0 +#define EPIC_GTVPR0 0x00041120 +#define EPIC_GTVPR1 0x00041160 +#define EPIC_GTVPR2 0x000411a0 +#define EPIC_GTVPR3 0x000411e0 +#define EPIC_GTDR0 0x00041130 +#define EPIC_GTDR1 0x00041170 +#define EPIC_GTDR2 0x000411b0 +#define EPIC_GTDR3 0x000411f0 + +#define EPIC_IVPR0 0x00050200 +#define EPIC_IVPR1 0x00050220 +#define EPIC_IVPR2 0x00050240 +#define EPIC_IVPR3 0x00050260 +#define EPIC_IVPR4 0x00050280 + +#define EPIC_SVPR0 0x00050200 +#define EPIC_SVPR1 0x00050220 +#define EPIC_SVPR2 0x00050240 +#define EPIC_SVPR3 0x00050260 +#define EPIC_SVPR4 0x00050280 +#define EPIC_SVPR5 0x000502A0 +#define EPIC_SVPR6 0x000502C0 +#define EPIC_SVPR7 0x000502E0 +#define EPIC_SVPR8 0x00050300 +#define EPIC_SVPR9 0x00050320 +#define EPIC_SVPRa 0x00050340 +#define EPIC_SVPRb 0x00050360 +#define EPIC_SVPRc 0x00050380 +#define EPIC_SVPRd 0x000503A0 +#define EPIC_SVPRe 0x000503C0 +#define EPIC_SVPRf 0x000503E0 + +#endif /* __MPC8240_H__ */ diff --git a/include/pcmcia.h b/include/pcmcia.h index 1f03376..3cf43bc 100644 --- a/include/pcmcia.h +++ b/include/pcmcia.h @@ -24,6 +24,100 @@ #ifndef _PCMCIA_H #define _PCMCIA_H +#include +#include + +#ifdef CONFIG_IDE_PCMCIA +/* + * Allow configuration to select PCMCIA slot, + * or try to generate a useful default + */ +#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) + + /* The RPX series use SLOT_B */ +#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE) +# define CONFIG_PCMCIA_SLOT_B +#elif defined(CONFIG_ADS) /* The ADS board use SLOT_A */ +# define CONFIG_PCMCIA_SLOT_A +#elif defined(CONFIG_FADS) /* The FADS series are a mess */ +# if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821) +# define CONFIG_PCMCIA_SLOT_A +# else +# define CONFIG_PCMCIA_SLOT_B +# endif +#elif defined(CONFIG_TQM860L) || defined(CONFIG_TQM855L) /* The TQM8xxL modules */ +# define CONFIG_PCMCIA_SLOT_A /* ... use SLOT_A on MPC860/855 */ +#elif defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) +# define CONFIG_PCMCIA_SLOT_B /* ... and SLOT_B else */ +#elif defined(CONFIG_SPD823TS) /* The SPD8xx use SLOT_B */ +# define CONFIG_PCMCIA_SLOT_B +#elif defined(CONFIG_IVMS8) /* The IVMS8 use SLOT_A */ +# define CONFIG_PCMCIA_SLOT_A +#else +# error "PCMCIA Slot not configured" +#endif + +#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */ + +/* Make sure exactly one slot is defined - we support only one for now */ +#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) +#error Neither CONFIG_PCMCIA_SLOT_A nor CONFIG_PCMCIA_SLOT_B configured +#endif +#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B) +#error Both CONFIG_PCMCIA_SLOT_A and CONFIG_PCMCIA_SLOT_B configured +#endif + +#define PCMCIA_SOCKETS_NO 1 +#define PCMCIA_MEM_WIN_NO 4 +#define PCMCIA_IO_WIN_NO 2 + +/* define _slot_ to be able to optimize macros */ +#ifdef CONFIG_PCMCIA_SLOT_A +# define _slot_ 0 +# define PCMCIA_SLOT_MSG "SLOT_A" +# define PCMCIA_SLOT_x PCMCIA_PSLOT_A +#else +# define _slot_ 1 +# define PCMCIA_SLOT_MSG "SLOT_B" +# define PCMCIA_SLOT_x PCMCIA_PSLOT_B +#endif + +/* + * The TQM850L hardware has two pins swapped! Grrrrgh! + */ +#ifdef CONFIG_TQM850L +#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXOE +#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXRESET +#else +#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXRESET +#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXOE +#endif + +/* look up table for pgcrx registers */ + +#if 0 +static u_int *pcmcia_pgcrx[2] = { + &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra, + &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb, +}; + +#define PCMCIA_PGCRX(slot) (*pcmcia_pgcrx[slot]) +#endif + +/* + * This structure is used to address each window in the PCMCIA controller. + * + * Keep in mind that we assume that pcmcia_win_t[n+1] is mapped directly + * after pcmcia_win_t[n]... + */ + +typedef struct { + ulong br; + ulong or; +} pcmcia_win_t; + +#endif /* CONFIG_IDE_PCMCIA */ + /* * Definitions for PCMCIA control registers to operate in IDE mode * @@ -32,7 +126,7 @@ */ /* Window 0: - * Base: 0x04100000 CS1 + * Base: 0xFE100000 CS1 * Port Size: 2 Bytes * Port Size: 16 Bit * Common Memory Space @@ -42,12 +136,12 @@ #define CFG_PCMCIA_POR0 ( PCMCIA_BSIZE_2 \ | PCMCIA_PPS_16 \ | PCMCIA_PRS_MEM \ - | PCMCIA_PSLOT_B \ + | PCMCIA_SLOT_x \ | PCMCIA_PV \ ) /* Window 1: - * Base: 0x04100080 CS1 + * Base: 0xFE100080 CS1 * Port Size: 8 Bytes * Port Size: 8 Bit * Common Memory Space @@ -57,12 +151,12 @@ #define CFG_PCMCIA_POR1 ( PCMCIA_BSIZE_8 \ | PCMCIA_PPS_8 \ | PCMCIA_PRS_MEM \ - | PCMCIA_PSLOT_B \ + | PCMCIA_SLOT_x \ | PCMCIA_PV \ ) /* Window 2: - * Base: 0x04100100 CS2 + * Base: 0xFE100100 CS2 * Port Size: 8 Bytes * Port Size: 8 Bit * Common Memory Space @@ -72,7 +166,7 @@ #define CFG_PCMCIA_POR2 ( PCMCIA_BSIZE_8 \ | PCMCIA_PPS_8 \ | PCMCIA_PRS_MEM \ - | PCMCIA_PSLOT_B \ + | PCMCIA_SLOT_x \ | PCMCIA_PV \ ) @@ -83,7 +177,7 @@ #define CFG_PCMCIA_POR3 0 /* Window 4: - * Base: 0x041000C00 CS1 + * Base: 0xFE100C00 CS1 * Port Size: 2 Bytes * Port Size: 16 Bit * Common Memory Space @@ -93,12 +187,12 @@ #define CFG_PCMCIA_POR4 ( PCMCIA_BSIZE_2 \ | PCMCIA_PPS_16 \ | PCMCIA_PRS_MEM \ - | PCMCIA_PSLOT_B \ + | PCMCIA_SLOT_x \ | PCMCIA_PV \ ) /* Window 5: - * Base: 0x04100C80 CS1 + * Base: 0xFE100C80 CS1 * Port Size: 8 Bytes * Port Size: 8 Bit * Common Memory Space @@ -108,12 +202,12 @@ #define CFG_PCMCIA_POR5 ( PCMCIA_BSIZE_8 \ | PCMCIA_PPS_8 \ | PCMCIA_PRS_MEM \ - | PCMCIA_PSLOT_B \ + | PCMCIA_SLOT_x \ | PCMCIA_PV \ ) /* Window 6: - * Base: 0x04100D00 CS2 + * Base: 0xFE100D00 CS2 * Port Size: 8 Bytes * Port Size: 8 Bit * Common Memory Space @@ -123,7 +217,7 @@ #define CFG_PCMCIA_POR6 ( PCMCIA_BSIZE_8 \ | PCMCIA_PPS_8 \ | PCMCIA_PRS_MEM \ - | PCMCIA_PSLOT_B \ + | PCMCIA_SLOT_x \ | PCMCIA_PV \ ) diff --git a/include/ppc_asm.tmpl b/include/ppc_asm.tmpl index d83ec19..63000b1 100644 --- a/include/ppc_asm.tmpl +++ b/include/ppc_asm.tmpl @@ -96,7 +96,7 @@ #define r31 31 -#if defined(CONFIG_8xx) +#if defined(CONFIG_8xx) || defined(CONFIG_MPC8240) /* Some special registers */ @@ -108,6 +108,9 @@ #define LCTRL2 157 /* Load/Store Support (37-41) */ #define ICTRL 158 +#endif /* CONFIG_8xx, CONFIG_MPC8240 */ + +#if defined(CONFIG_8xx) /* Registers in the processor's internal memory map that we use. */ diff --git a/include/status_led.h b/include/status_led.h new file mode 100644 index 0000000..8c97cb6 --- /dev/null +++ b/include/status_led.h @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +/* + * The purpose of this code is to signal the operational status of a + * target which usually boots over the network; while running in + * PCBoot, a status LED is blinking. As soon as a valid BOOTP reply + * message has been received, the LED is turned off. The Linux + * kernel, once it is running, will start blinking the LED again, + * with another frequency. + */ + +#ifndef _STATUS_LED_H_ +#define _STATUS_LED_H_ + +#ifdef CONFIG_STATUS_LED + + +#if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) || \ + defined(CONFIG_TQM855L) || defined(CONFIG_TQM860L) + +# define STATUS_LED_PAR im_cpm.cp_pbpar +# define STATUS_LED_DIR im_cpm.cp_pbdir +# define STATUS_LED_ODR im_cpm.cp_pbodr +# define STATUS_LED_DAT im_cpm.cp_pbdat + +# define STATUS_LED_BIT 0x00000001 + +# define STATUS_LED_PERIOD 500 + +#elif defined(CONFIG_ETX094) + +# define STATUS_LED_PAR im_ioport.iop_pdpar +# define STATUS_LED_DIR im_ioport.iop_pddir +# undef STATUS_LED_ODR +# define STATUS_LED_DAT im_ioport.iop_pddat + +# define STATUS_LED_BIT 0x00000001 + +# define STATUS_LED_PERIOD 500 + +#else +# error Status LED configuration missing +#endif + +#define STATUS_LED_OFF 0 +#define STATUS_LED_BLINKING 1 +#define STATUS_LED_ON 2 + +void status_led_tick (unsigned long timestamp); +void status_led_set (int state); + + +#endif /* CONFIG_STATUS_LED */ +#endif /* _STATUS_LED_H_ */ diff --git a/ivms8/ivms8.c b/ivms8/ivms8.c index 04f242d..4e77c6e 100644 --- a/ivms8/ivms8.c +++ b/ivms8/ivms8.c @@ -174,11 +174,13 @@ initdram (int board_type) memctl->memc_br2 = CFG_BR2; #endif +#if 0 /* * Map controller bank 4 to the PER8 bank. */ memctl->memc_or4 = CFG_OR4; memctl->memc_br4 = CFG_BR4; +#endif #if 0 /* Configure SHARC at UMA */ diff --git a/mpc8240/Makefile b/mpc8240/Makefile new file mode 100644 index 0000000..0bb8a01 --- /dev/null +++ b/mpc8240/Makefile @@ -0,0 +1,44 @@ +# +# (C) Copyright 2000 +# 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 +# + +include $(TOPDIR)/config.mk + +LIB = lib$(CPU).a + +START = start.S +OBJS = traps.o cpu.o cpu_init.o interrupts.o \ + drivers/epic/epic1.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/mpc8240/config.mk b/mpc8240/config.mk new file mode 100644 index 0000000..05222ea --- /dev/null +++ b/mpc8240/config.mk @@ -0,0 +1,26 @@ +# +# (C) Copyright 2000 +# 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_RELFLAGS += -ffixed-r14 + +PLATFORM_CPPFLAGS += -DCONFIG_MPC8240 -ffixed-r2 -mstring -mcpu=603e -msoft-float diff --git a/mpc8240/cpu.c b/mpc8240/cpu.c new file mode 100644 index 0000000..85acc65 --- /dev/null +++ b/mpc8240/cpu.c @@ -0,0 +1,111 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +#include +#include +#include + +int checkcpu(long clock) +{ + unsigned int pvr = get_pvr(); + unsigned int version = pvr >>16; + unsigned int revision = pvr &0xffff; + + switch(version) + { + case 0x0081: + printf("MPC8240"); + break; + default: + return -1; /*not valid for this source*/ + } + + switch(revision) + { + default: /*currently no info on revision numbers*/ + printf(" Revsion %d.%d",revision>>8, revision & 0xff); + } + + printf(" at %lu MHz:", clock); + + printf(" %u kB I-Cache", checkicache() >> 10); + printf(" %u kB D-Cache", checkdcache() >> 10); + return 0; +} + +/* ------------------------------------------------------------------------- */ +/* L1 i-cache */ + +int checkicache(void) +{ + /*TODO*/ + return 128*4*32; +}; +/* ------------------------------------------------------------------------- */ +/* L1 d-cache */ + +int checkdcache(void) +{ + /*TODO*/ + return 128*4*32; + +}; + +/*------------------------------------------------------------------- */ + +void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + ulong msr, addr; + + + /* Interrupts and MMU off */ + __asm__ ("mtspr 81, 0 + mfmsr %0": "=r"(msr) : ); + msr &= ~0x1030; + __asm__ ("mtmsr %0"::"r"(msr) ); + + /* jump to reset vector*/ + addr = 0xfff0100; + ((void (*)(void ))addr)(); + +} + +/* ------------------------------------------------------------------------- */ + +/* + * Get timebase clock frequency (like cpu_clk in Hz) + * + */ +unsigned long get_tbclk (void) +{ + ulong tbclk; + /* Pointer to initial global data area */ + init_data_t *idata = + (init_data_t *)(CFG_INIT_RAM_ADDR+CFG_INIT_DATA_OFFSET); + + tbclk = (idata->cpu_clk + 3L) / 4L; + + return (tbclk); +} + +/* ------------------------------------------------------------------------- */ diff --git a/mpc8240/cpu_init.c b/mpc8240/cpu_init.c new file mode 100644 index 0000000..7aae577 --- /dev/null +++ b/mpc8240/cpu_init.c @@ -0,0 +1,171 @@ +/* + * (C) Copyright 2000 + * Rob Taylor. Flying Pig Systems. robt@flyingpig.com. + * + * 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 + */ + +#include +#include +#include + +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers, + */ +void +cpu_init_f (void) +{ + register unsigned long val; + CONFIG_WRITE_WORD( PCICR, 0x06); /* Bus Master, respond to PCI memory space acesses*/ +/* CONFIG_WRITE_HALFWORD(PCISR, 0xffff); *//*reset PCISR*/ + + CONFIG_READ_WORD(PICR1, val); + CONFIG_WRITE_WORD( PICR1, + (val & (PICR1_ADDRESS_NAP | PICR1_RCS0)) | + PIRC1_MSK | PICR1_PROC_TYPE_603E | + PICR1_FLASH_WR_EN | PICR1_MCP_EN | + PICR1_CF_DPARK | PICR1_EN_PCS | + PICR1_CF_APARK ); + CONFIG_READ_WORD(PICR2, val); + val= val & ~ (PICR2_CF_SNOOP_WS_MASK | PICR2_CF_APHASE_WS_MASK); /*mask off waitstate bits*/ + CONFIG_WRITE_WORD(PICR2, val | PICR2_CF_SNOOP_WS_1WS | PICR2_CF_APHASE_WS_1WS); /*1 wait state*/ + CONFIG_WRITE_WORD(EUMBBAR, CFG_EUMB_ADDR); +#ifndef DEBUG + CONFIG_WRITE_WORD(MCCR1, (CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) | + (CFG_ROMFAL << MCCR1_ROMFAL_SHIFT)); + + CONFIG_WRITE_WORD(MCCR2, CFG_REFINT << MCCR2_REFINT_SHIFT); + + CONFIG_WRITE_WORD(MCCR3, + (((CFG_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) | + (CFG_REFREC << MCCR3_REFREC_SHIFT) | + (CFG_RDLAT << MCCR3_RDLAT_SHIFT)); + + CONFIG_WRITE_WORD(MCCR4, + (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) | + (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) | + MCCR4_BIT21 | + (CFG_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) | + ((CFG_BSTOPRE & 0x0003) < $*.lst + +.c.o: + $(CCobj) $< + +.c.s: + $(CCobj) $(LST) $< + +dma1.o: dma_export.h dma.h dma1.c + +dma2.o: dma.h dma2.s diff --git a/mpc8240/drivers/dma/Makefile_pc b/mpc8240/drivers/dma/Makefile_pc new file mode 100644 index 0000000..8d8c9b9 --- /dev/null +++ b/mpc8240/drivers/dma/Makefile_pc @@ -0,0 +1,138 @@ +########################################################################## +# +# makefile_pc for use with mksnt tools drivers/dma +# $Id: Makefile_pc,v 1.1 2000/11/20 17:22:32 wdenk Exp $ +# Copyright Motorola, Inc. 1997 +# ALL RIGHTS RESERVED +# +# You are hereby granted a copyright license to use, modify, and +# distribute the SOFTWARE so long as this entire notice is retained +# without alteration in any modified and/or redistributed versions, +# and that such modified versions are clearly identified as such. +# No licenses are granted by implication, estoppel or otherwise under +# any patents or trademarks of Motorola, Inc. +# +# The SOFTWARE is provided on an "AS IS" basis and without warranty. +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. +# +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR +# INABILITY TO USE THE SOFTWARE. +# +# $Log: Makefile_pc,v $ +# Revision 1.1 2000/11/20 17:22:32 wdenk +# +# * Added support for MBX860T (thanks to Rob Taylor) +# +# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is +# Work In Progress (TM); current status: boots to command line input. +# EPIC code non-functional (interrupts disabled), No net, No IDE. +# +# * Add support for Status LED +# +# * Optionally panic() to reboot instead of hanging +# +# * Misc bug fixes +# +# * All frequencies in HZ now (internally) +# +# * Add support for BOOTP Domain Name Server Option +# +# Revision 1.1.1.1 2000/11/14 16:54:07 robt +# no message +# +# Revision 1.1.1.1 2000/11/14 14:49:39 robt +# no message +# +# Revision 1.1 1999/06/11 20:04:36 maurie +# support for compiling dink on PC +# +# Revision 1.4 1999/05/28 21:23:18 charliem +# First pass at cleaning up DMA interface. This version is verified with +# transfers from and to local memory (M2M). +# +# Revision 1.3 1999/02/13 02:21:02 wyin +# Added DMAStatus enum type for better information exchange. +# +# Revision 1.2 1999/02/05 01:54:51 wyin +# modified to set up soft line for hearder files +# +# Revision 1.1 1999/02/03 18:56:13 wyin +# Base line +# +# Revision 1.12 1998/11/20 01:34:55 wyin +# Added INTMEM function and data structure. +# Enabled DCACHE. +# There is a minor problem with DCACHE, the cache policy had to be write-through. +# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length. +# But consequence measurement is fine. +# +# +############################################################################ +TARGET = libdma.a + +DEBUG = -DDMADBG +LST = -Hanno -S +OPTIM = +CC = m:/old_tools/tools/hcppc/bin/hcppc +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) +PREP = $(CC) $(CFLAGS) -P + +# Assembler used to build the .s files (for the board version) + +ASOPT = -big_si -c +ASDEBUG = -l -fm +AS = m:/old_tools/tools/hcppc/bin/asppc + +# Linker to bring .o files together into an executable. + +LKOPT = -Bbase=0 -q -r -Qn +LKCMD = +LINK = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT) + +# DOS Utilities + +DEL = rm +COPY = cp +LIST = ls + +OBJECTS = dma1.o dma2.o + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(LINK) $(OBJECTS) -o $@ + +objects: dma1.o + +clean: + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) + +.s.o: + $(DEL) -f $*.i + $(PREP) -Hasmcpp $< + $(AS) $(ASOPT) $*.i +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst + +.c.o: + $(CCobj) $< + +.c.s: + $(CCobj) $(LST) $< + +dma1.o: dma_export.h dma.h dma1.c + $(CCobj) $< + +dma2.o: dma.h dma2.s + $(DEL) -f $*.i + $(PREP) -Hasmcpp $< + $(AS) $(ASOPT) $*.i diff --git a/mpc8240/drivers/dma/README b/mpc8240/drivers/dma/README new file mode 100644 index 0000000..db7acb8 --- /dev/null +++ b/mpc8240/drivers/dma/README @@ -0,0 +1,102 @@ +CONTENT: + + dma.h + dma1.c + dma2.s + +WHAT ARE THESE FILES: + +These files contain MPC8240 (Kahlua) DMA controller +driver routines. The driver routines are not +written for any specific operating system. +They serves the purpose of code sample, and +jump-start for using the MPC8240 DMA controller. + +For the reason of correctness of C language +syntax, these files are compiled by Metaware +C compiler and assembler. + +ENDIAN NOTATION: + +The algorithm is designed for big-endian mode, +software is responsible for byte swapping. + +USAGE: + +1. The host system that is running on MPC8240 + or using MPC8240 as I/O device shall link + the files listed here. The memory location + of driver routines shall take into account of + that driver routines need to run in supervisor + mode and they process DMA controller interrupt. + +2. The host system is responsible for configuring + the MPC8240 including Embedded Utilities Memory + Block. Since the DMA controller on MPC8240 can + be accessed by either local 603e core or the host + that MPC8240 serves as I/O processor through host + PCI configuration, it is important that the local + processor uses EUMBBAR to access its local DMA + controller while the PCI master uses I/O + processor's PCSRBAR to access the DMA controller + on I/O device. + + To qualify whether is EUMBBAR or PCSRBAR, one + additional parameter is requied from the host + system, LOCAL or REMOTE so that the base value + can be correctly interpreted. + +3. If the host system is also using the EPIC unit + on MPC8240, the system can register the + DMA_ISR with the EPIC including other + desired resources. + + If the host system does not using the EPIC unit + on MPC8240, DMA_ISR function can be called for + each desired time interval. + + In both cases, the host system is free to + provide its own interrupt service routine. + +4. To start a direct mode DMA transaction, + use DMA_Bld_Curr with the start parameter + set to 1. + + To start a chaining mode DMA transaction, + the application shall build descriptors + in memory first, next, use DMA_Bld_Desp + with the start parameter set to 1. + +5. DMA_Start function clears, then sets the CS + bit of DMA mode register. + + DMA_Halt function clears the CS bit of DMA + mode register. + + These functions can be used to start and + halt the DMA transaction. + + If the chaining descriptors has been + modified since the last time a DMA + transaction started, use DMA_Chn_Cnt + function to let DMA controller process + the modified descriptor chain without + stopping or disturbing the current DMA + transaction. + + It is the host system's responsibility of + setting up the correct DMA transfer mode + and pass the correct memory address parameters. + +6. It is the host system's responsibility of + queueing the DMA I/O request. The host + system can call the DMA_ISR with its own + desired interrupt service subroutines to + handle each individual interrupt and queued + DMA I/O requests. + +7. The DMA driver routines contains a set + of utilities, Set and Get, for host system + to query and modify the desired DMA registers. + + diff --git a/mpc8240/drivers/dma/dma.h b/mpc8240/drivers/dma/dma.h new file mode 100644 index 0000000..23f644c --- /dev/null +++ b/mpc8240/drivers/dma/dma.h @@ -0,0 +1,327 @@ +#ifndef DMA_H +#define DMA_H +/******************************************************* + * $Id: dma.h,v 1.1 2000/11/20 17:22:32 wdenk Exp $ + * + * copyright @ Motorola 1999 + * + *******************************************************/ +#define NUM_DMA_REG 7 +#define DMA_MR_REG 0 +#define DMA_SR_REG 1 +#define DMA_CDAR_REG 2 +#define DMA_SAR_REG 3 +#define DMA_DAR_REG 4 +#define DMA_BCR_REG 5 +#define DMA_NDAR_REG 6 + +typedef enum _dmastatus +{ + DMASUCCESS = 0x1000, + DMALMERROR, + DMAPERROR, + DMACHNBUSY, + DMAEOSINT, + DMAEOCAINT, + DMAINVALID, + DMANOEVENT, +} DMAStatus; + +typedef enum _location +{ + LOCAL = 0, /* local processor accesses on board DMA, + local processor's eumbbar is required */ + REMOTE = 1, /* PCI master accesses DMA on I/O board, + I/O processor's pcsrbar is required */ +} LOCATION; + +typedef enum dma_mr_bit +{ + IRQS = 0x00080000, + PDE = 0x00040000, + DAHTS = 0x00030000, + SAHTS = 0x0000c000, + DAHE = 0x00002000, + SAHE = 0x00001000, + PRC = 0x00000c00, + EIE = 0x00000080, + EOTIE = 0x00000040, + DL = 0x00000008, + CTM = 0x00000004, + CC = 0x00000002, + CS = 0x00000001, +} DMA_MR_BIT; + +typedef enum dma_sr_bit +{ + LME = 0x00000080, + PE = 0x00000010, + CB = 0x00000004, + EOSI = 0x00000002, + EOCAI = 0x00000001, +} DMA_SR_BIT; + +/* structure for DMA Mode Register */ +typedef struct _dma_mr +{ + unsigned int reserved0 : 12; + unsigned int irqs : 1; + unsigned int pde : 1; + unsigned int dahts : 2; + unsigned int sahts : 2; + unsigned int dahe : 1; + unsigned int sahe : 1; + unsigned int prc : 2; + unsigned int reserved1 : 1; + unsigned int eie : 1; + unsigned int eotie : 1; + unsigned int reserved2 : 3; + unsigned int dl : 1; + unsigned int ctm : 1; + /* if chaining mode is enabled, any time, user can modify the + * descriptor and does not need to halt the current DMA transaction. + * Set CC bit, enable DMA to process the modified descriptors + * Hardware will clear this bit each time, DMA starts. + */ + unsigned int cc : 1; + /* cs bit has dua role, halt the current DMA transaction and + * (re)start DMA transaction. In chaining mode, if the descriptor + * needs modification, cs bit shall be used not the cc bit. + * Hardware will not set/clear this bit each time DMA transaction + * stops or starts. Software shall do it. + * + * cs bit shall not be used to halt chaining DMA transaction for + * modifying the descriptor. That is the role of CC bit. + */ + unsigned int cs : 1; +} DMA_MR; + +/* structure for DMA Status register */ +typedef struct _dma_sr +{ + unsigned int reserved0 : 24; + unsigned int lme : 1; + unsigned int reserved1 : 2; + unsigned int pe : 1; + unsigned int reserved2 : 1; + unsigned int cb : 1; + unsigned int eosi : 1; + unsigned int eocai : 1; +} DMA_SR; + +/* structure for DMA current descriptor address register */ +typedef struct _dma_cdar +{ + unsigned int cda : 27; + unsigned int snen : 1; + unsigned int eosie : 1; + unsigned int ctt : 2; + unsigned int eotd : 1; +} DMA_CDAR; + +/* structure for DMA byte count register */ +typedef struct _dma_bcr +{ + unsigned int reserved : 6; + unsigned int bcr : 26; +} DMA_BCR; + +/* structure for DMA Next Descriptor Address register */ +typedef struct _dma_ndar +{ + unsigned int nda : 27; + unsigned int ndsnen : 1; + unsigned int ndeosie: 1; + unsigned int ndctt : 2; + unsigned int eotd : 1; +} DMA_NDAR; + +/* structure for DMA current transaction info */ +typedef struct _dma_curr +{ + unsigned int src_addr; + unsigned int dest_addr; + unsigned int byte_cnt; +} DMA_CURR; + +/************************* Kernel API******************** + * Kernel APIs are used to interface with O.S. kernel. + * They are the functions required by O.S. kernel to + * provide I/O service. + ********************************************************/ + +/**************DMA Device Control Functions ********/ + +/** + * Note: + * + * In all following functions, the host (KAHLUA) processor has a + * choice of accessing on board local DMA (LOCAL), + * or DMA on a distributed KAHLUA (REMOTE). In either case, + * the caller shall pass the configured embedded utility memory + * block base address relative to the DMA. If LOCAL DMA is used, + * this parameter shall be EUMBBAR, if REMOTE is used, the + * parameter shall be the corresponding PCSRBAR. + **/ + +/************************************************************** + * function: DMA_Get_Stat + * + * description: return the content of status register of + * the given DMA channel + * if error, return DMAINVALID. Otherwise return + * DMASUCCESS. + * + **************************************************************/ +static DMAStatus DMA_Get_Stat( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_SR * ); + +/************************************************************** + * function: DMA_Get_Mode + * + * description: return the content of mode register of the + * given DMA channel + * if error, return DMAINVALID. Otherwise return DMASUCCESS. + * + **************************************************************/ +static DMAStatus DMA_Get_Mode( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_MR * ); + +/************************************************************** + * function: DMA_Set_Mode + * + * description: Set a new mode to a given DMA channel + * return DMASUCCESS if success, otherwise return DMACHNINVALID + * + * note: It is not a good idea of changing the DMA mode during + * the middle of a transaction. + **************************************************************/ +static DMAStatus DMA_Set_Mode( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_MR mode ); + +/************************************************************* + * function: DMA_ISR + * + * description: DMA interrupt service routine + * return DMAStatus based on the status + * + *************************************************************/ +static DMAStatus DMA_ISR( unsigned int eumbbar, + unsigned int channel, + DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ), + DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ), + DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ), + DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus )); + +static DMAStatus dma_error_func( unsigned int, unsigned int, DMAStatus ); + +/********************* DMA I/O function ********************/ + +/************************************************************ + * function: DMA_Start + * + * description: start a given DMA channel transaction + * return DMASUCCESS if success, otherwise return DMACHNINVALID + * + * note: this function will clear DMA_MR(CC) first, then + * set DMA_MR(CC). + ***********************************************************/ +static DMAStatus DMA_Start( LOCATION, unsigned int eumbbar,unsigned int channel ); + +/*********************************************************** + * function: DMA_Halt + * + * description: halt the current dma transaction on the specified + * channel. + * return DMASUCCESS if success, otherwise return DMACHNINVALID + * + * note: if the specified DMA channel is idle, nothing happens + *************************************************************/ +static DMAStatus DMA_Halt( LOCATION, unsigned int eumbbar,unsigned int channel ); + +/************************************************************* + * function: DMA_Chn_Cnt + * + * description: set the DMA_MR(CC) bit for a given channel + * that is in chaining mode. + * return DMASUCCESS if successfule, otherwise return DMACHNINVALID + * + * note: if the given channel is not in chaining mode, nothing + * happen. + * + *************************************************************/ +static DMAStatus DMA_Chn_Cnt( LOCATION, unsigned int eumbbar,unsigned int channel ); + +/*********************** App. API *************************** + * App. API are the APIs Kernel provides for the application + * level program + ************************************************************/ +/************************************************************** + * function: DMA_Bld_Curr + * + * description: set current src, dest, byte count registers + * according to the desp for a given channel + * + * if the given channel is busy, no change made, + * return DMACHNBUSY. + * + * otherwise return DMASUCCESS. + * + * note: + **************************************************************/ +static DMAStatus DMA_Bld_Curr( LOCATION, + unsigned int eumbbar, + unsigned int channel, + DMA_CURR desp ); + +/************************************************************** + * function: DMA_Poke_Curr + * + * description: poke the current src, dest, byte count registers + * for a given channel. + * + * return DMASUCCESS if no error otherwise return DMACHNERROR + * + * note: Due to the undeterministic parallelism, in chaining + * mode, the value returned by this function shall + * be taken as reference when the query is made rather + * than the absolute snapshot when the value is returned. + **************************************************************/ +static DMAStatus DMA_Poke_Curr( LOCATION, + unsigned int eumbbar, + unsigned int channel, + DMA_CURR* desp ); + +/************************************************************** + * function: DMA_Bld_Desp + * + * description: set current descriptor address register + * according to the desp for a given channel + * + * if the given channel is busy return DMACHNBUSY + * and no change made, otherwise return DMASUCCESS. + * + * note: + **************************************************************/ +static DMAStatus DMA_Bld_Desp( LOCATION host, + unsigned int eumbbar, + unsigned int channel, + DMA_CDAR desp ); + +/************************************************************** + * function: DMA_Poke_Desp + * + * description: poke the current descriptor address register + * for a given channel + * + * return DMASUCCESS if no error otherwise return + * DMAINVALID + * + * note: Due to the undeterministic parallellism of DMA operation, + * the value returned by this function shall be taken as + * the most recently used descriptor when the last time + * DMA starts a chaining mode operation. + **************************************************************/ +static DMAStatus DMA_Poke_Desp( LOCATION, + unsigned int eumbbar, + unsigned int channel, + DMA_CDAR *desp ); + +#endif diff --git a/mpc8240/drivers/dma/dma1.c b/mpc8240/drivers/dma/dma1.c new file mode 100644 index 0000000..cfdb17b --- /dev/null +++ b/mpc8240/drivers/dma/dma1.c @@ -0,0 +1,802 @@ +/************************************************************ + * $Id: dma1.c,v 1.1 2000/11/20 17:22:32 wdenk Exp $ + * + * copyright @ Motorola, 1999 + * + * App. API + * + * App. API are the APIs Kernel provides for the application + * level program + * + ************************************************************/ +#include "dma_export.h" +#include "dma.h" + +/* Define a macro to use an optional application-layer print function, if + * one was passed to the library during initialization. If there was no + * function pointer passed, this protects against referencing a NULL pointer. + * Also define The global variable that holds the passed pointer. + */ +#define PRINT if ( app_print ) app_print +static int (*app_print)(char *,...); + +/* Set by call to get_eumbbar during DMA_Initialize. + * This could be globally available to the library, but there is + * an advantage to passing it as a parameter: it is already in a register + * and doesn't have to be loaded from memory. Also, that is the way the + * library was already implemented and I don't want to change it without + * a more detailed analysis. + * It is being set as a global variable during initialization to hide it from + * the DINK application layer, because it is Kahlua-specific. I think that + * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in + * a Kahlua-specific library dealing with the embedded utilities memory block. + * Right now, get_eumbbar is defined in dink32/kahlua.s. The other two are + * defined in dink32/drivers/i2c/i2c2.s, drivers/dma/dma2.s, etc. + */ +static unsigned int Global_eumbbar = 0; +extern unsigned int get_eumbbar(); + + +extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg ); +#pragma Alias( load_runtime_reg, "load_runtime_reg" ); + +extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val ); +#pragma Alias( store_runtime_reg, "store_runtime_reg" ); + +unsigned int dma_reg_tb[][14] = { + /* local DMA registers */ + { + /* DMA_0_MR */ 0x00001100, + /* DMA_0_SR */ 0x00001104, + /* DMA_0_CDAR */ 0x00001108, + /* DMA_0_SAR */ 0x00001110, + /* DMA_0_DAR */ 0x00001118, + /* DMA_0_BCR */ 0x00001120, + /* DMA_0_NDAR */ 0x00001124, + /* DMA_1_MR */ 0x00001200, + /* DMA_1_SR */ 0x00001204, + /* DMA_1_CDAR */ 0x00001208, + /* DMA_1_SAR */ 0x00001210, + /* DMA_1_DAR */ 0x00001218, + /* DMA_1_BCR */ 0x00001220, + /* DMA_1_NDAR */ 0x00001224, + }, + /* remote DMA registers */ + { + /* DMA_0_MR */ 0x00000100, + /* DMA_0_SR */ 0x00000104, + /* DMA_0_CDAR */ 0x00000108, + /* DMA_0_SAR */ 0x00000110, + /* DMA_0_DAR */ 0x00000118, + /* DMA_0_BCR */ 0x00000120, + /* DMA_0_NDAR */ 0x00000124, + /* DMA_1_MR */ 0x00000200, + /* DMA_1_SR */ 0x00000204, + /* DMA_1_CDAR */ 0x00000208, + /* DMA_1_SAR */ 0x00000210, + /* DMA_1_DAR */ 0x00000218, + /* DMA_1_BCR */ 0x00000220, + /* DMA_1_NDAR */ 0x00000224, + }, +}; + +/* API functions */ + +/* Initialize DMA unit with the following: + * optional pointer to application layer print function + * + * These parameters may be added: + * ??? + * Interrupt enables, modes, etc. are set for each transfer. + * + * This function must be called before DMA unit can be used. + */ +extern +DMA_Status DMA_Initialize( int (*p)(char *,...)) +{ + DMAStatus status; + /* establish the pointer, if there is one, to the application's "printf" */ + app_print = p; + + /* If this is the first call, get the embedded utilities memory block + * base address. I'm not sure what to do about error handling here: + * if a non-zero value is returned, accept it. + */ + if ( Global_eumbbar == 0) + Global_eumbbar = get_eumbbar(); + if ( Global_eumbbar == 0) + { + PRINT( "DMA_Initialize: can't find EUMBBAR\n" ); + return DMA_ERROR; + } + + return DMA_SUCCESS; +} + + +/* Perform the DMA transfer, only direct mode is currently implemented. + * At this point, I think it would be better to define a different + * function for chaining mode. + * Also, I'm not sure if it is appropriate to have the "generic" API + * accept snoop and int_steer parameters. The DINK user interface allows + * them, so for now I'll leave them. + * + * int_steer controls DMA interrupt steering to PCI or local processor + * type is the type of transfer: M2M, M2P, P2M, P2P + * source is the source address of the data + * dest is the destination address of the data + * len is the length of data to transfer + * channel is the DMA channel to use for the transfer + * snoop is the snoop enable control + */ +extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer, + DMA_TRANSFER_TYPE type, + unsigned int source, + unsigned int dest, + unsigned int len, + DMA_CHANNEL channel, + DMA_SNOOP_MODE snoop) +{ + DMA_MR md; + DMA_CDAR cdar; + /* it's inappropriate for curr to be a struct, but I'll leave it */ + DMA_CURR curr; + + DMAStatus stat; + + /* The rest of this code was moved from device.c test_dma to here. + * It needs to be cleaned up and validated, but at least it is removed + * from the application and API. Most of the mode is left hard coded. + * This should be changed after the final API is defined and the user + * application has a way to control the transfer. + * + */ + + if ( DMA_Get_Mode( LOCAL, Global_eumbbar, channel, &md ) != DMASUCCESS ) + { + return DMA_ERROR; + } + + md.irqs = int_steer; + md.pde = 0; + md.dahts = 3; /* 8 - byte */ + md.sahts = 3; /* 8 - byte */ + md.dahe = 0; + md.sahe = 0; + md.prc = 0; + /* if steering interrupts to local processor, use polling mode */ + if ( int_steer == DMA_INT_STEER_PCI ) + { + md.eie = 1; + md.eotie = 1; + } else { + md.eie = 0; + md.eotie = 0; + } + md.dl = 0; + md.ctm = 1; /* direct mode */ + md.cc = 0; + + /* validate the length range */ + if (len > 0x3ffffff ) + { + PRINT( "dev DMA: length of transfer too large: %d\n", len ); + return DMA_ERROR; + } + + /* inappropriate to use a struct, but leave as is for now */ + curr.src_addr = source; + curr.dest_addr = dest; + curr.byte_cnt = len; + + (void)DMA_Poke_Desp( LOCAL, Global_eumbbar, channel, &cdar ); + cdar.snen = snoop; + cdar.ctt = type; + + if ( ( stat = DMA_Bld_Desp( LOCAL, Global_eumbbar, channel, cdar )) + != DMASUCCESS || + ( stat = DMA_Bld_Curr( LOCAL, Global_eumbbar, channel, curr )) + != DMASUCCESS || + ( stat = DMA_Set_Mode( LOCAL, Global_eumbbar, channel, md )) + != DMASUCCESS || + ( stat = DMA_Start( LOCAL, Global_eumbbar, channel )) + != DMASUCCESS ) + { + if ( stat == DMACHNBUSY ) + { + PRINT( "dev DMA: channel %d busy.\n", channel ); + } + else + { + PRINT( "dev DMA: invalid channel request.\n", channel ); + } + + return DMA_ERROR; + } + +/* Since we are interested at the DMA performace right now, + we are going to do as less as possible to burden the + 603e core. + + if you have epic enabled or don't care the return from + DMA operation, you can just return SUCCESS. + + if you don't have epic enabled and care the DMA result, + you can use the polling method below. + + Note: I'll attempt to activate the code for handling polling. + */ + +#if 0 + /* if steering interrupt to local processor, let it handle results */ + if ( int_steer == DMA_INT_STEER_LOCAL ) + { + return DMA_SUCCESS; + } + + /* polling since interrupt goes to PCI */ + do + { + stat = DMA_ISR( Global_eumbbar, channel, dma_error_func, + dma_error_func, dma_error_func, dma_error_func ); + } + while ( stat == DMANOEVENT ); +#endif + + return DMA_SUCCESS; +} + +/* DMA library internal functions */ + +/** + * Note: + * + * In all following functions, the host (KAHLUA) processor has a + * choice of accessing on board local DMA (LOCAL), + * or DMA on a distributed KAHLUA (REMOTE). In either case, + * the caller shall pass the configured embedded utility memory + * block base address relative to the DMA. If LOCAL DMA is used, + * this parameter shall be EUMBBAR, if REMOTE is used, the + * parameter shall be the corresponding PCSRBAR. + **/ + +/************************************************************** + * function: DMA_Get_Stat + * + * description: return the content of status register of + * the given DMA channel + * + * if error, reserved0 field all 1s. + **************************************************************/ +static +DMAStatus DMA_Get_Stat( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_SR *stat ) +{ + unsigned int tmp; + + if ( channel != 0 && channel != 1 || stat == 0 ) + { + return DMAINVALID; + } + + tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG] ); +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) stat = 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG], tmp ); +#endif + + stat->reserved0 = ( tmp & 0xffffff00 ) >> 8; + stat->lme = ( tmp & 0x00000080 ) >> 7; + stat->reserved1 = ( tmp & 0x00000060 ) >> 5; + stat->pe = ( tmp & 0x00000010 ) >> 4; + stat->reserved2 = ( tmp & 0x00000008 ) >> 3; + stat->cb = ( tmp & 0x00000004 ) >> 2; + stat->eosi = ( tmp & 0x00000002 ) >> 1; + stat->eocai = ( tmp & 0x00000001 ); + + return DMASUCCESS; +} + +/************************************************************** + * function: DMA_Get_Mode + * + * description: return the content of mode register of the + * given DMA channel + * + * if error, return DMAINVALID, otherwise return + * DMASUCCESS + **************************************************************/ +static +DMAStatus DMA_Get_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR *mode ) +{ + unsigned int tmp; + if ( channel != 0 && channel != 1 || mode == 0 ) + { + return DMAINVALID; + } + + tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG] ); + +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) mode = 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG], tmp ); +#endif + + mode->reserved0 = (tmp & 0xfff00000) >> 20; + mode->irqs = (tmp & 0x00080000) >> 19; + mode->pde = (tmp & 0x00040000) >> 18; + mode->dahts = (tmp & 0x00030000) >> 16; + mode->sahts = (tmp & 0x0000c000) >> 14; + mode->dahe = (tmp & 0x00002000) >> 13; + mode->sahe = (tmp & 0x00001000) >> 12; + mode->prc = (tmp & 0x00000c00) >> 10; + mode->reserved1 = (tmp & 0x00000200) >> 9; + mode->eie = (tmp & 0x00000100) >> 8; + mode->eotie = (tmp & 0x00000080) >> 7; + mode->reserved2 = (tmp & 0x00000070) >> 4; + mode->dl = (tmp & 0x00000008) >> 3; + mode->ctm = (tmp & 0x00000004) >> 2; + mode->cc = (tmp & 0x00000002) >> 1; + mode->cs = (tmp & 0x00000001); + + return DMASUCCESS; +} + +/************************************************************** + * function: DMA_Set_Mode + * + * description: Set a new mode to a given DMA channel + * + * note: It is not a good idea of changing the DMA mode during + * the middle of a transaction. + **************************************************************/ +static +DMAStatus DMA_Set_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR mode ) +{ + unsigned int tmp; + if ( channel != 0 && channel != 1 ) + { + return DMAINVALID; + } + + tmp = ( mode.reserved0 & 0xfff ) << 20; + tmp |= ( ( mode.irqs & 0x1 ) << 19); + tmp |= ( ( mode.pde & 0x1 ) << 18 ); + tmp |= ( ( mode.dahts & 0x3 ) << 16 ); + tmp |= ( ( mode.sahts & 0x3 ) << 14 ); + tmp |= ( ( mode.dahe & 0x1 ) << 13 ); + tmp |= ( ( mode.sahe & 0x1 ) << 12 ); + tmp |= ( ( mode.prc & 0x3 ) << 10 ); + tmp |= ( ( mode.reserved1 & 0x1 ) << 9 ); + tmp |= ( ( mode.eie & 0x1 ) << 8 ); + tmp |= ( ( mode.eotie & 0x1 ) << 7 ); + tmp |= ( ( mode.reserved2 & 0x7 ) << 4 ); + tmp |= ( ( mode.dl & 0x1 ) << 3 ); + tmp |= ( ( mode.ctm & 0x1 ) << 2 ); + tmp |= ( ( mode.cc & 0x1 ) << 1 ) ; + tmp |= ( mode.cs & 0x1 ); + + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], tmp ); + return DMASUCCESS; +} + +/************************************************************ + * function: DMA_Start + * + * description: start a given DMA channel transaction + * return DMASUCCESS if success otherwise return + * DMAStatus value + * + * note: this function will clear DMA_MR(CC) first, then + * set DMA_MR(CC). + ***********************************************************/ +static +DMAStatus DMA_Start( LOCATION host, unsigned int eumbbar, unsigned int channel ) +{ + DMA_SR stat; + unsigned int mode; + + if ( channel != 0 && channel != 1 ) + { + return DMAINVALID; + } + + if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS ) + { + return DMAINVALID; + } + + if ( stat.cb == 1 ) + { + /* DMA is not free */ + return DMACHNBUSY; + } + + mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] ); + /* clear DMA_MR(CS) */ + mode &= 0xfffffffe; + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); + + /* set DMA_MR(CS) */ + mode |= CS; + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); + return DMASUCCESS; +} + +/*********************************************************** + * function: DMA_Halt + * + * description: halt the current dma transaction on the specified + * channel. + * return DMASUCCESS if success otherwise return DMAINVALID + * + * note: if the specified DMA channel is idle, nothing happens + *************************************************************/ +static +DMAStatus DMA_Halt( LOCATION host, unsigned int eumbbar, unsigned int channel ) +{ + unsigned int mode; + if ( channel != 0 && channel != 1 ) + { + return DMAINVALID; + } + + mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG]); + + /* clear DMA_MR(CS) */ + mode &= 0xfffffffe; + store_runtime_reg(eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); + return DMASUCCESS; +} + +/************************************************************* + * function: DMA_Chn_Cnt + * + * description: set the DMA_MR(CC) bit for a given channel + * that is in chaining mode. + * return DMASUCCESS if successfule, otherwise return + * DMAINVALID. + * + * note: if the given channel is not in chaining mode, nothing + * happen. + * + *************************************************************/ +static +DMAStatus DMA_Chn_Cnt( LOCATION host, unsigned int eumbbar, unsigned int channel ) +{ + DMA_MR mode; + if ( channel != 0 && channel != 1 ) + { + return DMAINVALID; + } + + if ( DMA_Get_Mode( host, eumbbar, channel, &mode ) != DMASUCCESS ) + { + return DMAINVALID; + } + + if ( mode.ctm == 0 ) + { + /* either illegal mode or not chaining mode */ + return DMAINVALID; + } + + mode.cc = 1; + return DMA_Set_Mode( host, eumbbar, channel, mode ); +} + +/************************************************************** + * function: DMA_Bld_Desp + * + * description: set current descriptor address register + * according to the desp for a given channel + * + * if the given channel is busy return DMACHNBUSY + * and no change made, otherwise return DMASUCCESS. + * + * note: + **************************************************************/ +static +DMAStatus DMA_Bld_Desp( LOCATION host, + unsigned int eumbbar, + unsigned int channel, + DMA_CDAR desp ) +{ + DMA_SR status; + unsigned int temp; + + if ( channel != 0 && channel != 1 ) + { + /* channel number out of range */ + return DMAINVALID; + } + + if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS ) + { + return DMAINVALID; + } + + if ( status.cb == 1 ) + { + /* channel busy */ + return DMACHNBUSY; + } + + temp = ( desp.cda & 0x7ffffff ) << 5; + temp |= (( desp.snen & 0x1 ) << 4 ); + temp |= (( desp.eosie & 0x1 ) << 3 ); + temp |= (( desp.ctt & 0x3 ) << 1 ); + temp |= ( desp.eotd & 0x1 ); + + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp ); + +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) cdar := 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp ); +#endif + + return DMASUCCESS; +} + +/************************************************************** + * function: DMA_Poke_Desp + * + * description: poke the current descriptor address register + * for a given channel + * + * return DMASUCCESS if no error + * + * note: Due to the undeterministic parallellism of DMA operation, + * the value returned by this function shall be taken as + * the most recently used descriptor when the last time + * DMA starts a chaining mode operation. + **************************************************************/ +static +DMAStatus DMA_Poke_Desp( LOCATION host, + unsigned int eumbbar, + unsigned int channel, + DMA_CDAR *desp ) +{ + unsigned int cdar; + if ( channel != 0 && channel != 1 || desp == 0 ) + { + return DMAINVALID; + } + + cdar = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG] ); + +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) cdar : 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], cdar ); +#endif + + + desp->cda = ( cdar & 0xffffffe0 ) >> 5; + desp->snen = ( cdar & 0x00000010 ) >> 4; + desp->eosie = ( cdar & 0x00000008 ) >> 3; + desp->ctt = ( cdar & 0x00000006 ) >> 1; + desp->eotd = ( cdar & 0x00000001 ); + + return DMASUCCESS; +} + +/************************************************************** + * function: DMA_Bld_Curr + * + * description: set current src, dest, byte count registers + * according to the desp for a given channel + * return DMASUCCESS if no error. + * + * note: + **************************************************************/ +static +DMAStatus DMA_Bld_Curr( LOCATION host, + unsigned int eumbbar, + unsigned int channel, + DMA_CURR desp ) +{ + DMA_SR status; + if ( channel != 0 && channel != 1 ) + { + /* channel number out of range */ + return DMAINVALID; + } + + if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS ) + { + return DMAINVALID; + } + + if ( status.cb == 1 ) + { + /* channel busy */ + return DMACHNBUSY; + } + + desp.byte_cnt &= 0x03ffffff; /* upper 6-bits are 0s */ + + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG], desp.src_addr ); +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) src := 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.src_addr ); +#endif + + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG], desp.dest_addr ); +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) dest := 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.dest_addr ); +#endif + + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG], desp.byte_cnt ); +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) count := 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt ); +#endif + + + return DMASUCCESS; + +} + +/************************************************************** + * function: DMA_Poke_Curr + * + * description: poke the current src, dest, byte count registers + * for a given channel. + * + * return DMASUCCESS if no error + * + * note: Due to the undeterministic parallelism, in chaining + * mode, the value returned by this function shall + * be taken as reference when the query is made rather + * than the absolute snapshot when the value is returned. + **************************************************************/ +static +DMAStatus DMA_Poke_Curr( LOCATION host, + unsigned int eumbbar, + unsigned int channel, + DMA_CURR* desp ) +{ + if ( channel != 0 && channel != 1 || desp == 0 ) + { + return DMAINVALID; + } + + desp->src_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG] ); +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) src : 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->src_addr ); +#endif + + desp->dest_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG] ); +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) dest : 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->dest_addr ); +#endif + + desp->byte_cnt = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG] ); +#ifdef DMADBG0 + PRINT( "%s(%d): %s DMA %d (0x%08x) count : 0x%08x\n", __FILE__, __LINE__, + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt ); +#endif + + + return DMASUCCESS; +} + +/***************************************************************** + * function: dma_error_func + * + * description: display the error information + * + * note: This seems like a highly convoluted way to handle messages, + * but I'll leave it as it was in device.c when I moved it into the + * DMA library source. + ****************************************************************/ +static +DMAStatus dma_error_func( unsigned int eumbbar, unsigned int chn, DMAStatus err) +{ + unsigned char *msg[] = + { + "Local Memory Error", + "PCI Error", + "Channel Busy", + "End-of-Segment Interrupt", + "End-of-Chain/Direct Interrupt", + }; + + if ( err >= DMALMERROR && err <= DMAEOCAINT ) + { + PRINT( "DMA Status: channel %d %s\n", chn, msg[err-DMASUCCESS-1] ); + } + + return err; + +} + +/************************************************************* + * function: DMA_ISR + * + * description: DMA interrupt service routine + * return DMAStatus value based on + * the status + * + *************************************************************/ +static +DMAStatus DMA_ISR( unsigned int eumbbar, + unsigned int channel, + DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ), + DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ), + DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ), + DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus )) +{ + + DMA_SR stat; + DMAStatus rval = DMANOEVENT; + unsigned int temp; + + if ( channel != 0 && channel != 1 ) + { + return DMAINVALID; + } + + if ( DMA_Get_Stat( LOCAL, eumbbar, channel, &stat ) != DMASUCCESS ) + { + return DMAINVALID; + } + + if ( stat.lme == 1 ) + { + /* local memory error */ + rval = DMALMERROR; + if ( lme_func != 0 ) + { + rval = (*lme_func)(eumbbar, channel, DMALMERROR ); + } + + } + else if ( stat.pe == 1 ) + { + /* PCI error */ + rval = DMAPERROR; + if ( pe_func != 0 ) + { + rval = (*pe_func)(eumbbar, channel, DMAPERROR ); + } + + } + else if ( stat.eosi == 1 ) + { + /* end-of-segment interrupt */ + rval = DMAEOSINT; + if ( eosi_func != 0 ) + { + rval = (*eosi_func)(eumbbar, channel, DMAEOSINT ); + } + } + else + { + /* End-of-chain/direct interrupt */ + rval = DMAEOCAINT; + if ( eocai_func != 0 ) + { + rval = (*eocai_func)(eumbbar, channel, DMAEOCAINT ); + } + } + + temp = ( stat.reserved0 & 0xffffff ) << 8; + temp |= ( ( stat.lme & 0x1 ) << 7 ); /* write one to clear */ + temp |= ( ( stat.reserved1 & 0x3 ) << 5 ); + temp |= ( ( stat.pe & 0x1 ) << 4 ); /* write one to clear */ + temp |= ( ( stat.reserved2 & 0x1 ) << 3 ); + temp |= ( ( stat.cb & 0x1 ) << 2 ); /* write one to clear */ + temp |= ( ( stat.eosi & 0x1 ) << 1 ); /* write one to clear */ + temp |= ( stat.eocai & 0x1 ); /* write one to clear */ + + store_runtime_reg( eumbbar, dma_reg_tb[LOCAL][channel*NUM_DMA_REG + DMA_SR_REG], temp ); + +#ifdef DMADBG0 + PRINT( "%s(%d): DMA channel %d SR := 0x%08x\n", __FILE__, __LINE__, channel, temp ); +#endif + + return rval; +} diff --git a/mpc8240/drivers/dma/dma2.S b/mpc8240/drivers/dma/dma2.S new file mode 100644 index 0000000..fb176a0 --- /dev/null +++ b/mpc8240/drivers/dma/dma2.S @@ -0,0 +1,46 @@ +/************************************** + * $Id: dma2.S,v 1.1 2000/11/20 17:22:32 wdenk Exp $ + * + * copyright @ Motorola, 1999 + * + **************************************/ + +/********************************************************** + * function: load_runtime_reg + * + * input: r3 - value of eumbbar + * r4 - register offset in embedded utility space + * + * output: r3 - register content + **********************************************************/ + .text + .align 2 + .global load_runtime_reg + +load_runtime_reg: + + lwbrx r3,r4,r3 + sync + + bclr 20, 0 + +/**************************************************************** + * function: store_runtime_reg + * + * input: r3 - value of eumbbar + * r4 - register offset in embedded utility space + * r5 - new value to be stored + * + ****************************************************************/ + .text + .align 2 + .global store_runtime_reg +store_runtime_reg: + + stwbrx r5, r4, r3 + sync + + bclr 20,0 + + + diff --git a/mpc8240/drivers/dma/dma_export.h b/mpc8240/drivers/dma/dma_export.h new file mode 100644 index 0000000..2c9ca71 --- /dev/null +++ b/mpc8240/drivers/dma/dma_export.h @@ -0,0 +1,100 @@ +#ifndef DMA_EXPORT_H +#define DMA_EXPORT_H + +/**************************************************** + * $Id: + * + * Copyright Motorola 1999 + * + * $Log: + * + ****************************************************/ + +/* These are the defined return values for the DMA_* functions. + * Any non-zero value indicates failure. Failure modes can be added for + * more detailed error reporting. + */ +typedef enum _dma_status +{ + DMA_SUCCESS = 0, + DMA_ERROR, +} DMA_Status; + +/* These are the defined channel transfer types. */ +typedef enum _dma_transfer_types +{ + DMA_M2M = 0, /* local memory to local memory */ + DMA_M2P = 1, /* local memory to PCI */ + DMA_P2M = 2, /* PCI to local memory */ + DMA_P2P = 3, /* PCI to PCI */ +} DMA_TRANSFER_TYPE; + +typedef enum _dma_interrupt_steer +{ + DMA_INT_STEER_LOCAL = 0, /* steer DMA int to local processor */ + DMA_INT_STEER_PCI = 1, /* steer DMA int to PCI bus through INTA_ */ +} DMA_INTERRUPT_STEER; + +typedef enum _dma_channel +{ + DMA_CHN_0 = 0, /* kahlua has two dma channels: 0 and 1 */ + DMA_CHN_1 = 1, +} DMA_CHANNEL; + +typedef enum _dma_snoop_mode +{ + DMA_SNOOP_DISABLE = 0, + DMA_SNOOP_ENABLE = 1, +} DMA_SNOOP_MODE; + +/******************** App. API ******************** + * The application API is for user level application + * to use the functionality provided by DMA driver. + * This is a "generic" DMA interface, it should contain + * nothing specific to the Kahlua implementation. + * Only the generic functions are exported by the library. + * + * Note: Its App.s responsibility to swap the data + * byte. In our API, we currently transfer whatever + * we are given - Big/Little Endian. This could + * become part of the DMA config, though. + **************************************************/ + + +/* Initialize DMA unit with the following: + * optional pointer to application layer print function + * + * These parameters may be added: + * ??? + * Interrupt enables, modes, etc. are set for each transfer. + * + * This function must be called before DMA unit can be used. + */ +extern DMA_Status DMA_Initialize( + int (*app_print_function)(char *,...)); /* pointer to optional "printf" + * provided by application + */ + +/* Perform the DMA transfer, only direct mode is currently implemented. + * At this point, I think it would be better to define a different + * function for chaining mode. + * Also, I'm not sure if it is appropriate to have the "generic" API + * accept snoop and int_steer parameters. The DINK user interface allows + * them, so for now I'll leave them. + * + * int_steer controls DMA interrupt steering to PCI or local processor + * type is the type of transfer: M2M, M2P, P2M, P2P + * source is the source address of the data + * dest is the destination address of the data + * len is the length of data to transfer + * channel is the DMA channel to use for the transfer + * snoop is the snoop enable control + */ +extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer, + DMA_TRANSFER_TYPE type, + unsigned int source, + unsigned int dest, + unsigned int len, + DMA_CHANNEL channel, + DMA_SNOOP_MODE snoop); +#endif diff --git a/mpc8240/drivers/dma_export.h b/mpc8240/drivers/dma_export.h new file mode 100644 index 0000000..2c9ca71 --- /dev/null +++ b/mpc8240/drivers/dma_export.h @@ -0,0 +1,100 @@ +#ifndef DMA_EXPORT_H +#define DMA_EXPORT_H + +/**************************************************** + * $Id: + * + * Copyright Motorola 1999 + * + * $Log: + * + ****************************************************/ + +/* These are the defined return values for the DMA_* functions. + * Any non-zero value indicates failure. Failure modes can be added for + * more detailed error reporting. + */ +typedef enum _dma_status +{ + DMA_SUCCESS = 0, + DMA_ERROR, +} DMA_Status; + +/* These are the defined channel transfer types. */ +typedef enum _dma_transfer_types +{ + DMA_M2M = 0, /* local memory to local memory */ + DMA_M2P = 1, /* local memory to PCI */ + DMA_P2M = 2, /* PCI to local memory */ + DMA_P2P = 3, /* PCI to PCI */ +} DMA_TRANSFER_TYPE; + +typedef enum _dma_interrupt_steer +{ + DMA_INT_STEER_LOCAL = 0, /* steer DMA int to local processor */ + DMA_INT_STEER_PCI = 1, /* steer DMA int to PCI bus through INTA_ */ +} DMA_INTERRUPT_STEER; + +typedef enum _dma_channel +{ + DMA_CHN_0 = 0, /* kahlua has two dma channels: 0 and 1 */ + DMA_CHN_1 = 1, +} DMA_CHANNEL; + +typedef enum _dma_snoop_mode +{ + DMA_SNOOP_DISABLE = 0, + DMA_SNOOP_ENABLE = 1, +} DMA_SNOOP_MODE; + +/******************** App. API ******************** + * The application API is for user level application + * to use the functionality provided by DMA driver. + * This is a "generic" DMA interface, it should contain + * nothing specific to the Kahlua implementation. + * Only the generic functions are exported by the library. + * + * Note: Its App.s responsibility to swap the data + * byte. In our API, we currently transfer whatever + * we are given - Big/Little Endian. This could + * become part of the DMA config, though. + **************************************************/ + + +/* Initialize DMA unit with the following: + * optional pointer to application layer print function + * + * These parameters may be added: + * ??? + * Interrupt enables, modes, etc. are set for each transfer. + * + * This function must be called before DMA unit can be used. + */ +extern DMA_Status DMA_Initialize( + int (*app_print_function)(char *,...)); /* pointer to optional "printf" + * provided by application + */ + +/* Perform the DMA transfer, only direct mode is currently implemented. + * At this point, I think it would be better to define a different + * function for chaining mode. + * Also, I'm not sure if it is appropriate to have the "generic" API + * accept snoop and int_steer parameters. The DINK user interface allows + * them, so for now I'll leave them. + * + * int_steer controls DMA interrupt steering to PCI or local processor + * type is the type of transfer: M2M, M2P, P2M, P2P + * source is the source address of the data + * dest is the destination address of the data + * len is the length of data to transfer + * channel is the DMA channel to use for the transfer + * snoop is the snoop enable control + */ +extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer, + DMA_TRANSFER_TYPE type, + unsigned int source, + unsigned int dest, + unsigned int len, + DMA_CHANNEL channel, + DMA_SNOOP_MODE snoop); +#endif diff --git a/mpc8240/drivers/epic.h b/mpc8240/drivers/epic.h new file mode 100644 index 0000000..2803f63 --- /dev/null +++ b/mpc8240/drivers/epic.h @@ -0,0 +1 @@ +#include "epic/epic.h" diff --git a/mpc8240/drivers/epic/README b/mpc8240/drivers/epic/README new file mode 100644 index 0000000..7fea4e1 --- /dev/null +++ b/mpc8240/drivers/epic/README @@ -0,0 +1,104 @@ +CONTENT: + + epic.h + epic1.c + epic2.s + +WHAT ARE THESE FILES: + +These files contain MPC8240 (Kahlua) EPIC +driver routines. The driver routines are not +written for any specific operating system. +They serves the purpose of code sample, and +jump-start for using the MPC8240 EPIC unit. + +For the reason of correctness of C language +syntax, these files are compiled by Metaware +C compiler and assembler. + +ENDIAN NOTATION: + +The algorithm is designed for big-endian mode, +software is responsible for byte swapping. + +USAGE: + +1. The host system that is running on MPC8240 + shall link the files listed here. The memory + location of driver routines shall take into + account of that driver routines need to run + in supervisor mode and they process external + interrupts. + + The routine epic_exception shall be called by + exception vector at location 0x500, i.e., + 603e core external exception vector. + +2. The host system is responsible for configuring + the MPC8240 including Embedded Utilities Memory + Block. All EPIC driver functions require the + content of Embedded Utilities Memory Block + Base Address Register, EUMBBAR, as the first + parameter. + +3. Before EPIC unit of MPC8240 can be used, + initialize EPIC unit by calling epicInit + with the corresponding parameters. + + The initialization shall disable the 603e + core External Exception by calling CoreExtIntDisable( ). + Next, call epicInit( ). Last, enable the 603e core + External Exception by calling CoreExtIntEnable( ). + +4. After EPIC unit has been successfully initialized, + epicIntSourceSet( ) shall be used to register each + external interrupt source. Anytime, an external + interrupt source can be disabled or enabled by + calling corresponding function, epicIntDisable( ), + or epicIntEnable( ). + + Global Timers' resource, base count and frequency, + can be changed by calling epicTmFrequencySet( ) + and epicTmBaseSet( ). + + To stop counting a specific global timer, use + the function, epicTmInhibit while epicTmEnable + can be used to start counting a timer. + +5. To mask a set of external interrupts that are + are certain level below, epicIntPrioritySet( ) + can be used. For example, if the processor's + current task priority register is set to 0x7, + only interrupts of priority 0x8 or higher will + be passed to the processor. + + Be careful when using this function. It may + corrupt the current interrupt pending, selector, + and request registers, resulting an invalid vetor. + + After enabling an interrupt, disable it may also + cause an invalid vector. User may consider using + the spurious vector interrupt service routine to + handle this case. + +6. The EPIC driver routines contains a set + of utilities, Set and Get, for host system + to query and modify the desired EPIC source + registers. + +7. Each external interrupt source shall register + its interrupt service routine. The routine + shall contain all interrupt source specific + processes and keep as short as possible. + + Special customized end of interrupt routine + is optional. If it is needed, it shall contain + the external interrupt source specific end of + interrupt process. + + External interrupt exception vector at 0x500 + shall always call the epicEOI just before + rfi instruction. Refer to the routine, + epic_exception, for a code sample. + + diff --git a/mpc8240/drivers/epic/epic.h b/mpc8240/drivers/epic/epic.h new file mode 100644 index 0000000..76c5d4e --- /dev/null +++ b/mpc8240/drivers/epic/epic.h @@ -0,0 +1,160 @@ +/********************************************************************* + * mpc8240epic.h - EPIC module of the MPC8240 micro-controller + * + * Copyrigh 1999 Motorola Inc. + * + * Modification History: + * ===================== + * 01a,04Feb99,My Created. + * 15Nov200, robt -modified to use in ppcboot + * +*/ + +#ifndef __INCEPICh +#define __INCEPICh + +#define ULONG unsigned long +#define MAXVEC 20 +#define MAXIRQ 5 /* IRQs */ +#define EPIC_DIRECT_IRQ 0 /* Direct interrupt type */ + +/* EPIC register addresses */ + +#define EPIC_EUMBBAR 0x40000 /* EUMBBAR of EPIC */ +#define EPIC_FEATURES_REG (EPIC_EUMBBAR + 0x01000)/* Feature reporting */ +#define EPIC_GLOBAL_REG (EPIC_EUMBBAR + 0x01020)/* Global config. */ +#define EPIC_INT_CONF_REG (EPIC_EUMBBAR + 0x01030)/* Interrupt config. */ +#define EPIC_VENDOR_ID_REG (EPIC_EUMBBAR + 0x01080)/* Vendor id */ +#define EPIC_PROC_INIT_REG (EPIC_EUMBBAR + 0x01090)/* Processor init. */ +#define EPIC_SPUR_VEC_REG (EPIC_EUMBBAR + 0x010e0)/* Spurious vector */ +#define EPIC_TM_FREQ_REG (EPIC_EUMBBAR + 0x010f0)/* Timer Frequency */ + +#define EPIC_TM0_CUR_COUNT_REG (EPIC_EUMBBAR + 0x01100)/* Gbl TM0 Cur. Count*/ +#define EPIC_TM0_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01110)/* Gbl TM0 Base Count*/ +#define EPIC_TM0_VEC_REG (EPIC_EUMBBAR + 0x01120)/* Gbl TM0 Vector Pri*/ +#define EPIC_TM0_DES_REG (EPIC_EUMBBAR + 0x01130)/* Gbl TM0 Dest. */ + +#define EPIC_TM1_CUR_COUNT_REG (EPIC_EUMBBAR + 0x01140)/* Gbl TM1 Cur. Count*/ +#define EPIC_TM1_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01150)/* Gbl TM1 Base Count*/ +#define EPIC_TM1_VEC_REG (EPIC_EUMBBAR + 0x01160)/* Gbl TM1 Vector Pri*/ +#define EPIC_TM1_DES_REG (EPIC_EUMBBAR + 0x01170)/* Gbl TM1 Dest. */ + +#define EPIC_TM2_CUR_COUNT_REG (EPIC_EUMBBAR + 0x01180)/* Gbl TM2 Cur. Count*/ +#define EPIC_TM2_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01190)/* Gbl TM2 Base Count*/ +#define EPIC_TM2_VEC_REG (EPIC_EUMBBAR + 0x011a0)/* Gbl TM2 Vector Pri*/ +#define EPIC_TM2_DES_REG (EPIC_EUMBBAR + 0x011b0)/* Gbl TM2 Dest */ + +#define EPIC_TM3_CUR_COUNT_REG (EPIC_EUMBBAR + 0x011c0)/* Gbl TM3 Cur. Count*/ +#define EPIC_TM3_BASE_COUNT_REG (EPIC_EUMBBAR + 0x011d0)/* Gbl TM3 Base Count*/ +#define EPIC_TM3_VEC_REG (EPIC_EUMBBAR + 0x011e0)/* Gbl TM3 Vector Pri*/ +#define EPIC_TM3_DES_REG (EPIC_EUMBBAR + 0x011f0)/* Gbl TM3 Dest. */ + +#define EPIC_EX_INT0_VEC_REG (EPIC_EUMBBAR + 0x10200)/* Ext. Int. Sr0 Des */ +#define EPIC_EX_INT0_DES_REG (EPIC_EUMBBAR + 0x10210)/* Ext. Int. Sr0 Vect*/ +#define EPIC_EX_INT1_VEC_REG (EPIC_EUMBBAR + 0x10220)/* Ext. Int. Sr1 Des */ +#define EPIC_EX_INT1_DES_REG (EPIC_EUMBBAR + 0x10230)/* Ext. Int. Sr1 Vect*/ +#define EPIC_EX_INT2_VEC_REG (EPIC_EUMBBAR + 0x10240)/* Ext. Int. Sr2 Des */ +#define EPIC_EX_INT2_DES_REG (EPIC_EUMBBAR + 0x10250)/* Ext. Int. Sr2 Vect*/ +#define EPIC_EX_INT3_VEC_REG (EPIC_EUMBBAR + 0x10260)/* Ext. Int. Sr3 Des */ +#define EPIC_EX_INT3_DES_REG (EPIC_EUMBBAR + 0x10270)/* Ext. Int. Sr3 Vect*/ +#define EPIC_EX_INT4_VEC_REG (EPIC_EUMBBAR + 0x10280)/* Ext. Int. Sr4 Des */ +#define EPIC_EX_INT4_DES_REG (EPIC_EUMBBAR + 0x10290)/* Ext. Int. Sr4 Vect*/ + +#define EPIC_SR_INT0_VEC_REG (EPIC_EUMBBAR + 0x10200)/* Sr. Int. Sr0 Des */ +#define EPIC_SR_INT0_DES_REG (EPIC_EUMBBAR + 0x10210)/* Sr. Int. Sr0 Vect */ +#define EPIC_SR_INT1_VEC_REG (EPIC_EUMBBAR + 0x10220)/* Sr. Int. Sr1 Des */ +#define EPIC_SR_INT1_DES_REG (EPIC_EUMBBAR + 0x10230)/* Sr. Int. Sr1 Vect.*/ +#define EPIC_SR_INT2_VEC_REG (EPIC_EUMBBAR + 0x10240)/* Sr. Int. Sr2 Des */ +#define EPIC_SR_INT2_DES_REG (EPIC_EUMBBAR + 0x10250)/* Sr. Int. Sr2 Vect.*/ +#define EPIC_SR_INT3_VEC_REG (EPIC_EUMBBAR + 0x10260)/* Sr. Int. Sr3 Des */ +#define EPIC_SR_INT3_DES_REG (EPIC_EUMBBAR + 0x10270)/* Sr. Int. Sr3 Vect.*/ +#define EPIC_SR_INT4_VEC_REG (EPIC_EUMBBAR + 0x10280)/* Sr. Int. Sr4 Des */ +#define EPIC_SR_INT4_DES_REG (EPIC_EUMBBAR + 0x10290)/* Sr. Int. Sr4 Vect.*/ + +#define EPIC_SR_INT5_VEC_REG (EPIC_EUMBBAR + 0x102a0)/* Sr. Int. Sr5 Des */ +#define EPIC_SR_INT5_DES_REG (EPIC_EUMBBAR + 0x102b0)/* Sr. Int. Sr5 Vect.*/ +#define EPIC_SR_INT6_VEC_REG (EPIC_EUMBBAR + 0x102c0)/* Sr. Int. Sr6 Des */ +#define EPIC_SR_INT6_DES_REG (EPIC_EUMBBAR + 0x102d0)/* Sr. Int. Sr6 Vect.*/ +#define EPIC_SR_INT7_VEC_REG (EPIC_EUMBBAR + 0x102e0)/* Sr. Int. Sr7 Des */ +#define EPIC_SR_INT7_DES_REG (EPIC_EUMBBAR + 0x102f0)/* Sr. Int. Sr7 Vect.*/ +#define EPIC_SR_INT8_VEC_REG (EPIC_EUMBBAR + 0x10300)/* Sr. Int. Sr8 Des */ +#define EPIC_SR_INT8_DES_REG (EPIC_EUMBBAR + 0x10310)/* Sr. Int. Sr8 Vect.*/ +#define EPIC_SR_INT9_VEC_REG (EPIC_EUMBBAR + 0x10320)/* Sr. Int. Sr9 Des */ +#define EPIC_SR_INT9_DES_REG (EPIC_EUMBBAR + 0x10330)/* Sr. Int. Sr9 Vect.*/ + +#define EPIC_SR_INT10_VEC_REG (EPIC_EUMBBAR + 0x10340)/* Sr. Int. Sr10 Des */ +#define EPIC_SR_INT10_DES_REG (EPIC_EUMBBAR + 0x10350)/* Sr. Int. Sr10 Vect*/ +#define EPIC_SR_INT11_VEC_REG (EPIC_EUMBBAR + 0x10360)/* Sr. Int. Sr11 Des */ +#define EPIC_SR_INT11_DES_REG (EPIC_EUMBBAR + 0x10370)/* Sr. Int. Sr11 Vect*/ +#define EPIC_SR_INT12_VEC_REG (EPIC_EUMBBAR + 0x10380)/* Sr. Int. Sr12 Des */ +#define EPIC_SR_INT12_DES_REG (EPIC_EUMBBAR + 0x10390)/* Sr. Int. Sr12 Vect*/ +#define EPIC_SR_INT13_VEC_REG (EPIC_EUMBBAR + 0x103a0)/* Sr. Int. Sr13 Des */ +#define EPIC_SR_INT13_DES_REG (EPIC_EUMBBAR + 0x103b0)/* Sr. Int. Sr13 Vect*/ +#define EPIC_SR_INT14_VEC_REG (EPIC_EUMBBAR + 0x103c0)/* Sr. Int. Sr14 Des */ +#define EPIC_SR_INT14_DES_REG (EPIC_EUMBBAR + 0x103d0)/* Sr. Int. Sr14 Vect*/ +#define EPIC_SR_INT15_VEC_REG (EPIC_EUMBBAR + 0x103e0)/* Sr. Int. Sr15 Des */ +#define EPIC_SR_INT15_DES_REG (EPIC_EUMBBAR + 0x103f0)/* Sr. Int. Sr15 Vect*/ + +#define EPIC_I2C_INT_VEC_REG (EPIC_EUMBBAR + 0x11020)/* I2C Int. Vect Pri.*/ +#define EPIC_I2C_INT_DES_REG (EPIC_EUMBBAR + 0x11030)/* I2C Int. Dest */ +#define EPIC_DMA0_INT_VEC_REG (EPIC_EUMBBAR + 0x11040)/* DMA0 Int. Vect Pri*/ +#define EPIC_DMA0_INT_DES_REG (EPIC_EUMBBAR + 0x11050)/* DMA0 Int. Dest */ +#define EPIC_DMA1_INT_VEC_REG (EPIC_EUMBBAR + 0x11060)/* DMA1 Int. Vect Pri*/ +#define EPIC_DMA1_INT_DES_REG (EPIC_EUMBBAR + 0x11070)/* DMA1 Int. Dest */ +#define EPIC_MSG_INT_VEC_REG (EPIC_EUMBBAR + 0x110c0)/* Msg Int. Vect Pri*/ +#define EPIC_MSG_INT_DES_REG (EPIC_EUMBBAR + 0x110d0)/* Msg Int. Dest */ + +#define EPIC_PROC_CTASK_PRI_REG (EPIC_EUMBBAR + 0x20080)/* Proc. current task*/ +#define EPIC_PROC_INT_ACK_REG (EPIC_EUMBBAR + 0x200a0)/* Int. acknowledge */ +#define EPIC_PROC_EOI_REG (EPIC_EUMBBAR + 0x200b0)/* End of interrupt */ + +/* Error code */ + +#define OK 0 +#define ERROR -1 + +/* function prototypes */ + +void epicVendorId( unsigned int *step, + unsigned int *devId, + unsigned int *venId + ); +void epicFeatures( unsigned int *noIRQs, + unsigned int *noCPUs, + unsigned int *VerId ); +extern void epicInit( unsigned int IRQType, unsigned int clkRatio); +ULONG sysEUMBBARRead ( ULONG regNum ); +void sysEUMBBARWrite ( ULONG regNum, ULONG regVal); +extern void epicTmFrequencySet( unsigned int frq ); +extern unsigned int epicTmFrequencyGet(void); +extern unsigned int epicTmBaseSet( ULONG srcAddr, + unsigned int cnt, + unsigned int inhibit ); +extern unsigned int epicTmBaseGet ( ULONG srcAddr, unsigned int *val ); +extern unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val ); +extern unsigned int epicTmInhibit( unsigned int timer ); +extern unsigned int epicTmEnable( ULONG srcAdr ); +extern void CoreExtIntEnable(void); /* Enable 603e external interrupts */ +extern void CoreExtIntDisable(void); /* Disable 603e external interrupts */ +extern unsigned char epicIntTaskGet(void); +extern void epicIntTaskSet( unsigned char val ); +extern unsigned int epicIntAck(void); +extern void epicSprSet( unsigned int eumbbar, unsigned char ); +extern void epicConfigGet( unsigned int *clkRatio, + unsigned int *serEnable ); +extern void SrcVecTableInit(void); +extern unsigned int epicModeGet(void); +extern void epicIntEnable(int Vect); +extern void epicIntDisable(int Vect); +extern int epicIntSourceConfig(int Vect, int Polarity, int Sense, int Prio); +extern unsigned int epicIntAck(void); +extern void epicEOI(void); +extern int epicCurTaskPrioSet(int Vect); + +struct SrcVecTable + { + ULONG srcAddr; + char srcName[40]; + }; + +#endif /* EPIC_H */ diff --git a/mpc8240/drivers/epic/epic1.c b/mpc8240/drivers/epic/epic1.c new file mode 100644 index 0000000..e9d3861 --- /dev/null +++ b/mpc8240/drivers/epic/epic1.c @@ -0,0 +1,517 @@ +/************************************************** + * $Id: epic1.c,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * copyright @ motorola, 1999 + * + *************************************************/ +#include +#include +#include "epic.h" + + +#define PRINT(format, args...) printf(format , ## args) + +#define LONGSWAP(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\ + (((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) ) + +typedef void (*VOIDFUNCPTR) (void); /* ptr to function returning void */ +struct SrcVecTable SrcVecTable[MAXVEC] = /* Addr/Vector cross-reference tbl */ + { + { EPIC_EX_INT0_VEC_REG, "External Direct/Serial Source 0"}, + { EPIC_EX_INT1_VEC_REG, "External Direct/Serial Source 1"}, + { EPIC_EX_INT2_VEC_REG, "External Direct/Serial Source 2"}, + { EPIC_EX_INT3_VEC_REG, "External Direct/Serial Source 3"}, + { EPIC_EX_INT4_VEC_REG, "External Direct/Serial Source 4"}, + + { EPIC_SR_INT5_VEC_REG, "External Serial Source 5"}, + { EPIC_SR_INT6_VEC_REG, "External Serial Source 6"}, + { EPIC_SR_INT7_VEC_REG, "External Serial Source 7"}, + { EPIC_SR_INT8_VEC_REG, "External Serial Source 8"}, + { EPIC_SR_INT9_VEC_REG, "External Serial Source 9"}, + { EPIC_SR_INT10_VEC_REG, "External Serial Source 10"}, + { EPIC_SR_INT11_VEC_REG, "External Serial Source 11"}, + { EPIC_SR_INT12_VEC_REG, "External Serial Source 12"}, + { EPIC_SR_INT13_VEC_REG, "External Serial Source 13"}, + { EPIC_SR_INT14_VEC_REG, "External Serial Source 14"}, + { EPIC_SR_INT15_VEC_REG, "External Serial Source 15"}, + + { EPIC_I2C_INT_VEC_REG, "Internal I2C Source"}, + { EPIC_DMA0_INT_VEC_REG, "Internal DMA0 Source"}, + { EPIC_DMA1_INT_VEC_REG, "Internal DMA1 Source"}, + { EPIC_MSG_INT_VEC_REG, "Internal Message Source"}, + }; + +VOIDFUNCPTR intVecTbl[MAXVEC]; /* Interrupt vector table */ + + +/**************************************************************************** +* epicInit - Initialize the EPIC registers +* +* This routine resets the Global Configuration Register, thus it: +* - Disables all interrupts +* - Sets epic registers to reset values +* - Sets the value of the Processor Current Task Priority to the +* highest priority (0xF). +* epicInit then sets the EPIC operation mode to Mixed Mode (vs. Pass +* Through or 8259 compatible mode). +* +* If IRQType (input) is Direct IRQs: +* - IRQType is written to the SIE bit of the EPIC Interrupt +* Configuration register (ICR). +* - clkRatio is ignored. +* If IRQType is Serial IRQs: +* - both IRQType and clkRatio will be written to the ICR register +*/ + +void epicInit + ( + unsigned int IRQType, /* Direct or Serial */ + unsigned int clkRatio /* Clk Ratio for Serial IRQs */ + ) + { + ULONG tmp; + + tmp = sysEUMBBARRead(EPIC_GLOBAL_REG); + tmp |= 0xa0000000; /* Set the Global Conf. register */ + sysEUMBBARWrite(EPIC_GLOBAL_REG, tmp); + sysEUMBBARWrite(EPIC_GLOBAL_REG, 0x20000000); + tmp = sysEUMBBARRead(EPIC_INT_CONF_REG); /* Read interrupt conf. reg */ + + if (IRQType == EPIC_DIRECT_IRQ) /* direct mode */ + sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp & 0xf7ffffff); + else /* Serial mode */ + { + tmp = (clkRatio << 28) | 0x08000000; /* Set clock ratio */ + sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp); + } + + while (epicIntAck() != 0xff); /* Clear all pending interrupts */ +} + +/**************************************************************************** + * epicIntEnable - Enable an interrupt source + * + * This routine clears the mask bit of an external, an internal or + * a Timer register to enable the interrupt. + * + * RETURNS: None + */ +void epicIntEnable + ( + int intVec /* Interrupt Vector Number */ + ) + { + ULONG tmp; + ULONG srAddr; + + srAddr = SrcVecTable[intVec].srcAddr; /* Retrieve src Vec/Prio register */ + tmp = sysEUMBBARRead(srAddr); + tmp &= 0x7fffffff; /* Clear the mask bit */ + sysEUMBBARWrite(srAddr, tmp); + return; + } + +/**************************************************************************** + * epicIntDisable - Disable an interrupt source + * + * This routine sets the mask bit of an external, an internal or + * a Timer register to disable the interrupt. + * + * RETURNS: OK or ERROR + * + */ + +void epicIntDisable + ( + int intVec /* Interrupt vector number */ + ) + { + + ULONG tmp, srAddr; + + srAddr = SrcVecTable[intVec].srcAddr; + tmp = sysEUMBBARRead(srAddr); + tmp |= 0x80000000; /* Set the mask bit */ + sysEUMBBARWrite(srAddr, tmp); + return; + } + +/**************************************************************************** + * epicIntSourceConfig - Set properties of an interrupt source + * + * This function sets interrupt properites (Polarity, Sense, Interrupt + * Prority, and Interrupt Vector) of an Interrupt Source. The properties + * can be set when the current source is not in-request or in-service, + * which is determined by the Activity bit. This routine return ERROR + * if the the Activity bit is 1 (in-request or in-service). + * + * This function assumes that the Source Vector/Priority register (input) + * is a valid address. + * + * RETURNS: OK or ERROR + */ + +int epicIntSourceConfig + ( + int Vect, /* interrupt source vector number */ + int Polarity, /* interrupt source polarity */ + int Sense, /* interrupt source Sense */ + int Prio /* interrupt source priority */ + ) + + { + ULONG tmp, newVal; + ULONG actBit, srAddr; + + srAddr = SrcVecTable[Vect].srcAddr; + tmp = sysEUMBBARRead(srAddr); + actBit = (tmp & 40000000) >> 30; /* retrieve activity bit - bit 30 */ + if (actBit == 1) + return ERROR; + + tmp &= 0xff30ff00; /* Erase previously set P,S,Prio,Vector bits */ + newVal = (Polarity << 23) | (Sense << 22) | (Prio << 16) | Vect; + sysEUMBBARWrite(srAddr, tmp | newVal ); + return (OK); + } + +/**************************************************************************** + * epicIntAck - acknowledge an interrupt + * + * This function reads the Interrupt acknowldge register and return + * the vector number of the highest pending interrupt. + * + * RETURNS: Interrupt Vector number. + */ + +unsigned int epicIntAck(void) +{ + return(sysEUMBBARRead( EPIC_PROC_INT_ACK_REG )); +} + +/**************************************************************************** + * epicEOI - signal an end of interrupt + * + * This function writes 0x0 to the EOI register to signal end of interrupt. + * It is usually called after an interrupt routine is served. + * + * RETURNS: None + */ + +void epicEOI(void) + { + sysEUMBBARWrite(EPIC_PROC_EOI_REG, 0x0); + } + +/**************************************************************************** + * epicCurTaskPrioSet - sets the priority of the Processor Current Task + * + * This function should be called after epicInit() to lower the priority + * of the processor current task. + * + * RETURNS: OK or ERROR + */ + +int epicCurTaskPrioSet + ( + int prioNum /* New priority value */ + ) + { + + if ( (prioNum < 0) || (prioNum > 0xF)) + return ERROR; + sysEUMBBARWrite(EPIC_PROC_CTASK_PRI_REG, prioNum); + return OK; + } + + +/************************************************************************ + * function: epicIntTaskGet + * + * description: Get value of processor current interrupt task priority register + * + * note: + ***********************************************************************/ +unsigned char epicIntTaskGet() +{ + /* get the interrupt task priority register */ + ULONG reg; + unsigned char rec; + + reg = sysEUMBBARRead( EPIC_PROC_CTASK_PRI_REG ); + rec = ( reg & 0x0F ); + return rec; +} + + +/************************************************************** + * function: epicISR + * + * description: EPIC service routine called by the core exception + * at 0x500 + * + * note: + **************************************************************/ +unsigned int epicISR(void) +{ + return 0; +} + + +/************************************************************ + * function: epicModeGet + * + * description: query EPIC mode, return 0 if pass through mode + * return 1 if mixed mode + * + * note: + *************************************************************/ +unsigned int epicModeGet(void) +{ + ULONG val; + + val = sysEUMBBARRead( EPIC_GLOBAL_REG ); + return (( val & 0x20000000 ) >> 29); +} + + +/********************************************* + * function: epicConfigGet + * + * description: Get the EPIC interrupt Configuration + * return 0 if not error, otherwise return 1 + * + * note: + ********************************************/ +void epicConfigGet( unsigned int *clkRatio, unsigned int *serEnable) +{ + ULONG val; + + val = sysEUMBBARRead( EPIC_INT_CONF_REG ); + *clkRatio = ( val & 0x70000000 ) >> 28; + *serEnable = ( val & 0x8000000 ) >> 27; +} + + +/******************************************************************* + * sysEUMBBARRead - Read a 32-bit EUMBBAR register + * + * This routine reads the content of a register in the Embedded + * Utilities Memory Block, and swaps to big endian before returning + * the value. + * + * RETURNS: The content of the specified EUMBBAR register. + */ + +ULONG sysEUMBBARRead + ( + ULONG regNum + ) + { + ULONG temp; + + temp = *(ULONG *) (CFG_EUMB_ADDR + regNum); + return ( LONGSWAP(temp)); + } + +/******************************************************************* + * sysEUMBBARWrite - Write a 32-bit EUMBBAR register + * + * This routine swaps the value to little endian then writes it to + * a register in the Embedded Utilities Memory Block address space. + * + * RETURNS: N/A + */ + +void sysEUMBBARWrite + ( + ULONG regNum, /* EUMBBAR register address */ + ULONG regVal /* Value to be written */ + ) + { + + *(ULONG *) (EUMBBAR + regNum) = LONGSWAP(regVal); + return ; + } + + +/******************************************************** + * function: epicVendorId + * + * description: return the EPIC Vendor Identification + * register: + * + * siliccon version, device id, and vendor id + * + * note: + ********************************************************/ +void epicVendorId + ( + unsigned int *step, + unsigned int *devId, + unsigned int *venId + ) + { + ULONG val; + val = sysEUMBBARRead( EPIC_VENDOR_ID_REG ); + *step = ( val & 0x00FF0000 ) >> 16; + *devId = ( val & 0x0000FF00 ) >> 8; + *venId = ( val & 0x000000FF ); + } + +/************************************************** + * function: epicFeatures + * + * description: return the number of IRQ supported, + * number of CPU, and the version of the + * OpenEPIC + * + * note: + *************************************************/ +void epicFeatures + ( + unsigned int *noIRQs, + unsigned int *noCPUs, + unsigned int *verId + ) + { + ULONG val; + + val = sysEUMBBARRead( EPIC_FEATURES_REG ); + *noIRQs = ( val & 0x07FF0000 ) >> 16; + *noCPUs = ( val & 0x00001F00 ) >> 8; + *verId = ( val & 0x000000FF ); +} + + +/********************************************************* + * function: epciTmFrequncySet + * + * description: Set the timer frequency reporting register + ********************************************************/ +void epicTmFrequencySet( unsigned int frq ) +{ + sysEUMBBARWrite(EPIC_TM_FREQ_REG, frq); +} + +/******************************************************* + * function: epicTmFrequncyGet + * + * description: Get the current value of the Timer Frequency + * Reporting register + * + ******************************************************/ +unsigned int epicTmFrequencyGet(void) +{ + return( sysEUMBBARRead(EPIC_TM_FREQ_REG)) ; +} + + +/**************************************************** + * function: epicTmBaseSet + * + * description: Set the #n global timer base count register + * return 0 if no error, otherwise return 1. + * + * note: + ****************************************************/ +unsigned int epicTmBaseSet + ( + ULONG srcAddr, /* Address of the Timer Base register */ + unsigned int cnt, /* Base count */ + unsigned int inhibit /* 1 - count inhibit */ + ) +{ + + unsigned int val = 0x80000000; + /* First inhibit counting the timer */ + sysEUMBBARWrite(srcAddr, val) ; + + /* set the new value */ + val = (cnt & 0x7fffffff) | ((inhibit & 0x1) << 31); + sysEUMBBARWrite(srcAddr, val) ; + return 0; +} + +/*********************************************************************** + * function: epicTmBaseGet + * + * description: Get the current value of the global timer base count register + * return 0 if no error, otherwise return 1. + * + * note: + ***********************************************************************/ +unsigned int epicTmBaseGet( ULONG srcAddr, unsigned int *val ) +{ + *val = sysEUMBBARRead( srcAddr ); + *val = *val & 0x7fffffff; + return 0; +} + +/*********************************************************** + * function: epicTmCountGet + * + * description: Get the value of a given global timer + * current count register + * return 0 if no error, otherwise return 1 + * note: + **********************************************************/ +unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val ) +{ + *val = sysEUMBBARRead( srcAddr ); + *val = *val & 0x7fffffff; + return 0; +} + + + +/*********************************************************** + * function: epicTmInhibit + * + * description: Stop counting of a given global timer + * return 0 if no error, otherwise return 1 + * + * note: + ***********************************************************/ +unsigned int epicTmInhibit( unsigned int srcAddr ) +{ + ULONG val; + + val = sysEUMBBARRead( srcAddr ); + val |= 0x80000000; + sysEUMBBARWrite( srcAddr, val ); + return 0; +} + +/****************************************************************** + * function: epicTmEnable + * + * description: Enable counting of a given global timer + * return 0 if no error, otherwise return 1 + * + * note: + *****************************************************************/ +unsigned int epicTmEnable( ULONG srcAddr ) +{ + ULONG val; + + val = sysEUMBBARRead( srcAddr ); + val &= 0x7fffffff; + sysEUMBBARWrite( srcAddr, val ); + return 0; +} + +void epicSourcePrint(int Vect) + { + ULONG srcVal; + + srcVal = sysEUMBBARRead(SrcVecTable[Vect].srcAddr); + PRINT("%s\n", SrcVecTable[Vect].srcName); + PRINT("Address = 0x%lx\n", SrcVecTable[Vect].srcAddr); + PRINT("Vector = %ld\n", (srcVal & 0x000000FF) ); + PRINT("Mask = %ld\n", srcVal >> 31); + PRINT("Activitiy = %ld\n", (srcVal & 40000000) >> 30); + PRINT("Polarity = %ld\n", (srcVal & 0x00800000) >> 23); + PRINT("Sense = %ld\n", (srcVal & 0x00400000) >> 22); + PRINT("Priority = %ld\n", (srcVal & 0x000F0000) >> 16); + } diff --git a/mpc8240/drivers/epic/epic2.S b/mpc8240/drivers/epic/epic2.S new file mode 100644 index 0000000..873b95a --- /dev/null +++ b/mpc8240/drivers/epic/epic2.S @@ -0,0 +1,197 @@ +/************************************** + * $Id: epic2.S,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * copyright @ Motorola, 1999 + * + **************************************/ + +#include +#include +#include + +/********************************************* + * function: CoreExtIntEnable + * + * description: Enable 603e core external interrupt + * + * note: mtmsr is context-synchronization + **********************************************/ + .text + .align 2 + .global CoreExtIntEnable +CoreExtIntEnable: + mfmsr r3 + + ori r3,r3,0x8000 /* enable external interrupt */ + mtmsr r3 + + bclr 20, 0 + +/******************************************* + * function: CoreExtIntDisable + * + * description: Disable 603e core external interrupt + * + * note: + *******************************************/ + .text + .align 2 + .global CoreExtIntDisable +CoreExtIntDisable: + mfmsr r4 + + xor r3,r3,r3 + or r3,r3,r4 + + andis. r4,r4,0xffff + andi. r3,r3,0x7fff /* disable external interrupt */ + + or r3,r3,r4 + mtmsr r3 + + bclr 20, 0 + +/********************************************************* + * function: epicEOI + * + * description: signal the EOI and restore machine status + * Input: r3 - value of eumbbar + * Output: r3 - value of eumbbar + * r4 - ISR vector value + * note: + ********************************************************/ + .text + .align 2 + .global epicEOI +epicEOI: + lis r5,0x0006 /* Build End Of Interrupt Register offset */ + ori r5,r5,0x00b0 + xor r7,r7,r7 /* Clear r7 */ + stwbrx r7,r5,r3 /* Save r7, writing to this register will + * intidate the end of processing the + * highest interrupt. + */ + sync + + /* ---RESTORE MACHINE STATE */ + mfmsr r13 /* Clear Recoverable Interrupt bit in MSR */ + or r7,r7,r13 + + andis. r7,r7,0xffff + andi. r13,r13,0x7ffd /* (and disable interrupts) */ + or r13,r13,r7 + mtmsr r13 + + lwz r13,0x1c(r1) /* pull ctr */ + mtctr r13 + + lwz r13,0x18(r1) /* pull xer */ + mtctr r13 + + lwz r13,0x14(r1) /* pull lr */ + mtctr r13 + + lwz r13,0x10(r1) /* Pull SRR1 from stack */ + mtspr SRR1,r13 /* Restore SRR1 */ + + lwz r13,0xc(r1) /* Pull SRR0 from stack */ + mtspr SRR0,r13 /* Restore SRR0 */ + + lwz r13,0x8(r1) /* Pull User stack pointer from stack */ + mtspr SPRG1,r13 /* Restore SPRG1 */ + + lwz r4,0x4(r1) /* vector value */ + lwz r3,0x0(r1) /* eumbbar */ + sync + + addi r1,r1,0x20 /* Deallocate stack */ + mtspr SPRG0,r1 /* Save updated Supervisor stack pointer */ + mfspr r1,SPRG1 /* Restore User stack pointer */ + + bclr 20,0 + +/*********************************************************** + * function: exception routine called by exception vector + * at 0x500, external interrupt + * + * description: Kahlua EPIC controller + * + * input: r3 - content of eumbbar + * output: r3 - ISR return value + * r4 - Interrupt vector number + * note: + ***********************************************************/ + + .text + .align 2 + .global epic_exception + +epic_exception: + + /*---SAVE MACHINE STATE TO A STACK */ + mtspr SPRG1,r1 /* Save User stack pointer to SPRG1 */ + mfspr r1,SPRG0 /* Load Supervisor stack pointer into r1 */ + + stwu r3,-0x20(r1) /* Push the value of eumbbar onto stack */ + + mfspr r3,SPRG1 /* Push User stack pointer onto stack */ + stw r3,0x8(r1) + mfspr r3,SRR0 /* Push SRR0 onto stack */ + stw r1,0xc(r1) + mfspr r3,SRR1 /* Push SRR1 onto stack */ + stw r3,0x10(r1) + mflr r3 + stw r3,0x14(r1) /* Push LR */ + mfxer r3 + stw r3,0x18(r1) /* Push Xer */ + mfctr r3 + stw r3,0x1c(r1) /* Push CTR */ + + mtspr SPRG0,r1 /* Save updated Supervisor stack pointer + * value to SPRG0 + */ + mfmsr r3 + ori r3,r3,0x0002 /* Set Recoverable Interrupt bit in MSR */ + mtmsr r3 + + /* ---READ IN THE EUMBAR REGISTER */ + lwz r6,0(r1) /* this is eumbbar */ + sync + + /* ---READ EPIC REGISTER: PROCESSOR INTERRUPT ACKNOWLEDGE REGISTER */ + lis r5,0x0006 /* Build Interrupt Acknowledge Register + * offset + */ + ori r5,r5,0x00a0 + lwbrx r7,r5,r6 /* Load interrupt vector into r7 */ + sync + + /* --MASK OFF ALL BITS EXCEPT THE VECTOR */ + xor r3,r3,r3 + xor r4,r4,r4 + or r3, r3, r6 /* eumbbar in r3 */ + andi. r4,r7,0x00ff /* Mask off bits, vector in r4 */ + + stw r4,0x04(r1) /* save the vector value */ + + lis r5,epicISR@ha + ori r5,r5,epicISR@l + mtlr r5 + blrl + + xor r30,r30,r30 + or r30,r30,r3 /* save the r3 which containts the return value from epicISR */ + + /* ---READ IN THE EUMBAR REGISTER */ + lwz r3,0(r1) + sync + + lis r5,epicEOI@ha + ori r5,r5,epicEOI@l + mtlr r5 + blrl + + xor r3,r3,r3 + or r3,r3,r30 /* restore the ISR return value */ + + bclr 20,0 diff --git a/mpc8240/drivers/epic/epicutil.S b/mpc8240/drivers/epic/epicutil.S new file mode 100644 index 0000000..72787a5 --- /dev/null +++ b/mpc8240/drivers/epic/epicutil.S @@ -0,0 +1,59 @@ +/************************************** + * $Id: epicutil.S,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * copyright @ Motorola, 1999 + * + * + * This file contains two commonly used + * lower level utility routines. + * + * The utility routines are also in other + * Kahlua device driver libraries. The + * need to be linked in only once. + **************************************/ + +#include +#include + +/********************************************************** + * function: load_runtime_reg + * + * input: r3 - value of eumbbar + * r4 - register offset in embedded utility space + * + * output: r3 - register content + **********************************************************/ + .text + .align 2 + .global load_runtime_reg + +load_runtime_reg: + + xor r5,r5,r5 + or r5,r5,r3 /* save eumbbar */ + + lwbrx r3,r4,r5 + sync + + bclr 20, 0 + +/**************************************************************** + * function: store_runtime_reg + * + * input: r3 - value of eumbbar + * r4 - register offset in embedded utility space + * r5 - new value to be stored + * + ****************************************************************/ + .text + .align 2 + .global store_runtime_reg +store_runtime_reg: + + xor r0,r0,r0 + + stwbrx r5, r4, r3 + sync + + bclr 20,0 + diff --git a/mpc8240/drivers/errors.h b/mpc8240/drivers/errors.h new file mode 100644 index 0000000..aa707f0 --- /dev/null +++ b/mpc8240/drivers/errors.h @@ -0,0 +1,218 @@ +/* Copyright Motorola, Inc. 1993, 1994 + ALL RIGHTS RESERVED + + You are hereby granted a copyright license to use, modify, and + distribute the SOFTWARE so long as this entire notice is retained + without alteration in any modified and/or redistributed versions, + and that such modified versions are clearly identified as such. + No licenses are granted by implication, estoppel or otherwise under + any patents or trademarks of Motorola, Inc. + + The SOFTWARE is provided on an "AS IS" basis and without warranty. + To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS + ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR + PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH + REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS + THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. + + To the maximum extent permitted by applicable law, IN NO EVENT SHALL + MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER + (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF + BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS + INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR + INABILITY TO USE THE SOFTWARE. Motorola assumes no responsibility + for the maintenance and support of the SOFTWARE. + +*/ + + +#include "config.h" + +/* + 1 2 3 4 5 6 7 8 +01234567890123456789012345678901234567890123456789012345678901234567890123456789 +*/ +/* List define statements here */ + +/* These are for all the toolboxes and functions to use. These will help +to standardize the error handling in the current project */ + + /* this is the "data type" for the error + messages in the system */ +#define STATUS unsigned int + + /* this is a success status code */ +#define SUCCESS 1 + + /* likewise this is failure */ +#define FAILURE 0 + +#define NUM_ERRORS 47 + +/* This first section of "defines" are for error codes ONLY. The called + routine will return one of these error codes to the caller. If the final + returned code is "VALID", then everything is a-okay. However, if one + of the functions returns a non-valid status, that error code should be + propogated back to all the callers. At the end, the last caller will + call an error_processing function, and send in the status which was + returned. It's up to the error_processing function to determine which + error occured (as indicated by the status), and print an appropriate + message back to the user. +*/ +/*----------------------------------------------------------------------*/ +/* these are specifically for the parser routines */ + +#define UNKNOWN_COMMAND 0xfb00 /* "unrecognized command " */ +#define UNKNOWN_REGISTER 0xfb01 /* "unknown register "*/ +#define ILLEGAL_RD_STAGE 0xfb02 /* cannot specify reg. family in range*/ +#define ILLEGAL_REG_FAMILY 0xfb03 /* "cannot specify a range of special + or miscellaneous registers"*/ +#define RANGE_CROSS_FAMILY 0xfb04 /* "cannot specify a range across + register families" */ +#define UNIMPLEMENTED_STAGE 0xfb05 /* invalid rd or rmm parameter format */ +#define REG_NOT_WRITEABLE 0xfb06 /* "unknown operator in arguements"*/ +#define INVALID_FILENAME 0xfb07 /* "invalid download filename" */ +#define INVALID_BAUD_RATE 0xfb08 /* invalid baud rate from sb command */ +#define UNSUPPORTED_REGISTER 0xfb09 /* Special register is not supported */ +#define FOR_BOARD_ONLY 0xfb0a /* "Not available for Unix." */ + + + +/*----------------------------------------------------------------------*/ +/* these are for the error checking toolbox */ + +#define INVALID 0xfd00 /* NOT valid */ +#define VALID 0xfd01 /* valid */ + + /* This error is found in the fcn: + is_right_size_input() to indicate + that the input was not 8 characters + long. */ +#define INVALID_SIZE 0xfd02 + + /* This error is found in the fcn: + is_valid_address_range() to indicate + that the address given falls outside + of valid memory defined by MEM_START + to MEM_END. + */ +#define OUT_OF_BOUNDS_ADDRESS 0xfd03 + + /* This error is found in the fcn: + is_valid_hex_input() to indicate that + one of more of the characters entered + are not valid hex characters. Valid + hex characters are 0-9, A-F, a-f. + */ +#define INVALID_HEX_INPUT 0xfd04 + + /* This error is found in the fcn: + is_valid_register_number() to indicate + that a given register does not exist. + */ +#define REG_NOT_READABLE 0xfd05 + + /* This error is found in the fcn: + is_word_aligned_address() to indicate + that the given address is not word- + aligned. A word-aligned address ends + in 0x0,0x4,0x8,0xc. + */ +#define NOT_WORD_ALIGNED 0xfd07 + + /* This error is found in the fcn: + is_valid_address_range() to indicate + that the starting address is greater + than the ending address. + */ +#define REVERSED_ADDRESS 0xfd08 + + /* this error tells us that the address + specified as the destination is within + the source addresses */ +#define RANGE_OVERLAP 0xfd09 + + +#define ERROR 0xfd0a /* An error occured */ +#define INVALID_PARAM 0xfd0b /* "invalid input parameter " */ + + +#define INVALID_FLAG 0xfd0c /* invalid flag */ + +/*----------------------------------------------------------------------*/ +/* these are for the getarg toolbox */ + +#define INVALID_NUMBER_ARGS 0xFE00 /* invalid number of commd arguements */ +#define UNKNOWN_PARAMETER 0xFE01 /* "unknown type of parameter "*/ + + + + + +/*----------------------------------------------------------------------*/ +/* these are for the tokenizer toolbox */ + +#define ILLEGAL_CHARACTER 0xFF00 /* unrecognized char. in input stream*/ +#define TTL_NOT_SORTED 0xFF01 /* token translation list not sorted */ +#define TTL_NOT_DEFINED 0xFF02 /* token translation list not assigned*/ +#define INVALID_STRING 0xFF03 /* unable to extract string from input */ +#define BUFFER_EMPTY 0xFF04 /* "input buffer is empty" */ +#define INVALID_MODE 0xFF05 /* input buf is in an unrecognized mode*/ +#define TOK_INTERNAL_ERROR 0xFF06 /* "internal tokenizer error" */ +#define TOO_MANY_IBS 0xFF07 /* "too many open input buffers" */ +#define NO_OPEN_IBS 0xFF08 /* "no open input buffers" */ + + + +/* these are for the read from screen toolbox */ + +#define RESERVED_WORD 0xFC00 /* used a reserved word as an arguement*/ + + +/* these are for the breakpoint routines */ + +#define FULL_BPDS 0xFA00 /* breakpoint data structure is full */ + + + +/* THESE are for the downloader */ + +#define NOT_IN_S_RECORD_FORMAT 0xf900 /* "not in S-Record Format" */ +#define UNREC_RECORD_TYPE 0xf901 /* "unrecognized record type" */ +#define CONVERSION_ERROR 0xf902 /* "ascii to int conversion error" */ +#define INVALID_MEMORY 0xf903 /* "bad s-record memory address " */ + + +/* these are for the compression and decompression stuff */ + +#define COMP_UNK_CHARACTER 0xf800 /* "unknown compressed character " */ + +#define COMP_UNKNOWN_STATE 0xf801 /* "unknown binary state" */ + +#define NOT_IN_COMPRESSED_FORMAT 0xf802 /* not in compressed S-Record format */ + + +/* these are for the DUART handling things */ + + /* "unrecognized serial port configuration" */ +#define UNKNOWN_PORT_STATE 0xf700 + + +/* these are for the register toolbox */ + + /* "cannot find register in special + purpose register file " */ +#define SPR_NOT_FOUND 0xf600 + + +/* these are for the duart specific stuff */ + + /* "transparent mode needs access to + two serial ports" */ +#define TM_NEEDS_BOTH_PORTS 0xf500 + + +/*----------------------------------------------------------------------*/ +/* these are specifically for the flash routines */ +#define FLASH_ERROR 0xf100 /* general flash error */ diff --git a/mpc8240/drivers/i2c/Makefile b/mpc8240/drivers/i2c/Makefile new file mode 100644 index 0000000..faf599b --- /dev/null +++ b/mpc8240/drivers/i2c/Makefile @@ -0,0 +1,134 @@ +########################################################################## +# +# $Id: Makefile,v 1.1 2000/11/20 17:22:33 wdenk Exp $ +# +# Copyright Motorola, Inc. 1997 +# ALL RIGHTS RESERVED +# +# You are hereby granted a copyright license to use, modify, and +# distribute the SOFTWARE so long as this entire notice is retained +# without alteration in any modified and/or redistributed versions, +# and that such modified versions are clearly identified as such. +# No licenses are granted by implication, estoppel or otherwise under +# any patents or trademarks of Motorola, Inc. +# +# The SOFTWARE is provided on an "AS IS" basis and without warranty. +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. +# +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR +# INABILITY TO USE THE SOFTWARE. +# +# $Log: Makefile,v $ +# Revision 1.1 2000/11/20 17:22:33 wdenk +# +# * Added support for MBX860T (thanks to Rob Taylor) +# +# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is +# Work In Progress (TM); current status: boots to command line input. +# EPIC code non-functional (interrupts disabled), No net, No IDE. +# +# * Add support for Status LED +# +# * Optionally panic() to reboot instead of hanging +# +# * Misc bug fixes +# +# * All frequencies in HZ now (internally) +# +# * Add support for BOOTP Domain Name Server Option +# +# Revision 1.1.1.1 2000/11/14 16:54:07 robt +# no message +# +# Revision 1.1.1.1 2000/11/14 14:49:39 robt +# no message +# +# Revision 1.4 1999/04/29 13:41:07 charliem +# Capture first pass at modifications to the I2C interface. This version is +# correct, but there are some additional modifications to be implemented. +# Nothing but I2C should be affected. +# +# Revision 1.3 1999/02/11 23:14:58 wyin +# Added MasterRcvAddress variable to handle master receiver address phase +# +# Revision 1.2 1999/02/05 01:55:47 wyin +# modified to set up soft link for hearder files +# compilable version with dink +# +# Revision 1.1 1999/02/03 18:58:32 wyin +# Base line +# +# Revision 1.12 1998/11/20 01:34:55 wyin +# Added INTMEM function and data structure. +# Enabled DCACHE. +# There is a minor problem with DCACHE, the cache policy had to be write-through. +# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length. +# But consequence measurement is fine. +# +# +############################################################################ +TARGET = libi2c.a + +#DEBUG = -g +DEBUG = -DI2CDBG +LST = -Hanno -S +OPTIM = +CC = /risc/tools/pkgs/metaware/bin/hcppc +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) +PREP = $(CC) $(CFLAGS) -P + +# Assembler used to build the .s files (for the board version) + +ASOPT = -big_si -c +ASDEBUG = -l -fm +AS = /risc/tools/pkgs/metaware/bin/asppc + +# Linker to bring .o files together into an executable. + +LKOPT = -Bbase=0 -q -Qn -r +LKCMD = +LINK = /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT) + +# DOS Utilities + +DEL = rm +COPY = cp +LIST = ls + +OBJECTS = i2c1.o i2c2.o + +all: $(TARGET) + +objects: $(OBJECTS) + +$(TARGET): $(OBJECTS) + $(LINK) $(OBJECTS) -o $@ + +clean: + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) + +.s.o: + $(DEL) -f $*.i + $(PREP) -Hasmcpp $< + $(AS) $(ASOPT) $*.i +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst + +.c.o: + $(CCobj) $< + +.c.s: + $(CCobj) $(LST) $< + +i2c1.o: i2c_export.h i2c.h i2c1.c + +i2c2.o: i2c.h i2c2.s diff --git a/mpc8240/drivers/i2c/Makefile_pc b/mpc8240/drivers/i2c/Makefile_pc new file mode 100644 index 0000000..5fe9f7e --- /dev/null +++ b/mpc8240/drivers/i2c/Makefile_pc @@ -0,0 +1,143 @@ +########################################################################## +# +# makefile_pc for use with PC mksnt tools dink32/drivers/i2c +# $Id: Makefile_pc,v 1.1 2000/11/20 17:22:33 wdenk Exp $ +# +# Copyright Motorola, Inc. 1997 +# ALL RIGHTS RESERVED +# +# You are hereby granted a copyright license to use, modify, and +# distribute the SOFTWARE so long as this entire notice is retained +# without alteration in any modified and/or redistributed versions, +# and that such modified versions are clearly identified as such. +# No licenses are granted by implication, estoppel or otherwise under +# any patents or trademarks of Motorola, Inc. +# +# The SOFTWARE is provided on an "AS IS" basis and without warranty. +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. +# +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR +# INABILITY TO USE THE SOFTWARE. +# +# $Log: Makefile_pc,v $ +# Revision 1.1 2000/11/20 17:22:33 wdenk +# +# * Added support for MBX860T (thanks to Rob Taylor) +# +# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is +# Work In Progress (TM); current status: boots to command line input. +# EPIC code non-functional (interrupts disabled), No net, No IDE. +# +# * Add support for Status LED +# +# * Optionally panic() to reboot instead of hanging +# +# * Misc bug fixes +# +# * All frequencies in HZ now (internally) +# +# * Add support for BOOTP Domain Name Server Option +# +# Revision 1.1.1.1 2000/11/14 16:54:07 robt +# no message +# +# Revision 1.1.1.1 2000/11/14 14:49:39 robt +# no message +# +# Revision 1.1 1999/06/11 20:05:13 maurie +# support for compiling dink on PC +# +# Revision 1.4 1999/04/29 13:41:07 charliem +# Capture first pass at modifications to the I2C interface. This version is +# correct, but there are some additional modifications to be implemented. +# Nothing but I2C should be affected. +# +# Revision 1.3 1999/02/11 23:14:58 wyin +# Added MasterRcvAddress variable to handle master receiver address phase +# +# Revision 1.2 1999/02/05 01:55:47 wyin +# modified to set up soft link for hearder files +# compilable version with dink +# +# Revision 1.1 1999/02/03 18:58:32 wyin +# Base line +# +# Revision 1.12 1998/11/20 01:34:55 wyin +# Added INTMEM function and data structure. +# Enabled DCACHE. +# There is a minor problem with DCACHE, the cache policy had to be write-through. +# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length. +# But consequence measurement is fine. +# +# +############################################################################ +TARGET = libi2c.a + +#DEBUG = -g +DEBUG = -DI2CDBG +LST = -Hanno -S +OPTIM = +CC = m:/old_tools/tools/hcppc/bin/hcppc +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) +PREP = $(CC) $(CFLAGS) -P + +# Assembler used to build the .s files (for the board version) + +ASOPT = -big_si -c +ASDEBUG = -l -fm +AS = m:/old_tools/tools/hcppc/bin/asppc + +# Linker to bring .o files together into an executable. + +LKOPT = -Bbase=0 -q -Qn -r +LKCMD = +LINK = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT) + +# DOS Utilities + +DEL = rm +COPY = cp +LIST = ls + +OBJECTS = i2c1.o i2c2.o + +all: $(TARGET) + +objects: $(OBJECTS) + +$(TARGET): $(OBJECTS) + $(LINK) $(OBJECTS) -o $@ + +clean: + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) + +.s.o: + $(DEL) -f $*.i + $(PREP) -Hasmcpp $< + $(AS) $(ASOPT) $*.i +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst + +.c.o: + $(CCobj) $< + +.c.s: + $(CCobj) $(LST) $< + +i2c1.o: i2c_export.h i2c.h i2c1.c + $(CCobj) $< + + +i2c2.o: i2c.h i2c2.s + $(DEL) -f $*.i + $(PREP) -Hasmcpp $< + $(AS) $(ASOPT) $*.i diff --git a/mpc8240/drivers/i2c/README b/mpc8240/drivers/i2c/README new file mode 100644 index 0000000..73e211d --- /dev/null +++ b/mpc8240/drivers/i2c/README @@ -0,0 +1,105 @@ +CONTENT: + + i2c.h + i2c1.c + i2c2.s + +WHAT ARE THESE FILES: + +These files contain MPC8240 (Kahlua) I2C +driver routines. The driver routines are not +written for any specific operating system. +They serves the purpose of code sample, and +jump-start for using the MPC8240 I2C unit. + +For the reason of correctness of C language +syntax, these files are compiled by Metaware +C compiler and assembler. + +ENDIAN NOTATION: + +The algorithm is designed for big-endian mode, +software is responsible for byte swapping. + +USAGE: + +1. The host system that is running on MPC8240 + shall link the files listed here. The memory + location of driver routines shall take into + account of that driver routines need to run + in supervisor mode and they process I2C + interrupt. + +2. The host system is responsible for configuring + the MPC8240 including Embedded Utilities Memory + Block. All I2C driver functions require the + content of Embedded Utilities Memory Block + Base Address Register, EUMBBAR, as the first + parameter. + +3. Before I2C unit of MPC8240 can be used, + initialize I2C unit by calling I2C_Init + with the corresponding parameters. + + Note that the I2CFDR register shall be written + once during the initialization. If it is written + in the midst of transers, or after I2C STOPs or + REPEAT STATRs, depending on the data written, + a long reset time may be encountered. + +4. After I2C unit has been successfully initialized, + use the Application level API to send data or + receive data upon the desired mode, Master or + Slave. + +5. If the host system is also using the EPIC unit + on MPC8240, the system can register the + I2C_ISR with the EPIC including other + desired resources. + + If the host system does not using the EPIC unit + on MPC8240, I2C_Timer_Event function can + be called for each desired time interval. + + In both cases, the host system is free to provide + its own timer event handler and interrupt service + routine. + +6. The I2C driver routines contains a set + of utilities, Set and Get, for host system + to query and modify the desired I2C registers. + +7. It is the host system's responsibility of + queueing the I2C I/O request. The host + system shall check the I2C_ISR return code + for I2C I/O status. If I2C_ISR returns + I2CBUFFEMPTY or I2CBUFFFULL, it means + I2C unit has completed a I/O request + stated by the Application API. + +8. If the host system has more than one master + mode I2C unit I/O requests but doesn't want + to be intervented by being addressed as slave, + the host system can use the master mode + Application API with stop_flag set to 0 in + conjunction with is_cnt flag set to 1. + The first API call sets both stop_flag and + is_cnt to 0, indicating a START condition + shall be generated but when the end of + transaction is reached, do not generate a + STOP condition. Once the host system is + informed that the transaction has been + completed, the next Application API call + shall set is_cnt flag to 1, indicating a + repeated START condition shall be generated. + The last Application API call shall set + stop_flag + to 1. + +9. The I2C_Timer_Event function containes + a user defined function pointer. It + serves the purpose of providing the + host system a way to use its own event + handler instead of the I2C_ISR provided + here. + diff --git a/mpc8240/drivers/i2c/i2c.h b/mpc8240/drivers/i2c/i2c.h new file mode 100644 index 0000000..2482033 --- /dev/null +++ b/mpc8240/drivers/i2c/i2c.h @@ -0,0 +1,364 @@ +#ifndef I2C_H +#define I2C_H + +/**************************************************** + * $Id: i2c.h,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * Copyright Motrola 1999 + * + * $Log: i2c.h,v $ + * Revision 1.1 2000/11/20 17:22:33 wdenk + * + * * Added support for MBX860T (thanks to Rob Taylor) + * + * * Added support for Sandpoint8240 (thanks to Rob Taylor); this is + * Work In Progress (TM); current status: boots to command line input. + * EPIC code non-functional (interrupts disabled), No net, No IDE. + * + * * Add support for Status LED + * + * * Optionally panic() to reboot instead of hanging + * + * * Misc bug fixes + * + * * All frequencies in HZ now (internally) + * + * * Add support for BOOTP Domain Name Server Option + * + * Revision 1.1.1.1 2000/11/14 16:54:07 robt + * no message + * + * Revision 1.1.1.1 2000/11/14 14:49:39 robt + * no message + * + * Revision 1.7 1999/04/30 16:25:50 charliem + * Change the DINK to I2C_do_transaction interface to allow the application + * to specify the data address as a parameter to I2C_do_transaction, rather + * than putting the data address into the first byte of the buffer. + * There is a work-around in I2C_do_transaction in this version, see comments + * in the i2c1.c code. + * + * Revision 1.6 1999/04/29 13:41:03 charliem + * Capture first pass at modifications to the I2C interface. This version is + * correct, but there are some additional modifications to be implemented. + * Nothing but I2C should be affected. + * + * Revision 1.5 1999/02/12 20:08:28 wyin + * Use I2C's offset as the I2CStatus base value + * + * Revision 1.4 1999/02/12 15:02:23 wyin + * Added I2CADDRESS constant for better information + * exchange to apps. + * + * Revision 1.3 1999/02/10 01:48:27 wyin + * Modified the way of Master Rcv generating STOP. Setting TXAK bit to 1 will + * not automatically generat STOP. BOOK VI is wrong. + * + * Revision 1.2 1999/02/05 01:55:44 wyin + * modified to set up soft link for hearder files + * compilable version with dink + * + * Revision 1.1 1999/02/03 18:58:30 wyin + * Base line + * + ****************************************************/ + +#define I2CADR 0x00003000 +#define I2CFDR 0x00003004 +#define I2CCR 0x00003008 +#define I2CSR 0x0000300C +#define I2CDR 0x00003010 + +typedef enum _i2cstatus +{ + I2CSUCCESS = 0x3000, + I2CADDRESS, + I2CERROR, + I2CBUFFFULL, + I2CBUFFEMPTY, + I2CXMITERROR, + I2CRCVERROR, + I2CBUSBUSY, + I2CALOSS, + I2CNOEVENT, +} I2CStatus; + +typedef enum i2c_control +{ + MEN = 0x00000080, + MIEN = 0x00000040, + MSTA = 0x00000020, + MTX = 0x00000010, + TXAK = 0x00000008, + RSTA = 0x00000004, +} I2C_CONTROL; + +typedef enum i2c_status +{ + MCF = 0x00000080, + MAAS = 0x00000040, + MBB = 0x00000020, + MAL = 0x00000010, + SRW = 0x00000004, + MIF = 0x00000002, + RXAK = 0x00000001, +} I2C_STATUS; + +typedef struct _i2c_ctrl +{ + unsigned int reserved0 : 24; + unsigned int men : 1; + unsigned int mien : 1; + unsigned int msta : 1; + unsigned int mtx : 1; + unsigned int txak : 1; + unsigned int rsta : 1; + unsigned int reserved1 : 2; +} I2C_CTRL; + +typedef struct _i2c_stat +{ + unsigned int rsrv0 : 24; + unsigned int mcf : 1; + unsigned int maas : 1; + unsigned int mbb : 1; + unsigned int mal : 1; + unsigned int rsrv1 : 1; + unsigned int srw : 1; + unsigned int mif : 1; + unsigned int rxak : 1; +} I2C_STAT; + +typedef enum _i2c_mode +{ + RCV = 0, + XMIT = 1, +} I2C_MODE; + +/******************** App. API ******************** + * The application API is for user level application + * to use the funcitonality provided by I2C driver + * + * Note: Its App.s responsibility to swap the data + * byte. In our API, we just transfer whatever + * we are given + **************************************************/ +/** + * Note: + * + * In all following functions, + * the caller shall pass the configured embedded utility memory + * block base, EUMBBAR. + **/ + +/* Send a buffer of data to the intended rcv_addr. + * If stop_flag is set, after the whole buffer + * is sent, generate a STOP signal provided that the + * receiver doesn't signal the STOP in the middle. + * I2C is the master performing transmitting. If + * no STOP signal is generated at the end of current + * transaction, the master can generate a START signal + * to another slave addr. + * + * return I2CSUCCESS if no error. + */ +static I2CStatus I2C_put( unsigned int eumbbar, + unsigned char rcv_addr, /* receiver's address */ + unsigned char *buffer_ptr, /* pointer of data to be sent */ + unsigned int length, /* number of byte of in the buffer */ + unsigned int stop_flag, /* 1 - signal STOP when buffer is empty + * 0 - no STOP signal when buffer is empty + */ + unsigned int is_cnt ); /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + +/* Receive a buffer of data from the desired sender_addr + * If stop_flag is set, when the buffer is full and the + * sender does not signal STOP, generate a STOP signal. + * I2C is the master performing receiving. If no STOP signal + * is generated, the master can generate a START signal + * to another slave addr. + * + * return I2CSUCCESS if no error. + */ +static I2CStatus I2C_get( unsigned int eumbbar, + unsigned char sender_addr, /* sender's address */ + unsigned char *buffer_ptr, /* pointer of receiving buffer */ + unsigned int length, /* length of the receiving buffer */ + unsigned int stop_flag, /* 1 - signal STOP when buffer is full + * 0 - no STOP signal when buffer is full + */ + unsigned int is_cnt ); /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + +#if 0 /* the I2C_write and I2C_read functions are not active */ +/* Send a buffer of data to the requiring master. + * If stop_flag is set, after the whole buffer is sent, + * generate a STOP signal provided that the requiring + * receiver doesn't signal the STOP in the middle. + * I2C is the slave performing transmitting. + * + * return I2CSUCCESS if no error. + * + * Note: due to the Kahlua design, slave transmitter + * shall not signal STOP since there is no way + * for master to detect it, causing I2C bus hung. + * + * For the above reason, the stop_flag is always + * set, i.e., 1. + * + * programmer shall use the timer on Kahlua to + * control the interval of data byte at the + * master side. + */ +static I2CStatus I2C_write( unsigned int eumbbar, + unsigned char *buffer_ptr, /* pointer of data to be sent */ + unsigned int length, /* number of byte of in the buffer */ + unsigned int stop_flag ); /* 1 - signal STOP when buffer is empty + * 0 - no STOP signal when buffer is empty + */ + + /* Receive a buffer of data from the sending master. + * If stop_flag is set, when the buffer is full and the + * sender does not signal STOP, generate a STOP signal. + * I2C is the slave performing receiving. + * + * return I2CSUCCESS if no error. + */ +static I2CStatus I2C_read(unsigned int eumbbar, + unsigned char *buffer_ptr, /* pointer of receiving buffer */ + unsigned int length, /* length of the receiving buffer */ + unsigned int stop_flag ); /* 1 - signal STOP when buffer is full + * 0 - no STOP signal when buffer is full + */ +#endif /* of if0 for turning off I2C_read & I2C_write */ + +/* if interrupt is not used, this is the timer event handler. + * After each fixed time interval, this function can be called + * to check the I2C status and call appropriate function to + * handle the status event. + */ +static I2CStatus I2C_Timer_Event( unsigned int eumbbar, I2CStatus (*handler)( unsigned int ) ); + +/********************* Kernel API ************************ + * Kernel APIs are functions I2C driver provides to the + * O.S. + *********************************************************/ + +/******************* device I/O function ***************/ + +/* Generate a START signal in the desired mode. + * I2C is the master. + * + * return I2CSUCCESS if no error. + * I2CERROR if i2c unit is not enabled. + * I2CBUSBUSY if bus cannot be granted + */ +static I2CStatus I2C_Start( unsigned int eumbbar, + unsigned char slave_addr, /* address of the receiver */ + I2C_MODE mode, /* XMIT(1) - put (write) + * RCV(0) - get (read) + */ + unsigned int is_cnt ); /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + +/* Generate a STOP signal to terminate the transaction. */ +static I2CStatus I2C_Stop( unsigned int eumbbar ); + +/* Do a one-byte master transmit. + * + * return I2CBUFFEMPTY if this is the last byte. + * Otherwise return I2CSUCCESS + */ +static I2CStatus I2C_Master_Xmit( unsigned int eumbbar ); + +/* Do a one-byte master receive. + * + * return I2CBUFFFULL if this is the last byte. + * Otherwise return I2CSUCCESS + */ +static I2CStatus I2C_Master_Rcv( unsigned int eumbbar ); + +/* Do a one-byte slave transmit. + * + * return I2CBUFFEMPTY if this is the last byte. + * Otherwise return I2CSUCCESS + * + */ +static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar ); + +/* Do a one-byte slave receive. + * + * return I2CBUFFFULL if this is the last byte. + * Otherwise return I2CSUCCESS + */ +static I2CStatus I2C_Slave_Rcv( unsigned int eumbbar ); + +/* Process slave address phase. + * + * return I2CADDRESS if this is slave receiver's address phase + * Otherwise return the result of slave xmit one byte. + */ +static I2CStatus I2C_Slave_Addr( unsigned int eumbbar ); + +/******************* Device Control Fucntion ****************/ +/* Initialize I2C unit with desired frequency divider, + * driver's slave address w/o interrupt enabled. + * + * This function must be called before I2C unit can + * be used. + */ +static I2CStatus I2C_Init( unsigned int eumbbar, + unsigned char fdr, /* frequency divider */ + unsigned char addr, /* driver's address used for receiving */ + unsigned int en_int); /* 1 - enable I2C interrupt + * 0 - disable I2C interrup + */ + +/* I2C interrupt service routine. + * + * return I2CADDRESS if it is receiver's (either master or slave) address phase. + * return the result of xmit or receive one byte + */ +static I2CStatus I2C_ISR(unsigned int eumbbar ); + +/* Set I2C Status, i.e., write to I2CSR */ +static void I2C_Set_Stat( unsigned int eumbbar, I2C_STAT stat ); + +/* Query I2C Status, i.e., read I2CSR */ +static I2C_STAT I2C_Get_Stat( unsigned int eumbbar ); + +/* Change I2C Control bits, i.e., write to I2CCR */ +static void I2C_Set_Ctrl( unsigned int eumbbar, I2C_CTRL ); /* new control value */ + +/* Query I2C Control bits, i.e., read I2CCR */ +static I2C_CTRL I2C_Get_Ctrl( unsigned int eumbbar ); + +/* This function performs the work for I2C_do_transaction. The work is + * split into this function to enable I2C_do_transaction to first transmit + * the data address to the I2C slave device without putting the data address + * into the first byte of the buffer. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * i2c_addr is the I2C address of the slave device + * len is the length of data to send or receive + * buffer is the address of the data buffer + * stop = I2C_NO_STOP, don't signal STOP at end of transaction + * I2C_STOP, signal STOP at end of transaction + * retry is the timeout retry value, currently ignored + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction + * I2C_RESTART, this is a continuation of existing transaction + */ +static I2C_Status I2C_do_buffer( I2C_INTERRUPT_MODE en_int, + I2C_TRANSACTION_MODE act, + unsigned char i2c_addr, + int len, + unsigned char *buffer, + I2C_STOP_MODE stop, + int retry, + I2C_RESTART_MODE rsta); +#endif diff --git a/mpc8240/drivers/i2c/i2c1.c b/mpc8240/drivers/i2c/i2c1.c new file mode 100644 index 0000000..b63e633 --- /dev/null +++ b/mpc8240/drivers/i2c/i2c1.c @@ -0,0 +1,1140 @@ +/************************************************************* + * $Id: i2c1.c,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * Copyright @ Motorola, 1999 + * + ************************************************************/ +#include "i2c_export.h" +#include "i2c.h" + + +/* Define a macro to use an optional application-layer print function, if + * one was passed to the I2C library during initialization. If there was + * no function pointer passed, this protects against calling it. Also define + * the global variable that holds the passed pointer. + */ +#define PRINT if ( app_print ) app_print +static int (*app_print)(char *,...); + +/******************* Internal to I2C Driver *****************/ +static unsigned int ByteToXmit = 0; +static unsigned int XmitByte = 0; +static unsigned char *XmitBuf = 0; +static unsigned int XmitBufEmptyStop =0; +static unsigned int ByteToRcv = 0; +static unsigned int RcvByte = 0; +static unsigned char *RcvBuf = 0; +static unsigned int RcvBufFulStop = 0; +static unsigned int MasterRcvAddress = 0; + +/* Set by call to get_eumbbar during I2C_Initialize. + * This could be globally available to the I2C library, but there is + * an advantage to passing it as a parameter: it is already in a register + * and doesn't have to be loaded from memory. Also, that is the way the + * I2C library was already implemented and I don't want to change it without + * a more detailed analysis. + * It is being set as a global variable in I2C_Initialize to hide it from + * the DINK application layer, because it is Kahlua-specific. I think that + * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in + * a Kahlua-specific library dealing with the embedded utilities memory block. + * Right now, get_eumbbar is defined in dink32/kahlua.s. The other two are + * defined in dink32/drivers/i2c/i2c2.s. + */ +static unsigned int Global_eumbbar = 0; +extern unsigned int get_eumbbar(); + +extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg ); +#pragma Alias( load_runtime_reg, "load_runtime_reg" ) + +extern unsigned int store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val ); +#pragma Alias( store_runtime_reg, "store_runtime_reg" ) + +/************************** API *****************/ + +/* Application Program Interface (API) are the calls provided by the I2C + * library to upper layer applications (i.e., DINK) to access the Kahlua + * I2C bus interface. The functions and values that are part of this API + * are declared in i2c_export.h. + */ + +/* Initialize I2C unit with the following: + * driver's slave address + * interrupt enabled + * optional pointer to application layer print function + * + * These parameters may be added: + * desired clock rate + * digital filter frequency sampling rate + * + * This function must be called before I2C unit can be used. + */ +I2C_Status I2C_Initialize( + unsigned char addr, + I2C_INTERRUPT_MODE en_int, + int (*p)(char *,...)) +{ + I2CStatus status; + /* establish the pointer, if there is one, to the application's "printf" */ + app_print = p; + + /* If this is the first call, get the embedded utilities memory block + * base address. I'm not sure what to do about error handling here: + * if a non-zero value is returned, accept it. + */ + if ( Global_eumbbar == 0) + Global_eumbbar = get_eumbbar(); + if ( Global_eumbbar == 0) + { + PRINT( "I2C_Initialize: can't find EUMBBAR\n" ); + return I2C_ERROR; + } + + /* validate the I2C address */ + if (addr & 0x80) + { + PRINT( "I2C_Initialize, I2C address invalid: %d 0x%x\n", + (unsigned int)addr, (unsigned int)addr ); + return I2C_ERROR; + } + + /* Call the internal I2C library function to perform work. + * Accept the default frequency sampling rate (no way to set it currently, + * via I2C_Init) and set the clock frequency to something reasonable. + */ + status = I2C_Init( Global_eumbbar, (unsigned char)0x31, addr, en_int); + if (status != I2CSUCCESS) + { + PRINT( "I2C_Initialize: error in initiation\n" ); + return I2C_ERROR; + } + + /* all is well */ + return I2C_SUCCESS; +} + + +/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV + * are implemented. Both are only in polling mode. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * i2c_addr is the I2C address of the slave device + * data_addr is the address of the data on the slave device + * len is the length of data to send or receive + * buffer is the address of the data buffer + * stop = I2C_NO_STOP, don't signal STOP at end of transaction + * I2C_STOP, signal STOP at end of transaction + * retry is the timeout retry value, currently ignored + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction + * I2C_RESTART, this is a continuation of existing transaction + */ +I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int, + I2C_TRANSACTION_MODE act, + unsigned char i2c_addr, + unsigned char data_addr, + int len, + char *buffer, + I2C_STOP_MODE stop, + int retry, + I2C_RESTART_MODE rsta) +{ + I2C_Status status; + unsigned char data_addr_buffer[1]; + +#if 1 +/* This is a temporary work-around. The I2C library breaks the protocol + * if it attempts to handle a data transmission in more than one + * transaction, so the data address and the actual data bytes are put + * into a single buffer before sending it to the library internal functions. + * The problem is related to being able to restart a transaction without + * sending the I2C device address or repeating the data address. It may take + * a day or two to sort it all out, so I'll have to get back to it later. + * Look at I2C_Start to see about using some status flags (I'm not sure that + * "stop" and "rsta" are enough to reflect the states, maybe so; but the logic + * in the library is insufficient) to control correct handling of the protocol. + */ +unsigned char dummy_buffer[257]; +if (act == I2C_MASTER_XMIT) +{ +int i; +for (i=1;i<=len;i++)dummy_buffer[i]=buffer[i-1]; +dummy_buffer[0]=data_addr; + status = I2C_do_buffer(en_int, act, i2c_addr, 1 + len, + dummy_buffer, stop, retry, rsta); + if (status != I2C_SUCCESS) + { + PRINT( "I2C_do_transaction: can't perform data transfer\n"); + return I2C_ERROR; + } +return I2C_SUCCESS; +} +#endif /* end of temp work-around */ + + /* validate requested transaction type */ + if ((act != I2C_MASTER_XMIT) && (act != I2C_MASTER_RCV)) + { + PRINT( "I2C_do_transaction, invalid transaction request: %d\n", act); + return I2C_ERROR; + } + + /* range check the I2C address */ + if (i2c_addr & 0x80) + { + PRINT( "I2C_do_transaction, I2C address out of range: %d 0x%x\n", + (unsigned int)i2c_addr, (unsigned int)i2c_addr ); + return I2C_ERROR; + } else { + data_addr_buffer[0] = data_addr; + } + + /* We first have to contact the slave device and transmit the data address. + * Be careful about the STOP and restart stuff. We don't want to signal STOP + * after sending the data address, but this could be a continuation if the + * application didn't release the bus after the previous transaction, by + * not sending a STOP after it. + */ + status = I2C_do_buffer(en_int, I2C_MASTER_XMIT, i2c_addr, 1, + data_addr_buffer, I2C_NO_STOP, retry, rsta); + if (status != I2C_SUCCESS) + { + PRINT( "I2C_do_transaction: can't send data address for read\n"); + return I2C_ERROR; + } + + /* The data transfer will be a continuation. */ + rsta = I2C_RESTART; + + /* now handle the user data */ + status = I2C_do_buffer(en_int, act, i2c_addr, len, + buffer, stop, retry, rsta); + if (status != I2C_SUCCESS) + { + PRINT( "I2C_do_transaction: can't perform data transfer\n"); + return I2C_ERROR; + } + + /* all is well */ + return I2C_SUCCESS; +} + +/* This function performs the work for I2C_do_transaction. The work is + * split into this function to enable I2C_do_transaction to first transmit + * the data address to the I2C slave device without putting the data address + * into the first byte of the buffer. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * i2c_addr is the I2C address of the slave device + * len is the length of data to send or receive + * buffer is the address of the data buffer + * stop = I2C_NO_STOP, don't signal STOP at end of transaction + * I2C_STOP, signal STOP at end of transaction + * retry is the timeout retry value, currently ignored + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction + * I2C_RESTART, this is a continuation of existing transaction + */ +static I2C_Status I2C_do_buffer( I2C_INTERRUPT_MODE en_int, + I2C_TRANSACTION_MODE act, + unsigned char i2c_addr, + int len, + unsigned char *buffer, + I2C_STOP_MODE stop, + int retry, + I2C_RESTART_MODE rsta) +{ + I2CStatus rval; + unsigned int dev_stat; + if (act == I2C_MASTER_RCV) + { + /* set up for master-receive transaction */ + rval = I2C_get(Global_eumbbar,i2c_addr,buffer,len,stop,rsta); + } else { + /* set up for master-transmit transaction */ + rval = I2C_put(Global_eumbbar,i2c_addr,buffer,len,stop,rsta); + } + + /* validate the setup */ + if ( rval != I2CSUCCESS ) + { + dev_stat = load_runtime_reg( Global_eumbbar, I2CSR ); + PRINT( "Error(I2C_do_buffer): control phase, code(0x%08x), status(0x%08x)\n", rval, dev_stat); + I2C_Stop( Global_eumbbar ); + return I2C_ERROR; + } + + if (en_int == 1) + { + /* this should not happen, no interrupt handling yet */ + return I2C_SUCCESS; + } + + /* this performs the polling action, when the transfer is completed, + * the status returned from I2C_Timer_Event will be I2CBUFFFULL or + * I2CBUFFEMPTY (rcv or xmit), I2CSUCCESS or I2CADDRESS indicates the + * transaction is not yet complete, anything else is an error. + */ + while ( rval == I2CSUCCESS || rval == I2CADDRESS ) + { + /* poll the device until something happens */ + do + { + rval = I2C_Timer_Event( Global_eumbbar, 0 ); + } + while ( rval == I2CNOEVENT ); + + /* check for error condition */ + if ( rval == I2CSUCCESS || rval == I2CBUFFFULL || + rval == I2CBUFFEMPTY || rval == I2CADDRESS ) + { ; /* do nothing */ + } else { + /* report the error condition */ + dev_stat = load_runtime_reg( Global_eumbbar, I2CSR ); + PRINT( "Error(I2C_do_buffer): code(0x%08x), status(0x%08x)\n", rval, dev_stat ); + return I2C_ERROR; + } + } + + /* all is well */ + return I2C_SUCCESS; +} + +/** + * Note: + * + * In all following functions, + * the caller shall pass the configured embedded utility memory + * block base, EUMBBAR. + **/ + +/*********************************************************** + * function: I2C_put + * + * description: + Send a buffer of data to the intended rcv_addr. + * If stop_flag is set, after the whole buffer + * is sent, generate a STOP signal provided that the + * receiver doesn't signal the STOP in the middle. + * I2C is the master performing transmitting. If + * no STOP signal is generated at the end of current + * transaction, the master can generate a START signal + * to another slave addr. + * + * note: this is master xmit API + *********************************************************/ +static I2CStatus I2C_put( unsigned int eumbbar, + unsigned char rcv_addr, /* receiver's address */ + unsigned char *buffer_ptr, /* pointer of data to be sent */ + unsigned int length, /* number of byte of in the buffer */ + unsigned int stop_flag, /* 1 - signal STOP when buffer is empty + * 0 - no STOP signal when buffer is empty + */ + unsigned int is_cnt ) /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + +{ + if ( buffer_ptr == 0 || length == 0 ) + { + return I2CERROR; + } + +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_put\n", __FILE__, __LINE__ ); +#endif + + XmitByte = 0; + ByteToXmit = length; + XmitBuf = buffer_ptr; + XmitBufEmptyStop = stop_flag; + + RcvByte = 0; + ByteToRcv = 0; + RcvBuf = 0; + + /* we are the master, start transaction */ + return I2C_Start( eumbbar, rcv_addr, XMIT, is_cnt ); +} + +/*********************************************************** + * function: I2C_get + * + * description: + * Receive a buffer of data from the desired sender_addr + * If stop_flag is set, when the buffer is full and the + * sender does not signal STOP, generate a STOP signal. + * I2C is the master performing receiving. If no STOP signal + * is generated, the master can generate a START signal + * to another slave addr. + * + * note: this is master receive API + **********************************************************/ +static I2CStatus I2C_get( unsigned int eumbbar, + unsigned char rcv_from, /* sender's address */ + unsigned char *buffer_ptr, /* pointer of receiving buffer */ + unsigned int length, /* length of the receiving buffer */ + unsigned int stop_flag, /* 1 - signal STOP when buffer is full + * 0 - no STOP signal when buffer is full + */ + unsigned int is_cnt ) /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ +{ + if ( buffer_ptr == 0 || length == 0 ) + { + return I2CERROR; + } + +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_get\n", __FILE__, __LINE__ ); +#endif + + RcvByte = 0; + ByteToRcv = length; + RcvBuf = buffer_ptr; + RcvBufFulStop = stop_flag; + + XmitByte = 0; + ByteToXmit = 0; + XmitBuf = 0; + + /* we are the master, start the transaction */ + return I2C_Start( eumbbar, rcv_from, RCV, is_cnt ); + +} + +#if 0 /* turn off dead code */ +/********************************************************* + * function: I2C_write + * + * description: + * Send a buffer of data to the requiring master. + * If stop_flag is set, after the whole buffer is sent, + * generate a STOP signal provided that the requiring + * receiver doesn't signal the STOP in the middle. + * I2C is the slave performing transmitting. + * + * Note: this is slave xmit API. + * + * due to the current Kahlua design, slave transmitter + * shall not signal STOP since there is no way + * for master to detect it, causing I2C bus hung. + * + * For the above reason, the stop_flag is always + * set, i.e., 0. + * + * programmer shall use the timer on Kahlua to + * control the interval of data byte at the + * master side. + *******************************************************/ +static I2CStatus I2C_write( unsigned int eumbbar, + unsigned char *buffer_ptr, /* pointer of data to be sent */ + unsigned int length, /* number of byte of in the buffer */ + unsigned int stop_flag ) /* 1 - signal STOP when buffer is empty + * 0 - no STOP signal when buffer is empty + */ +{ + if ( buffer_ptr == 0 || length == 0 ) + { + return I2CERROR; + } + + XmitByte = 0; + ByteToXmit = length; + XmitBuf = buffer_ptr; + XmitBufEmptyStop = 0; /* in order to avoid bus hung, ignored the user's stop_flag */ + + RcvByte = 0; + ByteToRcv = 0; + RcvBuf = 0; + + /* we are the slave, just wait for being called, or pull */ + /* I2C_Timer_Event( eumbbar ); */ +} + +/****************************************************** + * function: I2C_read + * + * description: + * Receive a buffer of data from the sending master. + * If stop_flag is set, when the buffer is full and the + * sender does not signal STOP, generate a STOP signal. + * I2C is the slave performing receiving. + * + * note: this is slave receive API + ****************************************************/ +static I2CStatus I2C_read(unsigned int eumbbar, + unsigned char *buffer_ptr, /* pointer of receiving buffer */ + unsigned int length, /* length of the receiving buffer */ + unsigned int stop_flag ) /* 1 - signal STOP when buffer is full + * 0 - no STOP signal when buffer is full + */ +{ + if ( buffer_ptr == 0 || length == 0 ) + { + return I2CERROR; + } + + RcvByte = 0; + ByteToRcv = length; + RcvBuf = buffer_ptr; + RcvBufFulStop = stop_flag; + + XmitByte = 0; + ByteToXmit = 0; + XmitBuf = 0; + + /* wait for master to call us, or poll */ + /* I2C_Timer_Event( eumbbar ); */ +} +#endif /* turn off dead code */ + +/********************************************************* + * function: I2c_Timer_Event + * + * description: + * if interrupt is not used, this is the timer event handler. + * After each fixed time interval, this function can be called + * to check the I2C status and call appropriate function to + * handle the status event. + ********************************************************/ +static I2CStatus I2C_Timer_Event( unsigned int eumbbar, I2CStatus (*handler)( unsigned int ) ) +{ +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_Timer_Event\n", __FILE__, __LINE__ ); +#endif + + I2C_STAT stat = I2C_Get_Stat( eumbbar ); + + if ( stat.mif == 1 ) + { + if ( handler == 0 ) + { + return I2C_ISR( eumbbar ); + } + else + { + return (*handler)( eumbbar ); + } + } + + return I2CNOEVENT; +} + + +/****************** Device I/O function *****************/ + +/****************************************************** + * function: I2C_Start + * + * description: Generate a START signal in the desired mode. + * I2C is the master. + * + * Return I2CSUCCESS if no error. + * + * note: + ****************************************************/ +static I2CStatus I2C_Start( unsigned int eumbbar, + unsigned char slave_addr, /* address of the receiver */ + I2C_MODE mode, /* XMIT(1) - put (write) + * RCV(0) - get (read) + */ + unsigned int is_cnt ) /* 1 - this is a restart, don't check MBB + * 0 - this is a new start + */ +{ +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_Start addr 0x%x mode %d cnt %d\n", __FILE__, __LINE__ , + slave_addr,mode,is_cnt); +#endif + unsigned int tmp = 0; + I2C_STAT stat; + I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar ); + + /* first make sure I2C has been initialized */ + if ( ctrl.men == 0 ) + { + return I2CERROR; + } + + /* next make sure bus is idle */ + stat = I2C_Get_Stat( eumbbar ); + + if ( is_cnt == 0 && stat.mbb == 1 ) + { + /* sorry, we lost */ + return I2CBUSBUSY; + } + else if ( is_cnt == 1 && stat.mif == 1 && stat.mal == 0 ) + { + /* sorry, we lost the bus */ + return I2CALOSS; + } + + + /* OK, I2C is enabled and we have the bus */ + + /* prepare to write the slave address */ + ctrl.msta = 1; + ctrl.mtx = 1; + ctrl.txak = 0; + ctrl.rsta = is_cnt; /* set the repeat start bit */ + I2C_Set_Ctrl( eumbbar, ctrl ); + + /* write the slave address and xmit/rcv mode bit */ + tmp = load_runtime_reg( eumbbar, I2CDR ); + tmp = ( tmp & 0xffffff00 ) | ((slave_addr & 0x007f)<<1) | ( mode == XMIT ? 0x0 : 0x1 ); + store_runtime_reg( eumbbar, I2CDR, tmp ); + + if ( mode == RCV ) + { + MasterRcvAddress = 1; + } + else + { + MasterRcvAddress = 0; + } + +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_Start exit\n", __FILE__, __LINE__ ); +#endif + + /* wait for the interrupt or poll */ + return I2CSUCCESS; +} + +/*********************************************************** + * function: I2c_Stop + * + * description: Generate a STOP signal to terminate the master + * transaction. + * return I2CSUCCESS + * + **********************************************************/ +static I2CStatus I2C_Stop( unsigned int eumbbar ) +{ +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_Stop enter\n", __FILE__, __LINE__ ); +#endif + + I2C_CTRL ctrl = I2C_Get_Ctrl(eumbbar ); + ctrl.msta = 0; + I2C_Set_Ctrl( eumbbar, ctrl ); + +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_Stop exit\n", __FILE__, __LINE__ ); +#endif + + return I2CSUCCESS; +} + +/**************************************************** + * function: I2C_Master_Xmit + * + * description: Master sends one byte of data to + * slave target + * + * return I2CSUCCESS if the byte transmitted. + * Otherwise no-zero + * + * Note: condition must meet when this function is called: + * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && I2CSR(RXAK) == 0 + * I2CCR(MSTA) == 1 && I2CCR(MTX) == 1 + * + ***************************************************/ +static I2CStatus I2C_Master_Xmit( unsigned int eumbbar ) +{ + unsigned int val; + if ( ByteToXmit > 0 ) + { + + if ( ByteToXmit == XmitByte ) + { + /* all xmitted */ + ByteToXmit = 0; + + if ( XmitBufEmptyStop == 1 ) + { + I2C_Stop( eumbbar ); + } + + return I2CBUFFEMPTY; + + } + +#ifdef I2CDBG0 + PRINT( "%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, *(XmitBuf + XmitByte) ); +#endif + + val = *(XmitBuf + XmitByte); + val &= 0x000000ff; + store_runtime_reg( eumbbar, I2CDR, val ); + XmitByte++; + + return I2CSUCCESS; + + } + + return I2CBUFFEMPTY; +} + +/*********************************************** + * function: I2C_Master_Rcv + * + * description: master reads one byte data + * from slave source + * + * return I2CSUCCESS if no error + * + * Note: condition must meet when this function is called: + * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && + * I2CCR(MSTA) == 1 && I2CCR(MTX) == 0 + * + ***********************************************/ +static I2CStatus I2C_Master_Rcv( unsigned int eumbbar ) +{ + I2C_CTRL ctrl; + unsigned int val; + if ( ByteToRcv > 0 ) + { + + if ( ByteToRcv - RcvByte == 2 && RcvBufFulStop == 1 ) + { + /* master requests more than or equal to 2 bytes + * we are reading 2nd to last byte + */ + + /* we need to set I2CCR(TXAK) to generate a STOP */ + ctrl = I2C_Get_Ctrl( eumbbar ); + ctrl.txak = 1; + I2C_Set_Ctrl( eumbbar, ctrl ); + + /* Kahlua will automatically generate a STOP + * next time a transaction happens + */ + + /* note: the case of master requesting one byte is + * handled in I2C_ISR + */ + } + + /* generat a STOP before reading the last byte */ + if ( RcvByte + 1 == ByteToRcv && RcvBufFulStop == 1 ) + { + I2C_Stop( eumbbar ); + } + + val = load_runtime_reg( eumbbar, I2CDR ); + *(RcvBuf + RcvByte) = val & 0xFF; + +#ifdef I2CDBG0 + PRINT( "%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, *(RcvBuf + RcvByte) ); +#endif + + RcvByte++; + + if ( ByteToRcv == RcvByte ) + { + ByteToRcv = 0; + + return I2CBUFFFULL; + } + + return I2CSUCCESS; + } + + return I2CBUFFFULL; + +} + +/**************************************************** + * function: I2C_Slave_Xmit + * + * description: Slave sends one byte of data to + * requesting destination + * + * return SUCCESS if the byte transmitted. Otherwise + * No-zero + * + * Note: condition must meet when this function is called: + * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && I2CSR(RXAK) = 0 + * I2CCR(MSTA) == 0 && I2CCR(MTX) == 1 + * + ***************************************************/ +static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar ) +{ + unsigned int val; + if ( ByteToXmit > 0 ) + { + + if ( ByteToXmit == XmitByte ) + { + /* no more data to send */ + ByteToXmit = 0; + + /* do not toggle I2CCR(MTX). Doing so will cause bus-hung + * since current Kahlua design does not give master a way + * to detect slave stop. It is always a good idea for + * master to use timer to prevent the long long delays + */ + + return I2CBUFFEMPTY; + } + +#ifdef I2CDBG + PRINT( "%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, *(XmitBuf + XmitByte) ); +#endif + + val = *(XmitBuf + XmitByte); + val &= 0x000000ff; + store_runtime_reg( eumbbar, I2CDR, val ); + XmitByte++; + + + return I2CSUCCESS; + } + + return I2CBUFFEMPTY; +} + +/*********************************************** + * function: I2C_Slave_Rcv + * + * description: slave reads one byte data + * from master source + * + * return I2CSUCCESS if no error otherwise non-zero + * + * Note: condition must meet when this function is called: + * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && + * I2CCR(MSTA) == 0 && I2CCR(MTX) = 0 + * + ***********************************************/ +static I2CStatus I2C_Slave_Rcv(unsigned int eumbbar ) +{ + unsigned int val; + I2C_CTRL ctrl; + if ( ByteToRcv > 0 ) + { + val = load_runtime_reg( eumbbar, I2CDR ); + *( RcvBuf + RcvByte ) = val & 0xff; +#ifdef I2CDBG + PRINT( "%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, *(RcvBuf + RcvByte) ); +#endif + RcvByte++; + + if ( ByteToRcv == RcvByte ) + { + if ( RcvBufFulStop == 1 ) + { + /* all done */ + ctrl = I2C_Get_Ctrl( eumbbar ); + ctrl.txak = 1; + I2C_Set_Ctrl( eumbbar, ctrl ); + } + + ByteToRcv = 0; + return I2CBUFFFULL; + } + + return I2CSUCCESS; + } + + return I2CBUFFFULL; +} + +/****************** Device Control Function *************/ + +/********************************************************* + * function: I2C_Init + * + * description: Initialize I2C unit with desired frequency divider, + * master's listening address, with interrupt enabled + * or disabled. + * + * note: + ********************************************************/ +static I2CStatus I2C_Init( unsigned int eumbbar, + unsigned char fdr, /* frequency divider */ + unsigned char slave_addr, /* driver's address used for receiving */ + unsigned int en_int) /* 1 - enable I2C interrupt + * 0 - disable I2C interrup + */ +{ +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_Init enter\n", __FILE__, __LINE__ ); +#endif + + I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar ); + unsigned int tmp; + /* disable the I2C module before we change everything */ + ctrl.men = 0; + I2C_Set_Ctrl( eumbbar, ctrl ); + + /* set the frequency diver */ + tmp = load_runtime_reg( eumbbar, I2CFDR ); + tmp = ( tmp & 0xffffffc0 ) | ( fdr & 0x3f ); + store_runtime_reg( eumbbar, I2CFDR, tmp ); + + /* Set our listening (slave) address */ + tmp = load_runtime_reg( eumbbar, I2CADR ); + tmp = ( tmp & 0xffffff01 ) | ( ( slave_addr & 0x7f) << 1 ); + store_runtime_reg( eumbbar, I2CADR, tmp ); + + /* enable I2C with desired interrupt setting */ + ctrl.men = 1; + ctrl.mien = en_int & 0x1; + I2C_Set_Ctrl( eumbbar, ctrl ); +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_Init exit\n", __FILE__, __LINE__ ); +#endif + + return I2CSUCCESS; + +} + +/***************************************** + * function I2c_Get_Stat + * + * description: Query I2C Status, i.e., read I2CSR + * + ****************************************/ +static I2C_STAT I2C_Get_Stat( unsigned int eumbbar ) +{ + unsigned int temp = load_runtime_reg( eumbbar, I2CSR ); +#ifdef I2CDBG0 + PRINT( "%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp ); +#endif + + I2C_STAT stat; + stat.rsrv0 = ( temp & 0xffffff00 ) >> 8; + stat.mcf = ( temp & 0x00000080 ) >> 7; + stat.maas = ( temp & 0x00000040 ) >> 6; + stat.mbb = ( temp & 0x00000020 ) >> 5; + stat.mal = ( temp & 0x00000010 ) >> 4; + stat.rsrv1 = ( temp & 0x00000008 ) >> 3; + stat.srw = ( temp & 0x00000004 ) >> 2; + stat.mif = ( temp & 0x00000002 ) >> 1; + stat.rxak = ( temp & 0x00000001 ); + return stat; +} + +/********************************************* + * function: I2c_Set_Ctrl + * + * description: Change I2C Control bits, + * i.e., write to I2CCR + * + ********************************************/ +static void I2C_Set_Ctrl( unsigned int eumbbar, I2C_CTRL ctrl ) /* new control value */ +{ + unsigned int temp = load_runtime_reg( eumbbar, I2CCR ); + temp &= 0xffffff03; + temp |= ( ( ctrl.men & 0x1 ) << 7 ); + temp |= ( ( ctrl.mien & 0x1 ) << 6 ); + temp |= ( ( ctrl.msta & 0x1 ) << 5 ); + temp |= ( ( ctrl.mtx & 0x1 ) << 4 ); + temp |= ( ( ctrl.txak & 0x1 ) << 3 ); + temp |= ( ( ctrl.rsta & 0x1 ) << 2 ); +#ifdef I2CDBG0 + PRINT( "%s(%d): set ctrl = 0x%08x\n", __FILE__, __LINE__, temp ); +#endif + store_runtime_reg( eumbbar, I2CCR, temp ); + +} + +/***************************************** + * function: I2C_Get_Ctrl + * + * description: Query I2C Control bits, + * i.e., read I2CCR + *****************************************/ +static I2C_CTRL I2C_Get_Ctrl( unsigned int eumbbar ) +{ + union { + I2C_CTRL ctrl ; + unsigned int temp; + } s; + s.temp = load_runtime_reg( eumbbar, I2CCR ); +#ifdef I2CDBG0 + PRINT( "%s(%d): get ctrl = 0x%08x\n", __FILE__, __LINE__, s.temp ); +#endif + + return s.ctrl; +} + + +/**************************************** + * function: I2C_Slave_Addr + * + * description: Process slave address phase. + * return I2CSUCCESS if no error + * + * note: Precondition for calling this function: + * I2CSR(MIF) == 1 && + * I2CSR(MAAS) == 1 + ****************************************/ +static I2CStatus I2C_Slave_Addr( unsigned int eumbbar ) +{ + I2C_STAT stat = I2C_Get_Stat( eumbbar ); + I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar ); + + if ( stat.srw == 1 ) + { + /* we are asked to xmit */ + ctrl.mtx = 1; + I2C_Set_Ctrl( eumbbar, ctrl ); /* set MTX */ + return I2C_Slave_Xmit( eumbbar ); + } + + /* we are asked to receive data */ + ctrl.mtx = 0; + I2C_Set_Ctrl(eumbbar, ctrl ); + (void)load_runtime_reg( eumbbar, I2CDR ); /* do a fake read to start */ + + return I2CADDRESS; +} + +/*********************************************** + * function: I2C_ISR + * + * description: I2C Interrupt service routine + * + * note: Precondition: + * I2CSR(MIF) == 1 + **********************************************/ +static I2CStatus I2C_ISR( unsigned int eumbbar ) +{ +#ifdef I2CDBG0 + PRINT( "%s(%d): I2C_ISR\n", __FILE__, __LINE__ ); +#endif + + I2C_STAT stat = I2C_Get_Stat( eumbbar ); + I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar ); + + /* clear MIF */ + stat.mif = 0; + + /* Now let see what kind of event this is */ + if ( stat.mcf == 1 ) + { + /* transfer compete */ + + /* clear the MIF bit */ + I2C_Set_Stat( eumbbar, stat ); + + if ( ctrl.msta == 1 ) + { + /* master */ + if ( ctrl.mtx == 1 ) + { + /* check if this is the address phase for master receive */ + if ( MasterRcvAddress == 1 ) + { + /* Yes, it is the address phase of master receive */ + ctrl.mtx = 0; + /* now check how much we want to receive */ + if ( ByteToRcv == 1 && RcvBufFulStop == 1 ) + { + ctrl.txak = 1; + } + + I2C_Set_Ctrl( eumbbar, ctrl ); + (void)load_runtime_reg( eumbbar, I2CDR ); /* fake read first */ + + MasterRcvAddress = 0; + return I2CADDRESS; + + } + + /* master xmit */ + if ( stat.rxak == 0 ) + { + /* slave has acknowledged */ + return I2C_Master_Xmit( eumbbar ); + } + + /* slave has not acknowledged yet, generate a STOP */ + if ( XmitBufEmptyStop == 1 ) + { + ctrl.msta = 0; + I2C_Set_Ctrl( eumbbar, ctrl ); + } + + return I2CSUCCESS; + } + + /* master receive */ + return I2C_Master_Rcv( eumbbar ); + } + + /* slave */ + if ( ctrl.mtx == 1 ) + { + /* slave xmit */ + if ( stat.rxak == 0 ) + { + /* master has acknowledged */ + return I2C_Slave_Xmit( eumbbar ); + } + + /* master has not acknowledged, wait for STOP */ + /* do nothing for preventing bus from hung */ + return I2CSUCCESS; + } + + /* slave rcv */ + return I2C_Slave_Rcv( eumbbar ); + + } + else if ( stat.maas == 1 ) + { + /* received a call from master */ + + /* clear the MIF bit */ + I2C_Set_Stat(eumbbar, stat ); + + /* master is calling us, process the address phase */ + return I2C_Slave_Addr( eumbbar ); + } + else + { + /* has to be arbitration lost */ + stat.mal = 0; + I2C_Set_Stat( eumbbar, stat ); + + ctrl.msta = 0; /* return to receive mode */ + I2C_Set_Ctrl( eumbbar, ctrl ); + } + + return I2CSUCCESS; + +} + +/****************************************************** + * function: I2C_Set_Stat + * + * description: modify the I2CSR + * + *****************************************************/ +static void I2C_Set_Stat( unsigned int eumbbar, I2C_STAT stat ) +{ + union { + unsigned int val; + I2C_STAT stat; + } s_tmp; + union { + unsigned int val; + I2C_STAT stat; + } s; + s.val = load_runtime_reg( eumbbar, I2CSR ); + s.val &= 0xffffff08; + s_tmp.stat = stat; + s.val |= (s_tmp.val & 0xf7); + +#ifdef I2CDBG0 + PRINT( "%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val ); +#endif + + store_runtime_reg( eumbbar, I2CSR, s.val ); + +} diff --git a/mpc8240/drivers/i2c/i2c2.S b/mpc8240/drivers/i2c/i2c2.S new file mode 100644 index 0000000..fce84df --- /dev/null +++ b/mpc8240/drivers/i2c/i2c2.S @@ -0,0 +1,50 @@ +/************************************** + * $Id: i2c2.S,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * copyright @ Motorola, 1999 + * + **************************************/ + +/********************************************************** + * function: load_runtime_reg + * + * input: r3 - value of eumbbar + * r4 - register offset in embedded utility space + * + * output: r3 - register content + **********************************************************/ + .text + .align 2 + .global load_runtime_reg +load_runtime_reg: + +/* xor r5,r5,r5 +* or r5,r5,r3 +* +* lwbrx r3,r4,r5 +*/ + lwbrx r3,r4,r3 + sync + + bclr 20, 0 + +/**************************************************************** + * function: store_runtime_reg + * + * input: r3 - value of eumbbar + * r4 - register offset in embedded utility space + * r5 - new value to be stored + * + ****************************************************************/ + .text + .align 2 + .global store_runtime_reg +store_runtime_reg: + + stwbrx r5, r4, r3 + sync + + bclr 20,0 + + + diff --git a/mpc8240/drivers/i2c/i2c_export.h b/mpc8240/drivers/i2c/i2c_export.h new file mode 100644 index 0000000..14a6f09 --- /dev/null +++ b/mpc8240/drivers/i2c/i2c_export.h @@ -0,0 +1,148 @@ +#ifndef I2C_EXPORT_H +#define I2C_EXPORT_H + +/**************************************************** + * $Id: i2c_export.h,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * Copyright Motrola 1999 + * + * $Log: i2c_export.h,v $ + * Revision 1.1 2000/11/20 17:22:33 wdenk + * + * * Added support for MBX860T (thanks to Rob Taylor) + * + * * Added support for Sandpoint8240 (thanks to Rob Taylor); this is + * Work In Progress (TM); current status: boots to command line input. + * EPIC code non-functional (interrupts disabled), No net, No IDE. + * + * * Add support for Status LED + * + * * Optionally panic() to reboot instead of hanging + * + * * Misc bug fixes + * + * * All frequencies in HZ now (internally) + * + * * Add support for BOOTP Domain Name Server Option + * + * Revision 1.1.1.1 2000/11/14 16:54:07 robt + * no message + * + * Revision 1.1.1.1 2000/11/14 14:49:39 robt + * no message + * + * Revision 1.3 1999/05/03 14:57:54 charliem + * Decouple the I2C library from DINK application source by making the PRINT + * function an optional parameter that is passed to I2C_Inititalize. If the + * function pointer is passed, it is used by the library; otherwise, no print + * output is performed. + * + * Revision 1.2 1999/04/30 16:25:53 charliem + * Change the DINK to I2C_do_transaction interface to allow the application + * to specify the data address as a parameter to I2C_do_transaction, rather + * than putting the data address into the first byte of the buffer. + * There is a work-around in I2C_do_transaction in this version, see comments + * in the i2c1.c code. + * + * Revision 1.1 1999/04/29 13:41:07 charliem + * Capture first pass at modifications to the I2C interface. This version is + * correct, but there are some additional modifications to be implemented. + * Nothing but I2C should be affected. + * + * + ****************************************************/ + +/* These are the defined return values for the I2C_do_transaction function. + * Any non-zero value indicates failure. Failure modes can be added for + * more detailed error reporting. + */ +typedef enum _i2c_status +{ + I2C_SUCCESS = 0, + I2C_ERROR, +} I2C_Status; + +/* These are the defined tasks for I2C_do_transaction. + * Modes for SLAVE_RCV and SLAVE_XMIT will be added. + */ +typedef enum _i2c_transaction_mode +{ + I2C_MASTER_RCV = 0, + I2C_MASTER_XMIT = 1, +} I2C_TRANSACTION_MODE; + +typedef enum _i2c_interrupt_mode +{ + I2C_INT_DISABLE = 0, + I2C_INT_ENABLE = 1, +} I2C_INTERRUPT_MODE; + +typedef enum _i2c_stop +{ + I2C_NO_STOP = 0, + I2C_STOP = 1, +} I2C_STOP_MODE; + +typedef enum _i2c_restart +{ + I2C_NO_RESTART = 0, + I2C_RESTART = 1, +} I2C_RESTART_MODE; + +/******************** App. API ******************** + * The application API is for user level application + * to use the functionality provided by I2C driver. + * This is a "generic" I2C interface, it should contain + * nothing specific to the Kahlua implementation. + * Only the generic functions are exported by the library. + * + * Note: Its App.s responsibility to swap the data + * byte. In our API, we just transfer whatever + * we are given + **************************************************/ + + +/* Initialize I2C unit with the following: + * driver's slave address + * interrupt enabled + * optional pointer to application layer print function + * + * These parameters may be added: + * desired clock rate + * digital filter frequency sampling rate + * + * This function must be called before I2C unit can be used. + */ +extern I2C_Status I2C_Initialize( + unsigned char addr, /* driver's I2C slave address */ + I2C_INTERRUPT_MODE en_int, /* 1 - enable I2C interrupt + * 0 - disable I2C interrupt + */ + int (*app_print_function)(char *,...)); /* pointer to optional "printf" + * provided by application + */ + +/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV + * are implemented. Both are only in polling mode. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * addr is the I2C address of the slave device + * len is the length of data to send or receive + * buffer is the address of the data buffer + * stop = I2C_NO_STOP, don't signal STOP at end of transaction + * I2C_STOP, signal STOP at end of transaction + * retry is the timeout retry value, currently ignored + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction + * I2C_RESTART, this is a continuation of existing transaction + */ +extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int, + I2C_TRANSACTION_MODE act, + unsigned char i2c_addr, + unsigned char data_addr, + int len, + char *buffer, + I2C_STOP_MODE stop, + int retry, + I2C_RESTART_MODE rsta); +#endif diff --git a/mpc8240/drivers/i2c_export.h b/mpc8240/drivers/i2c_export.h new file mode 100644 index 0000000..93a4e9d --- /dev/null +++ b/mpc8240/drivers/i2c_export.h @@ -0,0 +1,148 @@ +#ifndef I2C_EXPORT_H +#define I2C_EXPORT_H + +/**************************************************** + * $Id: i2c_export.h,v 1.1 2000/11/20 17:22:32 wdenk Exp $ + * + * Copyright Motrola 1999 + * + * $Log: i2c_export.h,v $ + * Revision 1.1 2000/11/20 17:22:32 wdenk + * + * * Added support for MBX860T (thanks to Rob Taylor) + * + * * Added support for Sandpoint8240 (thanks to Rob Taylor); this is + * Work In Progress (TM); current status: boots to command line input. + * EPIC code non-functional (interrupts disabled), No net, No IDE. + * + * * Add support for Status LED + * + * * Optionally panic() to reboot instead of hanging + * + * * Misc bug fixes + * + * * All frequencies in HZ now (internally) + * + * * Add support for BOOTP Domain Name Server Option + * + * Revision 1.1.1.1 2000/11/14 16:54:07 robt + * no message + * + * Revision 1.1.1.1 2000/11/14 14:49:39 robt + * no message + * + * Revision 1.3 1999/05/03 14:57:54 charliem + * Decouple the I2C library from DINK application source by making the PRINT + * function an optional parameter that is passed to I2C_Inititalize. If the + * function pointer is passed, it is used by the library; otherwise, no print + * output is performed. + * + * Revision 1.2 1999/04/30 16:25:53 charliem + * Change the DINK to I2C_do_transaction interface to allow the application + * to specify the data address as a parameter to I2C_do_transaction, rather + * than putting the data address into the first byte of the buffer. + * There is a work-around in I2C_do_transaction in this version, see comments + * in the i2c1.c code. + * + * Revision 1.1 1999/04/29 13:41:07 charliem + * Capture first pass at modifications to the I2C interface. This version is + * correct, but there are some additional modifications to be implemented. + * Nothing but I2C should be affected. + * + * + ****************************************************/ + +/* These are the defined return values for the I2C_do_transaction function. + * Any non-zero value indicates failure. Failure modes can be added for + * more detailed error reporting. + */ +typedef enum _i2c_status +{ + I2C_SUCCESS = 0, + I2C_ERROR, +} I2C_Status; + +/* These are the defined tasks for I2C_do_transaction. + * Modes for SLAVE_RCV and SLAVE_XMIT will be added. + */ +typedef enum _i2c_transaction_mode +{ + I2C_MASTER_RCV = 0, + I2C_MASTER_XMIT = 1, +} I2C_TRANSACTION_MODE; + +typedef enum _i2c_interrupt_mode +{ + I2C_INT_DISABLE = 0, + I2C_INT_ENABLE = 1, +} I2C_INTERRUPT_MODE; + +typedef enum _i2c_stop +{ + I2C_NO_STOP = 0, + I2C_STOP = 1, +} I2C_STOP_MODE; + +typedef enum _i2c_restart +{ + I2C_NO_RESTART = 0, + I2C_RESTART = 1, +} I2C_RESTART_MODE; + +/******************** App. API ******************** + * The application API is for user level application + * to use the functionality provided by I2C driver. + * This is a "generic" I2C interface, it should contain + * nothing specific to the Kahlua implementation. + * Only the generic functions are exported by the library. + * + * Note: Its App.s responsibility to swap the data + * byte. In our API, we just transfer whatever + * we are given + **************************************************/ + + +/* Initialize I2C unit with the following: + * driver's slave address + * interrupt enabled + * optional pointer to application layer print function + * + * These parameters may be added: + * desired clock rate + * digital filter frequency sampling rate + * + * This function must be called before I2C unit can be used. + */ +extern I2C_Status I2C_Initialize( + unsigned char addr, /* driver's I2C slave address */ + I2C_INTERRUPT_MODE en_int, /* 1 - enable I2C interrupt + * 0 - disable I2C interrupt + */ + int (*app_print_function)(char *,...)); /* pointer to optional "printf" + * provided by application + */ + +/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV + * are implemented. Both are only in polling mode. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * addr is the I2C address of the slave device + * len is the length of data to send or receive + * buffer is the address of the data buffer + * stop = I2C_NO_STOP, don't signal STOP at end of transaction + * I2C_STOP, signal STOP at end of transaction + * retry is the timeout retry value, currently ignored + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction + * I2C_RESTART, this is a continuation of existing transaction + */ +extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int, + I2C_TRANSACTION_MODE act, + unsigned char i2c_addr, + unsigned char data_addr, + int len, + char *buffer, + I2C_STOP_MODE stop, + int retry, + I2C_RESTART_MODE rsta); +#endif diff --git a/mpc8240/drivers/i2o.h b/mpc8240/drivers/i2o.h new file mode 100644 index 0000000..8b46156 --- /dev/null +++ b/mpc8240/drivers/i2o.h @@ -0,0 +1,345 @@ +#ifndef I2O_H +#define I2O_H +/********************************************************* + * $Id: i2o.h,v 1.1 2000/11/20 17:22:32 wdenk Exp $ + * + * copyright @ Motorola, 1999 + *********************************************************/ + +#define I2O_REG_OFFSET 0x0004 + +#define PCI_CFG_CLA 0x0B +#define PCI_CFG_SCL 0x0A +#define PCI_CFG_PIC 0x09 + +#define I2O_IMR0 0x0050 +#define I2O_IMR1 0x0054 +#define I2O_OMR0 0x0058 +#define I2O_OMR1 0x005C + +#define I2O_ODBR 0x0060 +#define I2O_IDBR 0x0068 + +#define I2O_OMISR 0x0030 +#define I2O_OMIMR 0x0034 +#define I2O_IMISR 0x0100 +#define I2O_IMIMR 0x0104 + +/* accessable to PCI master but local processor */ +#define I2O_IFQPR 0x0040 +#define I2O_OFQPR 0x0044 + +/* accessable to local processor */ +#define I2O_IFHPR 0x0120 +#define I2O_IFTPR 0x0128 +#define I2O_IPHPR 0x0130 +#define I2O_IPTPR 0x0138 +#define I2O_OFHPR 0x0140 +#define I2O_OFTPR 0x0148 +#define I2O_OPHPR 0x0150 +#define I2O_OPTPR 0x0158 +#define I2O_MUCR 0x0164 +#define I2O_QBAR 0x0170 + +#define I2O_NUM_MSG 2 + +typedef enum _i2o_status +{ + I2OSUCCESS = 0, + I2OINVALID, + I2OMSGINVALID, + I2ODBINVALID, + I2OQUEINVALID, + I2OQUEEMPTY, + I2OQUEFULL, + I2ONOEVENT, +} I2OSTATUS; + +typedef enum _queue_size +{ + QSIZE_4K = 0x02, + QSIZE_8K = 0x04, + QSIZE_16K = 0x08, + QSIZE_32K = 0x10, + QSIZe_64K = 0x20, +} QUEUE_SIZE; + +typedef enum _location +{ + LOCAL = 0, /* used by local processor to access its own on board device, + local processor's eumbbar is required */ + REMOTE, /* used by PCI master to access the devices on its PCI device, + device's pcsrbar is required */ +} LOCATION; + +/* door bell */ +typedef enum _i2o_in_db +{ + IN_DB = 1, + MC, /* machine check */ +} I2O_IN_DB; + +/* I2O PCI configuration identification */ +typedef struct _i2o_iop +{ + unsigned int base_class : 8; + unsigned int sub_class : 8; + unsigned int prg_code : 8; +} I2OIOP; + +/* I2O Outbound Message Interrupt Status Register */ +typedef struct _i2o_om_stat +{ + unsigned int rsvd0 : 26; + unsigned int opqi : 1; + unsigned int rsvd1 : 1; + unsigned int odi : 1; + unsigned int rsvd2 : 1; + unsigned int om1i : 1; + unsigned int om0i : 1; +} I2OOMSTAT; + +/* I2O inbound Message Interrupt Status Register */ +typedef struct _i2o_im_stat +{ + unsigned int rsvd0 : 23; + unsigned int ofoi : 1; + unsigned int ipoi : 1; + unsigned int rsvd1 : 1; + unsigned int ipqi : 1; + unsigned int mci : 1; + unsigned int idi : 1; + unsigned int rsvd2 : 1; + unsigned int im1i : 1; + unsigned int im0i : 1; +} I2OIMSTAT; + +/** + Enable the interrupt associated with in/out bound msg + + Inbound message interrupt generated by PCI master and serviced by local processor + local processor needs to enable its inbound interrupts it wants to handle (LOCAL) + + Outbound message interrupt generated by local processor and serviced by PCI master + PCI master needs to enable the devices' outbound interrupts it wants to handle (REMOTE) + **/ +extern I2OSTATUS I2OMsgEnable( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned char n ); /* b'1' - msg 0 + * b'10'- msg 1 + * b'11'- both + */ + +/** + Disable the interrupt associated with in/out bound msg + + local processor needs to disable its inbound interrupts it is not interested (LOCAL) + + PCI master needs to disable outbound interrupts of devices it is not interested (REMOTE) + **/ +extern I2OSTATUS I2OMsgDisable( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned char n ); /* b'1' - msg 0 + * b'10'- msg 1 + * b'11'- both + */ + +/** + Read the msg register either from local inbound msg 0/1, + or an outbound msg 0/1 of devices. + + If it is not local, pcsrbar must be passed to the function. + Otherwise eumbbar is passed. + + If it is remote, outbound msg of the device is read. + Otherwise local inbound msg is read. + **/ +extern I2OSTATUS I2OMsgGet ( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /*pcsrbar/eumbbar */ + unsigned int n, /* 0 or 1 */ + unsigned int *msg ); + +/** + Write to nth Msg register either on local outbound msg 0/1, + or aninbound msg 0/1 of devices + + If it is not local, pcsrbar must be passed to the function. + Otherwise eumbbar is passed. + + If it is remote, inbound msg on the device is written. + Otherwise local outbound msg is written. + **/ +extern I2OSTATUS I2OMsgPost( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /*pcsrbar/eumbbar */ + unsigned int n, /* 0 or 1 */ + unsigned int msg ); + +/** + Enable the In/Out DoorBell Interrupt + + InDoorBell interrupt is generated by PCI master and serviced by local processor + local processor needs to enable its inbound doorbell interrupts it wants to handle + + OutDoorbell interrupt is generated by local processor and serviced by PCI master + PCI master needs to enable outbound doorbell interrupts of the devices it wants to handle + **/ +extern I2OSTATUS I2ODBEnable( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int in_db );/* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ + +/** + Disable the In/Out DoorBell Interrupt + + local processor needs to disable its inbound doorbell interrupts it is not interested + + PCI master needs to disable outbound doorbell interrupts of devices it is not interested + + **/ +extern I2OSTATUS I2ODBDisable( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int in_db ); /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ + +/** + Read a local indoorbell register, or an outdoorbell of devices. + Reading a doorbell register, the register will be cleared. + + If it is not local, pcsrbar must be passed to the function. + Otherwise eumbbar is passed. + + If it is remote, outdoorbell register on the device is read. + Otherwise local in doorbell is read + **/ +extern unsigned int I2ODBGet( LOCATION, /* REMOTE/LOCAL */ + unsigned int base); /* pcsrbar/eumbbar */ + +/** + Write to a local outdoorbell register, or an indoorbell register of devices. + + If it is not local, pcsrbar must be passed to the function. + Otherwise eumbbar is passed. + + If it is remote, in doorbell register on the device is written. + Otherwise local out doorbell is written + **/ +extern void I2ODBPost( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int msg ); /* in / out */ + +/** + Read the outbound msg unit interrupt status of devices. Reading an interrupt status register, + the register will be cleared. + + The outbound interrupt status is AND with the outbound + interrupt mask. The result is returned. + + PCI master must pass the pcsrbar to the function. + **/ +extern I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT * ); + +/** + Read the inbound msg unit interrupt status. Reading an interrupt status register, + the register will be cleared. + + The inbound interrupt status is AND with the inbound + interrupt mask. The result is returned. + + Local process must pass its eumbbar to the function. +**/ +extern I2OSTATUS I2OInMsgStatGet( unsigned int eumbbar, I2OIMSTAT * ); + +/** + Configure the I2O FIFO, including QBAR, IFHPR/IFTPR,IPHPR/IPTPR,OFHPR/OFTPR, OPHPR/OPTPR, + MUCR. + **/ +extern I2OSTATUS I2OFIFOInit( unsigned int eumbbar, + QUEUE_SIZE, + unsigned int qba);/* queue base address that must be aligned at 1M */ +/** + Enable the circular queue + **/ +extern I2OSTATUS I2OFIFOEnable( unsigned int eumbbar ); + +/** + Disable the circular queue + **/ +extern void I2OFIFODisable( unsigned int eumbbar ); + +/** + Enable the circular queue interrupt + PCI master enables outbound FIFO interrupt of device + Device enables its inbound FIFO interrupt + **/ +extern void I2OFIFOIntEnable( LOCATION, unsigned int base ); + +/** + Disable the circular queue interrupt + PCI master disables outbound FIFO interrupt of device + Device disables its inbound FIFO interrupt + **/ +extern void I2OFIFOIntDisable( LOCATION, unsigned int base ); + +/** + Enable the circular queue overflow interrupt + **/ +extern void I2OFIFOOverflowIntEnable( unsigned int eumbbar ); + +/** + Disable the circular queue overflow interrupt + **/ +extern void I2OFIFOOverflowIntDisable( unsigned int eumbbar ); + +/** + Allocate a free msg frame from free FIFO. + + PCI Master allocates a free msg frame through inbound queue port of device(IFQPR) + while local processor allocates a free msg frame from outbound free queue(OFTPR) + + Unless both free queues are initialized, allocating a free MF will return 0xffffffff + **/ +extern I2OSTATUS I2OFIFOAlloc( LOCATION, + unsigned int base, + void **pMsg); +/** + Free a used msg frame back to free queue + PCI Master frees a MFA through outbound queue port of device(OFQPR) + while local processor frees a MFA into its inbound free queue(IFHPR) + + Used msg frame does not need to be recycled in the order they + read + + This function has to be called by PCI master to initialize Inbound free queue + and by device to initialize Outbound free queue before I2OFIFOAlloc can be used. + **/ +extern I2OSTATUS I2OFIFOFree( LOCATION, + unsigned int base, + void *pMsg ); + +/** + Post a msg into FIFO + PCI Master posts a msg through inbound queue port of device(IFQPR) + while local processor post a msg into its outbound post queue(OPHPR) + + The total number of msg must be less than the max size of the queue + Otherwise queue overflow interrupt will assert. + **/ +extern I2OSTATUS I2OFIFOPost( LOCATION, + unsigned int base, + void *pMsg ); + +/** + Read a msg from FIFO + PCI Master reads a msg through outbound queue port of device(OFQPR) + while local processor reads a msg from its inbound post queue(IPTPR) + **/ +extern I2OSTATUS I2OFIFOGet( LOCATION, + unsigned int base, + void **pMsg ); + +/** + Get the I2O PCI configuration identification register + **/ +extern I2OSTATUS I2OPCIConfigGet( LOCATION, + unsigned int base, + I2OIOP *); + +#endif diff --git a/mpc8240/drivers/i2o/Makefile b/mpc8240/drivers/i2o/Makefile new file mode 100644 index 0000000..b409f0b --- /dev/null +++ b/mpc8240/drivers/i2o/Makefile @@ -0,0 +1,126 @@ +########################################################################## +# +# $Id: Makefile,v 1.1 2000/11/20 17:22:33 wdenk Exp $ +# +# Copyright Motorola, Inc. 1997 +# ALL RIGHTS RESERVED +# +# You are hereby granted a copyright license to use, modify, and +# distribute the SOFTWARE so long as this entire notice is retained +# without alteration in any modified and/or redistributed versions, +# and that such modified versions are clearly identified as such. +# No licenses are granted by implication, estoppel or otherwise under +# any patents or trademarks of Motorola, Inc. +# +# The SOFTWARE is provided on an "AS IS" basis and without warranty. +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. +# +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR +# INABILITY TO USE THE SOFTWARE. +# +# $Log: Makefile,v $ +# Revision 1.1 2000/11/20 17:22:33 wdenk +# +# * Added support for MBX860T (thanks to Rob Taylor) +# +# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is +# Work In Progress (TM); current status: boots to command line input. +# EPIC code non-functional (interrupts disabled), No net, No IDE. +# +# * Add support for Status LED +# +# * Optionally panic() to reboot instead of hanging +# +# * Misc bug fixes +# +# * All frequencies in HZ now (internally) +# +# * Add support for BOOTP Domain Name Server Option +# +# Revision 1.1.1.1 2000/11/14 16:54:07 robt +# no message +# +# Revision 1.1.1.1 2000/11/14 14:49:39 robt +# no message +# +# Revision 1.2 1999/02/05 01:55:54 wyin +# modified to set up soft link for hearder files +# compilable version with dink +# +# Revision 1.1 1999/02/03 18:57:23 wyin +# Base line +# +# Revision 1.12 1998/11/20 01:34:55 wyin +# Added INTMEM function and data structure. +# Enabled DCACHE. +# There is a minor problem with DCACHE, the cache policy had to be write-through. +# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length. +# But consequence measurement is fine. +# +# +############################################################################ +TARGET = libi2o.a + +#DEBUG = -g +DEBUG = +LST = -Hanno -S +OPTIM = +CC = /risc/tools/pkgs/metaware/bin/hcppc +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) +PREP = $(CC) $(CFLAGS) -P + +# Assembler used to build the .s files (for the board version) + +ASOPT = -big_si -c +ASDEBUG = -l -fm +AS = /risc/tools/pkgs/metaware/bin/asppc + +# Linker to bring .o files together into an executable. + +LKOPT = -Bbase=0 -Qn -q -r +LKCMD = +LINK = /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT) + +# DOS Utilities + +DEL = rm +COPY = cp +LIST = ls + +OBJECTS = i2o1.o i2o2.o + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(LINK) $(OBJECTS) -o $@ + +objects: i2o1.o + +clean: + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) + +.s.o: + $(DEL) -f $*.i + $(PREP) -Hasmcpp $< + $(AS) $(ASOPT) $*.i +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst + +.c.o: + $(CCobj) $< + +.c.s: + $(CCobj) $(LST) $< + +i2o1.o: i2o.h i2o1.c + +i2o2.o: i2o.h i2o2.s diff --git a/mpc8240/drivers/i2o/Makefile_pc b/mpc8240/drivers/i2o/Makefile_pc new file mode 100644 index 0000000..5fd13b6 --- /dev/null +++ b/mpc8240/drivers/i2o/Makefile_pc @@ -0,0 +1,134 @@ +########################################################################## +# +# makefile_pc for use with PC mksnt tools dink32/drivers/i2o +# $Id: Makefile_pc,v 1.1 2000/11/20 17:22:33 wdenk Exp $ +# +# Copyright Motorola, Inc. 1997 +# ALL RIGHTS RESERVED +# +# You are hereby granted a copyright license to use, modify, and +# distribute the SOFTWARE so long as this entire notice is retained +# without alteration in any modified and/or redistributed versions, +# and that such modified versions are clearly identified as such. +# No licenses are granted by implication, estoppel or otherwise under +# any patents or trademarks of Motorola, Inc. +# +# The SOFTWARE is provided on an "AS IS" basis and without warranty. +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. +# +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR +# INABILITY TO USE THE SOFTWARE. +# +# $Log: Makefile_pc,v $ +# Revision 1.1 2000/11/20 17:22:33 wdenk +# +# * Added support for MBX860T (thanks to Rob Taylor) +# +# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is +# Work In Progress (TM); current status: boots to command line input. +# EPIC code non-functional (interrupts disabled), No net, No IDE. +# +# * Add support for Status LED +# +# * Optionally panic() to reboot instead of hanging +# +# * Misc bug fixes +# +# * All frequencies in HZ now (internally) +# +# * Add support for BOOTP Domain Name Server Option +# +# Revision 1.1.1.1 2000/11/14 16:54:07 robt +# no message +# +# Revision 1.1.1.1 2000/11/14 14:49:39 robt +# no message +# +# Revision 1.1 1999/06/11 20:05:26 maurie +# support for compiling dink on PC +# +# Revision 1.2 1999/02/05 01:55:54 wyin +# modified to set up soft link for hearder files +# compilable version with dink +# +# Revision 1.1 1999/02/03 18:57:23 wyin +# Base line +# +# Revision 1.12 1998/11/20 01:34:55 wyin +# Added INTMEM function and data structure. +# Enabled DCACHE. +# There is a minor problem with DCACHE, the cache policy had to be write-through. +# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length. +# But consequence measurement is fine. +# +# +############################################################################ +TARGET = libi2o.a + +#DEBUG = -g +DEBUG = +LST = -Hanno -S +OPTIM = +CC = m:/old_tools/tools/hcppc/bin/hcppc +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) +PREP = $(CC) $(CFLAGS) -P + +# Assembler used to build the .s files (for the board version) + +ASOPT = -big_si -c +ASDEBUG = -l -fm +AS = m:/old_tools/tools/hcppc/bin/asppc + +# Linker to bring .o files together into an executable. + +LKOPT = -Bbase=0 -Qn -q -r +LKCMD = +LINK = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT) + +# DOS Utilities + +DEL = rm +COPY = cp +LIST = ls + +OBJECTS = i2o1.o i2o2.o + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(LINK) $(OBJECTS) -o $@ + +objects: i2o1.o + +clean: + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) + +.s.o: + $(DEL) -f $*.i + $(PREP) -Hasmcpp $< + $(AS) $(ASOPT) $*.i +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst + +.c.o: + $(CCobj) $< + +.c.s: + $(CCobj) $(LST) $< + +i2o1.o: i2o.h i2o1.c + $(CCobj) $< + +i2o2.o: i2o.h i2o2.s + $(DEL) -f $*.i + $(PREP) -Hasmcpp $< + $(AS) $(ASOPT) $*.i diff --git a/mpc8240/drivers/i2o/i2o.h b/mpc8240/drivers/i2o/i2o.h new file mode 100644 index 0000000..e82c723 --- /dev/null +++ b/mpc8240/drivers/i2o/i2o.h @@ -0,0 +1,345 @@ +#ifndef I2O_H +#define I2O_H +/********************************************************* + * $Id: i2o.h,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * copyright @ Motorola, 1999 + *********************************************************/ + +#define I2O_REG_OFFSET 0x0004 + +#define PCI_CFG_CLA 0x0B +#define PCI_CFG_SCL 0x0A +#define PCI_CFG_PIC 0x09 + +#define I2O_IMR0 0x0050 +#define I2O_IMR1 0x0054 +#define I2O_OMR0 0x0058 +#define I2O_OMR1 0x005C + +#define I2O_ODBR 0x0060 +#define I2O_IDBR 0x0068 + +#define I2O_OMISR 0x0030 +#define I2O_OMIMR 0x0034 +#define I2O_IMISR 0x0100 +#define I2O_IMIMR 0x0104 + +/* accessable to PCI master but local processor */ +#define I2O_IFQPR 0x0040 +#define I2O_OFQPR 0x0044 + +/* accessable to local processor */ +#define I2O_IFHPR 0x0120 +#define I2O_IFTPR 0x0128 +#define I2O_IPHPR 0x0130 +#define I2O_IPTPR 0x0138 +#define I2O_OFHPR 0x0140 +#define I2O_OFTPR 0x0148 +#define I2O_OPHPR 0x0150 +#define I2O_OPTPR 0x0158 +#define I2O_MUCR 0x0164 +#define I2O_QBAR 0x0170 + +#define I2O_NUM_MSG 2 + +typedef enum _i2o_status +{ + I2OSUCCESS = 0, + I2OINVALID, + I2OMSGINVALID, + I2ODBINVALID, + I2OQUEINVALID, + I2OQUEEMPTY, + I2OQUEFULL, + I2ONOEVENT, +} I2OSTATUS; + +typedef enum _queue_size +{ + QSIZE_4K = 0x02, + QSIZE_8K = 0x04, + QSIZE_16K = 0x08, + QSIZE_32K = 0x10, + QSIZe_64K = 0x20, +} QUEUE_SIZE; + +typedef enum _location +{ + LOCAL = 0, /* used by local processor to access its own on board device, + local processor's eumbbar is required */ + REMOTE, /* used by PCI master to access the devices on its PCI device, + device's pcsrbar is required */ +} LOCATION; + +/* door bell */ +typedef enum _i2o_in_db +{ + IN_DB = 1, + MC, /* machine check */ +} I2O_IN_DB; + +/* I2O PCI configuration identification */ +typedef struct _i2o_iop +{ + unsigned int base_class : 8; + unsigned int sub_class : 8; + unsigned int prg_code : 8; +} I2OIOP; + +/* I2O Outbound Message Interrupt Status Register */ +typedef struct _i2o_om_stat +{ + unsigned int rsvd0 : 26; + unsigned int opqi : 1; + unsigned int rsvd1 : 1; + unsigned int odi : 1; + unsigned int rsvd2 : 1; + unsigned int om1i : 1; + unsigned int om0i : 1; +} I2OOMSTAT; + +/* I2O inbound Message Interrupt Status Register */ +typedef struct _i2o_im_stat +{ + unsigned int rsvd0 : 23; + unsigned int ofoi : 1; + unsigned int ipoi : 1; + unsigned int rsvd1 : 1; + unsigned int ipqi : 1; + unsigned int mci : 1; + unsigned int idi : 1; + unsigned int rsvd2 : 1; + unsigned int im1i : 1; + unsigned int im0i : 1; +} I2OIMSTAT; + +/** + Enable the interrupt associated with in/out bound msg + + Inbound message interrupt generated by PCI master and serviced by local processor + local processor needs to enable its inbound interrupts it wants to handle (LOCAL) + + Outbound message interrupt generated by local processor and serviced by PCI master + PCI master needs to enable the devices' outbound interrupts it wants to handle (REMOTE) + **/ +extern I2OSTATUS I2OMsgEnable( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned char n ); /* b'1' - msg 0 + * b'10'- msg 1 + * b'11'- both + */ + +/** + Disable the interrupt associated with in/out bound msg + + local processor needs to disable its inbound interrupts it is not interested (LOCAL) + + PCI master needs to disable outbound interrupts of devices it is not interested (REMOTE) + **/ +extern I2OSTATUS I2OMsgDisable( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned char n ); /* b'1' - msg 0 + * b'10'- msg 1 + * b'11'- both + */ + +/** + Read the msg register either from local inbound msg 0/1, + or an outbound msg 0/1 of devices. + + If it is not local, pcsrbar must be passed to the function. + Otherwise eumbbar is passed. + + If it is remote, outbound msg of the device is read. + Otherwise local inbound msg is read. + **/ +extern I2OSTATUS I2OMsgGet ( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /*pcsrbar/eumbbar */ + unsigned int n, /* 0 or 1 */ + unsigned int *msg ); + +/** + Write to nth Msg register either on local outbound msg 0/1, + or aninbound msg 0/1 of devices + + If it is not local, pcsrbar must be passed to the function. + Otherwise eumbbar is passed. + + If it is remote, inbound msg on the device is written. + Otherwise local outbound msg is written. + **/ +extern I2OSTATUS I2OMsgPost( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /*pcsrbar/eumbbar */ + unsigned int n, /* 0 or 1 */ + unsigned int msg ); + +/** + Enable the In/Out DoorBell Interrupt + + InDoorBell interrupt is generated by PCI master and serviced by local processor + local processor needs to enable its inbound doorbell interrupts it wants to handle + + OutDoorbell interrupt is generated by local processor and serviced by PCI master + PCI master needs to enable outbound doorbell interrupts of the devices it wants to handle + **/ +extern I2OSTATUS I2ODBEnable( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int in_db );/* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ + +/** + Disable the In/Out DoorBell Interrupt + + local processor needs to disable its inbound doorbell interrupts it is not interested + + PCI master needs to disable outbound doorbell interrupts of devices it is not interested + + **/ +extern I2OSTATUS I2ODBDisable( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int in_db ); /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ + +/** + Read a local indoorbell register, or an outdoorbell of devices. + Reading a doorbell register, the register will be cleared. + + If it is not local, pcsrbar must be passed to the function. + Otherwise eumbbar is passed. + + If it is remote, outdoorbell register on the device is read. + Otherwise local in doorbell is read + **/ +extern unsigned int I2ODBGet( LOCATION, /* REMOTE/LOCAL */ + unsigned int base); /* pcsrbar/eumbbar */ + +/** + Write to a local outdoorbell register, or an indoorbell register of devices. + + If it is not local, pcsrbar must be passed to the function. + Otherwise eumbbar is passed. + + If it is remote, in doorbell register on the device is written. + Otherwise local out doorbell is written + **/ +extern void I2ODBPost( LOCATION, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int msg ); /* in / out */ + +/** + Read the outbound msg unit interrupt status of devices. Reading an interrupt status register, + the register will be cleared. + + The outbound interrupt status is AND with the outbound + interrupt mask. The result is returned. + + PCI master must pass the pcsrbar to the function. + **/ +extern I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT * ); + +/** + Read the inbound msg unit interrupt status. Reading an interrupt status register, + the register will be cleared. + + The inbound interrupt status is AND with the inbound + interrupt mask. The result is returned. + + Local process must pass its eumbbar to the function. +**/ +extern I2OSTATUS I2OInMsgStatGet( unsigned int eumbbar, I2OIMSTAT * ); + +/** + Configure the I2O FIFO, including QBAR, IFHPR/IFTPR,IPHPR/IPTPR,OFHPR/OFTPR, OPHPR/OPTPR, + MUCR. + **/ +extern I2OSTATUS I2OFIFOInit( unsigned int eumbbar, + QUEUE_SIZE, + unsigned int qba);/* queue base address that must be aligned at 1M */ +/** + Enable the circular queue + **/ +extern I2OSTATUS I2OFIFOEnable( unsigned int eumbbar ); + +/** + Disable the circular queue + **/ +extern void I2OFIFODisable( unsigned int eumbbar ); + +/** + Enable the circular queue interrupt + PCI master enables outbound FIFO interrupt of device + Device enables its inbound FIFO interrupt + **/ +extern void I2OFIFOIntEnable( LOCATION, unsigned int base ); + +/** + Disable the circular queue interrupt + PCI master disables outbound FIFO interrupt of device + Device disables its inbound FIFO interrupt + **/ +extern void I2OFIFOIntDisable( LOCATION, unsigned int base ); + +/** + Enable the circular queue overflow interrupt + **/ +extern void I2OFIFOOverflowIntEnable( unsigned int eumbbar ); + +/** + Disable the circular queue overflow interrupt + **/ +extern void I2OFIFOOverflowIntDisable( unsigned int eumbbar ); + +/** + Allocate a free msg frame from free FIFO. + + PCI Master allocates a free msg frame through inbound queue port of device(IFQPR) + while local processor allocates a free msg frame from outbound free queue(OFTPR) + + Unless both free queues are initialized, allocating a free MF will return 0xffffffff + **/ +extern I2OSTATUS I2OFIFOAlloc( LOCATION, + unsigned int base, + void **pMsg); +/** + Free a used msg frame back to free queue + PCI Master frees a MFA through outbound queue port of device(OFQPR) + while local processor frees a MFA into its inbound free queue(IFHPR) + + Used msg frame does not need to be recycled in the order they + read + + This function has to be called by PCI master to initialize Inbound free queue + and by device to initialize Outbound free queue before I2OFIFOAlloc can be used. + **/ +extern I2OSTATUS I2OFIFOFree( LOCATION, + unsigned int base, + void *pMsg ); + +/** + Post a msg into FIFO + PCI Master posts a msg through inbound queue port of device(IFQPR) + while local processor post a msg into its outbound post queue(OPHPR) + + The total number of msg must be less than the max size of the queue + Otherwise queue overflow interrupt will assert. + **/ +extern I2OSTATUS I2OFIFOPost( LOCATION, + unsigned int base, + void *pMsg ); + +/** + Read a msg from FIFO + PCI Master reads a msg through outbound queue port of device(OFQPR) + while local processor reads a msg from its inbound post queue(IPTPR) + **/ +extern I2OSTATUS I2OFIFOGet( LOCATION, + unsigned int base, + void **pMsg ); + +/** + Get the I2O PCI configuration identification register + **/ +extern I2OSTATUS I2OPCIConfigGet( LOCATION, + unsigned int base, + I2OIOP *); + +#endif diff --git a/mpc8240/drivers/i2o/i2o1.c b/mpc8240/drivers/i2o/i2o1.c new file mode 100644 index 0000000..355aa19 --- /dev/null +++ b/mpc8240/drivers/i2o/i2o1.c @@ -0,0 +1,890 @@ +/********************************************************* + * $Id + * + * copyright @ Motorola, 1999 + *********************************************************/ +#include "i2o.h" + +extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg ); +#pragma Alias( load_runtime_reg, "load_runtime_reg" ); + +extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val ); +#pragma Alias( store_runtime_reg, "store_runtime_reg" ); + +typedef struct _fifo_stat +{ + QUEUE_SIZE qsz; + unsigned int qba; +} FIFOSTAT; + +FIFOSTAT fifo_stat = { QSIZE_4K, 0xffffffff }; + +/********************************************************************************** + * function: I2OMsgEnable + * + * description: Enable the interrupt associated with in/out bound msg + * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID. + * + * All previously enabled interrupts are preserved. + * note: + * Inbound message interrupt generated by PCI master and serviced by local processor + * Outbound message interrupt generated by local processor and serviced by PCI master + * + * local processor needs to enable its inbound interrupts it wants to handle(LOCAL) + * PCI master needs to enable the outbound interrupts of devices it wants to handle(REMOTE) + ************************************************************************************/ +I2OSTATUS I2OMsgEnable ( LOCATION loc, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned char n ) /* b'1' - msg 0 + * b'10'- msg 1 + * b'11'- both + */ +{ + unsigned int reg, val; + if ( ( n & 0x3 ) == 0 ) + { + /* neither msg 0, nor msg 1 */ + return I2OMSGINVALID; + } + + n = (~n) & 0x3; + /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base + * LOCAL : enable local inbound message, eumbbar as base + */ + reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR ); + val = load_runtime_reg( base, reg ); + + val &= 0xfffffffc; /* masked out the msg interrupt bits */ + val |= n; /* LSB are the one we want */ + store_runtime_reg( base, reg, val ); + + return I2OSUCCESS; +} + +/********************************************************************************* + * function: I2OMsgDisable + * + * description: Disable the interrupt associated with in/out bound msg + * Other previously enabled interrupts are preserved. + * return I2OSUCCESS if no error otherwise return I2OMSGINVALID + * + * note: + * local processor needs to disable its inbound interrupts it is not interested(LOCAL) + * PCI master needs to disable outbound interrupts of devices it is not interested(REMOTE) + *********************************************************************************/ +I2OSTATUS I2OMsgDisable( LOCATION loc, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned char n ) /* b'1' - msg 0 + * b'10'- msg 1 + * b'11'- both + */ +{ + unsigned int reg, val; + + if ( ( n & 0x3 ) == 0 ) + { + /* neither msg 0, nor msg 1 */ + return I2OMSGINVALID; + } + + /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base + * LOCAL : disable local inbound message interrupt, eumbbar as base + */ + reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR ); + val = load_runtime_reg( base, reg ); + + val &= 0xfffffffc; /* masked out the msg interrupt bits */ + val |= ( n & 0x3 ); + store_runtime_reg( base, reg, val ); + + return I2OSUCCESS; + +} + +/************************************************************************** + * function: I2OMsgGet + * + * description: Local processor reads the nth Msg register from its inbound msg, + * or a PCI Master reads nth outbound msg from device + * + * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID. + * + * note: + * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed. + * If it is remote, outbound msg on the device is read; otherwise local inbound msg is read + *************************************************************************/ +I2OSTATUS I2OMsgGet ( LOCATION loc, /* REMOTE/LOCAL */ + unsigned int base, /*pcsrbar/eumbbar */ + unsigned int n, /* 0 or 1 */ + unsigned int *msg ) +{ + if ( n >= I2O_NUM_MSG || msg == 0 ) + { + return I2OMSGINVALID; + } + + if ( loc == REMOTE ) + { + /* read the outbound msg of the device, pcsrbar as base */ + *msg = load_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET ); + } + else + { + /* read the inbound msg sent by PCI master, eumbbar as base */ + *msg = load_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET ); + } + + return I2OSUCCESS; +} + +/*************************************************************** + * function: I2OMsgPost + * + * description: Kahlua writes to its nth outbound msg register + * PCI master writes to nth inbound msg register of device + * + * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID. + * + * note: + * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed. + * + * If it is remote, inbound msg on the device is written; otherwise local outbound msg is written + ***************************************************************/ +I2OSTATUS I2OMsgPost( LOCATION loc, /* REMOTE/LOCAL */ + unsigned int base, /*pcsrbar/eumbbar */ + unsigned int n, /* 0 or 1 */ + unsigned int msg ) +{ + if ( n >= I2O_NUM_MSG ) + { + return I2OMSGINVALID; + } + + if ( loc == REMOTE ) + { + /* write to the inbound msg register of the device, pcsrbar as base */ + store_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET, msg ); + } + else + { + /* write to the outbound msg register for PCI master to read, eumbbar as base */ + store_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET, msg ); + } + + return I2OSUCCESS; +} + +/*********************************************************************** + * function: I2ODBEnable + * + * description: Local processor enables it's inbound doorbell interrupt + * PCI master enables outbound doorbell interrupt of devices + * Other previously enabled interrupts are preserved. + * Return I2OSUCCESS if no error otherwise return I2ODBINVALID + * + * note: + * In DoorBell interrupt is generated by PCI master and serviced by local processor + * Out Doorbell interrupt is generated by local processor and serviced by PCI master + * + * Out Doorbell interrupt is generated by local processor and serviced by PCI master + * PCI master needs to enable the outbound doorbell interrupts of device it wants to handle + **********************************************************************/ +I2OSTATUS I2ODBEnable( LOCATION loc, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ +{ + + /* LOCATION - REMOTE : PCI master initializes outbound doorbell message of device + * LOCAL : Kahlua initializes its inbound doorbell message + */ + unsigned int val; + + if ( loc == LOCAL && ( in_db & 0x3 ) == 0 ) + { + return I2ODBINVALID; + } + + if ( loc == REMOTE ) + { + /* pcsrbar is base */ + val = load_runtime_reg( base, I2O_OMIMR ); + val &= 0xfffffff7; + store_runtime_reg( base, I2O_OMIMR , val ); + } + else + { + /* eumbbar is base */ + val = load_runtime_reg( base, I2O_IMIMR); + in_db = ( (~in_db) & 0x3 ) << 3; + val = ( val & 0xffffffe7) | in_db; + store_runtime_reg( base, I2O_IMIMR, val ); + } + + return I2OSUCCESS; +} + +/********************************************************************************** + * function: I2ODBDisable + * + * description: local processor disables its inbound DoorBell Interrupt + * PCI master disables outbound DoorBell interrupt of device + * Other previously enabled interrupts are preserved. + * return I2OSUCCESS if no error.Otherwise return I2ODBINVALID + * + * note: + * local processor needs to disable its inbound doorbell interrupts it is not interested + * + * PCI master needs to disable outbound doorbell interrupts of device it is not interested + ************************************************************************************/ +I2OSTATUS I2ODBDisable( LOCATION loc, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ +{ + /* LOCATION - REMOTE : handle device's out bound message initialization + * LOCAL : handle local in bound message initialization + */ + unsigned int val; + + if ( loc == LOCAL && ( in_db & 0x3 ) == 0 ) + { + return I2ODBINVALID; + } + + if ( loc == REMOTE ) + { + /* pcsrbar is the base */ + val = load_runtime_reg( base, I2O_OMIMR ); + val |= 0x8; + store_runtime_reg( base, I2O_OMIMR, val ); + } + else + { + val = load_runtime_reg( base, I2O_IMIMR); + in_db = ( in_db & 0x3 ) << 3; + val |= in_db; + store_runtime_reg( base, I2O_IMIMR, val ); + } + + return I2OSUCCESS; +} + +/********************************************************************************** + * function: I2ODBGet + * + * description: Local processor reads its in doorbell register, + * PCI master reads the outdoorbell register of device. + * After a doorbell register is read, the whole register will be cleared. + * Otherwise, HW keeps generating interrupt. + * + * note: + * If it is not local, pcsrbar must be passed to the function. + * Otherwise eumbbar is passed. + * + * If it is remote, out doorbell register on the device is read. + * Otherwise local in doorbell is read + * + * If the register is not cleared by write to it, any remaining bit of b'1's + * will cause interrupt pending. + *********************************************************************************/ +unsigned int I2ODBGet( LOCATION loc, /* REMOTE/LOCAL */ + unsigned int base) /* pcsrbar/eumbbar */ +{ + unsigned int msg, val; + + if ( loc == REMOTE ) + { + /* read outbound doorbell register of device, pcsrbar is the base */ + val = load_runtime_reg( base, I2O_ODBR ); + msg = val & 0xe0000000; + store_runtime_reg( base, I2O_ODBR, val ); /* clear the register */ + } + else + { + /* read the inbound doorbell register, eumbbar is the base */ + val = load_runtime_reg( base, I2O_IDBR ); + store_runtime_reg( base, I2O_IDBR, val ); /* clear the register */ + msg = val; + } + + return msg; +} + +/********************************************************************** + * function: I2ODBPost + * + * description: local processor writes to a outbound doorbell register, + * PCI master writes to the inbound doorbell register of device + * + * note: + * If it is not local, pcsrbar must be passed to the function. + * Otherwise eumbbar is passed. + * + * If it is remote, in doorbell register on the device is written. + * Otherwise local out doorbell is written + *********************************************************************/ +void I2ODBPost( LOCATION loc, /* REMOTE/LOCAL */ + unsigned int base, /* pcsrbar/eumbbar */ + unsigned int msg ) /* in / out */ +{ + if ( loc == REMOTE ) + { + /* write to inbound doorbell register of device, pcsrbar is the base */ + store_runtime_reg( base, I2O_IDBR, msg ); + } + else + { + /* write to local outbound doorbell register, eumbbar is the base */ + store_runtime_reg( base, I2O_ODBR, msg & 0x1fffffff ); + } + +} + +/******************************************************************** + * function: I2OOutMsgStatGet + * + * description: PCI master reads device's outbound msg unit interrupt status. + * Reading an interrupt status register, + * the register will be cleared. + * + * The value of the status register is AND with the outbound + * interrupt mask and result is returned. + * + * note: + * pcsrbar must be passed to the function. + ********************************************************************/ +I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT *val ) +{ + unsigned int stat; + unsigned int mask; + + if ( val == 0 ) + { + return I2OINVALID; + } + + /* read device's outbound status */ + stat = load_runtime_reg( pcsrbar, I2O_OMISR ); + mask = load_runtime_reg( pcsrbar, I2O_OMIMR ); + store_runtime_reg( pcsrbar, I2O_OMISR, stat & 0xffffffd7); + + stat &= mask; + val->rsvd0 = ( stat & 0xffffffc0 ) >> 6; + val->opqi = ( stat & 0x00000020 ) >> 5; + val->rsvd1 = ( stat & 0x00000010 ) >> 4; + val->odi = ( stat & 0x00000008 ) >> 3; + val->rsvd2 = ( stat & 0x00000004 ) >> 2; + val->om1i = ( stat & 0x00000002 ) >> 1; + val->om0i = ( stat & 0x00000001 ); + + return I2OSUCCESS; +} + +/******************************************************************** + * function: I2OInMsgStatGet + * + * description: Local processor reads its inbound msg unit interrupt status. + * Reading an interrupt status register, + * the register will be cleared. + * + * The inbound msg interrupt status is AND with the inbound + * msg interrupt mask and result is returned. + * + * note: + * eumbbar must be passed to the function. + ********************************************************************/ +I2OSTATUS I2OInMsgStatGet(unsigned int eumbbar, I2OIMSTAT *val) +{ + unsigned int stat; + unsigned int mask; + + if ( val == 0 ) + { + return I2OINVALID; + } + + /* read device's outbound status */ + stat = load_runtime_reg( eumbbar, I2O_OMISR ); + mask = load_runtime_reg( eumbbar, I2O_OMIMR ); + store_runtime_reg( eumbbar, I2O_OMISR, stat & 0xffffffe7 ); + + stat &= mask; + val->rsvd0 = ( stat & 0xfffffe00 ) >> 9; + val->ofoi = ( stat & 0x00000100 ) >> 8; + val->ipoi = ( stat & 0x00000080 ) >> 7; + val->rsvd1 = ( stat & 0x00000040 ) >> 6; + val->ipqi = ( stat & 0x00000020 ) >> 5; + val->mci = ( stat & 0x00000010 ) >> 4; + val->idi = ( stat & 0x00000008 ) >> 3; + val->rsvd2 = ( stat & 0x00000004 ) >> 2; + val->im1i = ( stat & 0x00000002 ) >> 1; + val->im0i = ( stat & 0x00000001 ); + + return I2OSUCCESS; + +} + +/*********************************************************** + * function: I2OFIFOInit + * + * description: Configure the I2O FIFO, including QBAR, + * IFHPR/IFTPR, IPHPR/IPTPR, OFHPR/OFTPR, + * OPHPR/OPTPR, MUCR. + * + * return I2OSUCCESS if no error, + * otherwise return I2OQUEINVALID + * + * note: It is NOT this driver's responsibility of initializing + * MFA blocks, i.e., FIFO queue itself. The MFA blocks + * must be initialized before I2O unit can be used. + ***********************************************************/ +I2OSTATUS I2OFIFOInit( unsigned int eumbbar, + QUEUE_SIZE sz, /* value of CQS of MUCR */ + unsigned int qba) /* queue base address that must be aligned at 1M */ +{ + + if ( ( qba & 0xfffff ) != 0 ) + { + /* QBA must be aligned at 1Mbyte boundary */ + return I2OQUEINVALID; + } + + store_runtime_reg( eumbbar, I2O_QBAR, qba ); + store_runtime_reg( eumbbar, I2O_MUCR, (unsigned int)sz ); + store_runtime_reg( eumbbar, I2O_IFHPR, qba ); + store_runtime_reg( eumbbar, I2O_IFTPR, qba ); + store_runtime_reg( eumbbar, I2O_IPHPR, qba + 1 * ( sz << 11 )); + store_runtime_reg( eumbbar, I2O_IPTPR, qba + 1 * ( sz << 11 )); + store_runtime_reg( eumbbar, I2O_OFHPR, qba + 2 * ( sz << 11 )); + store_runtime_reg( eumbbar, I2O_OFTPR, qba + 2 * ( sz << 11 )); + store_runtime_reg( eumbbar, I2O_OPHPR, qba + 3 * ( sz << 11 )); + store_runtime_reg( eumbbar, I2O_OPTPR, qba + 3 * ( sz << 11 )); + + fifo_stat.qsz = sz; + fifo_stat.qba = qba; + + return I2OSUCCESS; +} + +/************************************************** + * function: I2OFIFOEnable + * + * description: Enable the circular queue + * return I2OSUCCESS if no error. + * Otherwise I2OQUEINVALID is returned. + * + * note: + *************************************************/ +I2OSTATUS I2OFIFOEnable( unsigned int eumbbar ) +{ + unsigned int val; + + if ( fifo_stat.qba == 0xfffffff ) + { + return I2OQUEINVALID; + } + + val = load_runtime_reg( eumbbar, I2O_MUCR ); + store_runtime_reg( eumbbar, I2O_MUCR, val | 0x1 ); + + return I2OSUCCESS; +} + +/************************************************** + * function: I2OFIFODisable + * + * description: Disable the circular queue + * + * note: + *************************************************/ +void I2OFIFODisable( unsigned int eumbbar ) +{ + if ( fifo_stat.qba == 0xffffffff ) + { + /* not enabled */ + return; + } + + unsigned int val = load_runtime_reg( eumbbar, I2O_MUCR ); + store_runtime_reg( eumbbar, I2O_MUCR, val & 0xfffffffe ); +} + +/**************************************************** + * function: I2OFIFOAlloc + * + * description: Allocate a free MFA from free FIFO. + * return I2OSUCCESS if no error. + * return I2OQUEEMPTY if no more free MFA. + * return I2OINVALID on other errors. + * + * A free MFA must be allocated before a + * message can be posted. + * + * note: + * PCI Master allocates a free MFA from inbound queue of device + * (pcsrbar is the base,) through the inbound queue port of device + * while local processor allocates a free MFA from its outbound + * queue (eumbbar is the base.) + * + ****************************************************/ +I2OSTATUS I2OFIFOAlloc( LOCATION loc, + unsigned int base, + void **pMsg ) +{ + I2OSTATUS stat = I2OSUCCESS; + void *pHdr, *pTil; + + if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff ) + { + /* not configured */ + return I2OQUEINVALID; + } + + if ( loc == REMOTE ) + { + /* pcsrbar is the base and read the inbound free tail ptr */ + pTil = (void *)load_runtime_reg( base, I2O_IFQPR ); + if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF ) + { + stat = I2OQUEEMPTY; + } + else + { + *pMsg = pTil; + } + } + else + { + /* eumbbar is the base and read the outbound free tail ptr */ + pHdr = (void *)load_runtime_reg( base, I2O_OFHPR ); /* queue head */ + pTil = (void *)load_runtime_reg( base, I2O_OFTPR ); /* queue tail */ + + /* check underflow */ + if ( pHdr == pTil ) + { + /* hdr and til point to the same fifo item, no free MFA */ + stat = I2OQUEEMPTY; + } + else + { + /* update OFTPR */ + *pMsg = (void *)(*(unsigned char *)pTil); + pTil = (void *)((unsigned int)pTil + 4); + if ( (unsigned int)pTil == fifo_stat.qba + ( 4 * ( fifo_stat.qsz << 11 ) ) ) + { + /* reach the upper limit */ + pTil = (void *)(fifo_stat.qba + ( 3 * (fifo_stat.qsz << 11) )); + } + store_runtime_reg( base, I2O_OFTPR, (unsigned int)pTil ); + } + } + + return stat; +} + +/****************************************************** + * function: I2OFIFOFree + * + * description: Free a used MFA back to free queue after + * use. + * return I2OSUCCESS if no error. + * return I2OQUEFULL if inbound free queue + * overflow + * + * note: PCI Master frees a MFA into device's outbound queue + * (OFQPR) while local processor frees a MFA into its + * inbound queue (IFHPR). + *****************************************************/ +I2OSTATUS I2OFIFOFree( LOCATION loc, + unsigned int base, + void *pMsg ) +{ + void **pHdr, **pTil; + I2OSTATUS stat = I2OSUCCESS; + + if ( fifo_stat.qba == 0xffffffff || pMsg == 0 ) + { + return I2OQUEINVALID; + } + + if ( loc == REMOTE ) + { + /* pcsrbar is the base */ + store_runtime_reg( base, I2O_OFQPR, (unsigned int)pMsg ); + } + else + { + /* eumbbar is the base */ + pHdr = (void **)load_runtime_reg( base, I2O_IFHPR ); + pTil = (void **)load_runtime_reg( base, I2O_IFTPR ); + + /* store MFA */ + *pHdr = pMsg; + + /* update IFHPR */ + pHdr += 4; + + if ( (unsigned int)pHdr == fifo_stat.qba + ( fifo_stat.qsz << 11 ) ) + { + /* reach the upper limit */ + pHdr = (void **)fifo_stat.qba; + } + + /* check inbound free queue overflow */ + if ( pHdr != pTil ) + { + store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr); + } + else + { + stat = I2OQUEFULL; + } + + } + + return stat; + +} + +/********************************************* + * function: I2OFIFOPost + * + * description: Post a msg into FIFO post queue + * the value of msg must be the one + * returned by I2OFIFOAlloc + * + * note: PCI Master posts a msg into device's inbound queue + * (IFQPR) while local processor post a msg into device's + * outbound queue (OPHPR) + *********************************************/ +I2OSTATUS I2OFIFOPost( LOCATION loc, + unsigned int base, + void *pMsg ) +{ + void **pHdr, **pTil; + I2OSTATUS stat = I2OSUCCESS; + + if ( fifo_stat.qba == 0xffffffff || pMsg == 0 ) + { + return I2OQUEINVALID; + } + + if ( loc == REMOTE ) + { + /* pcsrbar is the base */ + store_runtime_reg( base, I2O_IFQPR, (unsigned int)pMsg ); + } + else + { + /* eumbbar is the base */ + pHdr = (void **)load_runtime_reg( base, I2O_OPHPR ); + pTil = (void **)load_runtime_reg( base, I2O_OPTPR ); + + /* store MFA */ + *pHdr = pMsg; + + /* update IFHPR */ + pHdr += 4; + + if ( (unsigned int)pHdr == fifo_stat.qba + 3 * ( fifo_stat.qsz << 11 ) ) + { + /* reach the upper limit */ + pHdr = (void **)(fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) ); + } + + /* check post queue overflow */ + if ( pHdr != pTil ) + { + store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr); + } + else + { + stat = I2OQUEFULL; + } + } + + return stat; +} + +/************************************************ + * function: I2OFIFOGet + * + * description: Read a msg from FIFO + * This function should be called + * only when there is a corresponding + * msg interrupt. + * + * note: PCI Master reads a msg from device's outbound queue + * (OFQPR) while local processor reads a msg from device's + * inbound queue (IPTPR) + ************************************************/ +I2OSTATUS I2OFIFOGet( LOCATION loc, + unsigned int base, + void **pMsg ) +{ + I2OSTATUS stat = I2OSUCCESS; + void *pHdr, *pTil; + + if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff ) + { + /* not configured */ + return I2OQUEINVALID; + } + + if ( loc == REMOTE ) + { + /* pcsrbar is the base */ + pTil = (void *)load_runtime_reg( base, I2O_OFQPR ); + if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF ) + { + stat = I2OQUEEMPTY; + } + else + { + *pMsg = pTil; + } + } + else + { + /* eumbbar is the base and read the outbound free tail ptr */ + pHdr = (void *)load_runtime_reg( base, I2O_IPHPR ); /* queue head */ + pTil = (void *)load_runtime_reg( base, I2O_IPTPR ); /* queue tail */ + + /* check underflow */ + if ( pHdr == pTil ) + { + /* no free MFA */ + stat = I2OQUEEMPTY; + } + else + { + /* update OFTPR */ + *pMsg = (void *)(*(unsigned char *)pTil); + pTil = (void *)((unsigned int)pTil + 4); + if ( (unsigned int)pTil == fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) ) + { + /* reach the upper limit */ + pTil = (void *)(fifo_stat.qba + 1 * (fifo_stat.qsz << 11) ); + } + + store_runtime_reg( base, I2O_IPTPR, (unsigned int)pTil ); + } + } + + return stat; +} + +/******************************************************** + * function: I2OIOP + * + * description: Get the I2O PCI configuration identification + * register. + * + * note: PCI master should pass pcsrbar while local processor + * should pass eumbbar. + *********************************************************/ +I2OSTATUS I2OPCIConfigGet( LOCATION loc, + unsigned int base, + I2OIOP * val) +{ + unsigned int tmp; + if ( val == 0 ) + { + return I2OINVALID; + } + tmp = load_runtime_reg( base, PCI_CFG_CLA ); + val->base_class = ( tmp & 0xFF) << 16; + tmp = load_runtime_reg( base, PCI_CFG_SCL ); + val->sub_class= ( (tmp & 0xFF) << 8 ); + tmp = load_runtime_reg( base, PCI_CFG_PIC ); + val->prg_code = (tmp & 0xFF); + return I2OSUCCESS; +} + +/********************************************************* + * function: I2OFIFOIntEnable + * + * description: Enable the circular post queue interrupt + * + * note: + * PCI master enables outbound FIFO interrupt of device + * pscrbar is the base + * Device enables its inbound FIFO interrupt + * eumbbar is the base + *******************************************************/ +void I2OFIFOIntEnable( LOCATION loc, unsigned int base ) +{ + unsigned int reg, val; + + /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base + * LOCAL : enable local inbound message, eumbbar as base + */ + reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR ); + val = load_runtime_reg( base, reg ); + + val &= 0xffffffdf; /* clear the msg interrupt bits */ + store_runtime_reg( base, reg, val ); + +} + +/**************************************************** + * function: I2OFIFOIntDisable + * + * description: Disable the circular post queue interrupt + * + * note: + * PCI master disables outbound FIFO interrupt of device + * (pscrbar is the base) + * Device disables its inbound FIFO interrupt + * (eumbbar is the base) + *****************************************************/ +void I2OFIFOIntDisable( LOCATION loc, unsigned int base ) +{ + + /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base + * LOCAL : disable local inbound message interrupt, eumbbar as base + */ + unsigned int reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR ); + unsigned int val = load_runtime_reg( base, reg ); + + val |= 0x00000020; /* masked out the msg interrupt bits */ + store_runtime_reg( base, reg, val ); + +} + +/********************************************************* + * function: I2OFIFOOverflowIntEnable + * + * description: Enable the circular queue overflow interrupt + * + * note: + * Device enables its inbound FIFO post overflow interrupt + * and outbound free overflow interrupt. + * eumbbar is the base + *******************************************************/ +void I2OFIFOOverflowIntEnable( unsigned int eumbbar ) +{ + unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR ); + + val &= 0xfffffe7f; /* clear the two overflow interrupt bits */ + store_runtime_reg( eumbbar, I2O_IMIMR, val ); + +} + +/**************************************************** + * function: I2OFIFOOverflowIntDisable + * + * description: Disable the circular queue overflow interrupt + * + * note: + * Device disables its inbound post FIFO overflow interrupt + * and outbound free FIFO overflow interrupt + * (eumbbar is the base) + *****************************************************/ +void I2OFIFOOverflowIntDisable( unsigned int eumbbar ) +{ + + unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR ); + + val |= 0x00000180; /* masked out the msg overflow interrupt bits */ + store_runtime_reg( eumbbar, I2O_IMIMR, val ); +} diff --git a/mpc8240/drivers/i2o/i2o2.S b/mpc8240/drivers/i2o/i2o2.S new file mode 100644 index 0000000..f9d9287 --- /dev/null +++ b/mpc8240/drivers/i2o/i2o2.S @@ -0,0 +1,49 @@ +/************************************** + * $Id: i2o2.S,v 1.1 2000/11/20 17:22:33 wdenk Exp $ + * + * copyright @ Motorola, 1999 + * + **************************************/ + +/********************************************************** + * function: load_runtime_reg + * + * input: r3 - value of eumbbar + * r4 - register offset in embedded utility space + * + * output: r3 - register content + **********************************************************/ + .text + .align 2 + .global load_runtime_reg + +load_runtime_reg: + + xor r5,r5,r5 + or r5,r5,r3 /* save eumbbar */ + + lwbrx r3,r4,r5 + sync + + bclr 20, 0 + +/**************************************************************** + * function: store_runtime_reg + * + * input: r3 - value of eumbbar + * r4 - register offset in embedded utility space + * r5 - new value to be stored + * + ****************************************************************/ + .text + .align 2 + .global store_runtime_reg +store_runtime_reg: + + xor r0,r0,r0 + + stwbrx r5, r4, r3 + sync + + bclr 20,0 + diff --git a/mpc8240/interrupts.c b/mpc8240/interrupts.c new file mode 100644 index 0000000..f405461 --- /dev/null +++ b/mpc8240/interrupts.c @@ -0,0 +1,146 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com + * + * 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 + */ + +#include +#include +#include +#include +#include +#include "drivers/epic.h" + +/****************************************************************************/ + +static __inline__ unsigned long get_msr(void) +{ + unsigned long msr; + + asm volatile("mfmsr %0" : "=r" (msr) :); + return msr; +} + +static __inline__ void set_msr(unsigned long msr) +{ + asm volatile("mtmsr %0" : : "r" (msr)); +} + +static __inline__ unsigned long get_dec(void) +{ + unsigned long val; + + asm volatile("mfdec %0" : "=r" (val) :); + return val; +} + + +static __inline__ void set_dec(unsigned long val) +{ + asm volatile("mtdec %0" : : "r" (val)); +} + + +void enable_interrupts (void) +{ + set_msr (get_msr() | MSR_EE); +} + +/* returns flag if MSR_EE was set before */ +int disable_interrupts (void) +{ + ulong msr = get_msr(); + set_msr (msr & ~MSR_EE); + return ((msr & MSR_EE) != 0); +} + +/****************************************************************************/ + +void +interrupt_init (bd_t *bd) +{ + /* it's all broken at the moment and I currently don't need interrupts + if you want to fix it, have a look at the epic drivers in dink32 v12 + they do everthing and motorola said I could use the dink source in this project + as long as copyright notices remain intact. + epicInit(EPIC_DIRECT_IRQ,0); + set_msr (get_msr() | MSR_EE); + */ +} + +/****************************************************************************/ + +/* + * Handle external interrupts + */ +void external_interrupt(struct pt_regs *regs) +{ + register unsigned long temp; + pci_readl(CFG_EUMB_ADDR + EPIC_PROC_INT_ACK_REG, temp); + sync(); /* i'm not convinced this is needed, but dink source has it */ + temp &= 0xff; /*get vector*/ + + /*TODO: handle them -...*/ + epicEOI(); +} + +/****************************************************************************/ + +/* + * blank int handlers. + */ + +void +irq_install_handler(int vec, interrupt_handler_t *handler, void *arg) +{ +} + +void +irq_free_handler(int vec) +{ + +} + +/*TODO: some handlers for winbond and 87308 interrupts + and what about generic pci inteerupts? + vga? + */ + +volatile ulong timestamp = 0; + + void timer_interrupt(struct pt_regs *regs) + { + } + + void reset_timer (void) + { + timestamp = 0; + } + + ulong get_timer (ulong base) + { + return (timestamp - base); + } + + void set_timer (ulong t) + { + timestamp = t; + } diff --git a/mpc8240/start.S b/mpc8240/start.S new file mode 100644 index 0000000..8fd23da --- /dev/null +++ b/mpc8240/start.S @@ -0,0 +1,653 @@ +/* + * Copyright (C) 1998 Dan Malek + * Copyright (C) 1999 Magnus Damm + * Copyright (C) 2000 Wolfgang Denk + * + * 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 + */ + +/* ppcboot - Startup Code for PowerPC based Embedded Boards + * + * + * The processor starts at 0x00000100 and the code is executed + * from flash. The code is organized to be at an other address + * in memory, but as long we don't jump around before relocating. + * board_init lies at a quite high address and when the cpu has + * jumped there, everything is ok. + * This works because the cpu gives the FLASH (CS0) the whole + * address space at startup, and board_init lies as a echo of + * the flash somewhere up there in the memorymap. + * + * board_init will change CS0 to be positioned at the correct + * address and (s)dram will be positioned at address 0 + */ +#include +#include +#include "version.h" + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include +#include + +#include +#include + +/* We don't want the MMU yet. +*/ +#undef MSR_KERNEL +#define MSR_KERNEL ( MSR_ME | MSR_RI ) /* Machine Check and Recoverable Interr. */ + +/* + * Set up GOT: Global Offset Table + * + * Use r14 to access the GOT + */ + START_GOT + GOT_ENTRY(_GOT2_TABLE_) + GOT_ENTRY(_FIXUP_TABLE_) + + GOT_ENTRY(_start) + GOT_ENTRY(_start_of_vectors) + GOT_ENTRY(_end_of_vectors) + GOT_ENTRY(transfer_to_handler) + + GOT_ENTRY(_end) + GOT_ENTRY(.bss) +#if defined(CONFIG_FADS) + GOT_ENTRY(environment) +#endif + END_GOT + +/* + * r3 - 1st arg to board_init(): IMMP pointer + * r4 - 2nd arg to board_init(): boot flag + */ + .text + .long 0x27051956 /* PPCBOOT Magic Number */ + .globl version_string +version_string: + .ascii PPCBOOT_VERSION, " (", __DATE__, " - ", __TIME__, ")\0" + + . = EXC_OFF_SYS_RESET + .globl _start +_start: + li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */ + b boot_cold + + . = EXC_OFF_SYS_RESET + 0x10 + + .globl _start_warm +_start_warm: + li r21, BOOTFLAG_WARM /* Software reboot */ + b boot_warm + +boot_cold: +boot_warm: + + /* Initialize machine status; enable machine check interrupt */ + /*----------------------------------------------------------------------*/ + li r3, MSR_KERNEL /* Set ME, RI flags */ + mtmsr r3 + mtspr SRR1, r3 /* Make SRR1 match MSR */ + + mfspr r3, ICR /* clear Interrupt Cause Register */ + + addis r0,0,0x0000 // lets make sure that r0 is really 0 + + mfmsr r3 // turn off address translation + addis r4,0,0xffff + ori r4,r4,0xffcf + and r3,r3,r4 + mtmsr r3 + isync + sync // the MMU should be off... + + + + /* + * Calculate absolute address in FLASH and jump there + *----------------------------------------------------------------------*/ +#ifndef DEBUG + lis r3, CFG_FLASH_BASE@h + ori r3, r3, CFG_FLASH_BASE@l + addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET + mtlr r3 + blr +#endif +in_flash: + + + /* thisk the stack pointer *somewhere* sensible. doesnt matter much where as we'll + move it when we relocate*/ + + lis r1, (CFG_MEMTEST_END - 0x3000)@h + ori r1, r1, (CFG_MEMTEST_END - 0x3000)@l + + + /* let the C-code set up the rest */ + /* */ + /* Be careful to keep code relocatable ! */ + /*----------------------------------------------------------------------*/ + + GET_GOT /* initialize GOT access */ + + /* r3: IMMR */ + bl cpu_init_f /* run low-level CPU init code (from Flash) */ + + mr r3, r21 + /* r3: BOOTFLAG */ + bl board_init_f /* run 1st part of board init code (from Flash) */ + + + + .globl _start_of_vectors +_start_of_vectors: + +/* Machine check */ + STD_EXCEPTION(EXC_OFF_MACH_CHCK, MachineCheck, MachineCheckException) + +/* Data Storage exception. "Never" generated on the 860. */ + STD_EXCEPTION(EXC_OFF_DATA_STOR, DataStorage, UnknownException) + +/* Instruction Storage exception. "Never" generated on the 860. */ + STD_EXCEPTION(EXC_OFF_INS_STOR, InstStorage, UnknownException) + +/* External Interrupt exception. */ + STD_EXCEPTION(EXC_OFF_EXTERNAL, ExtInterrupt, external_interrupt) + +/* Alignment exception. */ + . = EXC_OFF_ALIGN +Alignment: + EXCEPTION_PROLOG + mfspr r4,DAR + stw r4,_DAR(r21) + mfspr r5,DSISR + stw r5,_DSISR(r21) + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ + lwz r6,GOT(transfer_to_handler) + mtlr r6 + blrl +.L_Alignment: + .long AlignmentException - _start + EXC_OFF_SYS_RESET + .long int_return - _start + EXC_OFF_SYS_RESET + +/* Program check exception */ + . = EXC_OFF_PROGRAM +ProgramCheck: + EXCEPTION_PROLOG + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ + lwz r6,GOT(transfer_to_handler) + mtlr r6 + blrl +.L_ProgramCheck: + .long ProgramCheckException - _start + EXC_OFF_SYS_RESET + .long int_return - _start + EXC_OFF_SYS_RESET + + /* No FPU on MPC8xx. This exception is not supposed to happen. + */ + STD_EXCEPTION(EXC_OFF_FPUNAVAIL, FPUnavailable, UnknownException) + + /* I guess we could implement decrementer, and may have + * to someday for timekeeping. + */ + STD_EXCEPTION(EXC_OFF_DECR, Decrementer, timer_interrupt) + STD_EXCEPTION(0xa00, Trap_0a, UnknownException) + STD_EXCEPTION(0xb00, Trap_0b, UnknownException) + + STD_EXCEPTION(EXC_OFF_SYS_CALL, SystemCall, UnknownException) + STD_EXCEPTION(EXC_OFF_TRACE, SingleStep, UnknownException) + + STD_EXCEPTION(EXC_OFF_FPUNASSIST, Trap_0e, UnknownException) + STD_EXCEPTION(EXC_OFF_PMI, Trap_0f, UnknownException) + + STD_EXCEPTION(EXC_OFF_ITME, InstructionTransMiss, UnknownException) + STD_EXCEPTION(EXC_OFF_DLTME, DataLoadTransMiss, UnknownException) + STD_EXCEPTION(EXC_OFF_DSTME, DataStoreTransMiss, UnknownException) + STD_EXCEPTION(EXC_OFF_IABE, InstructionBreakpoint, UnknownException) + STD_EXCEPTION(EXC_OFF_SMIE, SysManageInt, UnknownException) + STD_EXCEPTION(0x1500, Reserved5, UnknownException) + STD_EXCEPTION(0x1600, Reserved6, UnknownException) + STD_EXCEPTION(0x1700, Reserved7, UnknownException) + STD_EXCEPTION(0x1800, Reserved8, UnknownException) + STD_EXCEPTION(0x1900, Reserved9, UnknownException) + STD_EXCEPTION(0x1a00, ReservedA, UnknownException) + STD_EXCEPTION(0x1b00, ReservedB, UnknownException) + STD_EXCEPTION(0x1c00, ReservedC, UnknownException) + STD_EXCEPTION(0x1d00, ReservedD, UnknownException) + STD_EXCEPTION(0x1e00, ReservedE, UnknownException) + STD_EXCEPTION(0x1f00, ReservedF, UnknownException) + + STD_EXCEPTION(EXC_OFF_RMTE, RunModeTrace, UnknownException) + + .globl _end_of_vectors +_end_of_vectors: + + + . = 0x3000 + +/* + * This code finishes saving the registers to the exception frame + * and jumps to the appropriate handler for the exception. + * Register r21 is pointer into trap frame, r1 has new stack pointer. + */ + .globl transfer_to_handler +transfer_to_handler: + stw r22,_NIP(r21) + lis r22,MSR_POW@h + andc r23,r23,r22 + stw r23,_MSR(r21) + SAVE_GPR(7, r21) + SAVE_4GPRS(8, r21) + SAVE_8GPRS(12, r21) + SAVE_8GPRS(24, r21) +#if 0 + andi. r23,r23,MSR_PR + mfspr r23,SPRG3 /* if from user, fix up tss.regs */ + beq 2f + addi r24,r1,STACK_FRAME_OVERHEAD + stw r24,PT_REGS(r23) +2: addi r2,r23,-TSS /* set r2 to current */ + tovirt(r2,r2,r23) +#endif + mflr r23 + andi. r24,r23,0x3f00 /* get vector offset */ + stw r24,TRAP(r21) + li r22,0 + stw r22,RESULT(r21) + mtspr SPRG2,r22 /* r1 is now kernel sp */ +#if 0 + addi r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */ + cmplw 0,r1,r2 + cmplw 1,r1,r24 + crand 1,1,4 + bgt stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */ +#endif + lwz r24,0(r23) /* virtual address of handler */ + lwz r23,4(r23) /* where to go when done */ + mtspr SRR0,r24 + mtspr SRR1,r20 + mtlr r23 + SYNC + rfi /* jump to handler, enable MMU */ + +int_return: + mfmsr r29 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r29,r29,r4 + SYNC /* Some chip revs need this... */ + mtmsr r29 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr SRR0,r2 + mtspr SRR1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfi + +/* Cache functions. +*/ + .globl icache_enable +icache_enable: + mfspr r5,HID0 // turn on the I cache. + ori r5,r5,0x8800 // Instruction cache only//! + addis r6,0,0xFFFF + ori r6,r6,0xF7FF + and r6,r5,r6 // clear the invalidate bit + sync + mtspr HID0,r5 + mtspr HID0,r6 + isync + sync + blr + + .globl icache_disable +icache_disable: + mfspr r5,HID0 + addis r6,0,0xFFFF + ori r6,r6,0x7FFF + and r5,r5,r6 + sync + mtspr HID0,r5 + isync + sync + blr + + .globl icache_status +icache_status: + mfspr r3, HID0 + srwi r3, r3, 15 /* >>15 & 1=> select bit 16 */ + andi. r3, r3, 1 + blr + + .globl dcache_enable +dcache_enable: + mfspr r5,HID0 // turn on the D cache. + ori r5,r5,0x4400 // Data cache only//! + mfspr r4, PVR // read PVR + srawi r3, r4, 16 // shift off the least 16 bits + cmpi 0, 0, r3, 0xC // Check for Max pvr + bne NotMax + ori r5,r5,0x0040 // setting the DCFA bit, for Max rev 1 errata +NotMax: + addis r6,0,0xFFFF + ori r6,r6,0xFBFF + and r6,r5,r6 // clear the invalidate bit + sync + mtspr HID0,r5 + mtspr HID0,r6 + isync + sync + blr + + .globl dcache_disable +dcache_disable: + mfspr r5,HID0 + addis r6,0,0xFFFF + ori r6,r6,0xBFFF + and r5,r5,r6 + sync + mtspr HID0,r5 + isync + sync + blr + + .globl dcache_status +dcache_status: + mfspr r3, HID0 + srwi r3, r3, 14 /* >>14 & 1=> select bit 17 */ + andi. r3, r3, 1 + blr + + .globl dc_read +dc_read: +/*TODO : who uses this, what should it do? +*/ + blr + + + .globl get_pvr +get_pvr: + mfspr r3, PVR + blr + + +/*------------------------------------------------------------------------------*/ + +/* + * void relocate_code (addr_sp, bd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r3 = dest + * r4 = src + * r5 = length in bytes + * r6 = cachelinesize + */ + .globl relocate_code +relocate_code: + + mr r1, r3 /* Set new stack pointer */ + mr r9, r4 /* Save copy of Board Info pointer */ + mr r10, r5 /* Save copy of Destination Address */ + + mr r3, r5 /* Destination Address */ +#ifdef DEBUG + lis r4, CFG_SDRAM_BASE@h /* Source Address */ + ori r4, r4, CFG_SDRAM_BASE@l +#else + lis r4, CFG_FLASH_BASE@h /* Source Address */ + ori r4, r4, CFG_FLASH_BASE@l +#endif + lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */ + ori r5, r5, CFG_MONITOR_LEN@l + li r6, CFG_CACHELINE_SIZE /* Cache Line Size */ + + /* + * Fix GOT pointer: + * + * New GOT-PTR = (old GOT-PTR - CFG_FLASH_BASE) + Destination Address + * + * Offset: + */ + sub r15, r10, r4 + + /* First our own GOT */ + add r14, r14, r15 + /* the the one used by the C code */ + add r30, r30, r15 + + /* + * Now relocate code + */ + + cmplw cr1,r3,r4 + addi r0,r5,3 + srwi. r0,r0,2 + beq cr1,4f /* In place copy is not necessary */ + beq 7f /* Protect against 0 count */ + mtctr r0 + bge cr1,2f + + la r8,-4(r4) + la r7,-4(r3) +1: lwzu r0,4(r8) + stwu r0,4(r7) + bdnz 1b + b 4f + +2: slwi r0,r0,2 + add r8,r4,r0 + add r7,r3,r0 +3: lwzu r0,-4(r8) + stwu r0,-4(r7) + bdnz 3b + +/* + * Now flush the cache: note that we must start from a cache aligned + * address. Otherwise we might miss one cache line. + */ +4: cmpwi r6,0 + add r5,r3,r5 + beq 7f /* Always flush prefetch queue in any case */ + subi r0,r6,1 + andc r3,r3,r0 + mr r4,r3 +5: cmplw r4,r5 + dcbst 0,r4 + add r4,r4,r6 + blt 5b + sync /* Wait for all dcbst to complete on bus */ + mr r4,r3 +6: cmplw r4,r5 + icbi 0,r4 + add r4,r4,r6 + blt 6b +7: sync /* Wait for all icbi to complete on bus */ + isync + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ + + addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET + mtlr r0 + blr + +in_ram: + + /* + * Relocation Function, r14 point to got2+0x8000 + * + * Adjust got2 pointers, no need to check for 0, this code + * already puts a few entries in the table. + */ + li r0,__got2_entries@sectoff@l + la r3,GOT(_GOT2_TABLE_) + lwz r11,GOT(_GOT2_TABLE_) + mtctr r0 + sub r11,r3,r11 + addi r3,r3,-4 +1: lwzu r0,4(r3) + add r0,r0,r11 + stw r0,0(r3) + bdnz 1b + + /* + * Now adjust the fixups and the pointers to the fixups + * in case we need to move ourselves again. + */ +2: li r0,__fixup_entries@sectoff@l + lwz r3,GOT(_FIXUP_TABLE_) + cmpwi r0,0 + mtctr r0 + addi r3,r3,-4 + beq 4f +3: lwzu r4,4(r3) + lwzux r0,r4,r11 + add r0,r0,r11 + stw r10,0(r3) + stw r0,0(r4) + bdnz 3b +4: +clear_bss: + /* + * Now clear BSS segment + */ + lwz r3,GOT(.bss) +#if defined(CONFIG_FADS) + /* + * For the FADS - the environment is the very last item in flash. + * The real .bss stops just before environment starts, so only + * clear up to that point. + */ + lwz r4,GOT(environment) +#else + lwz r4,GOT(_end) +#endif + + cmplw 0, r3, r4 + beq 6f + + li r0, 0 +5: + stw r0, 0(r3) + addi r3, r3, 4 + cmplw 0, r3, r4 + blt 5b +6: + + mr r3, r9 /* Board Info pointer */ + mr r4, r10 /* Destination Address */ + bl board_init_r + + /* Problems accessing "end" in C, so do it here */ + .globl get_endaddr +get_endaddr: + lwz r3,GOT(_end) + blr + + /* + * Copy exception vector code to low memory + * + * r3: dest_addr + * r7: source address, r8: end address, r9: target address + */ + .globl trap_init +trap_init: + lwz r7, GOT(_start) + lwz r8, GOT(_end_of_vectors) + + rlwinm r9, r7, 0, 18, 31 /* _start & 0x3FFF */ + + cmplw 0, r7, r8 + bgelr /* return if r7>=r8 - just in case */ + + mflr r4 /* save link register */ +1: + lwz r0, 0(r7) + stw r0, 0(r9) + addi r7, r7, 4 + addi r9, r9, 4 + cmplw 0, r7, r8 + bne 1b + + /* + * relocate `hdlr' and `int_return' entries + */ + li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET + li r8, Alignment - _start + EXC_OFF_SYS_RESET +2: + bl trap_reloc + addi r7, r7, 0x100 /* next exception vector */ + cmplw 0, r7, r8 + blt 2b + + li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET + bl trap_reloc + + li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET + bl trap_reloc + + li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET + li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET +3: + bl trap_reloc + addi r7, r7, 0x100 /* next exception vector */ + cmplw 0, r7, r8 + blt 3b + + mtlr r4 /* restore link register */ + blr + + /* + * Function: relocate entries for one exception vector + */ +trap_reloc: + lwz r0, 0(r7) /* hdlr ... */ + add r0, r0, r3 /* ... += dest_addr */ + stw r0, 0(r7) + + lwz r0, 4(r7) /* int_return ... */ + add r0, r0, r3 /* ... += dest_addr */ + stw r0, 4(r7) + + blr diff --git a/mpc8240/start1.S b/mpc8240/start1.S new file mode 100644 index 0000000..f81cd68 --- /dev/null +++ b/mpc8240/start1.S @@ -0,0 +1,1812 @@ +Analyzing: d:\ppcboot\mpc8240\start1.o +Header idenfication: 0x7f, ELF, 32 bit MSB v1 + type: 1, machine: 20 + version: 00000001, entry: 00000000, phoff: 00000000 + shoff: 00003410, flags: 00000000, ehsize: 52, phentsize: 0 + phnum: 0, shentsize: 40, shnum: 10, shstrndx: 7 + + +==> .shstrtab + [ 1] .symtab + [ 9] .strtab + [ 17] .shstrtab + [ 27] .text + [ 33] .rela.text + [ 44] .data + [ 50] .bss + [ 55] .got2 + [ 61] .rela.got2 + +==> .text [1]: Section Header + type: 00000001, flags: 00000006 + address: 00000000, offset: 00000034, size: 00003374 + link: 00000000, info: 00000000, alignment: 1, entry size: 0 + + +==> .rela.text [2]: Section Header + type: 00000004, flags: 00000000 + address: 00000000, offset: 0000416c, size: 000001a4 + link: 00000008, info: 00000001, alignment: 4, entry size: 12 + + +==> .data [3]: Section Header + type: 00000001, flags: 00000003 + address: 00000000, offset: 000033a8, size: 00000000 + link: 00000000, info: 00000000, alignment: 1, entry size: 0 + + +==> .bss [4]: Section Header + type: 00000008, flags: 00000003 + address: 00000000, offset: 000033a8, size: 00000000 + link: 00000000, info: 00000000, alignment: 1, entry size: 0 + + +==> .got2 [5]: Section Header + type: 00000001, flags: 00000003 + address: 00000000, offset: 000033a8, size: 00000020 + link: 00000000, info: 00000000, alignment: 1, entry size: 0 + + +==> .rela.got2 [6]: Section Header + type: 00000004, flags: 00000000 + address: 00000000, offset: 00004310, size: 00000060 + link: 00000008, info: 00000005, alignment: 4, entry size: 12 + + +==> .shstrtab [7]: Section Header + type: 00000003, flags: 00000000 + address: 00000000, offset: 000033c8, size: 00000048 + link: 00000000, info: 00000000, alignment: 1, entry size: 0 + + +==> .symtab [8]: Section Header + type: 00000002, flags: 00000000 + address: 00000000, offset: 000035a0, size: 00000680 + link: 00000009, info: 0000004a, alignment: 4, entry size: 16 + + +==> .strtab [9]: Section Header + type: 00000003, flags: 00000000 + address: 00000000, offset: 00003c20, size: 00000549 + link: 00000000, info: 00000000, alignment: 1, entry size: 0 + + +==> .strtab + [ 1] start.S + [ 9] /cygdrive/d/ppcboot/include/asm/mmu.h + [ 47] /cygdrive/d/ppcboot/include/linux/config.h + [ 90] /cygdrive/d/ppcboot/include/asm/cache.h + [ 130] /cygdrive/d/ppcboot/include/asm/processor.h + [ 174] /cygdrive/d/ppcboot/include/asm/types.h + [ 214] /cygdrive/d/ppcboot/include/asm/ptrace.h + [ 255] /cygdrive/d/ppcboot/include/ppc_defs.h + [ 294] /cygdrive/d/ppcboot/include/ppc_asm.tmpl + [ 335] /cygdrive/d/ppcboot/include/version.h + [ 373] /cygdrive/d/ppcboot/include/mpc8240.h + [ 411] /cygdrive/d/ppcboot/include/config.h + [ 448] /cygdrive/d/ppcboot/include/config_Sandpoint8240.h + [ 499] boot_cold + [ 509] boot_warm + [ 519] in_flash + [ 528] MachineCheck + [ 541] int_return + [ 552] DataStorage + [ 564] InstStorage + [ 576] ExtInterrupt + [ 589] Alignment + [ 599] ProgramCheck + [ 612] FPUnavailable + [ 626] Decrementer + [ 638] Trap_0a + [ 646] Trap_0b + [ 654] SystemCall + [ 665] SingleStep + [ 676] Trap_0e + [ 684] Trap_0f + [ 692] InstructionTransMiss + [ 713] DataLoadTransMiss + [ 731] DataStoreTransMiss + [ 750] InstructionBreakpoint + [ 772] SysManageInt + [ 785] Reserved5 + [ 795] Reserved6 + [ 805] Reserved7 + [ 815] Reserved8 + [ 825] Reserved9 + [ 835] ReservedA + [ 845] ReservedB + [ 855] ReservedC + [ 865] ReservedD + [ 875] ReservedE + [ 885] ReservedF + [ 895] RunModeTrace + [ 908] NotMax + [ 915] clear_bss + [ 925] trap_reloc + [ 936] _GOT2_TABLE_ + [ 949] _FIXUP_TABLE_ + [ 963] _start + [ 970] _start_of_vectors + [ 988] _end_of_vectors + [ 1004] transfer_to_handler + [ 1024] _end + [ 1029] version_string + [ 1044] _start_warm + [ 1056] cpu_init_f + [ 1067] board_init_f + [ 1080] MachineCheckException + [ 1102] UnknownException + [ 1119] external_interrupt + [ 1138] AlignmentException + [ 1157] ProgramCheckException + [ 1179] timer_interrupt + [ 1195] icache_enable + [ 1209] icache_disable + [ 1224] icache_status + [ 1238] dcache_enable + [ 1252] dcache_disable + [ 1267] dcache_status + [ 1281] dc_read + [ 1289] get_pvr + [ 1297] udelay + [ 1304] relocate_code + [ 1318] board_init_r + [ 1331] get_endaddr + [ 1343] trap_init + +==> .symtab + entry spndx value size bind type other shndx name + [ 0] 0 00000000 0 LOC NULL 0 UND + [ 1] 1 00000000 0 LOC FILE 0 ABS start.S + [ 2] 9 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/mmu.h + [ 3] 47 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/linux/config.h + [ 4] 9 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/mmu.h + [ 5] 1 00000000 0 LOC FILE 0 ABS start.S + [ 6] 90 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/cache.h + [ 7] 130 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/processor.h + [ 8] 174 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/types.h + [ 9] 130 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/processor.h + [ 10] 214 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/ptrace.h + [ 11] 47 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/linux/config.h + [ 12] 214 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/ptrace.h + [ 13] 130 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/processor.h + [ 14] 47 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/linux/config.h + [ 15] 130 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/processor.h + [ 16] 90 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/cache.h + [ 17] 47 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/linux/config.h + [ 18] 90 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/asm/cache.h + [ 19] 1 00000000 0 LOC FILE 0 ABS start.S + [ 20] 255 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/ppc_defs.h + [ 21] 1 00000000 0 LOC FILE 0 ABS start.S + [ 22] 294 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/ppc_asm.tmpl + [ 23] 1 00000000 0 LOC FILE 0 ABS start.S + [ 24] 335 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/version.h + [ 25] 1 00000000 0 LOC FILE 0 ABS start.S + [ 26] 373 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/mpc8240.h + [ 27] 1 00000000 0 LOC FILE 0 ABS start.S + [ 28] 411 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/config.h + [ 29] 448 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/config_Sandpoint8240.h + [ 30] 411 00000000 0 LOC FILE 0 ABS /cygdrive/d/ppcboot/include/config.h + [ 31] 1 00000000 0 LOC FILE 0 ABS start.S + [ 32] 0 00000000 0 LOC SECT 0 .text .text + [ 33] 0 00000000 0 LOC SECT 0 .data .data + [ 34] 0 00000000 0 LOC SECT 0 .bss .bss + [ 35] 0 00000000 0 LOC SECT 0 .got2 .got2 + [ 36] 499 00000118 0 LOC NULL 0 .text boot_cold + [ 37] 509 00000118 0 LOC NULL 0 .text boot_warm + [ 38] 519 00000148 0 LOC NULL 0 .text in_flash + [ 39] 528 00000200 0 LOC NULL 0 .text MachineCheck + [ 40] 541 0000309c 0 LOC NULL 0 .text int_return + [ 41] 552 00000300 0 LOC NULL 0 .text DataStorage + [ 42] 564 00000400 0 LOC NULL 0 .text InstStorage + [ 43] 576 00000500 0 LOC NULL 0 .text ExtInterrupt + [ 44] 589 00000600 0 LOC NULL 0 .text Alignment + [ 45] 599 00000700 0 LOC NULL 0 .text ProgramCheck + [ 46] 612 00000800 0 LOC NULL 0 .text FPUnavailable + [ 47] 626 00000900 0 LOC NULL 0 .text Decrementer + [ 48] 638 00000a00 0 LOC NULL 0 .text Trap_0a + [ 49] 646 00000b00 0 LOC NULL 0 .text Trap_0b + [ 50] 654 00000c00 0 LOC NULL 0 .text SystemCall + [ 51] 665 00000d00 0 LOC NULL 0 .text SingleStep + [ 52] 676 00000e00 0 LOC NULL 0 .text Trap_0e + [ 53] 684 00000f00 0 LOC NULL 0 .text Trap_0f + [ 54] 692 00001000 0 LOC NULL 0 .text InstructionTransMiss + [ 55] 713 00001100 0 LOC NULL 0 .text DataLoadTransMiss + [ 56] 731 00001200 0 LOC NULL 0 .text DataStoreTransMiss + [ 57] 750 00001300 0 LOC NULL 0 .text InstructionBreakpoint + [ 58] 772 00001400 0 LOC NULL 0 .text SysManageInt + [ 59] 785 00001500 0 LOC NULL 0 .text Reserved5 + [ 60] 795 00001600 0 LOC NULL 0 .text Reserved6 + [ 61] 805 00001700 0 LOC NULL 0 .text Reserved7 + [ 62] 815 00001800 0 LOC NULL 0 .text Reserved8 + [ 63] 825 00001900 0 LOC NULL 0 .text Reserved9 + [ 64] 835 00001a00 0 LOC NULL 0 .text ReservedA + [ 65] 845 00001b00 0 LOC NULL 0 .text ReservedB + [ 66] 855 00001c00 0 LOC NULL 0 .text ReservedC + [ 67] 865 00001d00 0 LOC NULL 0 .text ReservedD + [ 68] 875 00001e00 0 LOC NULL 0 .text ReservedE + [ 69] 885 00001f00 0 LOC NULL 0 .text ReservedF + [ 70] 895 00002000 0 LOC NULL 0 .text RunModeTrace + [ 71] 908 000031f8 0 LOC NULL 0 .text NotMax + [ 72] 915 000032a4 0 LOC NULL 0 .text clear_bss + [ 73] 925 00003354 0 LOC NULL 0 .text trap_reloc + [ 74] 936 00000000 0 GLOB NULL 0 UND _GOT2_TABLE_ + [ 75] 949 00000000 0 GLOB NULL 0 UND _FIXUP_TABLE_ + [ 76] 963 00000100 0 GLOB NULL 0 .text _start + [ 77] 970 0000016c 0 GLOB NULL 0 .text _start_of_vectors + [ 78] 988 00002090 0 GLOB NULL 0 .text _end_of_vectors + [ 79] 1004 00003000 0 GLOB NULL 0 .text transfer_to_handler + [ 80] 1024 00000000 0 GLOB NULL 0 UND _end + [ 81] 1029 00000004 0 GLOB NULL 0 .text version_string + [ 82] 1044 00000110 0 GLOB NULL 0 .text _start_warm + [ 83] 1056 00000000 0 GLOB NULL 0 UND cpu_init_f + [ 84] 1067 00000000 0 GLOB NULL 0 UND board_init_f + [ 85] 1080 00000000 0 GLOB NULL 0 UND MachineCheckException + [ 86] 1102 00000000 0 GLOB NULL 0 UND UnknownException + [ 87] 1119 00000000 0 GLOB NULL 0 UND external_interrupt + [ 88] 1138 00000000 0 GLOB NULL 0 UND AlignmentException + [ 89] 1157 00000000 0 GLOB NULL 0 UND ProgramCheckException + [ 90] 1179 00000000 0 GLOB NULL 0 UND timer_interrupt + [ 91] 1195 0000317c 0 GLOB NULL 0 .text icache_enable + [ 92] 1209 000031a8 0 GLOB NULL 0 .text icache_disable + [ 93] 1224 000031cc 0 GLOB NULL 0 .text icache_status + [ 94] 1238 000031dc 0 GLOB NULL 0 .text dcache_enable + [ 95] 1252 0000321c 0 GLOB NULL 0 .text dcache_disable + [ 96] 1267 00003240 0 GLOB NULL 0 .text dcache_status + [ 97] 1281 00003250 0 GLOB NULL 0 .text dc_read + [ 98] 1289 00003254 0 GLOB NULL 0 .text get_pvr + [ 99] 1297 0000325c 0 GLOB NULL 0 .text udelay + [ 100] 1304 000032a4 0 GLOB NULL 0 .text relocate_code + [ 101] 1318 00000000 0 GLOB NULL 0 UND board_init_r + [ 102] 1331 000032d4 0 GLOB NULL 0 .text get_endaddr + [ 103] 1343 000032dc 0 GLOB NULL 0 .text trap_init + +==> .rela.text + entry offset addend type name(symbol id) + [ 0] 00000160 00000000 10 cpu_init_f(83) + [ 1] 00000168 00000000 10 board_init_f(84) + [ 2] 00000288 00000288 26 MachineCheckException(85) + [ 3] 00000388 00000388 26 UnknownException(86) + [ 4] 00000488 00000488 26 UnknownException(86) + [ 5] 00000588 00000588 26 external_interrupt(87) + [ 6] 0000069c 0000069c 26 AlignmentException(88) + [ 7] 0000078c 0000078c 26 ProgramCheckException(89) + [ 8] 00000888 00000888 26 UnknownException(86) + [ 9] 00000988 00000988 26 timer_interrupt(90) + [ 10] 00000a88 00000a88 26 UnknownException(86) + [ 11] 00000b88 00000b88 26 UnknownException(86) + [ 12] 00000c88 00000c88 26 UnknownException(86) + [ 13] 00000d88 00000d88 26 UnknownException(86) + [ 14] 00000e88 00000e88 26 UnknownException(86) + [ 15] 00000f88 00000f88 26 UnknownException(86) + [ 16] 00001088 00001088 26 UnknownException(86) + [ 17] 00001188 00001188 26 UnknownException(86) + [ 18] 00001288 00001288 26 UnknownException(86) + [ 19] 00001388 00001388 26 UnknownException(86) + [ 20] 00001488 00001488 26 UnknownException(86) + [ 21] 00001588 00001588 26 UnknownException(86) + [ 22] 00001688 00001688 26 UnknownException(86) + [ 23] 00001788 00001788 26 UnknownException(86) + [ 24] 00001888 00001888 26 UnknownException(86) + [ 25] 00001988 00001988 26 UnknownException(86) + [ 26] 00001a88 00001a88 26 UnknownException(86) + [ 27] 00001b88 00001b88 26 UnknownException(86) + [ 28] 00001c88 00001c88 26 UnknownException(86) + [ 29] 00001d88 00001d88 26 UnknownException(86) + [ 30] 00001e88 00001e88 26 UnknownException(86) + [ 31] 00001f88 00001f88 26 UnknownException(86) + [ 32] 00002088 00002088 26 UnknownException(86) + [ 33] 000032d0 00000000 10 board_init_r(101) + [ 34] 00003370 0000b21c 26 .got2(35) + +==> .text +00000000: 27051956 dc.l 0x27051956 ; Invalid opcode ''..V' + +Hunk: Kind=HUNK_GLOBAL_CODE Name="version_string" Size=0 +00000004: 70706362 andi. r16,r3,0x6362 +00000008: 6F6F7420 xoris r15,r27,0x7420 +0000000C: 302E352E addic rsp,r14,13614 +00000010: 3020284F addic rsp,r0,10319 +00000014: 63742031 ori r20,r27,0x2031 +00000018: 31203230 addic r9,r0,12848 +0000001C: 3030202D addic rsp,r16,8237 +00000020: 2031363A subfic rsp,r17,13882 +00000024: 35353A34 addic. r9,r21,14900 +00000028: 38290000 addi rsp,r9,0 + +Hunk: Kind=HUNK_GLOBAL_CODE Name="_start" Size=0 +00000100: 3AA00001 li r21,1 +00000104: 48000014 b *+20 ; 0x00000118 + +Hunk: Kind=HUNK_GLOBAL_CODE Name="_start_warm" Size=0 +00000110: 3AA00002 li r21,2 +00000114: 48000004 b *+4 ; 0x00000118 + +Hunk: Kind=HUNK_LOCAL_CODE Name="boot_warm" Size=0 + +Hunk: Kind=HUNK_LOCAL_CODE Name="boot_cold" Size=0 +00000118: 38601002 li r3,4098 +0000011C: 7C600124 mtmsr r3 +00000120: 7C7B03A6 mtsrr1 r3 +00000124: 7C7422A6 mfspr r3,ECR +00000128: 3C000000 lis r0,0 +0000012C: 7C6000A6 mfmsr r3 +00000130: 3C80FFFF lis r4,-1 +00000134: 6084FFCF ori r4,r4,0xffcf +00000138: 7C632038 and r3,r3,r4 +0000013C: 7C600124 mtmsr r3 +00000140: 4C00012C isync +00000144: 7C0004AC sync + +Hunk: Kind=HUNK_LOCAL_CODE Name="in_flash" Size=0 +00000148: 3C20007F lis rsp,127 +0000014C: 6021D000 ori rsp,rsp,0xd000 +00000150: 48000005 bl *+4 ; 0x00000154 +00000154: 7DC802A6 mflr r14 +00000158: 800E321C lwz r0,12828(r14) +0000015C: 7DC07214 add r14,r0,r14 +00000160: 48000001 bl cpu_init_f +00000164: 7EA3AB78 mr r3,r21 +00000168: 48000001 bl board_init_f + +Hunk: Kind=HUNK_GLOBAL_CODE Name="_start_of_vectors" Size=0 + +Hunk: Kind=HUNK_LOCAL_CODE Name="MachineCheck" Size=0 +00000200: 7E9043A6 mtsprg0 r20 +00000204: 7EB143A6 mtsprg1 r21 +00000208: 7E800026 mfcr r20 +0000020C: 7C350B78 mr r21,rsp +00000210: 3AB5FF00 subi r21,r21,256 +00000214: 929500A8 stw r20,168(r21) +00000218: 92D50068 stw r22,104(r21) +0000021C: 92F5006C stw r23,108(r21) +00000220: 7E9042A6 mfsprg0 r20 +00000224: 92950060 stw r20,96(r21) +00000228: 7ED142A6 mfsprg1 r22 +0000022C: 92D50064 stw r22,100(r21) +00000230: 7E8802A6 mflr r20 +00000234: 929500A0 stw r20,160(r21) +00000238: 7EC902A6 mfctr r22 +0000023C: 92D5009C stw r22,156(r21) +00000240: 7E8102A6 mfxer r20 +00000244: 929500A4 stw r20,164(r21) +00000248: 7EDA02A6 mfsrr0 r22 +0000024C: 7EFB02A6 mfsrr1 r23 +00000250: 90150010 stw r0,16(r21) +00000254: 90350014 stw rsp,20(r21) +00000258: 90550018 stw r2,24(r21) +0000025C: 90350000 stw rsp,0(r21) +00000260: 7EA1AB78 mr rsp,r21 +00000264: 9075001C stw r3,28(r21) +00000268: 90950020 stw r4,32(r21) +0000026C: 90B50024 stw r5,36(r21) +00000270: 90D50028 stw r6,40(r21) +00000274: 806E8014 lwz r3,-32748(r14) +00000278: 7C6803A6 mtlr r3 +0000027C: 38610010 addi r3,rsp,16 +00000280: 3A801002 li r20,4098 +00000284: 4E800021 blrl +00000288: 00000288 dc.l 0x00000288 ; Invalid opcode '....' +0000028C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="DataStorage" Size=0 +00000300: 7E9043A6 mtsprg0 r20 +00000304: 7EB143A6 mtsprg1 r21 +00000308: 7E800026 mfcr r20 +0000030C: 7C350B78 mr r21,rsp +00000310: 3AB5FF00 subi r21,r21,256 +00000314: 929500A8 stw r20,168(r21) +00000318: 92D50068 stw r22,104(r21) +0000031C: 92F5006C stw r23,108(r21) +00000320: 7E9042A6 mfsprg0 r20 +00000324: 92950060 stw r20,96(r21) +00000328: 7ED142A6 mfsprg1 r22 +0000032C: 92D50064 stw r22,100(r21) +00000330: 7E8802A6 mflr r20 +00000334: 929500A0 stw r20,160(r21) +00000338: 7EC902A6 mfctr r22 +0000033C: 92D5009C stw r22,156(r21) +00000340: 7E8102A6 mfxer r20 +00000344: 929500A4 stw r20,164(r21) +00000348: 7EDA02A6 mfsrr0 r22 +0000034C: 7EFB02A6 mfsrr1 r23 +00000350: 90150010 stw r0,16(r21) +00000354: 90350014 stw rsp,20(r21) +00000358: 90550018 stw r2,24(r21) +0000035C: 90350000 stw rsp,0(r21) +00000360: 7EA1AB78 mr rsp,r21 +00000364: 9075001C stw r3,28(r21) +00000368: 90950020 stw r4,32(r21) +0000036C: 90B50024 stw r5,36(r21) +00000370: 90D50028 stw r6,40(r21) +00000374: 806E8014 lwz r3,-32748(r14) +00000378: 7C6803A6 mtlr r3 +0000037C: 38610010 addi r3,rsp,16 +00000380: 3A801002 li r20,4098 +00000384: 4E800021 blrl +00000388: 00000388 dc.l 0x00000388 ; Invalid opcode '....' +0000038C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="InstStorage" Size=0 +00000400: 7E9043A6 mtsprg0 r20 +00000404: 7EB143A6 mtsprg1 r21 +00000408: 7E800026 mfcr r20 +0000040C: 7C350B78 mr r21,rsp +00000410: 3AB5FF00 subi r21,r21,256 +00000414: 929500A8 stw r20,168(r21) +00000418: 92D50068 stw r22,104(r21) +0000041C: 92F5006C stw r23,108(r21) +00000420: 7E9042A6 mfsprg0 r20 +00000424: 92950060 stw r20,96(r21) +00000428: 7ED142A6 mfsprg1 r22 +0000042C: 92D50064 stw r22,100(r21) +00000430: 7E8802A6 mflr r20 +00000434: 929500A0 stw r20,160(r21) +00000438: 7EC902A6 mfctr r22 +0000043C: 92D5009C stw r22,156(r21) +00000440: 7E8102A6 mfxer r20 +00000444: 929500A4 stw r20,164(r21) +00000448: 7EDA02A6 mfsrr0 r22 +0000044C: 7EFB02A6 mfsrr1 r23 +00000450: 90150010 stw r0,16(r21) +00000454: 90350014 stw rsp,20(r21) +00000458: 90550018 stw r2,24(r21) +0000045C: 90350000 stw rsp,0(r21) +00000460: 7EA1AB78 mr rsp,r21 +00000464: 9075001C stw r3,28(r21) +00000468: 90950020 stw r4,32(r21) +0000046C: 90B50024 stw r5,36(r21) +00000470: 90D50028 stw r6,40(r21) +00000474: 806E8014 lwz r3,-32748(r14) +00000478: 7C6803A6 mtlr r3 +0000047C: 38610010 addi r3,rsp,16 +00000480: 3A801002 li r20,4098 +00000484: 4E800021 blrl +00000488: 00000488 dc.l 0x00000488 ; Invalid opcode '....' +0000048C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="ExtInterrupt" Size=0 +00000500: 7E9043A6 mtsprg0 r20 +00000504: 7EB143A6 mtsprg1 r21 +00000508: 7E800026 mfcr r20 +0000050C: 7C350B78 mr r21,rsp +00000510: 3AB5FF00 subi r21,r21,256 +00000514: 929500A8 stw r20,168(r21) +00000518: 92D50068 stw r22,104(r21) +0000051C: 92F5006C stw r23,108(r21) +00000520: 7E9042A6 mfsprg0 r20 +00000524: 92950060 stw r20,96(r21) +00000528: 7ED142A6 mfsprg1 r22 +0000052C: 92D50064 stw r22,100(r21) +00000530: 7E8802A6 mflr r20 +00000534: 929500A0 stw r20,160(r21) +00000538: 7EC902A6 mfctr r22 +0000053C: 92D5009C stw r22,156(r21) +00000540: 7E8102A6 mfxer r20 +00000544: 929500A4 stw r20,164(r21) +00000548: 7EDA02A6 mfsrr0 r22 +0000054C: 7EFB02A6 mfsrr1 r23 +00000550: 90150010 stw r0,16(r21) +00000554: 90350014 stw rsp,20(r21) +00000558: 90550018 stw r2,24(r21) +0000055C: 90350000 stw rsp,0(r21) +00000560: 7EA1AB78 mr rsp,r21 +00000564: 9075001C stw r3,28(r21) +00000568: 90950020 stw r4,32(r21) +0000056C: 90B50024 stw r5,36(r21) +00000570: 90D50028 stw r6,40(r21) +00000574: 806E8014 lwz r3,-32748(r14) +00000578: 7C6803A6 mtlr r3 +0000057C: 38610010 addi r3,rsp,16 +00000580: 3A801002 li r20,4098 +00000584: 4E800021 blrl +00000588: 00000588 dc.l 0x00000588 ; Invalid opcode '....' +0000058C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Alignment" Size=0 +00000600: 7E9043A6 mtsprg0 r20 +00000604: 7EB143A6 mtsprg1 r21 +00000608: 7E800026 mfcr r20 +0000060C: 7C350B78 mr r21,rsp +00000610: 3AB5FF00 subi r21,r21,256 +00000614: 929500A8 stw r20,168(r21) +00000618: 92D50068 stw r22,104(r21) +0000061C: 92F5006C stw r23,108(r21) +00000620: 7E9042A6 mfsprg0 r20 +00000624: 92950060 stw r20,96(r21) +00000628: 7ED142A6 mfsprg1 r22 +0000062C: 92D50064 stw r22,100(r21) +00000630: 7E8802A6 mflr r20 +00000634: 929500A0 stw r20,160(r21) +00000638: 7EC902A6 mfctr r22 +0000063C: 92D5009C stw r22,156(r21) +00000640: 7E8102A6 mfxer r20 +00000644: 929500A4 stw r20,164(r21) +00000648: 7EDA02A6 mfsrr0 r22 +0000064C: 7EFB02A6 mfsrr1 r23 +00000650: 90150010 stw r0,16(r21) +00000654: 90350014 stw rsp,20(r21) +00000658: 90550018 stw r2,24(r21) +0000065C: 90350000 stw rsp,0(r21) +00000660: 7EA1AB78 mr rsp,r21 +00000664: 9075001C stw r3,28(r21) +00000668: 90950020 stw r4,32(r21) +0000066C: 90B50024 stw r5,36(r21) +00000670: 90D50028 stw r6,40(r21) +00000674: 7C9302A6 mfspr r4,DAR +00000678: 909500B4 stw r4,180(r21) +0000067C: 7CB202A6 mfspr r5,DSISR +00000680: 90B500B8 stw r5,184(r21) +00000684: 38610010 addi r3,rsp,16 +00000688: 3A801002 li r20,4098 +0000068C: 52F40420 rlwimi r20,r23,0,16,16 +00000690: 80CE8014 lwz r6,-32748(r14) +00000694: 7CC803A6 mtlr r6 +00000698: 4E800021 blrl +0000069C: 0000069C dc.l 0x0000069c ; Invalid opcode '....' +000006A0: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="ProgramCheck" Size=0 +00000700: 7E9043A6 mtsprg0 r20 +00000704: 7EB143A6 mtsprg1 r21 +00000708: 7E800026 mfcr r20 +0000070C: 7C350B78 mr r21,rsp +00000710: 3AB5FF00 subi r21,r21,256 +00000714: 929500A8 stw r20,168(r21) +00000718: 92D50068 stw r22,104(r21) +0000071C: 92F5006C stw r23,108(r21) +00000720: 7E9042A6 mfsprg0 r20 +00000724: 92950060 stw r20,96(r21) +00000728: 7ED142A6 mfsprg1 r22 +0000072C: 92D50064 stw r22,100(r21) +00000730: 7E8802A6 mflr r20 +00000734: 929500A0 stw r20,160(r21) +00000738: 7EC902A6 mfctr r22 +0000073C: 92D5009C stw r22,156(r21) +00000740: 7E8102A6 mfxer r20 +00000744: 929500A4 stw r20,164(r21) +00000748: 7EDA02A6 mfsrr0 r22 +0000074C: 7EFB02A6 mfsrr1 r23 +00000750: 90150010 stw r0,16(r21) +00000754: 90350014 stw rsp,20(r21) +00000758: 90550018 stw r2,24(r21) +0000075C: 90350000 stw rsp,0(r21) +00000760: 7EA1AB78 mr rsp,r21 +00000764: 9075001C stw r3,28(r21) +00000768: 90950020 stw r4,32(r21) +0000076C: 90B50024 stw r5,36(r21) +00000770: 90D50028 stw r6,40(r21) +00000774: 38610010 addi r3,rsp,16 +00000778: 3A801002 li r20,4098 +0000077C: 52F40420 rlwimi r20,r23,0,16,16 +00000780: 80CE8014 lwz r6,-32748(r14) +00000784: 7CC803A6 mtlr r6 +00000788: 4E800021 blrl +0000078C: 0000078C dc.l 0x0000078c ; Invalid opcode '....' +00000790: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="FPUnavailable" Size=0 +00000800: 7E9043A6 mtsprg0 r20 +00000804: 7EB143A6 mtsprg1 r21 +00000808: 7E800026 mfcr r20 +0000080C: 7C350B78 mr r21,rsp +00000810: 3AB5FF00 subi r21,r21,256 +00000814: 929500A8 stw r20,168(r21) +00000818: 92D50068 stw r22,104(r21) +0000081C: 92F5006C stw r23,108(r21) +00000820: 7E9042A6 mfsprg0 r20 +00000824: 92950060 stw r20,96(r21) +00000828: 7ED142A6 mfsprg1 r22 +0000082C: 92D50064 stw r22,100(r21) +00000830: 7E8802A6 mflr r20 +00000834: 929500A0 stw r20,160(r21) +00000838: 7EC902A6 mfctr r22 +0000083C: 92D5009C stw r22,156(r21) +00000840: 7E8102A6 mfxer r20 +00000844: 929500A4 stw r20,164(r21) +00000848: 7EDA02A6 mfsrr0 r22 +0000084C: 7EFB02A6 mfsrr1 r23 +00000850: 90150010 stw r0,16(r21) +00000854: 90350014 stw rsp,20(r21) +00000858: 90550018 stw r2,24(r21) +0000085C: 90350000 stw rsp,0(r21) +00000860: 7EA1AB78 mr rsp,r21 +00000864: 9075001C stw r3,28(r21) +00000868: 90950020 stw r4,32(r21) +0000086C: 90B50024 stw r5,36(r21) +00000870: 90D50028 stw r6,40(r21) +00000874: 806E8014 lwz r3,-32748(r14) +00000878: 7C6803A6 mtlr r3 +0000087C: 38610010 addi r3,rsp,16 +00000880: 3A801002 li r20,4098 +00000884: 4E800021 blrl +00000888: 00000888 dc.l 0x00000888 ; Invalid opcode '....' +0000088C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Decrementer" Size=0 +00000900: 7E9043A6 mtsprg0 r20 +00000904: 7EB143A6 mtsprg1 r21 +00000908: 7E800026 mfcr r20 +0000090C: 7C350B78 mr r21,rsp +00000910: 3AB5FF00 subi r21,r21,256 +00000914: 929500A8 stw r20,168(r21) +00000918: 92D50068 stw r22,104(r21) +0000091C: 92F5006C stw r23,108(r21) +00000920: 7E9042A6 mfsprg0 r20 +00000924: 92950060 stw r20,96(r21) +00000928: 7ED142A6 mfsprg1 r22 +0000092C: 92D50064 stw r22,100(r21) +00000930: 7E8802A6 mflr r20 +00000934: 929500A0 stw r20,160(r21) +00000938: 7EC902A6 mfctr r22 +0000093C: 92D5009C stw r22,156(r21) +00000940: 7E8102A6 mfxer r20 +00000944: 929500A4 stw r20,164(r21) +00000948: 7EDA02A6 mfsrr0 r22 +0000094C: 7EFB02A6 mfsrr1 r23 +00000950: 90150010 stw r0,16(r21) +00000954: 90350014 stw rsp,20(r21) +00000958: 90550018 stw r2,24(r21) +0000095C: 90350000 stw rsp,0(r21) +00000960: 7EA1AB78 mr rsp,r21 +00000964: 9075001C stw r3,28(r21) +00000968: 90950020 stw r4,32(r21) +0000096C: 90B50024 stw r5,36(r21) +00000970: 90D50028 stw r6,40(r21) +00000974: 806E8014 lwz r3,-32748(r14) +00000978: 7C6803A6 mtlr r3 +0000097C: 38610010 addi r3,rsp,16 +00000980: 3A801002 li r20,4098 +00000984: 4E800021 blrl +00000988: 00000988 dc.l 0x00000988 ; Invalid opcode '....' +0000098C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Trap_0a" Size=0 +00000A00: 7E9043A6 mtsprg0 r20 +00000A04: 7EB143A6 mtsprg1 r21 +00000A08: 7E800026 mfcr r20 +00000A0C: 7C350B78 mr r21,rsp +00000A10: 3AB5FF00 subi r21,r21,256 +00000A14: 929500A8 stw r20,168(r21) +00000A18: 92D50068 stw r22,104(r21) +00000A1C: 92F5006C stw r23,108(r21) +00000A20: 7E9042A6 mfsprg0 r20 +00000A24: 92950060 stw r20,96(r21) +00000A28: 7ED142A6 mfsprg1 r22 +00000A2C: 92D50064 stw r22,100(r21) +00000A30: 7E8802A6 mflr r20 +00000A34: 929500A0 stw r20,160(r21) +00000A38: 7EC902A6 mfctr r22 +00000A3C: 92D5009C stw r22,156(r21) +00000A40: 7E8102A6 mfxer r20 +00000A44: 929500A4 stw r20,164(r21) +00000A48: 7EDA02A6 mfsrr0 r22 +00000A4C: 7EFB02A6 mfsrr1 r23 +00000A50: 90150010 stw r0,16(r21) +00000A54: 90350014 stw rsp,20(r21) +00000A58: 90550018 stw r2,24(r21) +00000A5C: 90350000 stw rsp,0(r21) +00000A60: 7EA1AB78 mr rsp,r21 +00000A64: 9075001C stw r3,28(r21) +00000A68: 90950020 stw r4,32(r21) +00000A6C: 90B50024 stw r5,36(r21) +00000A70: 90D50028 stw r6,40(r21) +00000A74: 806E8014 lwz r3,-32748(r14) +00000A78: 7C6803A6 mtlr r3 +00000A7C: 38610010 addi r3,rsp,16 +00000A80: 3A801002 li r20,4098 +00000A84: 4E800021 blrl +00000A88: 00000A88 dc.l 0x00000a88 ; Invalid opcode '....' +00000A8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Trap_0b" Size=0 +00000B00: 7E9043A6 mtsprg0 r20 +00000B04: 7EB143A6 mtsprg1 r21 +00000B08: 7E800026 mfcr r20 +00000B0C: 7C350B78 mr r21,rsp +00000B10: 3AB5FF00 subi r21,r21,256 +00000B14: 929500A8 stw r20,168(r21) +00000B18: 92D50068 stw r22,104(r21) +00000B1C: 92F5006C stw r23,108(r21) +00000B20: 7E9042A6 mfsprg0 r20 +00000B24: 92950060 stw r20,96(r21) +00000B28: 7ED142A6 mfsprg1 r22 +00000B2C: 92D50064 stw r22,100(r21) +00000B30: 7E8802A6 mflr r20 +00000B34: 929500A0 stw r20,160(r21) +00000B38: 7EC902A6 mfctr r22 +00000B3C: 92D5009C stw r22,156(r21) +00000B40: 7E8102A6 mfxer r20 +00000B44: 929500A4 stw r20,164(r21) +00000B48: 7EDA02A6 mfsrr0 r22 +00000B4C: 7EFB02A6 mfsrr1 r23 +00000B50: 90150010 stw r0,16(r21) +00000B54: 90350014 stw rsp,20(r21) +00000B58: 90550018 stw r2,24(r21) +00000B5C: 90350000 stw rsp,0(r21) +00000B60: 7EA1AB78 mr rsp,r21 +00000B64: 9075001C stw r3,28(r21) +00000B68: 90950020 stw r4,32(r21) +00000B6C: 90B50024 stw r5,36(r21) +00000B70: 90D50028 stw r6,40(r21) +00000B74: 806E8014 lwz r3,-32748(r14) +00000B78: 7C6803A6 mtlr r3 +00000B7C: 38610010 addi r3,rsp,16 +00000B80: 3A801002 li r20,4098 +00000B84: 4E800021 blrl +00000B88: 00000B88 dc.l 0x00000b88 ; Invalid opcode '....' +00000B8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="SystemCall" Size=0 +00000C00: 7E9043A6 mtsprg0 r20 +00000C04: 7EB143A6 mtsprg1 r21 +00000C08: 7E800026 mfcr r20 +00000C0C: 7C350B78 mr r21,rsp +00000C10: 3AB5FF00 subi r21,r21,256 +00000C14: 929500A8 stw r20,168(r21) +00000C18: 92D50068 stw r22,104(r21) +00000C1C: 92F5006C stw r23,108(r21) +00000C20: 7E9042A6 mfsprg0 r20 +00000C24: 92950060 stw r20,96(r21) +00000C28: 7ED142A6 mfsprg1 r22 +00000C2C: 92D50064 stw r22,100(r21) +00000C30: 7E8802A6 mflr r20 +00000C34: 929500A0 stw r20,160(r21) +00000C38: 7EC902A6 mfctr r22 +00000C3C: 92D5009C stw r22,156(r21) +00000C40: 7E8102A6 mfxer r20 +00000C44: 929500A4 stw r20,164(r21) +00000C48: 7EDA02A6 mfsrr0 r22 +00000C4C: 7EFB02A6 mfsrr1 r23 +00000C50: 90150010 stw r0,16(r21) +00000C54: 90350014 stw rsp,20(r21) +00000C58: 90550018 stw r2,24(r21) +00000C5C: 90350000 stw rsp,0(r21) +00000C60: 7EA1AB78 mr rsp,r21 +00000C64: 9075001C stw r3,28(r21) +00000C68: 90950020 stw r4,32(r21) +00000C6C: 90B50024 stw r5,36(r21) +00000C70: 90D50028 stw r6,40(r21) +00000C74: 806E8014 lwz r3,-32748(r14) +00000C78: 7C6803A6 mtlr r3 +00000C7C: 38610010 addi r3,rsp,16 +00000C80: 3A801002 li r20,4098 +00000C84: 4E800021 blrl +00000C88: 00000C88 dc.l 0x00000c88 ; Invalid opcode '....' +00000C8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="SingleStep" Size=0 +00000D00: 7E9043A6 mtsprg0 r20 +00000D04: 7EB143A6 mtsprg1 r21 +00000D08: 7E800026 mfcr r20 +00000D0C: 7C350B78 mr r21,rsp +00000D10: 3AB5FF00 subi r21,r21,256 +00000D14: 929500A8 stw r20,168(r21) +00000D18: 92D50068 stw r22,104(r21) +00000D1C: 92F5006C stw r23,108(r21) +00000D20: 7E9042A6 mfsprg0 r20 +00000D24: 92950060 stw r20,96(r21) +00000D28: 7ED142A6 mfsprg1 r22 +00000D2C: 92D50064 stw r22,100(r21) +00000D30: 7E8802A6 mflr r20 +00000D34: 929500A0 stw r20,160(r21) +00000D38: 7EC902A6 mfctr r22 +00000D3C: 92D5009C stw r22,156(r21) +00000D40: 7E8102A6 mfxer r20 +00000D44: 929500A4 stw r20,164(r21) +00000D48: 7EDA02A6 mfsrr0 r22 +00000D4C: 7EFB02A6 mfsrr1 r23 +00000D50: 90150010 stw r0,16(r21) +00000D54: 90350014 stw rsp,20(r21) +00000D58: 90550018 stw r2,24(r21) +00000D5C: 90350000 stw rsp,0(r21) +00000D60: 7EA1AB78 mr rsp,r21 +00000D64: 9075001C stw r3,28(r21) +00000D68: 90950020 stw r4,32(r21) +00000D6C: 90B50024 stw r5,36(r21) +00000D70: 90D50028 stw r6,40(r21) +00000D74: 806E8014 lwz r3,-32748(r14) +00000D78: 7C6803A6 mtlr r3 +00000D7C: 38610010 addi r3,rsp,16 +00000D80: 3A801002 li r20,4098 +00000D84: 4E800021 blrl +00000D88: 00000D88 dc.l 0x00000d88 ; Invalid opcode '....' +00000D8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Trap_0e" Size=0 +00000E00: 7E9043A6 mtsprg0 r20 +00000E04: 7EB143A6 mtsprg1 r21 +00000E08: 7E800026 mfcr r20 +00000E0C: 7C350B78 mr r21,rsp +00000E10: 3AB5FF00 subi r21,r21,256 +00000E14: 929500A8 stw r20,168(r21) +00000E18: 92D50068 stw r22,104(r21) +00000E1C: 92F5006C stw r23,108(r21) +00000E20: 7E9042A6 mfsprg0 r20 +00000E24: 92950060 stw r20,96(r21) +00000E28: 7ED142A6 mfsprg1 r22 +00000E2C: 92D50064 stw r22,100(r21) +00000E30: 7E8802A6 mflr r20 +00000E34: 929500A0 stw r20,160(r21) +00000E38: 7EC902A6 mfctr r22 +00000E3C: 92D5009C stw r22,156(r21) +00000E40: 7E8102A6 mfxer r20 +00000E44: 929500A4 stw r20,164(r21) +00000E48: 7EDA02A6 mfsrr0 r22 +00000E4C: 7EFB02A6 mfsrr1 r23 +00000E50: 90150010 stw r0,16(r21) +00000E54: 90350014 stw rsp,20(r21) +00000E58: 90550018 stw r2,24(r21) +00000E5C: 90350000 stw rsp,0(r21) +00000E60: 7EA1AB78 mr rsp,r21 +00000E64: 9075001C stw r3,28(r21) +00000E68: 90950020 stw r4,32(r21) +00000E6C: 90B50024 stw r5,36(r21) +00000E70: 90D50028 stw r6,40(r21) +00000E74: 806E8014 lwz r3,-32748(r14) +00000E78: 7C6803A6 mtlr r3 +00000E7C: 38610010 addi r3,rsp,16 +00000E80: 3A801002 li r20,4098 +00000E84: 4E800021 blrl +00000E88: 00000E88 dc.l 0x00000e88 ; Invalid opcode '....' +00000E8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Trap_0f" Size=0 +00000F00: 7E9043A6 mtsprg0 r20 +00000F04: 7EB143A6 mtsprg1 r21 +00000F08: 7E800026 mfcr r20 +00000F0C: 7C350B78 mr r21,rsp +00000F10: 3AB5FF00 subi r21,r21,256 +00000F14: 929500A8 stw r20,168(r21) +00000F18: 92D50068 stw r22,104(r21) +00000F1C: 92F5006C stw r23,108(r21) +00000F20: 7E9042A6 mfsprg0 r20 +00000F24: 92950060 stw r20,96(r21) +00000F28: 7ED142A6 mfsprg1 r22 +00000F2C: 92D50064 stw r22,100(r21) +00000F30: 7E8802A6 mflr r20 +00000F34: 929500A0 stw r20,160(r21) +00000F38: 7EC902A6 mfctr r22 +00000F3C: 92D5009C stw r22,156(r21) +00000F40: 7E8102A6 mfxer r20 +00000F44: 929500A4 stw r20,164(r21) +00000F48: 7EDA02A6 mfsrr0 r22 +00000F4C: 7EFB02A6 mfsrr1 r23 +00000F50: 90150010 stw r0,16(r21) +00000F54: 90350014 stw rsp,20(r21) +00000F58: 90550018 stw r2,24(r21) +00000F5C: 90350000 stw rsp,0(r21) +00000F60: 7EA1AB78 mr rsp,r21 +00000F64: 9075001C stw r3,28(r21) +00000F68: 90950020 stw r4,32(r21) +00000F6C: 90B50024 stw r5,36(r21) +00000F70: 90D50028 stw r6,40(r21) +00000F74: 806E8014 lwz r3,-32748(r14) +00000F78: 7C6803A6 mtlr r3 +00000F7C: 38610010 addi r3,rsp,16 +00000F80: 3A801002 li r20,4098 +00000F84: 4E800021 blrl +00000F88: 00000F88 dc.l 0x00000f88 ; Invalid opcode '....' +00000F8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="InstructionTransMiss" Size=0 +00001000: 7E9043A6 mtsprg0 r20 +00001004: 7EB143A6 mtsprg1 r21 +00001008: 7E800026 mfcr r20 +0000100C: 7C350B78 mr r21,rsp +00001010: 3AB5FF00 subi r21,r21,256 +00001014: 929500A8 stw r20,168(r21) +00001018: 92D50068 stw r22,104(r21) +0000101C: 92F5006C stw r23,108(r21) +00001020: 7E9042A6 mfsprg0 r20 +00001024: 92950060 stw r20,96(r21) +00001028: 7ED142A6 mfsprg1 r22 +0000102C: 92D50064 stw r22,100(r21) +00001030: 7E8802A6 mflr r20 +00001034: 929500A0 stw r20,160(r21) +00001038: 7EC902A6 mfctr r22 +0000103C: 92D5009C stw r22,156(r21) +00001040: 7E8102A6 mfxer r20 +00001044: 929500A4 stw r20,164(r21) +00001048: 7EDA02A6 mfsrr0 r22 +0000104C: 7EFB02A6 mfsrr1 r23 +00001050: 90150010 stw r0,16(r21) +00001054: 90350014 stw rsp,20(r21) +00001058: 90550018 stw r2,24(r21) +0000105C: 90350000 stw rsp,0(r21) +00001060: 7EA1AB78 mr rsp,r21 +00001064: 9075001C stw r3,28(r21) +00001068: 90950020 stw r4,32(r21) +0000106C: 90B50024 stw r5,36(r21) +00001070: 90D50028 stw r6,40(r21) +00001074: 806E8014 lwz r3,-32748(r14) +00001078: 7C6803A6 mtlr r3 +0000107C: 38610010 addi r3,rsp,16 +00001080: 3A801002 li r20,4098 +00001084: 4E800021 blrl +00001088: 00001088 dc.l 0x00001088 ; Invalid opcode '....' +0000108C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="DataLoadTransMiss" Size=0 +00001100: 7E9043A6 mtsprg0 r20 +00001104: 7EB143A6 mtsprg1 r21 +00001108: 7E800026 mfcr r20 +0000110C: 7C350B78 mr r21,rsp +00001110: 3AB5FF00 subi r21,r21,256 +00001114: 929500A8 stw r20,168(r21) +00001118: 92D50068 stw r22,104(r21) +0000111C: 92F5006C stw r23,108(r21) +00001120: 7E9042A6 mfsprg0 r20 +00001124: 92950060 stw r20,96(r21) +00001128: 7ED142A6 mfsprg1 r22 +0000112C: 92D50064 stw r22,100(r21) +00001130: 7E8802A6 mflr r20 +00001134: 929500A0 stw r20,160(r21) +00001138: 7EC902A6 mfctr r22 +0000113C: 92D5009C stw r22,156(r21) +00001140: 7E8102A6 mfxer r20 +00001144: 929500A4 stw r20,164(r21) +00001148: 7EDA02A6 mfsrr0 r22 +0000114C: 7EFB02A6 mfsrr1 r23 +00001150: 90150010 stw r0,16(r21) +00001154: 90350014 stw rsp,20(r21) +00001158: 90550018 stw r2,24(r21) +0000115C: 90350000 stw rsp,0(r21) +00001160: 7EA1AB78 mr rsp,r21 +00001164: 9075001C stw r3,28(r21) +00001168: 90950020 stw r4,32(r21) +0000116C: 90B50024 stw r5,36(r21) +00001170: 90D50028 stw r6,40(r21) +00001174: 806E8014 lwz r3,-32748(r14) +00001178: 7C6803A6 mtlr r3 +0000117C: 38610010 addi r3,rsp,16 +00001180: 3A801002 li r20,4098 +00001184: 4E800021 blrl +00001188: 00001188 dc.l 0x00001188 ; Invalid opcode '....' +0000118C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="DataStoreTransMiss" Size=0 +00001200: 7E9043A6 mtsprg0 r20 +00001204: 7EB143A6 mtsprg1 r21 +00001208: 7E800026 mfcr r20 +0000120C: 7C350B78 mr r21,rsp +00001210: 3AB5FF00 subi r21,r21,256 +00001214: 929500A8 stw r20,168(r21) +00001218: 92D50068 stw r22,104(r21) +0000121C: 92F5006C stw r23,108(r21) +00001220: 7E9042A6 mfsprg0 r20 +00001224: 92950060 stw r20,96(r21) +00001228: 7ED142A6 mfsprg1 r22 +0000122C: 92D50064 stw r22,100(r21) +00001230: 7E8802A6 mflr r20 +00001234: 929500A0 stw r20,160(r21) +00001238: 7EC902A6 mfctr r22 +0000123C: 92D5009C stw r22,156(r21) +00001240: 7E8102A6 mfxer r20 +00001244: 929500A4 stw r20,164(r21) +00001248: 7EDA02A6 mfsrr0 r22 +0000124C: 7EFB02A6 mfsrr1 r23 +00001250: 90150010 stw r0,16(r21) +00001254: 90350014 stw rsp,20(r21) +00001258: 90550018 stw r2,24(r21) +0000125C: 90350000 stw rsp,0(r21) +00001260: 7EA1AB78 mr rsp,r21 +00001264: 9075001C stw r3,28(r21) +00001268: 90950020 stw r4,32(r21) +0000126C: 90B50024 stw r5,36(r21) +00001270: 90D50028 stw r6,40(r21) +00001274: 806E8014 lwz r3,-32748(r14) +00001278: 7C6803A6 mtlr r3 +0000127C: 38610010 addi r3,rsp,16 +00001280: 3A801002 li r20,4098 +00001284: 4E800021 blrl +00001288: 00001288 dc.l 0x00001288 ; Invalid opcode '....' +0000128C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="InstructionBreakpoint" Size=0 +00001300: 7E9043A6 mtsprg0 r20 +00001304: 7EB143A6 mtsprg1 r21 +00001308: 7E800026 mfcr r20 +0000130C: 7C350B78 mr r21,rsp +00001310: 3AB5FF00 subi r21,r21,256 +00001314: 929500A8 stw r20,168(r21) +00001318: 92D50068 stw r22,104(r21) +0000131C: 92F5006C stw r23,108(r21) +00001320: 7E9042A6 mfsprg0 r20 +00001324: 92950060 stw r20,96(r21) +00001328: 7ED142A6 mfsprg1 r22 +0000132C: 92D50064 stw r22,100(r21) +00001330: 7E8802A6 mflr r20 +00001334: 929500A0 stw r20,160(r21) +00001338: 7EC902A6 mfctr r22 +0000133C: 92D5009C stw r22,156(r21) +00001340: 7E8102A6 mfxer r20 +00001344: 929500A4 stw r20,164(r21) +00001348: 7EDA02A6 mfsrr0 r22 +0000134C: 7EFB02A6 mfsrr1 r23 +00001350: 90150010 stw r0,16(r21) +00001354: 90350014 stw rsp,20(r21) +00001358: 90550018 stw r2,24(r21) +0000135C: 90350000 stw rsp,0(r21) +00001360: 7EA1AB78 mr rsp,r21 +00001364: 9075001C stw r3,28(r21) +00001368: 90950020 stw r4,32(r21) +0000136C: 90B50024 stw r5,36(r21) +00001370: 90D50028 stw r6,40(r21) +00001374: 806E8014 lwz r3,-32748(r14) +00001378: 7C6803A6 mtlr r3 +0000137C: 38610010 addi r3,rsp,16 +00001380: 3A801002 li r20,4098 +00001384: 4E800021 blrl +00001388: 00001388 dc.l 0x00001388 ; Invalid opcode '....' +0000138C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="SysManageInt" Size=0 +00001400: 7E9043A6 mtsprg0 r20 +00001404: 7EB143A6 mtsprg1 r21 +00001408: 7E800026 mfcr r20 +0000140C: 7C350B78 mr r21,rsp +00001410: 3AB5FF00 subi r21,r21,256 +00001414: 929500A8 stw r20,168(r21) +00001418: 92D50068 stw r22,104(r21) +0000141C: 92F5006C stw r23,108(r21) +00001420: 7E9042A6 mfsprg0 r20 +00001424: 92950060 stw r20,96(r21) +00001428: 7ED142A6 mfsprg1 r22 +0000142C: 92D50064 stw r22,100(r21) +00001430: 7E8802A6 mflr r20 +00001434: 929500A0 stw r20,160(r21) +00001438: 7EC902A6 mfctr r22 +0000143C: 92D5009C stw r22,156(r21) +00001440: 7E8102A6 mfxer r20 +00001444: 929500A4 stw r20,164(r21) +00001448: 7EDA02A6 mfsrr0 r22 +0000144C: 7EFB02A6 mfsrr1 r23 +00001450: 90150010 stw r0,16(r21) +00001454: 90350014 stw rsp,20(r21) +00001458: 90550018 stw r2,24(r21) +0000145C: 90350000 stw rsp,0(r21) +00001460: 7EA1AB78 mr rsp,r21 +00001464: 9075001C stw r3,28(r21) +00001468: 90950020 stw r4,32(r21) +0000146C: 90B50024 stw r5,36(r21) +00001470: 90D50028 stw r6,40(r21) +00001474: 806E8014 lwz r3,-32748(r14) +00001478: 7C6803A6 mtlr r3 +0000147C: 38610010 addi r3,rsp,16 +00001480: 3A801002 li r20,4098 +00001484: 4E800021 blrl +00001488: 00001488 dc.l 0x00001488 ; Invalid opcode '....' +0000148C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Reserved5" Size=0 +00001500: 7E9043A6 mtsprg0 r20 +00001504: 7EB143A6 mtsprg1 r21 +00001508: 7E800026 mfcr r20 +0000150C: 7C350B78 mr r21,rsp +00001510: 3AB5FF00 subi r21,r21,256 +00001514: 929500A8 stw r20,168(r21) +00001518: 92D50068 stw r22,104(r21) +0000151C: 92F5006C stw r23,108(r21) +00001520: 7E9042A6 mfsprg0 r20 +00001524: 92950060 stw r20,96(r21) +00001528: 7ED142A6 mfsprg1 r22 +0000152C: 92D50064 stw r22,100(r21) +00001530: 7E8802A6 mflr r20 +00001534: 929500A0 stw r20,160(r21) +00001538: 7EC902A6 mfctr r22 +0000153C: 92D5009C stw r22,156(r21) +00001540: 7E8102A6 mfxer r20 +00001544: 929500A4 stw r20,164(r21) +00001548: 7EDA02A6 mfsrr0 r22 +0000154C: 7EFB02A6 mfsrr1 r23 +00001550: 90150010 stw r0,16(r21) +00001554: 90350014 stw rsp,20(r21) +00001558: 90550018 stw r2,24(r21) +0000155C: 90350000 stw rsp,0(r21) +00001560: 7EA1AB78 mr rsp,r21 +00001564: 9075001C stw r3,28(r21) +00001568: 90950020 stw r4,32(r21) +0000156C: 90B50024 stw r5,36(r21) +00001570: 90D50028 stw r6,40(r21) +00001574: 806E8014 lwz r3,-32748(r14) +00001578: 7C6803A6 mtlr r3 +0000157C: 38610010 addi r3,rsp,16 +00001580: 3A801002 li r20,4098 +00001584: 4E800021 blrl +00001588: 00001588 dc.l 0x00001588 ; Invalid opcode '....' +0000158C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Reserved6" Size=0 +00001600: 7E9043A6 mtsprg0 r20 +00001604: 7EB143A6 mtsprg1 r21 +00001608: 7E800026 mfcr r20 +0000160C: 7C350B78 mr r21,rsp +00001610: 3AB5FF00 subi r21,r21,256 +00001614: 929500A8 stw r20,168(r21) +00001618: 92D50068 stw r22,104(r21) +0000161C: 92F5006C stw r23,108(r21) +00001620: 7E9042A6 mfsprg0 r20 +00001624: 92950060 stw r20,96(r21) +00001628: 7ED142A6 mfsprg1 r22 +0000162C: 92D50064 stw r22,100(r21) +00001630: 7E8802A6 mflr r20 +00001634: 929500A0 stw r20,160(r21) +00001638: 7EC902A6 mfctr r22 +0000163C: 92D5009C stw r22,156(r21) +00001640: 7E8102A6 mfxer r20 +00001644: 929500A4 stw r20,164(r21) +00001648: 7EDA02A6 mfsrr0 r22 +0000164C: 7EFB02A6 mfsrr1 r23 +00001650: 90150010 stw r0,16(r21) +00001654: 90350014 stw rsp,20(r21) +00001658: 90550018 stw r2,24(r21) +0000165C: 90350000 stw rsp,0(r21) +00001660: 7EA1AB78 mr rsp,r21 +00001664: 9075001C stw r3,28(r21) +00001668: 90950020 stw r4,32(r21) +0000166C: 90B50024 stw r5,36(r21) +00001670: 90D50028 stw r6,40(r21) +00001674: 806E8014 lwz r3,-32748(r14) +00001678: 7C6803A6 mtlr r3 +0000167C: 38610010 addi r3,rsp,16 +00001680: 3A801002 li r20,4098 +00001684: 4E800021 blrl +00001688: 00001688 dc.l 0x00001688 ; Invalid opcode '....' +0000168C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Reserved7" Size=0 +00001700: 7E9043A6 mtsprg0 r20 +00001704: 7EB143A6 mtsprg1 r21 +00001708: 7E800026 mfcr r20 +0000170C: 7C350B78 mr r21,rsp +00001710: 3AB5FF00 subi r21,r21,256 +00001714: 929500A8 stw r20,168(r21) +00001718: 92D50068 stw r22,104(r21) +0000171C: 92F5006C stw r23,108(r21) +00001720: 7E9042A6 mfsprg0 r20 +00001724: 92950060 stw r20,96(r21) +00001728: 7ED142A6 mfsprg1 r22 +0000172C: 92D50064 stw r22,100(r21) +00001730: 7E8802A6 mflr r20 +00001734: 929500A0 stw r20,160(r21) +00001738: 7EC902A6 mfctr r22 +0000173C: 92D5009C stw r22,156(r21) +00001740: 7E8102A6 mfxer r20 +00001744: 929500A4 stw r20,164(r21) +00001748: 7EDA02A6 mfsrr0 r22 +0000174C: 7EFB02A6 mfsrr1 r23 +00001750: 90150010 stw r0,16(r21) +00001754: 90350014 stw rsp,20(r21) +00001758: 90550018 stw r2,24(r21) +0000175C: 90350000 stw rsp,0(r21) +00001760: 7EA1AB78 mr rsp,r21 +00001764: 9075001C stw r3,28(r21) +00001768: 90950020 stw r4,32(r21) +0000176C: 90B50024 stw r5,36(r21) +00001770: 90D50028 stw r6,40(r21) +00001774: 806E8014 lwz r3,-32748(r14) +00001778: 7C6803A6 mtlr r3 +0000177C: 38610010 addi r3,rsp,16 +00001780: 3A801002 li r20,4098 +00001784: 4E800021 blrl +00001788: 00001788 dc.l 0x00001788 ; Invalid opcode '....' +0000178C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Reserved8" Size=0 +00001800: 7E9043A6 mtsprg0 r20 +00001804: 7EB143A6 mtsprg1 r21 +00001808: 7E800026 mfcr r20 +0000180C: 7C350B78 mr r21,rsp +00001810: 3AB5FF00 subi r21,r21,256 +00001814: 929500A8 stw r20,168(r21) +00001818: 92D50068 stw r22,104(r21) +0000181C: 92F5006C stw r23,108(r21) +00001820: 7E9042A6 mfsprg0 r20 +00001824: 92950060 stw r20,96(r21) +00001828: 7ED142A6 mfsprg1 r22 +0000182C: 92D50064 stw r22,100(r21) +00001830: 7E8802A6 mflr r20 +00001834: 929500A0 stw r20,160(r21) +00001838: 7EC902A6 mfctr r22 +0000183C: 92D5009C stw r22,156(r21) +00001840: 7E8102A6 mfxer r20 +00001844: 929500A4 stw r20,164(r21) +00001848: 7EDA02A6 mfsrr0 r22 +0000184C: 7EFB02A6 mfsrr1 r23 +00001850: 90150010 stw r0,16(r21) +00001854: 90350014 stw rsp,20(r21) +00001858: 90550018 stw r2,24(r21) +0000185C: 90350000 stw rsp,0(r21) +00001860: 7EA1AB78 mr rsp,r21 +00001864: 9075001C stw r3,28(r21) +00001868: 90950020 stw r4,32(r21) +0000186C: 90B50024 stw r5,36(r21) +00001870: 90D50028 stw r6,40(r21) +00001874: 806E8014 lwz r3,-32748(r14) +00001878: 7C6803A6 mtlr r3 +0000187C: 38610010 addi r3,rsp,16 +00001880: 3A801002 li r20,4098 +00001884: 4E800021 blrl +00001888: 00001888 dc.l 0x00001888 ; Invalid opcode '....' +0000188C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="Reserved9" Size=0 +00001900: 7E9043A6 mtsprg0 r20 +00001904: 7EB143A6 mtsprg1 r21 +00001908: 7E800026 mfcr r20 +0000190C: 7C350B78 mr r21,rsp +00001910: 3AB5FF00 subi r21,r21,256 +00001914: 929500A8 stw r20,168(r21) +00001918: 92D50068 stw r22,104(r21) +0000191C: 92F5006C stw r23,108(r21) +00001920: 7E9042A6 mfsprg0 r20 +00001924: 92950060 stw r20,96(r21) +00001928: 7ED142A6 mfsprg1 r22 +0000192C: 92D50064 stw r22,100(r21) +00001930: 7E8802A6 mflr r20 +00001934: 929500A0 stw r20,160(r21) +00001938: 7EC902A6 mfctr r22 +0000193C: 92D5009C stw r22,156(r21) +00001940: 7E8102A6 mfxer r20 +00001944: 929500A4 stw r20,164(r21) +00001948: 7EDA02A6 mfsrr0 r22 +0000194C: 7EFB02A6 mfsrr1 r23 +00001950: 90150010 stw r0,16(r21) +00001954: 90350014 stw rsp,20(r21) +00001958: 90550018 stw r2,24(r21) +0000195C: 90350000 stw rsp,0(r21) +00001960: 7EA1AB78 mr rsp,r21 +00001964: 9075001C stw r3,28(r21) +00001968: 90950020 stw r4,32(r21) +0000196C: 90B50024 stw r5,36(r21) +00001970: 90D50028 stw r6,40(r21) +00001974: 806E8014 lwz r3,-32748(r14) +00001978: 7C6803A6 mtlr r3 +0000197C: 38610010 addi r3,rsp,16 +00001980: 3A801002 li r20,4098 +00001984: 4E800021 blrl +00001988: 00001988 dc.l 0x00001988 ; Invalid opcode '....' +0000198C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="ReservedA" Size=0 +00001A00: 7E9043A6 mtsprg0 r20 +00001A04: 7EB143A6 mtsprg1 r21 +00001A08: 7E800026 mfcr r20 +00001A0C: 7C350B78 mr r21,rsp +00001A10: 3AB5FF00 subi r21,r21,256 +00001A14: 929500A8 stw r20,168(r21) +00001A18: 92D50068 stw r22,104(r21) +00001A1C: 92F5006C stw r23,108(r21) +00001A20: 7E9042A6 mfsprg0 r20 +00001A24: 92950060 stw r20,96(r21) +00001A28: 7ED142A6 mfsprg1 r22 +00001A2C: 92D50064 stw r22,100(r21) +00001A30: 7E8802A6 mflr r20 +00001A34: 929500A0 stw r20,160(r21) +00001A38: 7EC902A6 mfctr r22 +00001A3C: 92D5009C stw r22,156(r21) +00001A40: 7E8102A6 mfxer r20 +00001A44: 929500A4 stw r20,164(r21) +00001A48: 7EDA02A6 mfsrr0 r22 +00001A4C: 7EFB02A6 mfsrr1 r23 +00001A50: 90150010 stw r0,16(r21) +00001A54: 90350014 stw rsp,20(r21) +00001A58: 90550018 stw r2,24(r21) +00001A5C: 90350000 stw rsp,0(r21) +00001A60: 7EA1AB78 mr rsp,r21 +00001A64: 9075001C stw r3,28(r21) +00001A68: 90950020 stw r4,32(r21) +00001A6C: 90B50024 stw r5,36(r21) +00001A70: 90D50028 stw r6,40(r21) +00001A74: 806E8014 lwz r3,-32748(r14) +00001A78: 7C6803A6 mtlr r3 +00001A7C: 38610010 addi r3,rsp,16 +00001A80: 3A801002 li r20,4098 +00001A84: 4E800021 blrl +00001A88: 00001A88 dc.l 0x00001a88 ; Invalid opcode '....' +00001A8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="ReservedB" Size=0 +00001B00: 7E9043A6 mtsprg0 r20 +00001B04: 7EB143A6 mtsprg1 r21 +00001B08: 7E800026 mfcr r20 +00001B0C: 7C350B78 mr r21,rsp +00001B10: 3AB5FF00 subi r21,r21,256 +00001B14: 929500A8 stw r20,168(r21) +00001B18: 92D50068 stw r22,104(r21) +00001B1C: 92F5006C stw r23,108(r21) +00001B20: 7E9042A6 mfsprg0 r20 +00001B24: 92950060 stw r20,96(r21) +00001B28: 7ED142A6 mfsprg1 r22 +00001B2C: 92D50064 stw r22,100(r21) +00001B30: 7E8802A6 mflr r20 +00001B34: 929500A0 stw r20,160(r21) +00001B38: 7EC902A6 mfctr r22 +00001B3C: 92D5009C stw r22,156(r21) +00001B40: 7E8102A6 mfxer r20 +00001B44: 929500A4 stw r20,164(r21) +00001B48: 7EDA02A6 mfsrr0 r22 +00001B4C: 7EFB02A6 mfsrr1 r23 +00001B50: 90150010 stw r0,16(r21) +00001B54: 90350014 stw rsp,20(r21) +00001B58: 90550018 stw r2,24(r21) +00001B5C: 90350000 stw rsp,0(r21) +00001B60: 7EA1AB78 mr rsp,r21 +00001B64: 9075001C stw r3,28(r21) +00001B68: 90950020 stw r4,32(r21) +00001B6C: 90B50024 stw r5,36(r21) +00001B70: 90D50028 stw r6,40(r21) +00001B74: 806E8014 lwz r3,-32748(r14) +00001B78: 7C6803A6 mtlr r3 +00001B7C: 38610010 addi r3,rsp,16 +00001B80: 3A801002 li r20,4098 +00001B84: 4E800021 blrl +00001B88: 00001B88 dc.l 0x00001b88 ; Invalid opcode '....' +00001B8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="ReservedC" Size=0 +00001C00: 7E9043A6 mtsprg0 r20 +00001C04: 7EB143A6 mtsprg1 r21 +00001C08: 7E800026 mfcr r20 +00001C0C: 7C350B78 mr r21,rsp +00001C10: 3AB5FF00 subi r21,r21,256 +00001C14: 929500A8 stw r20,168(r21) +00001C18: 92D50068 stw r22,104(r21) +00001C1C: 92F5006C stw r23,108(r21) +00001C20: 7E9042A6 mfsprg0 r20 +00001C24: 92950060 stw r20,96(r21) +00001C28: 7ED142A6 mfsprg1 r22 +00001C2C: 92D50064 stw r22,100(r21) +00001C30: 7E8802A6 mflr r20 +00001C34: 929500A0 stw r20,160(r21) +00001C38: 7EC902A6 mfctr r22 +00001C3C: 92D5009C stw r22,156(r21) +00001C40: 7E8102A6 mfxer r20 +00001C44: 929500A4 stw r20,164(r21) +00001C48: 7EDA02A6 mfsrr0 r22 +00001C4C: 7EFB02A6 mfsrr1 r23 +00001C50: 90150010 stw r0,16(r21) +00001C54: 90350014 stw rsp,20(r21) +00001C58: 90550018 stw r2,24(r21) +00001C5C: 90350000 stw rsp,0(r21) +00001C60: 7EA1AB78 mr rsp,r21 +00001C64: 9075001C stw r3,28(r21) +00001C68: 90950020 stw r4,32(r21) +00001C6C: 90B50024 stw r5,36(r21) +00001C70: 90D50028 stw r6,40(r21) +00001C74: 806E8014 lwz r3,-32748(r14) +00001C78: 7C6803A6 mtlr r3 +00001C7C: 38610010 addi r3,rsp,16 +00001C80: 3A801002 li r20,4098 +00001C84: 4E800021 blrl +00001C88: 00001C88 dc.l 0x00001c88 ; Invalid opcode '....' +00001C8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="ReservedD" Size=0 +00001D00: 7E9043A6 mtsprg0 r20 +00001D04: 7EB143A6 mtsprg1 r21 +00001D08: 7E800026 mfcr r20 +00001D0C: 7C350B78 mr r21,rsp +00001D10: 3AB5FF00 subi r21,r21,256 +00001D14: 929500A8 stw r20,168(r21) +00001D18: 92D50068 stw r22,104(r21) +00001D1C: 92F5006C stw r23,108(r21) +00001D20: 7E9042A6 mfsprg0 r20 +00001D24: 92950060 stw r20,96(r21) +00001D28: 7ED142A6 mfsprg1 r22 +00001D2C: 92D50064 stw r22,100(r21) +00001D30: 7E8802A6 mflr r20 +00001D34: 929500A0 stw r20,160(r21) +00001D38: 7EC902A6 mfctr r22 +00001D3C: 92D5009C stw r22,156(r21) +00001D40: 7E8102A6 mfxer r20 +00001D44: 929500A4 stw r20,164(r21) +00001D48: 7EDA02A6 mfsrr0 r22 +00001D4C: 7EFB02A6 mfsrr1 r23 +00001D50: 90150010 stw r0,16(r21) +00001D54: 90350014 stw rsp,20(r21) +00001D58: 90550018 stw r2,24(r21) +00001D5C: 90350000 stw rsp,0(r21) +00001D60: 7EA1AB78 mr rsp,r21 +00001D64: 9075001C stw r3,28(r21) +00001D68: 90950020 stw r4,32(r21) +00001D6C: 90B50024 stw r5,36(r21) +00001D70: 90D50028 stw r6,40(r21) +00001D74: 806E8014 lwz r3,-32748(r14) +00001D78: 7C6803A6 mtlr r3 +00001D7C: 38610010 addi r3,rsp,16 +00001D80: 3A801002 li r20,4098 +00001D84: 4E800021 blrl +00001D88: 00001D88 dc.l 0x00001d88 ; Invalid opcode '....' +00001D8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="ReservedE" Size=0 +00001E00: 7E9043A6 mtsprg0 r20 +00001E04: 7EB143A6 mtsprg1 r21 +00001E08: 7E800026 mfcr r20 +00001E0C: 7C350B78 mr r21,rsp +00001E10: 3AB5FF00 subi r21,r21,256 +00001E14: 929500A8 stw r20,168(r21) +00001E18: 92D50068 stw r22,104(r21) +00001E1C: 92F5006C stw r23,108(r21) +00001E20: 7E9042A6 mfsprg0 r20 +00001E24: 92950060 stw r20,96(r21) +00001E28: 7ED142A6 mfsprg1 r22 +00001E2C: 92D50064 stw r22,100(r21) +00001E30: 7E8802A6 mflr r20 +00001E34: 929500A0 stw r20,160(r21) +00001E38: 7EC902A6 mfctr r22 +00001E3C: 92D5009C stw r22,156(r21) +00001E40: 7E8102A6 mfxer r20 +00001E44: 929500A4 stw r20,164(r21) +00001E48: 7EDA02A6 mfsrr0 r22 +00001E4C: 7EFB02A6 mfsrr1 r23 +00001E50: 90150010 stw r0,16(r21) +00001E54: 90350014 stw rsp,20(r21) +00001E58: 90550018 stw r2,24(r21) +00001E5C: 90350000 stw rsp,0(r21) +00001E60: 7EA1AB78 mr rsp,r21 +00001E64: 9075001C stw r3,28(r21) +00001E68: 90950020 stw r4,32(r21) +00001E6C: 90B50024 stw r5,36(r21) +00001E70: 90D50028 stw r6,40(r21) +00001E74: 806E8014 lwz r3,-32748(r14) +00001E78: 7C6803A6 mtlr r3 +00001E7C: 38610010 addi r3,rsp,16 +00001E80: 3A801002 li r20,4098 +00001E84: 4E800021 blrl +00001E88: 00001E88 dc.l 0x00001e88 ; Invalid opcode '....' +00001E8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="ReservedF" Size=0 +00001F00: 7E9043A6 mtsprg0 r20 +00001F04: 7EB143A6 mtsprg1 r21 +00001F08: 7E800026 mfcr r20 +00001F0C: 7C350B78 mr r21,rsp +00001F10: 3AB5FF00 subi r21,r21,256 +00001F14: 929500A8 stw r20,168(r21) +00001F18: 92D50068 stw r22,104(r21) +00001F1C: 92F5006C stw r23,108(r21) +00001F20: 7E9042A6 mfsprg0 r20 +00001F24: 92950060 stw r20,96(r21) +00001F28: 7ED142A6 mfsprg1 r22 +00001F2C: 92D50064 stw r22,100(r21) +00001F30: 7E8802A6 mflr r20 +00001F34: 929500A0 stw r20,160(r21) +00001F38: 7EC902A6 mfctr r22 +00001F3C: 92D5009C stw r22,156(r21) +00001F40: 7E8102A6 mfxer r20 +00001F44: 929500A4 stw r20,164(r21) +00001F48: 7EDA02A6 mfsrr0 r22 +00001F4C: 7EFB02A6 mfsrr1 r23 +00001F50: 90150010 stw r0,16(r21) +00001F54: 90350014 stw rsp,20(r21) +00001F58: 90550018 stw r2,24(r21) +00001F5C: 90350000 stw rsp,0(r21) +00001F60: 7EA1AB78 mr rsp,r21 +00001F64: 9075001C stw r3,28(r21) +00001F68: 90950020 stw r4,32(r21) +00001F6C: 90B50024 stw r5,36(r21) +00001F70: 90D50028 stw r6,40(r21) +00001F74: 806E8014 lwz r3,-32748(r14) +00001F78: 7C6803A6 mtlr r3 +00001F7C: 38610010 addi r3,rsp,16 +00001F80: 3A801002 li r20,4098 +00001F84: 4E800021 blrl +00001F88: 00001F88 dc.l 0x00001f88 ; Invalid opcode '....' +00001F8C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_LOCAL_CODE Name="RunModeTrace" Size=0 +00002000: 7E9043A6 mtsprg0 r20 +00002004: 7EB143A6 mtsprg1 r21 +00002008: 7E800026 mfcr r20 +0000200C: 7C350B78 mr r21,rsp +00002010: 3AB5FF00 subi r21,r21,256 +00002014: 929500A8 stw r20,168(r21) +00002018: 92D50068 stw r22,104(r21) +0000201C: 92F5006C stw r23,108(r21) +00002020: 7E9042A6 mfsprg0 r20 +00002024: 92950060 stw r20,96(r21) +00002028: 7ED142A6 mfsprg1 r22 +0000202C: 92D50064 stw r22,100(r21) +00002030: 7E8802A6 mflr r20 +00002034: 929500A0 stw r20,160(r21) +00002038: 7EC902A6 mfctr r22 +0000203C: 92D5009C stw r22,156(r21) +00002040: 7E8102A6 mfxer r20 +00002044: 929500A4 stw r20,164(r21) +00002048: 7EDA02A6 mfsrr0 r22 +0000204C: 7EFB02A6 mfsrr1 r23 +00002050: 90150010 stw r0,16(r21) +00002054: 90350014 stw rsp,20(r21) +00002058: 90550018 stw r2,24(r21) +0000205C: 90350000 stw rsp,0(r21) +00002060: 7EA1AB78 mr rsp,r21 +00002064: 9075001C stw r3,28(r21) +00002068: 90950020 stw r4,32(r21) +0000206C: 90B50024 stw r5,36(r21) +00002070: 90D50028 stw r6,40(r21) +00002074: 806E8014 lwz r3,-32748(r14) +00002078: 7C6803A6 mtlr r3 +0000207C: 38610010 addi r3,rsp,16 +00002080: 3A801002 li r20,4098 +00002084: 4E800021 blrl +00002088: 00002088 dc.l 0x00002088 ; Invalid opcode '.. .' +0000208C: 0000309C dc.l 0x0000309c ; Invalid opcode '..0.' + +Hunk: Kind=HUNK_GLOBAL_CODE Name="_end_of_vectors" Size=0 + +Hunk: Kind=HUNK_GLOBAL_CODE Name="transfer_to_handler" Size=0 +00003000: 92D50090 stw r22,144(r21) +00003004: 3EC00004 lis r22,4 +00003008: 7EF7B078 andc r23,r23,r22 +0000300C: 92F50094 stw r23,148(r21) +00003010: 90F5002C stw r7,44(r21) +00003014: 91150030 stw r8,48(r21) +00003018: 91350034 stw r9,52(r21) +0000301C: 91550038 stw r10,56(r21) +00003020: 9175003C stw r11,60(r21) +00003024: 91950040 stw r12,64(r21) +00003028: 91B50044 stw r13,68(r21) +0000302C: 91D50048 stw r14,72(r21) +00003030: 91F5004C stw r15,76(r21) +00003034: 92150050 stw r16,80(r21) +00003038: 92350054 stw r17,84(r21) +0000303C: 92550058 stw r18,88(r21) +00003040: 9275005C stw r19,92(r21) +00003044: 93150070 stw r24,112(r21) +00003048: 93350074 stw r25,116(r21) +0000304C: 93550078 stw r26,120(r21) +00003050: 9375007C stw r27,124(r21) +00003054: 93950080 stw r28,128(r21) +00003058: 93B50084 stw r29,132(r21) +0000305C: 93D50088 stw r30,136(r21) +00003060: 93F5008C stw r31,140(r21) +00003064: 7EE802A6 mflr r23 +00003068: 72F83F00 andi. r24,r23,0x3f00 +0000306C: 931500B0 stw r24,176(r21) +00003070: 3AC00000 li r22,0 +00003074: 92D500BC stw r22,188(r21) +00003078: 7ED243A6 mtsprg2 r22 +0000307C: 83170000 lwz r24,0(r23) +00003080: 82F70004 lwz r23,4(r23) +00003084: 7F1A03A6 mtsrr0 r24 +00003088: 7E9B03A6 mtsrr1 r20 +0000308C: 7EE803A6 mtlr r23 +00003090: 7C0004AC sync +00003094: 4C00012C isync +00003098: 4C000064 rfi + +Hunk: Kind=HUNK_LOCAL_CODE Name="int_return" Size=0 +0000309C: 7FA000A6 mfmsr r29 +000030A0: 38800000 li r4,0 +000030A4: 60848000 ori r4,r4,0x8000 +000030A8: 7FBD2078 andc r29,r29,r4 +000030AC: 7C0004AC sync +000030B0: 4C00012C isync +000030B4: 7FA00124 mtmsr r29 +000030B8: 7C0004AC sync +000030BC: 4C00012C isync +000030C0: 8041009C lwz r2,156(rsp) +000030C4: 800100A0 lwz r0,160(rsp) +000030C8: 7C4903A6 mtctr r2 +000030CC: 7C0803A6 mtlr r0 +000030D0: 804100A4 lwz r2,164(rsp) +000030D4: 800100A8 lwz r0,168(rsp) +000030D8: 7C4103A6 mtxer r2 +000030DC: 7C0FF120 mtcrf 0xff,r0 +000030E0: 8061001C lwz r3,28(rsp) +000030E4: 80810020 lwz r4,32(rsp) +000030E8: 80A10024 lwz r5,36(rsp) +000030EC: 80C10028 lwz r6,40(rsp) +000030F0: 80E1002C lwz r7,44(rsp) +000030F4: 81010030 lwz r8,48(rsp) +000030F8: 81210034 lwz r9,52(rsp) +000030FC: 81410038 lwz r10,56(rsp) +00003100: 8161003C lwz r11,60(rsp) +00003104: 81810040 lwz r12,64(rsp) +00003108: 81A10044 lwz r13,68(rsp) +0000310C: 81C10048 lwz r14,72(rsp) +00003110: 81E1004C lwz r15,76(rsp) +00003114: 82010050 lwz r16,80(rsp) +00003118: 82210054 lwz r17,84(rsp) +0000311C: 82410058 lwz r18,88(rsp) +00003120: 8261005C lwz r19,92(rsp) +00003124: 82810060 lwz r20,96(rsp) +00003128: 82A10064 lwz r21,100(rsp) +0000312C: 82C10068 lwz r22,104(rsp) +00003130: 82E1006C lwz r23,108(rsp) +00003134: 83010070 lwz r24,112(rsp) +00003138: 83210074 lwz r25,116(rsp) +0000313C: 83410078 lwz r26,120(rsp) +00003140: 8361007C lwz r27,124(rsp) +00003144: 83810080 lwz r28,128(rsp) +00003148: 83A10084 lwz r29,132(rsp) +0000314C: 83C10088 lwz r30,136(rsp) +00003150: 83E1008C lwz r31,140(rsp) +00003154: 80410090 lwz r2,144(rsp) +00003158: 80010094 lwz r0,148(rsp) +0000315C: 7C5A03A6 mtsrr0 r2 +00003160: 7C1B03A6 mtsrr1 r0 +00003164: 80010010 lwz r0,16(rsp) +00003168: 80410018 lwz r2,24(rsp) +0000316C: 80210014 lwz rsp,20(rsp) +00003170: 7C0004AC sync +00003174: 4C00012C isync +00003178: 4C000064 rfi + +Hunk: Kind=HUNK_GLOBAL_CODE Name="icache_enable" Size=0 +0000317C: 7CB0FAA6 mfdbsr r5 +00003180: 60A58800 ori r5,r5,0x8800 +00003184: 3CC0FFFF lis r6,-1 +00003188: 60C6F7FF ori r6,r6,0xf7ff +0000318C: 7CA63038 and r6,r5,r6 +00003190: 7C0004AC sync +00003194: 7CB0FBA6 mtdbsr r5 +00003198: 7CD0FBA6 mtdbsr r6 +0000319C: 4C00012C isync +000031A0: 7C0004AC sync +000031A4: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="icache_disable" Size=0 +000031A8: 7CB0FAA6 mfdbsr r5 +000031AC: 3CC0FFFF lis r6,-1 +000031B0: 60C67FFF ori r6,r6,0x7fff +000031B4: 7CA53038 and r5,r5,r6 +000031B8: 7C0004AC sync +000031BC: 7CB0FBA6 mtdbsr r5 +000031C0: 4C00012C isync +000031C4: 7C0004AC sync +000031C8: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="icache_status" Size=0 +000031CC: 7C70FAA6 mfdbsr r3 +000031D0: 54638BFE srwi r3,r3,15 +000031D4: 70630001 andi. r3,r3,0x0001 +000031D8: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="dcache_enable" Size=0 +000031DC: 7CB0FAA6 mfdbsr r5 +000031E0: 60A54400 ori r5,r5,0x4400 +000031E4: 7C9F42A6 mfpvr r4 +000031E8: 7C838670 srawi r3,r4,16 +000031EC: 2C03000C cmpwi r3,0x000c +000031F0: 40820008 bne *+8 ; 0x000031F8 +000031F4: 60A50040 ori r5,r5,0x0040 + +Hunk: Kind=HUNK_LOCAL_CODE Name="NotMax" Size=0 +000031F8: 3CC0FFFF lis r6,-1 +000031FC: 60C6FBFF ori r6,r6,0xfbff +00003200: 7CA63038 and r6,r5,r6 +00003204: 7C0004AC sync +00003208: 7CB0FBA6 mtdbsr r5 +0000320C: 7CD0FBA6 mtdbsr r6 +00003210: 4C00012C isync +00003214: 7C0004AC sync +00003218: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="dcache_disable" Size=0 +0000321C: 7CB0FAA6 mfdbsr r5 +00003220: 3CC0FFFF lis r6,-1 +00003224: 60C6BFFF ori r6,r6,0xbfff +00003228: 7CA53038 and r5,r5,r6 +0000322C: 7C0004AC sync +00003230: 7CB0FBA6 mtdbsr r5 +00003234: 4C00012C isync +00003238: 7C0004AC sync +0000323C: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="dcache_status" Size=0 +00003240: 7C70FAA6 mfdbsr r3 +00003244: 546393BE srwi r3,r3,14 +00003248: 70630001 andi. r3,r3,0x0001 +0000324C: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="dc_read" Size=0 +00003250: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="get_pvr" Size=0 +00003254: 7C7F42A6 mfpvr r3 +00003258: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="udelay" Size=0 +0000325C: 1C832710 mulli r4,r3,10000 +00003260: 38A00C35 li r5,3125 +00003264: 7C842BD6 divw r4,r4,r5 +00003268: 7CAD42E6 mftbu r5 +0000326C: 7CCC42E6 mftb r6 +00003270: 7CED42E6 mftbu r7 +00003274: 7C053800 cmpw r5,r7 +00003278: 4082FFF0 bne *-16 ; 0x00003268 +0000327C: 7D262014 addc r9,r6,r4 +00003280: 7D050194 addze r8,r5 +00003284: 7CAD42E6 mftbu r5 +00003288: 7C054000 cmpw r5,r8 +0000328C: 4180FFF8 blt *-8 ; 0x00003284 +00003290: 41810010 bgt *+16 ; 0x000032A0 +00003294: 7CCC42E6 mftb r6 +00003298: 7C064800 cmpw r6,r9 +0000329C: 4180FFE8 blt *-24 ; 0x00003284 +000032A0: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="relocate_code" Size=0 + +Hunk: Kind=HUNK_LOCAL_CODE Name="clear_bss" Size=0 +000032A4: 806E801C lwz r3,-32740(r14) +000032A8: 808E8018 lwz r4,-32744(r14) +000032AC: 7C032040 cmplw r3,r4 +000032B0: 41820018 beq *+24 ; 0x000032C8 +000032B4: 38000000 li r0,0 +000032B8: 90030000 stw r0,0(r3) +000032BC: 38630004 addi r3,r3,4 +000032C0: 7C032040 cmplw r3,r4 +000032C4: 4082FFF4 bne *-12 ; 0x000032B8 +000032C8: 7D234B78 mr r3,r9 +000032CC: 7D445378 mr r4,r10 +000032D0: 48000001 bl *+0 ; 0x000032D0 + +Hunk: Kind=HUNK_GLOBAL_CODE Name="get_endaddr" Size=0 +000032D4: 806E8018 lwz r3,-32744(r14) +000032D8: 4E800020 blr + +Hunk: Kind=HUNK_GLOBAL_CODE Name="trap_init" Size=0 +000032DC: 80EE8008 lwz r7,-32760(r14) +000032E0: 810E8010 lwz r8,-32752(r14) +000032E4: 54E904BE clrlwi r9,r7,18 +000032E8: 7C074040 cmplw r7,r8 +000032EC: 4C800020 bgelr +000032F0: 7C8802A6 mflr r4 +000032F4: 80070000 lwz r0,0(r7) +000032F8: 90090000 stw r0,0(r9) +000032FC: 38E70004 addi r7,r7,4 +00003300: 39290004 addi r9,r9,4 +00003304: 7C074040 cmplw r7,r8 +00003308: 4082FFEC bne *-20 ; 0x000032F4 +0000330C: 38E00288 li r7,648 +00003310: 39000600 li r8,1536 +00003314: 48000041 bl *+64 ; 0x00003354 +00003318: 38E70100 addi r7,r7,256 +0000331C: 7C074040 cmplw r7,r8 +00003320: 4180FFF4 blt *-12 ; 0x00003314 +00003324: 38E0069C li r7,1692 +00003328: 4800002D bl *+44 ; 0x00003354 +0000332C: 38E0078C li r7,1932 +00003330: 48000025 bl *+36 ; 0x00003354 +00003334: 38E00888 li r7,2184 +00003338: 39002090 li r8,8336 +0000333C: 48000019 bl *+24 ; 0x00003354 +00003340: 38E70100 addi r7,r7,256 +00003344: 7C074040 cmplw r7,r8 +00003348: 4180FFF4 blt *-12 ; 0x0000333C +0000334C: 7C8803A6 mtlr r4 +00003350: 4E800020 blr + +Hunk: Kind=HUNK_LOCAL_CODE Name="trap_reloc" Size=0 +00003354: 80070000 lwz r0,0(r7) +00003358: 7C001A14 add r0,r0,r3 +0000335C: 90070000 stw r0,0(r7) +00003360: 80070004 lwz r0,4(r7) +00003364: 7C001A14 add r0,r0,r3 +00003368: 90070004 stw r0,4(r7) +0000336C: 4E800020 blr +00003370: 0000B21C dc.l 0x0000b21c ; Invalid opcode '....' + +==> .data + +==> .bss + +==> .rela.got2 + entry offset addend type name(symbol id) + [ 0] 00000000 00000000 1 _GOT2_TABLE_(74) + [ 1] 00000004 00000000 1 _FIXUP_TABLE_(75) + [ 2] 00000008 00000000 1 _start(76) + [ 3] 0000000c 00000000 1 _start_of_vectors(77) + [ 4] 00000010 00000000 1 _end_of_vectors(78) + [ 5] 00000014 00000000 1 transfer_to_handler(79) + [ 6] 00000018 00000000 1 _end(80) + [ 7] 0000001c 00000000 1 .bss(34) + +==> .got2 +00000000: 00000000 00000000 00000000 00000000 '................' +00000010: 00000000 00000000 00000000 00000000 '................' diff --git a/mpc8240/traps.c b/mpc8240/traps.c new file mode 100644 index 0000000..227b41d --- /dev/null +++ b/mpc8240/traps.c @@ -0,0 +1,205 @@ +/* + * linux/arch/ppc/kernel/traps.c + * + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modified by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras (paulus@cs.anu.edu.au) + * + * (C) Copyright 2000 + * 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 + */ + +/* + * This file handles the architecture-dependent parts of hardware exceptions + */ + +#include +#include + +/* Returns 0 if exception not found and fixup otherwise. */ +extern unsigned long search_exception_table(unsigned long); + +/* THIS NEEDS CHANGING to use the board info structure. +*/ +#define END_OF_MEM 0x00400000 + +/* + * Trap & Exception support + */ + +void +print_backtrace(unsigned long *sp) +{ + int cnt = 0; + unsigned long i; + + printf("Call backtrace: "); + while (sp) { + if ((uint)sp > END_OF_MEM) + break; + + i = sp[1]; + if (cnt++ % 7 == 0) + printf("\n"); + printf("%08lX ", i); + if (cnt > 32) break; + sp = (unsigned long *)*sp; + } + printf("\n"); +} + +void show_regs(struct pt_regs * regs) +{ + int i; + + printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n", + regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); + printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", + regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, + regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, + regs->msr&MSR_IR ? 1 : 0, + regs->msr&MSR_DR ? 1 : 0); + + printf("\n"); + for (i = 0; i < 32; i++) { + if ((i % 8) == 0) + { + printf("GPR%02d: ", i); + } + + printf("%08lX ", regs->gpr[i]); + if ((i % 8) == 7) + { + printf("\n"); + } + } +} + + +void +_exception(int signr, struct pt_regs *regs) +{ + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); + panic("Exception in kernel pc %lx signal %d",regs->nip,signr); +} + +void +MachineCheckException(struct pt_regs *regs) +{ + unsigned long fixup; + + /* Probing PCI using config cycles cause this exception + * when a device is not present. Catch it and return to + * the PCI exception handler. + */ + if ((fixup = search_exception_table(regs->nip)) != 0) { + regs->nip = fixup; + return; + } + + printf("Machine check in kernel mode.\n"); + printf("Caused by (from msr): "); + printf("regs %p ",regs); + switch( regs->msr & 0x0000F000) + { + case (1<<12) : + printf("Machine check signal - probably due to mm fault\n" + "with mmu off\n"); + break; + case (1<<13) : + printf("Transfer error ack signal\n"); + break; + case (1<<14) : + printf("Data parity signal\n"); + break; + case (1<<15) : + printf("Address parity signal\n"); + break; + default: + printf("Unknown values in msr\n"); + } + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); + panic("machine check"); +} + +void +AlignmentException(struct pt_regs *regs) +{ + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); + panic("Alignment Exception"); +} + +void +ProgramCheckException(struct pt_regs *regs) +{ + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); + panic("Program Check Exception"); +} + +void +SoftEmuException(struct pt_regs *regs) +{ + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); + panic("Software Emulation Exception"); +} + + +void +UnknownException(struct pt_regs *regs) +{ + printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", + regs->nip, regs->msr, regs->trap); + _exception(0, regs); +} + +/* Probe an address by reading. If not present, return -1, otherwise + * return 0. + */ +int +addr_probe(uint *addr) +{ +#if 0 + int retval; + + __asm__ __volatile__( \ + "1: lwz %0,0(%1)\n" \ + " eieio\n" \ + " li %0,0\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: li %0,-1\n" \ + " b 2b\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 2\n" \ + " .long 1b,3b\n" \ + ".text" \ + : "=r" (retval) : "r"(addr)); + + return (retval); +#endif + return 0; +} diff --git a/mpc8xx/Makefile b/mpc8xx/Makefile index a011d81..14de409 100644 --- a/mpc8xx/Makefile +++ b/mpc8xx/Makefile @@ -29,7 +29,8 @@ LIB = lib$(CPU).a START = start.o kgdb.o OBJS = traps.o serial.o cpu.o cpu_init.o speed.o \ - commproc.o interrupts.o scc.o i2c.o video.o wlkbd.o + commproc.o interrupts.o fec.o scc.o \ + i2c.o video.o wlkbd.o status_led.o all: .depend $(START) $(LIB) diff --git a/mpc8xx/fec.c b/mpc8xx/fec.c index a38e102..36de2e9 100644 --- a/mpc8xx/fec.c +++ b/mpc8xx/fec.c @@ -26,7 +26,9 @@ #include #include -#if (CONFIG_COMMANDS & CFG_CMD_NET) +#define ET_DEBUG + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET) #define BD_OFFSET 0x860 /* offset to begin of DPRAM + allocation for serial IF*/ @@ -35,7 +37,12 @@ #define TX_BUF_CNT 2 -#define TOUT_LOOP 1000000 +#define TOUT_LOOP 100000 + +#define PKT_MAXBUF_SIZE 1518 +#define PKT_MINBUF_SIZE 64 +#define PKT_MAXBLR_SIZE 1520 + /* static char rxbuf[PKTBUFSRX][ DBUF_LENGTH ]; */ static char txbuf[TX_BUF_CNT][ DBUF_LENGTH ]; @@ -60,6 +67,8 @@ static RTXBD *rtx; int eth_send(volatile void *packet, int length) { int i, j=0; + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile fec_t *fecp = &(immr->im_cpm.cp_fec); #if 0 volatile char *in, *out; #endif @@ -79,7 +88,8 @@ int eth_send(volatile void *packet, int length) while (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) j++; #ifdef ET_DEBUG - printf("cycles: %d status: %x\n", j, rtx->txbd[txIdx].cbd_sc); + printf("%s[%d] %s: cycles: %d status: %x\n", + __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc); #endif i = (rtx->txbd[txIdx++].cbd_sc & BD_ENET_TX_STATS) /* return only status bits */; @@ -87,23 +97,57 @@ int eth_send(volatile void *packet, int length) if (txIdx >= TX_BUF_CNT) txIdx = 0; #endif - while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j=TOUT_LOOP) printf("TX not ready\n"); + while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j=TOUT_LOOP) { + printf("TX not ready\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_HB) printf("- No heartbeat\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_LC) printf("- Late collision\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_RL) printf("- Retrans limit\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_UN) printf("- Underrun\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_CSL) printf("- Carrier lost\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_DEF) printf("- Deferred\n"); + } rtx->txbd[txIdx].cbd_bufaddr = (uint)packet; rtx->txbd[txIdx].cbd_datlen = length; rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |BD_ENET_TX_WRAP); - while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j=TOUT_LOOP) printf("TX timeout\n"); + + /* Activate transmit Buffer Descriptor polling */ + fecp->fec_x_des_active = 0x01000000; /* Descriptor polling active */ + + while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j=TOUT_LOOP) { + printf("TX timeout\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_HB) printf("- No heartbeat\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_LC) printf("- Late collision\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_RL) printf("- Retrans limit\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_UN) printf("- Underrun\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_CSL) printf("- Carrier lost\n"); +if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_DEF) printf("- Deferred\n"); + } #ifdef ET_DEBUG - printf("cycles: %d status: %x\n", j, rtx->txbd[txIdx].cbd_sc); + printf("%s[%d] %s: cycles: %d status: %x\n", + __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc); #endif i = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS) /* return only status bits */; + +printf("%s[%d] %s: return 0x%x\n",__FILE__,__LINE__,__FUNCTION__,i); return i; } int eth_rx(void) { int length; + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile fec_t *fecp = &(immr->im_cpm.cp_fec); + + /* Try to fill Buffer Descriptors */ + fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ for (;;) { @@ -115,14 +159,12 @@ int eth_rx(void) length = rtx->rxbd[rxIdx].cbd_datlen; - if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) - { + if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) { #ifdef ET_DEBUG - printf("err: %x\n", rtx->rxbd[rxIdx].cbd_sc); + printf("%s[%d] %s: err: %x\n", + __FILE__,__LINE__,__FUNCTION__,rtx->rxbd[rxIdx].cbd_sc); #endif - } - else - { + } else { /* Pass the packet up to the protocol layers. */ NetReceive(NetRxPackets[rxIdx], length - 4); } @@ -135,338 +177,170 @@ int eth_rx(void) if ((rxIdx + 1) >= PKTBUFSRX) { rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); rxIdx = 0; - } - else { + } else { rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; rxIdx++; } } + + /* Try to fill Buffer Descriptors */ + fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ +printf("%s[%d] %s: len=%d\n",__FILE__,__LINE__,__FUNCTION__,length); return length; } /************************************************************** - * - * FEC Ethernet Initialization Routine - * - *************************************************************/ + * + * FEC Ethernet Initialization Routine + * + *************************************************************/ + +#define FEC_ECNTRL_PINMUX 0x00000004 +#define FEC_ECNTRL_ETHER_EN 0x00000002 +#define FEC_ECNTRL_RESET 0x00000001 + +#define FEC_RESET_DELAY 50 -int eth_init(bd_t *bis) +int eth_init (bd_t * bd) { - int i; - volatile immap_t *immr = (immap_t *)CFG_IMMR; - volatile fec_t *fecp = &(immr->im_cpm.cp_fec); - - /* Whack a reset. - * A delay is required between a reset of the FEC block and - * initialization of other FEC registers because the reset takes - * some time to complete. If you don't delay, subsequent writes - * to FEC registers might get killed by the reset routinewhich is - * still in progress. - */ - fecp->fec_ecntrl = 1; - udelay (20); - - /* We use striclty polling mode only - */ - fecp->fec_imask = 0; - - /* Clear any outstanding interrupt. - */ - fecp->fec_ievent = 0xffc0; - - /* Reset all multicast. - */ - fecp->fec_hash_table_high = 0; - fecp->fec_hash_table_low = 0; - - /* Set maximum receive buffer size. - */ - fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - fecp->fec_r_hash = PKT_MAXBUF_SIZE; - - /* Configure all of port D for MII. - */ - immr->im_ioport.iop_pdpar = 0x1fff; - - /* Bits moved from Rev. D onward */ - if ((_get_IMMR() & 0xffff) < 0x0501) { - immr->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ - } else { - immr->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ - } - - /* Set MII speed to 2.5 MHz - */ - fecp->fec_mii_speed = fep->phy_speed = - ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e; - - - rxIdx = 0; - txIdx = 0; - - /* assign static pointer to BD area */ - rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + BD_OFFSET); - - /* Set receive and transmit descriptor base - */ - fecp->fec_r_des_start = (unsigned int)(&rtx->rxbd[0]); - fecp->fec_x_des_start = (unsigned int)(&rtx->txbd[0]); - - -#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD)) - /* Configure port A pins for Txd and Rxd. - */ - immr->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD); - immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD); - immr->im_ioport.iop_paodr &= ~PA_ENET_TXD; -#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD)) - /* Configure port B pins for Txd and Rxd. - */ - immr->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD); - immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD); - immr->im_cpm.cp_pbodr &= ~PB_ENET_TXD; -#else -#error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined -#endif + int i; + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile fec_t *fecp = &(immr->im_cpm.cp_fec); + +printf ("Start FEC init\n"); + /* Whack a reset. + * A delay is required between a reset of the FEC block and + * initialization of other FEC registers because the reset takes + * some time to complete. If you don't delay, subsequent writes + * to FEC registers might get killed by the reset routine which is + * still in progress. + */ + fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET; + for (i = 0; + (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); + ++i) { + udelay (1); + } + if (i == FEC_RESET_DELAY) { + printf ("FEC_RESET_DELAY timeout\n"); + return 0; + } + + /* We use strictly polling mode only + */ + fecp->fec_imask = 0; + + /* Clear any pending interrupt + */ + fecp->fec_ievent = 0xffc0; -#if defined(PC_ENET_LBK) - /* Configure port C pins to disable External Loopback - */ - immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK; - immr->im_ioport.iop_pcdir |= PC_ENET_LBK; - immr->im_ioport.iop_pcso &= ~PC_ENET_LBK; - immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK; /* Disable Loopback */ -#endif /* PC_ENET_LBK */ - - /* Configure port C pins to enable CLSN and RENA. - */ - immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA); - immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA); - immr->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA); - - /* Configure port A for TCLK and RCLK. - */ - immr->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK); - immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK); - - /* - * Configure Serial Interface clock routing -- see section 16.7.5.3 - * First, clear all FEC bits to zero, then set the ones we want. - */ - - immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK; - immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT; - - - /* - * Initialize SDCR -- see section 16.9.23.7 - * SDMA configuration register - */ - immr->im_siu_conf.sc_sdcr = 0x01; - - - /* - * Setup FEC Ethernet Parameter RAM - */ - - pram_ptr->sen_genscc.scc_rfcr = 0x18; /* Normal Operation and Mot byte ordering */ - pram_ptr->sen_genscc.scc_tfcr = 0x18; /* Mot byte ordering, Normal access */ - - pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH; /* max. ET package len 1520 */ - - - /* - * Setup Receiver Buffer Descriptors (13.14.24.18) - * Settings: - * Empty, Wrap - */ - - for (i = 0; i < PKTBUFSRX; i++) - { - rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; - rtx->rxbd[i].cbd_datlen = 0; /* Reset */ - rtx->rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i]; - } - - rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; - - /* - * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) - * Settings: - * Add PADs to Short FRAMES, Wrap, Last, Tx CRC - */ - - for (i = 0; i < TX_BUF_CNT; i++) - { - rtx->txbd[i].cbd_sc = (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC); - rtx->txbd[i].cbd_datlen = 0; /* Reset */ - rtx->txbd[i].cbd_bufaddr = (uint)&txbuf[i][0]; - } - - rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; - - /* - * Enter Command: Initialize Rx Params for FEC - */ - - do { /* Spin until ready to issue command */ - __asm__ ("eieio"); - } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); - /* Issue command */ - immr->im_cpm.cp_cpcr = ((CPM_CR_INIT_RX << 8) | (CPM_CR_ENET << 4) | CPM_CR_FLG); - do { /* Spin until command processed */ - __asm__ ("eieio"); - } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); - - /* - * Ethernet Specific Parameter RAM - * see table 13-16, pg. 660, - * pg. 681 (example with suggested settings) - */ - - pram_ptr->sen_cpres = ~(0x0); /* Preset CRC */ - pram_ptr->sen_cmask = 0xdebb20e3; /* Constant Mask for CRC */ - pram_ptr->sen_crcec = 0x0; /* Error Counter CRC (unused) */ - pram_ptr->sen_alec = 0x0; /* Alignment Error Counter (unused) */ - pram_ptr->sen_disfc = 0x0; /* Discard Frame Counter (unused) */ - pram_ptr->sen_pads = 0x8888; /* Short Frame PAD Characters */ - - pram_ptr->sen_retlim = 15; /* Retry Limit Threshold */ - pram_ptr->sen_maxflr = 1518; /* MAX Frame Length Register */ - pram_ptr->sen_minflr = 64; /* MIN Frame Length Register */ - - pram_ptr->sen_maxd1 = DBUF_LENGTH; /* MAX DMA1 Length Register */ - pram_ptr->sen_maxd2 = DBUF_LENGTH; /* MAX DMA2 Length Register */ - - pram_ptr->sen_gaddr1 = 0x0; /* Group Address Filter 1 (unused) */ - pram_ptr->sen_gaddr2 = 0x0; /* Group Address Filter 2 (unused) */ - pram_ptr->sen_gaddr3 = 0x0; /* Group Address Filter 3 (unused) */ - pram_ptr->sen_gaddr4 = 0x0; /* Group Address Filter 4 (unused) */ - -#define ea bis->bi_enetaddr - pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4]; - pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2]; - pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0]; + /* No need to set the IVEC register */ + + /* Set station address + */ +#define ea bd->bi_enetaddr + fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | + (ea[2] << 8) | (ea[3] ) ; + fecp->fec_addr_high = (ea[4] << 24) | (ea[5] << 16) ; #undef ea - pram_ptr->sen_pper = 0x0; /* Persistence (unused) */ - pram_ptr->sen_iaddr1 = 0x0; /* Individual Address Filter 1 (unused) */ - pram_ptr->sen_iaddr2 = 0x0; /* Individual Address Filter 2 (unused) */ - pram_ptr->sen_iaddr3 = 0x0; /* Individual Address Filter 3 (unused) */ - pram_ptr->sen_iaddr4 = 0x0; /* Individual Address Filter 4 (unused) */ - pram_ptr->sen_taddrh = 0x0; /* Tmp Address (MSB) (unused) */ - pram_ptr->sen_taddrm = 0x0; /* Tmp Address (unused) */ - pram_ptr->sen_taddrl = 0x0; /* Tmp Address (LSB) (unused) */ - - /* - * Enter Command: Initialize Tx Params for FEC - */ - - do { /* Spin until ready to issue command */ - __asm__ ("eieio"); - } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); - /* Issue command */ - immr->im_cpm.cp_cpcr = ((CPM_CR_INIT_TX << 8) | (CPM_CR_ENET << 4) | CPM_CR_FLG); - do { /* Spin until command processed */ - __asm__ ("eieio"); - } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); - - /* - * Mask all Events in SCCM - we use polling mode - */ - immr->im_cpm.cp_scc[SCC_ENET].scc_sccm = 0; - - /* - * Clear Events in SCCE -- Clear bits by writing 1's - */ - - immr->im_cpm.cp_scc[SCC_ENET].scc_scce = ~(0x0); - - - /* - * Initialize GSMR High 32-Bits - * Settings: Normal Mode - */ - - immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrh = 0; - - /* - * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive - * Settings: - * TCI = Invert - * TPL = 48 bits - * TPP = Repeating 10's - * MODE = Ethernet - */ - - immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl = ( SCC_GSMRL_TCI | \ - SCC_GSMRL_TPL_48 | \ - SCC_GSMRL_TPP_10 | \ - SCC_GSMRL_MODE_ENET); - - /* - * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4 - */ - - immr->im_cpm.cp_scc[SCC_ENET].scc_dsr = 0xd555; - - /* - * Initialize the PSMR - * Settings: - * CRC = 32-Bit CCITT - * NIB = Begin searching for SFD 22 bits after RENA - * BRO = Reject broadcast packets - * PROMISCOUS = Catch all packets regardless of dest. MAC adress - */ - immr->im_cpm.cp_scc[SCC_ENET].scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_NIB22 - /* | SCC_PMSR_BRO | SCC_PMSR_PRO */); - - /* - * Configure Ethernet TENA Signal - */ - -#if (defined(PC_ENET_TENA) && !defined(PB_ENET_TENA)) - immr->im_ioport.iop_pcpar |= PC_ENET_TENA; - immr->im_ioport.iop_pcdir &= ~PC_ENET_TENA; -#elif (defined(PB_ENET_TENA) && !defined(PC_ENET_TENA)) - immr->im_cpm.cp_pbpar |= PB_ENET_TENA; - immr->im_cpm.cp_pbdir |= PB_ENET_TENA; -#else -#error Configuration Error: exactly ONE of PB_ENET_TENA, PC_ENET_TENA must be defined -#endif + rxIdx = 0; + txIdx = 0; + + rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + m8xx_cpm_dpbase_align(8)); + /* + * Setup Receiver Buffer Descriptors (13.14.24.18) + * Settings: + * Empty, Wrap + */ + for (i = 0; i < PKTBUFSRX; i++) { + rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; + rtx->rxbd[i].cbd_datlen = 0; /* Reset */ + rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; + } + rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; + + /* + * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) + * Settings: + * Add PADs to Short FRAMES, Wrap, Last, Tx CRC + */ + for (i = 0; i < TX_BUF_CNT; i++) { + rtx->txbd[i].cbd_sc = + (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC); + rtx->txbd[i].cbd_datlen = 0; /* Reset */ + rtx->txbd[i].cbd_bufaddr = (uint) & txbuf[i][0]; + } + rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; -#if defined(CONFIG_FADS) && defined(CONFIG_MPC860T) - /* - * Port C is used to control the PHY,MC68160. - */ - immr->im_ioport.iop_pcdir |= - (PC_ENET_ETHLOOP | PC_ENET_TPFLDL | PC_ENET_TPSQEL); + /* Clear multicast address hash table + */ + fecp->fec_hash_table_high = 0; + fecp->fec_hash_table_low = 0; - immr->im_ioport.iop_pcdat |= PC_ENET_TPFLDL; - immr->im_ioport.iop_pcdat &= ~(PC_ENET_ETHLOOP | PC_ENET_TPSQEL); - *((uint *) BCSR1) &= ~BCSR1_ETHEN; -#endif /* FADS860T */ + /* Set maximum receive buffer size. + */ + fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; -#ifdef CONFIG_MBX - board_ether_init(); + /* Set receive and transmit descriptor base + */ + fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]); + fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]); + + /* Set maximum frame length + */ + fecp->fec_r_hash = PKT_MAXBUF_SIZE; + + /* Enable MII mode + */ +#if 0 /* Full duplex mode */ + fecp->fec_r_cntrl = 0x04; /* MII enable */ + fecp->fec_x_cntrl = 0x04; /* FD enable */ +#else /* Half duplex mode */ + fecp->fec_r_cntrl = 0x06; /* MII enable | No Rcv on Xmit */ + fecp->fec_x_cntrl = 0x00; #endif - /* - * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive - */ + /* Enable big endian and don't care about SDMA FC. + */ + fecp->fec_fun_code = 0x78000000; - immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + /* Configure all of port D for MII. + */ + immr->im_ioport.iop_pdpar = 0x1fff; - return 1; + /* Bits moved from Rev. D onward */ + if ((get_immr (0) & 0xffff) < 0x0501) { + immr->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ + } else { + immr->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ + } + + /* Set MII speed to 2.5 MHz + */ + fecp->fec_mii_speed = ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e; + + rxIdx = 0; + txIdx = 0; + + /* And last, enable the transmit and receive processing + */ + fecp->fec_ecntrl = 6; + fecp->fec_r_des_active = 0x01000000; + +printf ("FEC init done\n"); + return 1; } void eth_halt(void) { +#if 0 volatile immap_t *immr = (immap_t *)CFG_IMMR; immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#endif } #if 0 diff --git a/mpc8xx/fec.h b/mpc8xx/fec.h new file mode 100644 index 0000000..a49417c --- /dev/null +++ b/mpc8xx/fec.h @@ -0,0 +1,28 @@ +/* + * (C) Copyright 2000 + * 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 _FEC_H_ +#define _FEC_H_ + + +#endif /* _FEC_H_ */ diff --git a/mpc8xx/interrupts.c b/mpc8xx/interrupts.c index ff6c32f..0d12cb9 100644 --- a/mpc8xx/interrupts.c +++ b/mpc8xx/interrupts.c @@ -285,6 +285,9 @@ volatile ulong timestamp = 0; void timer_interrupt(struct pt_regs *regs) { volatile immap_t *immr = (immap_t *)CFG_IMMR; +#ifdef CONFIG_STATUS_LED + extern void status_led_tick (ulong); +#endif #if 0 printf ("*** Timer Interrupt *** "); #endif @@ -298,13 +301,15 @@ void timer_interrupt(struct pt_regs *regs) timestamp++; +#ifdef CONFIG_STATUS_LED + status_led_tick (timestamp); +#endif /* CONFIG_STATUS_LED */ + #if defined(CONFIG_WATCHDOG) || defined(CFG_CMA_LCD_HEARTBEAT) if ((timestamp % 1000) == 0) { - #if defined(CFG_CMA_LCD_HEARTBEAT) extern void lcd_heartbeat(void); - lcd_heartbeat(); #endif /* CFG_CMA_LCD_HEARTBEAT */ diff --git a/mpc8xx/scc.c b/mpc8xx/scc.c index 374eb58..e3b94d3 100644 --- a/mpc8xx/scc.c +++ b/mpc8xx/scc.c @@ -45,7 +45,7 @@ #include #include -#if (CONFIG_COMMANDS & CFG_CMD_NET) +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(SCC_ENET) #if 0 #define BD_OFFSET 0x860 /* offset to begin of DPRAM + allocation for serial IF*/ @@ -466,4 +466,4 @@ void restart(void) } #endif -#endif /* CFG_CMD_NET */ +#endif /* CFG_CMD_NET, SCC_ENET */ diff --git a/mpc8xx/status_led.c b/mpc8xx/status_led.c new file mode 100644 index 0000000..6b8d88a --- /dev/null +++ b/mpc8xx/status_led.c @@ -0,0 +1,95 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +#include +#include "mpc8xx.h" +#include + +/* + * The purpose of this code is to signal the operational status of a + * target which usually boots over the network; while running in + * PCBoot, a status LED is blinking. As soon as a valid BOOTP reply + * message has been received, the LED is turned off. The Linux + * kernel, once it is running, will start blinking the LED again, + * with another frequency. + */ + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_STATUS_LED + +static int status_led_state; +static int status_led_init_done = 0; + +static void status_led_init (void) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + + immr->STATUS_LED_PAR &= ~(STATUS_LED_BIT); +#ifdef STATUS_LED_ODR + immr->STATUS_LED_ODR &= ~(STATUS_LED_BIT); +#endif + immr->STATUS_LED_DAT &= ~(STATUS_LED_BIT); /* start with off */ + immr->STATUS_LED_DIR |= STATUS_LED_BIT ; + status_led_state = STATUS_LED_BLINKING; + status_led_init_done = 1; +} + +void status_led_tick (ulong timestamp) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + + if (status_led_state != STATUS_LED_BLINKING) + return; + + if (!status_led_init_done) + status_led_init(); + + if ((timestamp % STATUS_LED_PERIOD) == 0) { + immr->STATUS_LED_DAT ^= STATUS_LED_BIT; + } +} + +void status_led_set (int state) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + + if (!status_led_init_done) + status_led_init(); + + switch (state) { + default: + return; + case STATUS_LED_BLINKING: + break; + case STATUS_LED_ON: + immr->STATUS_LED_DAT |= STATUS_LED_BIT; + break; + case STATUS_LED_OFF: + immr->STATUS_LED_DAT &= ~(STATUS_LED_BIT); + break; + } + status_led_state = state; +} + +#endif /* CONFIG_STATUS_LED */ diff --git a/net/bootp.c b/net/bootp.c index 6e7f1aa..7711c96 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -14,6 +14,9 @@ #include "net.h" #include "bootp.h" #include "tftp.h" +#ifdef CONFIG_STATUS_LED +#include +#endif #define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */ @@ -199,6 +202,9 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) /* * Got a good BOOTP reply. Copy the data into our variables. */ +#ifdef CONFIG_STATUS_LED + status_led_set (STATUS_LED_OFF); +#endif NetOurIP = bp->bp_yiaddr; NetServerIP = bp->bp_siaddr; NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src); diff --git a/ppc/vsprintf.c b/ppc/vsprintf.c index d42b362..898c7c5 100644 --- a/ppc/vsprintf.c +++ b/ppc/vsprintf.c @@ -324,8 +324,12 @@ void panic(const char *fmt, ...) va_list args; va_start(args, fmt); printf(fmt); + putc('\n'); va_end(args); - - /* Hang */ - for(;;); +#if 1 + hang(); +#else + udelay (100000); /* allow messages to go out */ + do_reset (NULL, NULL, 0, 0, NULL); +#endif } diff --git a/ppc4xx/405gp_enet.c b/ppc4xx/405gp_enet.c index bb7f437..a5aec1d 100644 --- a/ppc4xx/405gp_enet.c +++ b/ppc4xx/405gp_enet.c @@ -220,12 +220,12 @@ int eth_init (bd_t *bis) out32 (EMAC_M0, in32 (EMAC_M0) & ~EMAC_M0_SRST); speed = miiphy_speed(); - printf("ENET Speed is %d Mbs... \n\r", (int)speed); + printf("ENET Speed is %d Mbs... \n", (int)speed); duplex = miiphy_duplex(); if( duplex == HALF) - printf("HALF duplex connection\n\r"); + printf("HALF duplex connection\n"); else - printf("FULL duplex connection\n\r"); + printf("FULL duplex connection\n"); /* set the Mal configuration reg */ mtdcr(malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); @@ -535,7 +535,7 @@ void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef, unsigned long mal_errr) { mtdcr(malesr, isr); /* clear interrupt */ - printf ("MAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n\r", + printf ("MAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n", isr, uic, maldef, mal_errr); #if 0 @@ -556,7 +556,7 @@ void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef, +-----------------------------------------------------------------------------*/ void emac_err (unsigned long isr) { - printf ("EMAC error occured.... ISR = %lx\n\r", isr); + printf ("EMAC error occured.... ISR = %lx\n", isr); out32(EMAC_ISR, isr); } diff --git a/ppc4xx/miiphy.c b/ppc4xx/miiphy.c index 0f60337..72a8296 100644 --- a/ppc4xx/miiphy.c +++ b/ppc4xx/miiphy.c @@ -65,10 +65,10 @@ void miiphy_dump(void) { if(miiphy_read(i, &data)) { - printf("read error for reg %lx\n\r",i); + printf("read error for reg %lx\n",i); return; } - printf("Phy reg %lx ==> %4x\n\r", i, data); + printf("Phy reg %lx ==> %4x\n", i, data); /* jump to the next set of regs */ if(i==0x07) @@ -96,7 +96,7 @@ int miiphy_read(unsigned char reg, unsigned short * value) { udelay(7); if(i > 5) - { printf("read err 1\n\r"); + { printf("read err 1\n"); return -1; } i++; @@ -117,14 +117,14 @@ int miiphy_read(unsigned char reg, unsigned short * value) { udelay(7); if(i > 5) - { printf("read err 2\n\r"); + { printf("read err 2\n"); return -1; } i++; sta_reg = in32(EMAC_STACR); } if ((sta_reg & EMAC_STACR_PHYE) !=0) - { printf("read err 3\n\r"); + { printf("read err 3\n"); printf("a2: read: EMAC_STACR=0x%0lx, i=%d\n", sta_reg, (int)i); /* test-only */ return -1; } @@ -191,7 +191,7 @@ int miiphy_speed() unsigned short bmcr = 0x0; if (miiphy_read(PHY_ANLPAR,&bmcr)) { - printf("phy speed1 read failed \n\r"); + printf("phy speed1 read failed \n"); miiphy_dump(); } @@ -211,7 +211,7 @@ int miiphy_duplex() if (miiphy_read(PHY_ANLPAR,&bmcr)) { - printf("phy duplex read failed \n\r"); + printf("phy duplex read failed \n"); miiphy_dump(); } diff --git a/sandpoint/Makefile b/sandpoint/Makefile new file mode 100644 index 0000000..6c8a6c2 --- /dev/null +++ b/sandpoint/Makefile @@ -0,0 +1,41 @@ +# +# (C) Copyright 2000 +# 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 +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o board_init.o ns16550.o ns87308.o serial.o speed.o +#eepro100.o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $^ + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/sandpoint/board_init.c b/sandpoint/board_init.c new file mode 100644 index 0000000..e69de29 diff --git a/sandpoint/config.mk b/sandpoint/config.mk new file mode 100644 index 0000000..ccf6830 --- /dev/null +++ b/sandpoint/config.mk @@ -0,0 +1,30 @@ +# +# (C) Copyright 2000 +# 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 +# + +# +# Sandpoint boards +# + +TEXT_BASE = 0xFE000000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) diff --git a/sandpoint/flash.c b/sandpoint/flash.c new file mode 100644 index 0000000..f2de593 --- /dev/null +++ b/sandpoint/flash.c @@ -0,0 +1,760 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +#include +#include +#include +#include +#include "w83c553f.h" + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +ulong flash_get_size (vu_long *addr, flash_info_t *info); + +int flash_write (uchar *, ulong, ulong); +flash_info_t *addr2info (ulong); + +static int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt); +static int write_word (flash_info_t *info, ulong dest, ulong data); +static void flash_get_offsets (ulong base, flash_info_t *info); +static int flash_protect (int flag, ulong from, ulong to, flash_info_t *info); + +/*----------------------------------------------------------------------- + * Protection Flags: + */ +#define FLAG_PROTECT_SET 0x01 +#define FLAG_PROTECT_CLEAR 0x02 + +/*flash command address offsets*/ + +#define ADDR0 (0x555) +#define ADDR1 (0x2AA) +#define ADDR3 (0x001) + +#define FLASH_WORD_SIZE unsigned char + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size; + int i; + unsigned long base; + register unsigned long temp; + + /* Init: no FLASHes known */ + for (i=0; istart[0] + info->size - 1; /* bank end address */ + int rc = 0; + int first = -1; + int last = -1; + int i; + + if (to < info->start[0]) { + return (0); + } + + for (i=0; isector_count; ++i) { + ulong end; /* last address in current sect */ + short s_end; + + s_end = info->sector_count - 1; + + end = (i == s_end) ? b_end : info->start[i + 1] - 1; + + if (from > end) { + continue; + } + if (to < info->start[i]) { + continue; + } + + if (from == info->start[i]) { + first = i; + if (last < 0) { + last = s_end; + } + } + if (to == end) { + last = i; + if (first < 0) { + first = 0; + } + } + } + + for (i=first; i<=last; ++i) { + if (flag & FLAG_PROTECT_CLEAR) { + info->protect[i] = 0; + } else if (flag & FLAG_PROTECT_SET) { + info->protect[i] = 1; + } + if (info->protect[i]) { + rc = 1; + } + } + return (rc); +} + + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start adress table */ + if (info->flash_id & FLASH_MAN_SST) + { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } + else + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *flash; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_SST: printf ("SST "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + case FLASH_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n"); + break; + case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + /* + * Check if whole sector is erased + */ + if (i != (info->sector_count-1)) + size = info->start[i+1] - info->start[i]; + else + size = info->start[0] + info->size - info->start[i]; + erased = 1; + flash = (volatile unsigned long *)info->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k=0; kstart[i], + info->protect[i] ? " (RO)" : " " +#else + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + info->protect[i] ? "RO " : " " +#endif + ); + } + printf ("\n"); +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ +ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + FLASH_WORD_SIZE value; + ulong base = (ulong)addr; + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; + + printf("flash_get_size: \n"); + /* Write auto select command: read Manufacturer ID */ + eieio(); + addr2[ADDR0] = (FLASH_WORD_SIZE)0xAA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x55; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x90; + value = addr2[0]; + + switch (value) { + case (FLASH_WORD_SIZE)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (FLASH_WORD_SIZE)FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (FLASH_WORD_SIZE)SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + printf("recognised manufacturer"); + + value = addr2[ADDR3]; /* device ID */ + // printf("\ndev_code=%x\n", value); + + switch (value) { + case (FLASH_WORD_SIZE)AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ +#if 0 /* enable when device IDs are available */ + case (FLASH_WORD_SIZE)AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ +#endif + case (FLASH_WORD_SIZE)SST_ID_xF800A: + info->flash_id += FLASH_SST800A; + info->sector_count = 16; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)SST_ID_xF160A: + info->flash_id += FLASH_SST160A; + info->sector_count = 32; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_F040B: + info->flash_id += FLASH_AM040B; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + + printf("flash id %lx; sector count %x, size %lx\n", info->flash_id,info->sector_count,info->size); + /* set up sector start adress table */ + if (info->flash_id & FLASH_MAN_SST) + { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } + else + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + if (info->flash_id & FLASH_MAN_SST) + info->protect[i] = 0; + else + info->protect[i] = addr2[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + } + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +void flash_erase (flash_info_t *info, int s_first, int s_last) +{ + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return; + } + + if ((info->flash_id == FLASH_UNKNOWN) || + (info->flash_id > FLASH_AMD_COMP)) { + printf ("Can't erase unknown flash type - aborted\n"); + return; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (FLASH_WORD_SIZE *)(info->start[sect]); + if (info->flash_id & FLASH_MAN_SST) + { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */ + udelay(30000); /* wait 30 ms */ + } + else + addr[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */ + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = (FLASH_WORD_SIZE *)(info->start[l_sect]); + while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + serial_putc ('.'); + last = now; + } + } + +DONE: + /* reset to read mode */ + addr = (FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + + printf (" done\n"); +} + +/*----------------------------------------------------------------------- + */ + +flash_info_t *addr2info (ulong addr) +{ + flash_info_t *info; + int i; + + for (i=0, info=&flash_info[0]; i= info->start[0]) && + (addr <= (info->start[0] + info->size - 1)) ) { + return (info); + } + } + + return (NULL); +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + * Make sure all target addresses are within Flash bounds, + * and no protected sectors are hit. + * Returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - target range includes protected sectors + * 8 - target address not in Flash memory + */ +int flash_write (uchar *src, ulong addr, ulong cnt) +{ + int i; + ulong end = addr + cnt - 1; + flash_info_t *info_first = addr2info (addr); + flash_info_t *info_last = addr2info (end ); + flash_info_t *info; + + if (cnt == 0) { + return (0); + } + + if (!info_first || !info_last) { + return (8); + } + + for (info = info_first; info <= info_last; ++info) { + ulong b_end = info->start[0] + info->size; /* bank end addr */ + short s_end = info->sector_count - 1; + for (i=0; isector_count; ++i) { + ulong e_addr = (i == s_end) ? b_end : info->start[i + 1]; + + if ((end >= info->start[i]) && (addr < e_addr) && + (info->protect[i] != 0) ) { + return (4); + } + } + } + + /* finally write data to flash */ + for (info = info_first; info <= info_last && cnt>0; ++info) { + ulong len; + + len = info->start[0] + info->size - addr; + if (len > cnt) + len = cnt; + if ((i = write_buff(info, src, addr, len)) != 0) { + return (i); + } + cnt -= len; + addr += len; + src += len; + } + return (0); +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +static int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i=0; i<4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_word(info, wp, data)); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest; + volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data; + ulong start; + int flag; + int i; + + /* Check if Flash is (sufficiently) erased */ + if ((*((volatile FLASH_WORD_SIZE *)dest) & + (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++) + { + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0; + + dest2[i] = data2[i]; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != + (data2[i] & (FLASH_WORD_SIZE)0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + } + + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/sandpoint/interrupts.c b/sandpoint/interrupts.c new file mode 100644 index 0000000..8a3e8b1 --- /dev/null +++ b/sandpoint/interrupts.c @@ -0,0 +1,134 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com + * + * 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 + */ + +#include +#include +#include + + +/****************************************************************************/ + +static __inline__ unsigned long get_msr(void) +{ + unsigned long msr; + + asm volatile("mfmsr %0" : "=r" (msr) :); + return msr; +} + +static __inline__ void set_msr(unsigned long msr) +{ + asm volatile("mtmsr %0" : : "r" (msr)); +} + +static __inline__ unsigned long get_dec(void) +{ + unsigned long val; + + asm volatile("mfdec %0" : "=r" (val) :); + return val; +} + + +static __inline__ void set_dec(unsigned long val) +{ + asm volatile("mtdec %0" : : "r" (val)); +} + + +void enable_interrupts (void) +{ + set_msr (get_msr() | MSR_EE); +} + +/* returns flag if MSR_EE was set before */ +int disable_interrupts (void) +{ + ulong msr = get_msr(); + set_msr (msr & ~MSR_EE); + return ((msr & MSR_EE) != 0); +} + +/****************************************************************************/ + +void +interrupt_init (bd_t *bd) +{ + + set_msr (get_msr() | MSR_EE); +} + +/****************************************************************************/ + +/* + * Handle external interrupts + */ +void external_interrupt(struct pt_regs *regs) +{ + +} + +/****************************************************************************/ + +/* + * blank int handlers. + */ + +void +irq_install_handler(int vec, interrupt_handler_t *handler, void *arg) +{ +} + +void +irq_free_handler(int vec) +{ + +} + +/*TODO: some handlers for winbond and 87308 interrupts + and what about generic pci inteerupts? + vga? + */ + +volatile ulong timestamp = 0; + +void timer_interrupt(struct pt_regs *regs) +{ + timestamp++; +} + +void reset_timer (void) +{ + timestamp = 0; +} + +ulong get_timer (ulong base) +{ + return (timestamp - base); +} + +void set_timer (ulong t) +{ + timestamp = t; +} diff --git a/sandpoint/interrupts.h b/sandpoint/interrupts.h new file mode 100644 index 0000000..316d04c --- /dev/null +++ b/sandpoint/interrupts.h @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com + * + * 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 _INTERRUPTS_H_ +#define _INTERRUPTS_H_ + +void irq_install_handler(int vec, interrupt_handler_t *handler, void *arg); + +void irq_free_handler(int vec); + +#endif diff --git a/sandpoint/ns16550.c b/sandpoint/ns16550.c new file mode 100644 index 0000000..1fb9779 --- /dev/null +++ b/sandpoint/ns16550.c @@ -0,0 +1,61 @@ +/* + * COM1 NS16550 support + * originally from linux source (arch/ppc/boot/ns16550.c) + * modified to use CFG_ISA_MEM and new defines + */ + +#include +#include "ns16550.h" + +typedef struct NS16550 *NS16550_t; + +const NS16550_t COM_PORTS[] = { (NS16550_t) (CFG_ISA_IO + COM1), + (NS16550_t) (CFG_ISA_IO + COM2) }; + +volatile struct NS16550 * +NS16550_init(int chan, int baud_divisor) +{ + volatile struct NS16550 *com_port; + com_port = (struct NS16550 *) COM_PORTS[chan]; + com_port->ier = 0x00; + com_port->lcr = LCR_BKSE; /* Access baud rate */ + com_port->dll = baud_divisor & 0xff; /* 9600 baud */ + com_port->dlm = (baud_divisor >> 8) & 0xff; + com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */ + com_port->mcr = MCR_DTR | MCR_RTS; /* RTS/DTR */ + com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; /* Clear & enable FIFOs */ + return (com_port); +} + +void +NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor) +{ + com_port->ier = 0x00; + com_port->lcr = LCR_BKSE; /* Access baud rate */ + com_port->dll = baud_divisor & 0xff; /* 9600 baud */ + com_port->dlm = (baud_divisor >> 8) & 0xff; + com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */ + com_port->mcr = MCR_DTR | MCR_RTS; /* RTS/DTR */ + com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; /* Clear & enable FIFOs */ +} + +void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c) +{ + while ((com_port->lsr & LSR_THRE) == 0) ; + com_port->thr = c; +} + +unsigned char +NS16550_getc(volatile struct NS16550 *com_port) +{ + while ((com_port->lsr & LSR_DR) == 0) ; + return (com_port->rbr); +} + +int NS16550_tstc(volatile struct NS16550 *com_port) +{ + return ((com_port->lsr & LSR_DR) != 0); +} + + + diff --git a/sandpoint/ns16550.h b/sandpoint/ns16550.h new file mode 100644 index 0000000..3a28d9d --- /dev/null +++ b/sandpoint/ns16550.h @@ -0,0 +1,74 @@ +/* + * NS16550 Serial Port + * originally from linux source (arch/ppc/boot/ns16550.h) + * modified slightly to + * have addresses as offsets from CFG_ISA_BASE + * added a few more definitions + * added prototypes for ns16550.c + * reduced no of com ports to 2 + * modifications (c) Rob Taylor, Flying Pig Systems. 2000. + */ + + +struct NS16550 + { + unsigned char rbr; /* 0 */ + unsigned char ier; /* 1 */ + unsigned char fcr; /* 2 */ + unsigned char lcr; /* 3 */ + unsigned char mcr; /* 4 */ + unsigned char lsr; /* 5 */ + unsigned char msr; /* 6 */ + unsigned char scr; /* 7 */ + }; + +#define thr rbr +#define iir fcr +#define dll rbr +#define dlm ier + +#define FCR_FIFO_EN 0x01 /*fifo enable*/ +#define FCR_RXSR 0x02 /*reciever soft reset*/ +#define FCR_TXSR 0x04 /*transmitter soft reset*/ + + +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_DMA_EN 0x04 +#define MCR_TX_DFR 0x08 + + +#define LCR_WLS_MSK 0x03 /* character length slect mask*/ +#define LCR_WLS_5 0x00 /* 5 bit character length */ +#define LCR_WLS_6 0x01 /* 6 bit character length */ +#define LCR_WLS_7 0x02 /* 7 bit character length */ +#define LCR_WLS_8 0x03 /* 8 bit character length */ +#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */ +#define LCR_PEN 0x08 /* Parity eneble*/ +#define LCR_EPS 0x10 /* Even Parity Select*/ +#define LCR_STKP 0x20 /* Stick Parity*/ +#define LCR_SBRK 0x40 /* Set Break*/ +#define LCR_BKSE 0x80 /* Bank select enable*/ + +#define LSR_DR 0x01 /* Data ready */ +#define LSR_OE 0x02 /* Overrun */ +#define LSR_PE 0x04 /* Parity error */ +#define LSR_FE 0x08 /* Framing error */ +#define LSR_BI 0x10 /* Break */ +#define LSR_THRE 0x20 /* Xmit holding register empty */ +#define LSR_TEMT 0x40 /* Xmitter empty */ +#define LSR_ERR 0x80 /* Error */ + +/* useful defaults for LCR*/ +#define LCR_8N1 0x03 + + +#define COM1 0x03F8 +#define COM2 0x02F8 + +volatile struct NS16550 * NS16550_init(int chan, int baud_divisor); +void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c); +unsigned char NS16550_getc(volatile struct NS16550 *com_port); +int NS16550_tstc(volatile struct NS16550 *com_port); +void NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor); + diff --git a/sandpoint/ns87308.c b/sandpoint/ns87308.c new file mode 100644 index 0000000..ad00a46 --- /dev/null +++ b/sandpoint/ns87308.c @@ -0,0 +1,62 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 + */ + +#include + +#include +#include "ns87308.h" +#include "ns16550.h" /*to configure the 87308's internal 16550's*/ +#include /* to configure 87308's RTC*/ + +void initialise_ns87308 (void) +{ + PNP_SET_DEVICE_BASE(LDEV_UART1, COM1); + PNP_SET_DEVICE_BASE(LDEV_UART2, COM2); + + PNP_SET_DEVICE_BASE(LDEV_RTC_APC, RTC_PORT(0)); + PNP_ACTIVATE_DEVICE(LDEV_POWRMAN); + + /* set up the NVRAM access registers + NVRAM's controlled by the configurable CS line from the 87308*/ + + PNP_PGCS_CSLINE_BASE(0, 0x76); + PNP_PGCS_CSLINE_CONF(0, 0x30); + PNP_PGCS_CSLINE_BASE(1, 0x75); + PNP_PGCS_CSLINE_CONF(1, 0x30); + PNP_PGCS_CSLINE_BASE(2, 0x74); + PNP_PGCS_CSLINE_CONF(2, 0x30); +} +/* +void write_pnp_config(unsigned char index, unsigned char data) +{ + unsigned char *io_index = (unsigned char *) IO_INDEX; + unsigned char *io_data = (unsigned char *) IO_DATA; + *io_index = index; + *io_data = data; +} + +void pnp_set_device(unsigned char dev) +{ + write_pnp_config(LOGICAL_DEVICE, dev); +} +*/ diff --git a/sandpoint/ns87308.h b/sandpoint/ns87308.h new file mode 100644 index 0000000..14b9f5c --- /dev/null +++ b/sandpoint/ns87308.h @@ -0,0 +1,170 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 _NS87308_H_ +#define _NS87308_H_ + +#include + +/* Note: I couldn't find a full data sheet for the ns87308, but the ns87307 seems to be pretty + functionally- (and pin-) equivalent to the 87308, but the 308 has better ir support. */ + +/*PNP config registers: + * these depend on the stated of BADDR1 and BADDR0 on startup + * so there's three versions here with the last two digits indicating + * for which configuration their valid + * the 1st of the two digits indicates the state of BADDR1 + * the 2st of the two digits indicates the state of BADDR0 + */ + + +#define IO_INDEX_OFFSET_0x 0x0279 /* full PnP isa Mode */ +#define IO_INDEX_OFFSET_10 0x015C /* PnP motherboard mode */ +#define IO_INDEX_OFFSET_11 0x002E /* PnP motherboard mode */ +#define IO_DATA_OFFSET_0x 0x0A79 /* full PnP isa Mode */ +#define IO_DATA_OFFSET_10 0x015D /* PnP motherboard mode */ +#define IO_DATA_OFFSET_11 0x002F /* PnP motherboard mode */ + +#if defined(CFG_NS87308_BADDR_0x) +#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_0x) +#define IO_DATA (CFG_ISA_IO + IO_DATA_OFFSET_0x) +#elif defined(CFG_NS87308_BADDR_10) +#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_10) +#define IO_DATA (CFG_ISA_IO + IO_DATA_OFFSET_10) +#elif defined(CFG_NS87308_BADDR_11) +#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_11) +#define IO_DATA (CFG_ISA_IO + IO_DATA_OFFSET_11) +#endif + +/* PnP register definitions */ + +#define SET_RD_DATA_PORT 0x00 +#define SERIAL_ISOLATION 0x01 +#define CONFIG_CONTROL 0x02 +#define WAKE_CSN 0x03 +#define RES_DATA 0x04 +#define STATUS 0x05 +#define SET_CSN 0x06 +#define LOGICAL_DEVICE 0x07 +/*vendor defined values */ +#define SID_REG 0x20 +#define SUPOERIO_CONF1 0x21 +#define SUPOERIO_CONF2 0x21 +#define PGCS_INDEX 0x22 +#define PGCS_DATA 0x22 + +/* values above 30 are different for each logical device + but I can't be arsed to enter them all. the ones here + are pretty consistent between all logical devices + feel free to correct the situation if you want.. ;) + */ +#define ACTIVATE 0x30 +#define ACTIVATE_OFF 0x00 +#define ACTIVATE_ON 0x01 + +#define BASE_ADDR_HIGH 0x60 +#define BASE_ADDR_LOW 0x61 + +/* the logical devices*/ +#define LDEV_KBC1 0x00 /* 2 devices for keyboard and mouse controller*/ +#define LDEV_KBC2 0x01 +#define LDEV_RTC_APC 0x02 /*Real Time Clock and Advanced Power Control*/ +#define LDEV_FDC 0x03 /*floppy disk controller*/ +#define LDEV_PARP 0x04 /*Parallel port*/ +#define LDEV_UART1 0x05 +#define LDEV_UART2 0x06 +#define LDEV_GPIO 0x07 /*Gennerla Purpose IO and chip select output signals*/ +#define LDEV_POWRMAN 0x08 /*Power Managment*/ + +/*some functions and macro's for doing configuration */ + +static inline void write_pnp_config(unsigned char index, unsigned char data) +{ + pci_writeb(index,IO_INDEX); + pci_writeb(data, IO_DATA); +} + +static inline void pnp_set_device(unsigned char dev) +{ + write_pnp_config(LOGICAL_DEVICE, dev); +} + + +/*void write_pnp_config(unsigned char index, unsigned char data); +void pnp_set_device(unsigned char dev); +*/ + +#define PNP_SET_DEVICE_BASE(dev,base) \ + pnp_set_device(dev); \ + write_pnp_config(ACTIVATE, ACTIVATE_OFF); \ + write_pnp_config(BASE_ADDR_HIGH, ((base) >> 8) & 0xff ); \ + write_pnp_config(BASE_ADDR_LOW, (base) &0xff); \ + write_pnp_config(ACTIVATE, ACTIVATE_ON); + +#define PNP_ACTIVATE_DEVICE(dev) \ + pnp_set_device(dev); \ + write_pnp_config(ACTIVATE, ACTIVATE_ON); + +#define PNP_DEACTIVATE_DEVICE(dev) \ + pnp_set_device(dev); \ + write_pnp_config(ACTIVATE, ACTIVATE_OFF); + + +static inline void write_pgcs_config(unsigned char index, unsigned char data) +{ + write_pnp_config(PGCS_INDEX, index); + write_pnp_config(PGCS_DATA, data); +} + +/* these macrose configure the 3 CS lines + on the sandpoint board these controll NVRAM + CS0 is connected to NVRAMCS + CS1 is connected to NVRAMAS0 + CS2 is connected to NVRAMAS1 + */ +#define PGCS_CS_ASSERT_ON_WRITE 0x10 +#define PGCS_CS_ASSERT_ON_READ 0x20 + +#define PNP_PGCS_CSLINE_BASE(cs, base) \ + write_pgcs_config((cs) << 2, ((base) >> 8) & 0xff ); \ + write_pgcs_config(((cs) << 2) + 1, (base) & 0xff ); + +#define PNP_PGCS_CSLINE_CONF(cs, conf) \ + write_pgcs_config(((cs) << 2) + 2, (conf) ); + + +/* The following sections are for 87308 extensions to the standard compoents it emulates */ + +/* extensions to 16550*/ + +#define MCR_MDSL_MSK 0xe0 /*mode select mask*/ +#define MCR_MDSL_UART 0x00 /*uart, default*/ +#define MCR_MDSL_SHRPIR 0x02 /*Sharp IR*/ +#define MCR_MDSL_SIR 0x03 /*SIR*/ +#define MCR_MDSL_CIR 0x06 /*Consumer IR*/ + +#define FCR_TXFTH0 0x10 /* these bits control threshod of data level in fifo */ +#define FCR_TXFTH1 0x20 /* for interrupt trigger */ + + +#endif /*_NS87308_H_*/ diff --git a/sandpoint/ppcboot.lds b/sandpoint/ppcboot.lds new file mode 100644 index 0000000..9754ffa --- /dev/null +++ b/sandpoint/ppcboot.lds @@ -0,0 +1,101 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com + * + * 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 + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); + +MEMORY { + ram (!rx) : org = 0x00000000 , LENGTH = 8M + code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000) + rom (rx) : org = 0xfe000000 , LENGTH = (0x100000000 - 0xfe000000) +} + +SECTIONS +{ + _f_init = .; + PROVIDE(_f_init = .); + _f_init_rom = .; + PROVIDE(_f_init_rom = .); + + .init : { + mpc8240/start.o (.text) + *(.init) + } > ram + _init_size = SIZEOF(.init); + PROVIDE(_init_size = SIZEOF(.init)); + + ENTRY(_start) + +/* _ftext = .; + _ftext_rom = .; + _text_size = SIZEOF(.text); + */ + .text : { + *(.text) + *(.got1) + } > ram + .rodata : { *(.rodata) } > ram + .dtors : { *(.dtors) } > ram + .data : { *(.data) } > ram + .sdata : { *(.sdata) } > ram + .sdata2 : { *(.sdata2) + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } > ram + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .sbss : { *(.sbss) } > ram + .sbss2 : { *(.sbss2) } > ram + .bss : { *(.bss) } > ram + .debug : { *(.debug) } > ram + .line : { *(.line) } > ram + .symtab : { *(.symtab) } > ram + .shrstrtab : { *(.shstrtab) } > ram + .strtab : { *(.strtab) } > ram + /* .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } > ram + */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } > ram + __stop___ex_table = .; + + + .ppcenv : + { + common/environment.o (.ppcenv) + } > ram + + _end = . ; + PROVIDE (end = .); +} + diff --git a/sandpoint/ppcboot.lds.mw.debug b/sandpoint/ppcboot.lds.mw.debug new file mode 100644 index 0000000..9754ffa --- /dev/null +++ b/sandpoint/ppcboot.lds.mw.debug @@ -0,0 +1,101 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com + * + * 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 + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); + +MEMORY { + ram (!rx) : org = 0x00000000 , LENGTH = 8M + code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000) + rom (rx) : org = 0xfe000000 , LENGTH = (0x100000000 - 0xfe000000) +} + +SECTIONS +{ + _f_init = .; + PROVIDE(_f_init = .); + _f_init_rom = .; + PROVIDE(_f_init_rom = .); + + .init : { + mpc8240/start.o (.text) + *(.init) + } > ram + _init_size = SIZEOF(.init); + PROVIDE(_init_size = SIZEOF(.init)); + + ENTRY(_start) + +/* _ftext = .; + _ftext_rom = .; + _text_size = SIZEOF(.text); + */ + .text : { + *(.text) + *(.got1) + } > ram + .rodata : { *(.rodata) } > ram + .dtors : { *(.dtors) } > ram + .data : { *(.data) } > ram + .sdata : { *(.sdata) } > ram + .sdata2 : { *(.sdata2) + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } > ram + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .sbss : { *(.sbss) } > ram + .sbss2 : { *(.sbss2) } > ram + .bss : { *(.bss) } > ram + .debug : { *(.debug) } > ram + .line : { *(.line) } > ram + .symtab : { *(.symtab) } > ram + .shrstrtab : { *(.shstrtab) } > ram + .strtab : { *(.strtab) } > ram + /* .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } > ram + */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } > ram + __stop___ex_table = .; + + + .ppcenv : + { + common/environment.o (.ppcenv) + } > ram + + _end = . ; + PROVIDE (end = .); +} + diff --git a/sandpoint/sandpoint.c b/sandpoint/sandpoint.c new file mode 100644 index 0000000..b1a3fb9 --- /dev/null +++ b/sandpoint/sandpoint.c @@ -0,0 +1,100 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 + */ + +#include + +int checkboard (void) +{ + printf("Sandpoint "); + /*TODO: Check processor type*/ + printf("8240 Unity ##Test not implemented yet##\n"); + return 0; +} + +int checkflash (void) +{ + /* TODO: XXX XXX XXX */ + printf ("8 MB ## Test not implemented yet ##\n"); + + return (0); +} + +long int dram_size (int board_type) +{ + /* No actual initialisation to do - done when setting up PICRs MCCRs ME/SARs etc + * in cpu_init.c - done there to keep init sequence same as Dink. May be able to move some of + * it here and refine the configuration defines to be more high-level, but I haven't had time + * to investigate that yet + */ + #if defined(CFG_MEM_TEST) + + register unsigned long reg; + + //write each mem addr with it's address + for (reg = CFG_MEM_TEST_START; reg < CGF_MEM_TEST_END; reg+=4 + *reg = reg; + + for (reg = CFG_MEM_TEST_START; reg < CGF_MEM_TEST_END; reg+=4 + { + if (*reg != reg) + return -1; + } + #endif + + //TODO: calculate amount of dram..for now just return MEMTEST_END + return CFG_MEMTEST_END; + +} + +long int initdram(int board_type) +{ +return dram_size(board_type); +} + + + +/*temporarlyily here: to be removed:*/ + + +int eth_init(bd_t *bis) +{ + /* Initialize the device */ + return 0; +} + +int eth_send(volatile void *packet, int length) +{ + /* Send a packet */ + return 0; +} + +int eth_rx(void) +{ + /* Check for received packets */ + return 0; +} + +void eth_halt(void) +{ + /* stop ethernet */ +} diff --git a/sandpoint/serial.c b/sandpoint/serial.c new file mode 100644 index 0000000..ec7afa0 --- /dev/null +++ b/sandpoint/serial.c @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 + */ + +#include "ns16550.h" + +void initialise_ns87308(void); + +/* + * Minimal serial functions needed to use one87308's UARTs + * as serial console interface. + */ + +volatile struct NS16550 *console; + +void +serial_init (unsigned long dummy, int baudrate) +{ + int clock_divisor = 115200/baudrate; + initialise_ns87308(); + console = NS16550_init(0, clock_divisor); +} + +void +serial_putc(const char c) +{ + NS16550_putc(console, c); +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + + +int +serial_getc(void) +{ + return NS16550_getc(console); +} + +int +serial_tstc(void) +{ + return NS16550_tstc(console); +} + +void +serial_setbrg (unsigned long dummy, int baudrate) +{ + int clock_divisor = 115200/baudrate; + NS16550_reinit(console, clock_divisor); +} diff --git a/sandpoint/serial.h b/sandpoint/serial.h new file mode 100644 index 0000000..94ab81e --- /dev/null +++ b/sandpoint/serial.h @@ -0,0 +1,23 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 + */ + diff --git a/sandpoint/speed.c b/sandpoint/speed.c new file mode 100644 index 0000000..c44297c --- /dev/null +++ b/sandpoint/speed.c @@ -0,0 +1,114 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +#include +#include +#include +#include "speed.h" + +/*use UART2 to measure bus speed*/ +#include "ns16550.h" + + +/* Access functions for the Machine State Register */ +static __inline__ unsigned long get_msr(void) +{ + unsigned long msr; + + asm volatile("mfmsr %0" : "=r" (msr) :); + return msr; +} + +static __inline__ void set_msr(unsigned long msr) +{ + asm volatile("mtmsr %0" : : "r" (msr)); +} + +/* ------------------------------------------------------------------------- */ + +ulong get_bus_freq (ulong ignore) +{ + /* measure the bus frequency using UART2 */ + /* 1st initilise it to run at 9600 + it takes approx 10*(1/9600) us to sens an 8N1 character at 9600bps + but due to chrystal inaccuracies on sandpoint we use 1145us */ + + int count=0, start, end; + int i; + volatile struct NS16550 *uart2; + + uart2=NS16550_init(1,115200/9600); + + + for (i =0; i< 10 ; i++) + { + NS16550_putc(uart2,0); /*send NUL*/ + start=mfspr(DEC); + NS16550_putc(uart2,0); /*send NUL*/ + end=mfspr(DEC); + count +=(start-end); + } + + count /=10; /*average number of decrements per char send*/ + count *=4; /*1 decrement per 4 bus cycles*/ + + /*time taken to do count cycles = 1145 us + therefore number of cycles per second is (1/(1145*10-6))*count + */ + return (1000000/1145)*count; +} + +/* ------------------------------------------------------------------------- */ + +/* + * Measure CPU clock speed + */ + +/*table to convert pllratio to actual processor clock scaling factor (*10)*/ +/* if you are using a a different processor with your sandpoint, + have a look at pmc.c in the dink source for values, or + figure it out from the hardware book*/ + +#ifdef CONFIG_MPC8240 +short pllratio_to_factor[] = { + 00, 00, 00, 10, 20, 20, 25, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 10, 00, 00, 00, 45, 30, 00, 40, 00, 00, 00, 35, 00, +}; +#endif + +ulong get_gclk_freq (void) +{ + uint hid1; + hid1=mfspr(HID1); + #ifdef CONFIG_MPC8240 + hid1=(hid1 >> (32-5)) & 0x1f; /* 5 bits for PLL ration on 8240*/ + #else + hid1=(hid1 >> (32-4)) & 0xf; /* 4 bits on everythings else*/ + #endif + + return (pllratio_to_factor[hid1] * get_bus_freq(0))/10; + +} + +/* ------------------------------------------------------------------------- */ + diff --git a/sandpoint/speed.h b/sandpoint/speed.h new file mode 100644 index 0000000..204f7ec --- /dev/null +++ b/sandpoint/speed.h @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +/*----------------------------------------------------------------------- + * Timer value for timer 2, ICLK = 10 + * + * SPEED_FCOUNT2 = GCLK / (16 * (TIMER_TMR_PS + 1)) + * SPEED_TMR3_PS = (GCLK / (16 * SPEED_FCOUNT3)) - 1 + * + * SPEED_FCOUNT2 timer 2 counting frequency + * GCLK CPU clock + * SPEED_TMR2_PS prescaler + */ +#define SPEED_TMR2_PS (250 - 1) /* divide by 250 */ + +/*----------------------------------------------------------------------- + * Timer value for PIT + * + * PIT_TIME = SPEED_PITC / PITRTCLK + * PITRTCLK = 8192 + */ +#define SPEED_PITC (82 << 16) /* start counting from 82 */ + +/* + * The new value for PTA is calculated from + * + * PTA = (gclk * Trefresh) / (2 ^ (2 * DFBRG) * PTP * NCS) + * + * gclk CPU clock (not bus clock !) + * Trefresh Refresh cycle * 4 (four word bursts used) + * DFBRG For normal mode (no clock reduction) always 0 + * PTP Prescaler (already adjusted for no. of banks and 4K / 8K refresh) + * NCS Number of SDRAM banks (chip selects) on this UPM. + */ diff --git a/sandpoint/w83c553f.c b/sandpoint/w83c553f.c new file mode 100644 index 0000000..aac06e1 --- /dev/null +++ b/sandpoint/w83c553f.c @@ -0,0 +1,24 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 + */ + +#include "w83c553f.h" diff --git a/sandpoint/w83c553f.h b/sandpoint/w83c553f.h new file mode 100644 index 0000000..79fe669 --- /dev/null +++ b/sandpoint/w83c553f.h @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 + */ + + /* winbond access routines and defines*/ + +/* from the winbond data sheet - + The W83C553F SIO controller with PCI arbiter is a multi-function PCI device. + Function 0 is the ISA bridge, and Function 1 is the bus master IDE controller. +*/ + +/*ISA bridge configuration space*/ + +#define WINBOND_PCICONTR 0x40 /*pci control reg*/ +#define WINBOND_SGBAR 0x41 /*scatter/gather base address reg*/ +#define WINBOND_LBCR 0x42 /*Line Buffer Control reg*/ +#define WINBOND_IDEIRCR 0x43 /*IDE Interrupt Routing Control Reg*/ +#define WINBOND_PCIIRCR 0x44 /*PCI Interrupt Routing Control Reg*/ +#define WINBOND_BTBAR 0x46 /*BIOS Timer Base Address Register*/ +#define WINBOND_IPADCR 0x48 /*ISA to PCI Address Decoder Control Register*/ +#define WINBOND_IRADCR 0x49 /*ISA ROM Address Decoder Control Register*/ +#define WINBOND_IPMHSAR 0x4a /*ISA to PCI Memory Hole STart Address Register*/ +#define WINBOND_IPMHSR 0x4b /*ISA to PCI Memory Hols Size Register*/ +#define WINBOND_CDR 0x4c /*Clock Divisor Register*/ +#define WINBOND_CSCR 0x4d /*Chip Select Control Register*/ +#define WINBOND_ATSCR 0x4e /*AT System Control register*/ +#define WINBOND_ATBCR 0x4f /*AT Bus ControL Register*/ +#define WINBOND_IRQBEE0R 0x60 /*IRQ Break Event Enable 0 Register*/ +#define WINBOND_IRQBEE1R 0x61 /*IRQ Break Event Enable 1 Register*/ +#define WINBOND_ABEER 0x62 /*Additional Break Event Enable Register*/ +#define WINBOND_DMABEER 0x63 /*DMA Break Event Enable Register*/ + + diff --git a/tools/gdb/Makefile b/tools/gdb/Makefile index 68e68ac..670d3ca 100644 --- a/tools/gdb/Makefile +++ b/tools/gdb/Makefile @@ -35,6 +35,10 @@ CFLAGS = $(CPPFLAGS) CC = $(HOSTCC) MAKEDEPEND = makedepend +ifeq ($(OSTYPE),cygwin) +all: +.depend: +else all: $(BINS) gdbsend: gdbsend.o error.o remote.o serial.o @@ -60,3 +64,5 @@ distclean: clean -include .depend ######################################################################### + +endif # cygwin diff --git a/tools/gdb/remote.c b/tools/gdb/remote.c index d736c65..5e33c0a 100644 --- a/tools/gdb/remote.c +++ b/tools/gdb/remote.c @@ -12,7 +12,35 @@ #include #include #include + +/*nicked from gcc..*/ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) #include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +extern "C" { + void* alloca(size_t); +} +#endif /* alloca not defined. */ + + #include "serial.h" #include "error.h" #include "remote.h" diff --git a/tools/img2srec.c b/tools/img2srec.c index b153d0d..330ae02 100644 --- a/tools/img2srec.c +++ b/tools/img2srec.c @@ -59,6 +59,7 @@ #include #include #include +#include extern int errno; diff --git a/tools/mkimage.c b/tools/mkimage.c index 9c1a2f3..5bf8902 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -4,8 +4,8 @@ * Wolfgang Denk, wd@denx.de * All rights reserved. * - * $Date: 2000/10/25 10:46:51 $ - * $Revision: 1.9 $ + * $Date: 2000/11/16 20:16:58 $ + * $Revision: 1.10 $ */ #include @@ -23,6 +23,10 @@ extern int errno; +#ifndef MAP_FAILED +#define MAP_FAILED -1 +#endif + char *cmdname; extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); @@ -309,7 +313,7 @@ NXTARG: ; if (opt_type == IH_TYPE_MULTI) { char *file = datafile; - ulong size; + unsigned long size; for (;;) { char *sep = NULL; @@ -515,7 +519,9 @@ print_header (image_header_t *hdr) if (hdr->ih_type == IH_TYPE_MULTI) { int i; - ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t)); + unsigned long *len_ptr = (unsigned long *) ( + (unsigned long)hdr + sizeof(image_header_t) + ); printf ("Contents:\n"); for (i=0; *len_ptr; ++i, ++len_ptr) {