/*
 * (C) Copyright 2000, 2001
 * 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 _PPCBOOT_H_
#define _PPCBOOT_H_	1

#undef	_LINUX_CONFIG_H
#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/

typedef unsigned char		uchar;
typedef volatile unsigned long	vu_long;
typedef volatile unsigned short	vu_short;

#include "config.h"
#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/string.h>
#include <asm/ptrace.h>
#include <stdarg.h>
#ifdef	CONFIG_8xx
#include <asm/8xx_immap.h>
#elif defined(CONFIG_8260)
#include <asm/immap_8260.h>
#endif
#ifdef	CONFIG_4xx
#include <ppc4xx.h>
#endif
#ifdef CONFIG_HYMOD
#include <asm/hymod.h>
#endif

#include <part.h>
#include <flash.h>
#include <image.h>

#ifdef	DEBUG
#define debug(fmt,args...)	printf (fmt ,##args)
#else
#define debug(fmt,args...)
#endif

typedef	void (interrupt_handler_t)(void *);

typedef struct monitor_functions {
	int	(*getc)(void);
	int	(*tstc)(void);
	void	(*putc)(const char c);
	void	(*puts)(const char *s);
	void	(*printf)(const char *fmt, ...);
	void	(*install_hdlr)(int, interrupt_handler_t *, void *);
	void	(*free_hdlr)(int);
	void	*(*malloc)(size_t);
	void	(*free)(void *);
} mon_fnc_t;

/* A Board Information structure that is given to a program when
 * ppcboot starts it up.
 */
typedef struct bd_info {
	unsigned long	bi_memstart;	/* start of  DRAM memory		*/
	unsigned long	bi_memsize;	/* size	 of  DRAM memory in bytes	*/
	unsigned long	bi_flashstart;	/* start of FLASH memory		*/
	unsigned long	bi_flashsize;	/* size	 of FLASH memory		*/
	unsigned long	bi_flashoffset; /* reserved area for startup monitor	*/
	unsigned long	bi_sramstart;	/* start of  SRAM memory		*/
	unsigned long	bi_sramsize;	/* size	 of  SRAM memory		*/
#if defined(CONFIG_8xx) || defined(CONFIG_8260)
	unsigned long	bi_immr_base;	/* base of IMMR register		*/
#endif
	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS)	*/
	unsigned long	bi_ip_addr;	/* IP Address				*/
	unsigned char	bi_enetaddr[6]; /* Ethernet adress			*/
	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps		*/
	unsigned long	bi_intfreq;	/* Internal Freq, in MHz		*/
	unsigned long	bi_busfreq;	/* Bus Freq, in MHz			*/
#if defined(CONFIG_8260)
	unsigned long	bi_cpmfreq;	/* CPM_CLK Freq, in MHz */
	unsigned long	bi_brgfreq;	/* BRG_CLK Freq, in MHz */
	unsigned long	bi_sccfreq;	/* SCC_CLK Freq, in MHz */
	unsigned long	bi_vco;		/* VCO Out from PLL, in MHz */
#endif
	unsigned long	bi_baudrate;	/* Console Baudrate			*/
#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
	unsigned char	bi_s_version[4];  /* Version of this structure		*/
	unsigned char	bi_r_version[32]; /* Version of the ROM (IBM)		*/
	unsigned int	bi_procfreq;	/* CPU (Internal) Freq, in Hz		*/
	unsigned int	bi_plb_busfreq;	/* PLB Bus speed, in Hz */
	unsigned int	bi_pci_busfreq;	/* PCI Bus speed, in Hz */
	unsigned char	bi_pci_enetaddr[6];	/* PCI Ethernet MAC address     */
#endif
#if defined(CONFIG_HYMOD)
	hymod_conf_t	bi_hymod_conf;	/* hymod configuration information	*/
#endif
#if defined(CONFIG_EVB64260)
	/* the board has three onboard ethernet ports */
	unsigned char   bi_enet1addr[6];
	unsigned char   bi_enet2addr[6];
#endif
#if defined(CONFIG_NX823)
	unsigned char	bi_sernum[8];
#endif
	mon_fnc_t	*bi_mon_fnc;	/* Pointer to monitor functions		*/
} bd_t;

/* The following data structure is placed in DPRAM to allow for a
 * minimum set of global variables during system initialization
 * (until we have set up the memory controller so that we can use
 * RAM).
 *
 * Keep it *SMALL* and remember to set CFG_INIT_DATA_SIZE > sizeof(init_data_t)
 */
typedef	struct	init_data {
#if !defined(CONFIG_8260)
	unsigned long	cpu_clk;	/* VCOOUT = CPU clock in Hz!		*/
#else
	/* There are many clocks on the MPC8260 - see page 9-5 */
	unsigned long	vco_out;
	unsigned long	cpm_clk;
	unsigned long	bus_clk;
	unsigned long	scc_clk;
	unsigned long	brg_clk;
	unsigned long	cpu_clk;
	unsigned long	reset_status;	/* reset status register at boot	*/
#endif
	unsigned long	env_addr;	/* Address  of Environment struct	*/
	unsigned long	env_valid;	/* Checksum of Environment valid?	*/
	unsigned long	relocated;	/* Relocat. offset when running in RAM 	*/
	unsigned long	have_console;	/* serial_init() was called		*/
	mon_fnc_t	bi_mon_fnc;	/* Monitor functions			*/
#if defined(CFG_ALLOC_DPRAM) || defined(CONFIG_8260)
	unsigned int	dp_alloc_base;
	unsigned int	dp_alloc_top;
#endif
#if defined(CONFIG_SANDPOINT)
	void *		console_addr;
#endif
} init_data_t;

/*
 * Function Prototypes
 */
void	hang	      (void);


/* */
long int initdram (int);
void	display_options	 (void);

/* common/main.c */
void	main_loop	(bd_t *bd);
int	run_command	(const char *cmd, bd_t *bd, int flag);
int	readline	(const char *const prompt);
void	reset_cmd_timeout(void);

/* common/board.c */
void	board_init_f  (ulong);
void	board_init_r  (bd_t *, ulong);
int	checkboard    (void);
int	checkflash    (void);
int	checkdram     (void);
char *	strmhz(char *buf, long hz);

/* common/cmd_bootm.c */
void print_image_hdr (image_header_t *hdr);

extern ulong load_addr;		/* Default Load Address	*/

/* common/cmd_nvedit.c */
void		env_init (init_data_t *);
void		env_relocate (ulong);
char 	       *getenv (uchar *);
int	      getenv_r (uchar *name, uchar *buf, unsigned len);
void inline 	setenv (char *, char *);

#if defined(CONFIG_CPCI405)	|| \
    defined(CONFIG_AR405)	|| \
    defined (CONFIG_WALNUT405)	|| \
    defined (CONFIG_PIP405)	|| \
    defined (CONFIG_CPCIISER4)	|| \
    defined (CONFIG_OCRTC)	|| \
    defined (CONFIG_DASA_SIM)	|| \
    defined (CONFIG_ERIC)	|| \
    defined (CONFIG_MOUSSE)
/* $(CPU)/405gp_pci.c */
void    pci_init      (bd_t *);
void    pciinfo       (int);
#endif

#if defined(CONFIG_COGENT)	|| defined(CONFIG_SXNI855T)	|| \
    defined(CONFIG_RSD_PROTO)	|| defined(CONFIG_HYMOD)	|| \
    defined(CONFIG_CPCI405)	|| defined(CONFIG_PCU_E)        || \
    defined(CONFIG_EVB64260)	|| defined(CONFIG_LWMON) 	|| \
    defined(CONFIG_CCM)		|| \
    defined(CONFIG_MISC_INIT_R)
/* cogent - $(BOARD)/mb.c */
/* SXNI855T and HYMOD - $(BOARD)/$(BOARD).c */
# if !defined(CONFIG_PCU_E) && !defined(CONFIG_CCM)
int	misc_init_f   (void);
# endif
void	misc_init_r   (bd_t *);
#endif

#if defined(CONFIG_SPD823TS)	|| \
    defined(CONFIG_IVMS8)	|| \
    defined(CONFIG_IVML24)	|| \
    defined(CONFIG_IP860)	|| \
    defined(CONFIG_LWMON)	|| \
    defined(CONFIG_MPC8260ADS)	|| \
    defined(CONFIG_RPXSUPER)	|| \
    defined(CONFIG_PCU_E)	|| \
    defined(CONFIG_CCM)
/* $(BOARD)/$(BOARD).c */
void	reset_phy     (void);
#endif

#if defined(CONFIG_IP860)	|| \
    defined(CONFIG_SXNI855T)	|| \
    defined(CONFIG_CPCI405)	|| \
    defined(CONFIG_CANBT)	|| \
    defined(CONFIG_WALNUT405)	|| \
    defined(CONFIG_PIP405)	|| \
    defined(CONFIG_CPCIISER4)	|| \
    defined(CONFIG_OCRTC)	|| \
    defined(CONFIG_LWMON)	|| \
    defined(CONFIG_TQM8260)	|| \
    defined(CONFIG_PM826)	|| \
    defined(CONFIG_PCU_E)	|| \
    defined(CONFIG_CCM)		|| \
    defined(CONFIG_HYMOD)
/* $(BOARD)/eeprom.c */
void eeprom_init  (void);
void eeprom_read  (unsigned offset, uchar *buffer, unsigned cnt);
void eeprom_write (unsigned offset, uchar *buffer, unsigned cnt);
# ifdef CONFIG_LWMON
extern uchar pic_read  (uchar reg);
extern void  pic_write (uchar reg, uchar val);
# endif
#endif

#if defined(CONFIG_PCU_E) || defined(CONFIG_CCM)
extern void spi_init_f (void);
extern void spi_init_r (void);
extern ssize_t spi_read  (uchar *, int, uchar *, int);
extern ssize_t spi_write (uchar *, int, uchar *, int);
#endif

#ifdef CONFIG_MBX
/* $(BOARD)/mbx8xx.c */
void	mbx_init (void);
void	board_get_enetaddr (uchar *addr);
void	board_serial_init (void);
void	board_ether_init (void);
#endif

#ifdef CONFIG_HERMES
/* $(BOARD)/hermes.c */
void hermes_set_led (int);
void hermes_show_led_err (int);
void hermes_flash_led (void);
void hermes_start_lxt980 (int speed);
#endif

#ifdef CONFIG_EVB64260
void  evb64260_init(void);
void  debug_led(int, int);
void  display_mem_map(void);
void  perform_soft_reset(void);
#endif

#ifdef CONFIG_NX823
void	load_sernum_ethaddr(bd_t *bd);
#endif

#if defined(CONFIG_CPCI405)	|| \
    defined(CONFIG_AR405)	|| \
    defined(CONFIG_CANBT)	|| \
    defined(CONFIG_WALNUT405)	|| \
    defined(CONFIG_PIP405)	|| \
    defined(CONFIG_CPCIISER4)	|| \
    defined(CONFIG_OCRTC)	|| \
    defined(CONFIG_ADCIOP)	|| \
    defined(CONFIG_DASA_SIM)	|| \
    defined(CONFIG_LWMON)	|| \
    defined(CONFIG_MPC8260ADS)	|| \
    defined(CONFIG_RPXSUPER)	|| \
    defined(CONFIG_CU824)	|| \
    defined(CONFIG_EVB64260)	|| \
    defined(CONFIG_BOARD_PRE_INIT)
/* $(BOARD)/$(BOARD).c */
int	board_pre_init (void);
#endif
#if defined(CONFIG_HYMOD)
void	board_postclk_init(void); /* after clocks/timebase, before env/serial */
#endif

/* $(CPU)/serial.c */
void	serial_init   (ulong, int);
void	serial_setbrg (ulong, int);
void	serial_putc   (const char);
void	serial_puts   (const char *);
void	serial_addr   (unsigned int);
int	serial_getc   (void);
int	serial_tstc   (void);
#if CONFIG_SERIAL_SOFTWARE_FIFO
void	serial_buffered_init (void);
void	serial_buffered_putc (const char);
void	serial_buffered_puts (const char *);
int	serial_buffered_getc (void);
int	serial_buffered_tstc (void);
#endif

/* $(CPU)/start.S */
#ifdef	CONFIG_8xx
uint	get_immr      (uint);
#endif
uint	get_pvr	      (void);
uint	rd_ic_cst     (void);
void	wr_ic_cst     (uint);
void	wr_ic_adr     (uint);
uint	rd_dc_cst     (void);
void	wr_dc_cst     (uint);
void	wr_dc_adr     (uint);
int	icache_status (void);
void	icache_enable (void);
void	icache_disable(void);
int	dcache_status (void);
void	dcache_enable (void);
void	dcache_disable(void);
void	relocate_code (ulong, bd_t *, ulong);
ulong	get_endaddr   (void);
void	trap_init     (ulong);
#ifdef  CONFIG_4xx
unsigned char   in8(unsigned int);
void            out8(unsigned int, unsigned char);
unsigned short  in16(unsigned int);
unsigned short  in16r(unsigned int);
void            out16(unsigned int, unsigned short value);
void            out16r(unsigned int, unsigned short value);
unsigned long   in32(unsigned int);
unsigned long   in32r(unsigned int);
void            out32(unsigned int, unsigned long value);
void            out32r(unsigned int, unsigned long value);
void            ppcDcbf(unsigned long value);
void            ppcDcbi(unsigned long value);
void            ppcSync(void);
#endif

/* $(CPU)/cpu.c */
int	checkcpu      (long);
int	checkicache   (void);
int	checkdcache   (void);
void	upmconfig     (unsigned int, unsigned int *, unsigned int);
ulong	get_tbclk     (void);
#if defined(CONFIG_WATCHDOG)
void	watchdog_reset(void);
#endif	/* CONFIG_WATCHDOG */

/* $(CPU)/speed.c */
#if defined(CONFIG_8260)
void	get_8260_clks (void);
void	prt_8260_clks (void);
#elif defined(CONFIG_8xx)	|| \
      defined(CONFIG_IOP480)	|| \
      defined(CONFIG_4xx)	|| \
      defined(CONFIG_CU824)	|| \
      defined(CONFIG_EVB64260)	|| \
      defined(CONFIG_MOUSSE)
ulong	get_gclk_freq (void);
ulong get_OPB_freq (void);
#ifdef CONFIG_4xx
ulong get_PCI_freq (void);
#endif
#endif

ulong	get_bus_freq  (ulong);

#if defined(CONFIG_4xx) || defined(CONFIG_IOP480)
void    get_sys_info  (PPC405_SYS_INFO *);
#endif

/* $(CPU)/cpu.c */
#if defined(CONFIG_8xx)
void reset_8xx_watchdog(volatile immap_t *immr);
#endif

/* $(CPU)/cpu.c */
#if defined(CONFIG_4xx)
void reset_4xx_watchdog(void);
#endif

/* $(CPU)/cpu_init.c */
#if defined(CONFIG_8xx) || defined(CONFIG_8260)
void	cpu_init_f    (volatile immap_t *immr);
#endif
#ifdef	CONFIG_4xx
void	cpu_init_f    (void);
#endif
void	cpu_init_r    (bd_t *bd);
#if defined(CONFIG_8260)
void	prt_8260_rsr  (void);
#endif

/* $(CPU)/interrupts.c */
void	interrupt_init     (bd_t *bd);
void	timer_interrupt    (struct pt_regs *);
void	external_interrupt (struct pt_regs *);
void	irq_install_handler(int, interrupt_handler_t *, void *);
void	irq_free_handler   (int);
void	reset_timer	   (void);
ulong	get_timer	   (ulong base);
void	set_timer	   (ulong t);
void	enable_interrupts  (void);
int	disable_interrupts (void);

/* $(CPU)/traps.c */

/* ppc/ticks.S */
unsigned long long get_ticks(void);
void	wait_ticks    (unsigned long);

/* ppc/time.c */
void	udelay	      (unsigned long);
ulong	usec2ticks    (unsigned long usec);
ulong	ticks2usec    (unsigned long ticks);
void	init_timebase (void);

/* ppc/vsprintf.c */
ulong	simple_strtoul(const char *cp,char **endp,unsigned int base);
long	simple_strtol(const char *cp,char **endp,unsigned int base);
void	panic(const char *fmt, ...);
int	sprintf(char * buf, const char *fmt, ...);
int 	vsprintf(char *buf, const char *fmt, va_list args);

/* ppc/crc32.c */
ulong crc32 (ulong, const unsigned char *, uint);

/* common/console.c */
bd_t	*bd_ptr ;

void	console_init_f(void);	/* Before relocation; uses the serial  stuff	*/
void	console_init_r(ulong);	/* After  relocation; uses the console stuff	*/
int	console_assign (int file, char *devname);	/* Assign the console	*/
int	ctrlc (void);
int	had_ctrlc (void);	/* have we had a Control-C since last clear? */
void	clear_ctrlc (void);	/* clear the Control-C condition */
int	disable_ctrlc (int);	/* 1 to disable, 0 to enable Control-C detect */

/*
 * STDIO based functions (can always be used)
 */

/* serial stuff */
void	serial_printf (const char *fmt, ...);

/* stdin */
int	getc(void);
int	tstc(void);

/* stdout */
void	putc(const char c);
void	puts(const char *s);
void	printf(const char *fmt, ...);

/* stderr */
#define eputc(c)		fputc(stderr, c)
#define eputs(s)		fputs(stderr, s)
#define eprintf(fmt,args...)	fprintf(stderr,fmt ,##args)

/*
 * FILE based functions (can only be used AFTER relocation!)
 */

#define stdin		0
#define stdout		1
#define stderr		2
#define MAX_FILES	3

void	fprintf(int file, const char *fmt, ...);
void	fputs(int file, const char *s);
void	fputc(int file, const char c);
int	ftstc(int file);
int	fgetc(int file);

int	pcmcia_init (void);

#endif	/* _PPCBOOT_H_ */
