Skip to content
Snippets Groups Projects
cpu_init.c 11.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Wolfgang Denk's avatar
    Wolfgang Denk committed
    /*
    
     * (C) Copyright 2000-2006
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     * 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 <common.h>
    #include <watchdog.h>
    
    #include <ppc4xx_enet.h>
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #include <asm/processor.h>
    #include <ppc4xx.h>
    
    
    #if defined(CONFIG_405GP)  || defined(CONFIG_405EP)
    DECLARE_GLOBAL_DATA_PTR;
    #endif
    
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    #define mtebc(reg, data)  mtdcr(ebccfga,reg);mtdcr(ebccfgd,data)
    
    
    #ifdef CFG_INIT_DCACHE_CS
    # if (CFG_INIT_DCACHE_CS == 0)
    #  define PBxAP pb0ap
    #  define PBxCR pb0cr
    #  if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
    #   define PBxAP_VAL CFG_EBC_PB0AP
    #   define PBxCR_VAL CFG_EBC_PB0CR
    #  endif
    # endif
    # if (CFG_INIT_DCACHE_CS == 1)
    #  define PBxAP pb1ap
    #  define PBxCR pb1cr
    #  if (defined(CFG_EBC_PB1AP) && defined(CFG_EBC_PB1CR))
    #   define PBxAP_VAL CFG_EBC_PB1AP
    #   define PBxCR_VAL CFG_EBC_PB1CR
    #  endif
    # endif
    # if (CFG_INIT_DCACHE_CS == 2)
    #  define PBxAP pb2ap
    #  define PBxCR pb2cr
    #  if (defined(CFG_EBC_PB2AP) && defined(CFG_EBC_PB2CR))
    #   define PBxAP_VAL CFG_EBC_PB2AP
    #   define PBxCR_VAL CFG_EBC_PB2CR
    #  endif
    # endif
    # if (CFG_INIT_DCACHE_CS == 3)
    #  define PBxAP pb3ap
    #  define PBxCR pb3cr
    #  if (defined(CFG_EBC_PB3AP) && defined(CFG_EBC_PB3CR))
    #   define PBxAP_VAL CFG_EBC_PB3AP
    #   define PBxCR_VAL CFG_EBC_PB3CR
    #  endif
    # endif
    # if (CFG_INIT_DCACHE_CS == 4)
    #  define PBxAP pb4ap
    #  define PBxCR pb4cr
    #  if (defined(CFG_EBC_PB4AP) && defined(CFG_EBC_PB4CR))
    #   define PBxAP_VAL CFG_EBC_PB4AP
    #   define PBxCR_VAL CFG_EBC_PB4CR
    #  endif
    # endif
    # if (CFG_INIT_DCACHE_CS == 5)
    #  define PBxAP pb5ap
    #  define PBxCR pb5cr
    #  if (defined(CFG_EBC_PB5AP) && defined(CFG_EBC_PB5CR))
    #   define PBxAP_VAL CFG_EBC_PB5AP
    #   define PBxCR_VAL CFG_EBC_PB5CR
    #  endif
    # endif
    # if (CFG_INIT_DCACHE_CS == 6)
    #  define PBxAP pb6ap
    #  define PBxCR pb6cr
    #  if (defined(CFG_EBC_PB6AP) && defined(CFG_EBC_PB6CR))
    #   define PBxAP_VAL CFG_EBC_PB6AP
    #   define PBxCR_VAL CFG_EBC_PB6CR
    #  endif
    # endif
    # if (CFG_INIT_DCACHE_CS == 7)
    #  define PBxAP pb7ap
    #  define PBxCR pb7cr
    #  if (defined(CFG_EBC_PB7AP) && defined(CFG_EBC_PB7CR))
    #   define PBxAP_VAL CFG_EBC_PB7AP
    #   define PBxCR_VAL CFG_EBC_PB7CR
    #  endif
    # endif
    #endif /* CFG_INIT_DCACHE_CS */
    
    
    #if defined(CFG_440_GPIO_TABLE)
    gpio_param_s gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CFG_440_GPIO_TABLE;
    
    void set_chip_gpio_configuration(gpio_param_s (*gpio_tab)[GPIO_GROUP_MAX][GPIO_MAX])
    {
    	unsigned char i=0, j=0, reg_offset = 0, gpio_core;
    	unsigned long gpio_reg, gpio_core_add;
    
    	for (gpio_core=0; gpio_core<GPIO_GROUP_MAX; gpio_core++) {
    		j = 0;
    		reg_offset = 0;
    		/* GPIO config of the GPIOs 0 to 31 */
    		for (i=0; i<GPIO_MAX; i++, j++) {
    			if (i == GPIO_MAX/2) {
    				reg_offset = 4;
    				j = i-16;
    			}
    
    			gpio_core_add = (*gpio_tab)[gpio_core][i].add;
    
    			if (((*gpio_tab)[gpio_core][i].in_out == GPIO_IN) ||
    			     ((*gpio_tab)[gpio_core][i].in_out == GPIO_BI)) {
    
    				switch ((*gpio_tab)[gpio_core][i].alt_nb) {
    				case GPIO_SEL:
    					break;
    
    				case GPIO_ALT1:
    					gpio_reg = in32(GPIO_IS1(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
    					out32(GPIO_IS1(gpio_core_add+reg_offset), gpio_reg);
    					break;
    
    				case GPIO_ALT2:
    					gpio_reg = in32(GPIO_IS2(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
    					out32(GPIO_IS2(gpio_core_add+reg_offset), gpio_reg);
    					break;
    
    				case GPIO_ALT3:
    					gpio_reg = in32(GPIO_IS3(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
    					out32(GPIO_IS3(gpio_core_add+reg_offset), gpio_reg);
    					break;
    				}
    			}
    
    			if (((*gpio_tab)[gpio_core][i].in_out == GPIO_OUT) ||
    			     ((*gpio_tab)[gpio_core][i].in_out == GPIO_BI)) {
    
    				switch ((*gpio_tab)[gpio_core][i].alt_nb) {
    				case GPIO_SEL:
    					if (gpio_core == GPIO0) {
    						gpio_reg = in32(GPIO0_TCR) | (0x80000000 >> (j));
    						out32(GPIO0_TCR, gpio_reg);
    					}
    
    					if (gpio_core == GPIO1) {
    						gpio_reg = in32(GPIO1_TCR) | (0x80000000 >> (j));
    						out32(GPIO1_TCR, gpio_reg);
    					}
    
    					gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
    					gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
    					break;
    
    				case GPIO_ALT1:
    					gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_ALT1_SEL >> (j*2));
    					out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
    					gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_ALT1_SEL >> (j*2));
    					out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
    					break;
    
    				case GPIO_ALT2:
    					gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_ALT2_SEL >> (j*2));
    					out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
    					gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_ALT2_SEL >> (j*2));
    					out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
    					break;
    
    				case GPIO_ALT3:
    					gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_ALT3_SEL >> (j*2));
    					out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
    					gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
    						& ~(GPIO_MASK >> (j*2));
    					gpio_reg = gpio_reg | (GPIO_ALT3_SEL >> (j*2));
    					out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
    					break;
    				}
    			}
    		}
    	}
    }
    #endif /* CFG_440_GPIO_TABLE */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    /*
     * Breath some life into the CPU...
     *
     * Set up the memory map,
     * initialize a bunch of registers
     */
    void
    cpu_init_f (void)
    {
    
    Stefan Roese's avatar
    Stefan Roese committed
    #if defined(CONFIG_405EP)
    	/*
    	 * GPIO0 setup (select GPIO or alternate function)
    	 */
    
    #if defined(CFG_GPIO0_OR)
    	out32(GPIO0_OR, CFG_GPIO0_OR);		/* set initial state of output pins	*/
    #endif
    #if defined(CFG_GPIO0_ODR)
    	out32(GPIO0_ODR, CFG_GPIO0_ODR);	/* open-drain select			*/
    #endif
    	out32(GPIO0_OSRH, CFG_GPIO0_OSRH);	/* output select			*/
    
    Stefan Roese's avatar
    Stefan Roese committed
    	out32(GPIO0_OSRL, CFG_GPIO0_OSRL);
    
    	out32(GPIO0_ISR1H, CFG_GPIO0_ISR1H);	/* input select				*/
    
    Stefan Roese's avatar
    Stefan Roese committed
    	out32(GPIO0_ISR1L, CFG_GPIO0_ISR1L);
    
    	out32(GPIO0_TSRH, CFG_GPIO0_TSRH);	/* three-state select			*/
    
    Stefan Roese's avatar
    Stefan Roese committed
    	out32(GPIO0_TSRL, CFG_GPIO0_TSRL);
    
    	out32(GPIO0_TCR, CFG_GPIO0_TCR);	/* enable output driver for outputs	*/
    
    Stefan Roese's avatar
    Stefan Roese committed
    
    	/*
    	 * Set EMAC noise filter bits
    	 */
    	mtdcr(cpc0_epctl, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE);
    #endif /* CONFIG_405EP */
    
    
    #if defined(CFG_440_GPIO_TABLE)
    	set_chip_gpio_configuration(&gpio_tab);
    #endif /* CFG_440_GPIO_TABLE */
    
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	/*
    	 * External Bus Controller (EBC) Setup
    	 */
    #if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
    
    #if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
         defined(CONFIG_405EP) || defined(CONFIG_405))
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	/*
    	 * Move the next instructions into icache, since these modify the flash
    	 * we are running from!
    	 */
    	asm volatile("	bl	0f"		::: "lr");
    	asm volatile("0:	mflr	3"		::: "r3");
    	asm volatile("	addi 	4, 0, 14"	::: "r4");
    	asm volatile("	mtctr	4"		::: "ctr");
    	asm volatile("1:	icbt	0, 3");
    	asm volatile("	addi	3, 3, 32"	::: "r3");
    	asm volatile("	bdnz	1b"		::: "ctr", "cr0");
    	asm volatile("	addis	3, 0, 0x0"	::: "r3");
    	asm volatile("	ori	3, 3, 0xA000"	::: "r3");
    	asm volatile("	mtctr	3"		::: "ctr");
    	asm volatile("2:	bdnz	2b"		::: "ctr", "cr0");
    
    #endif
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    	mtebc(pb0ap, CFG_EBC_PB0AP);
    	mtebc(pb0cr, CFG_EBC_PB0CR);
    #endif
    
    
    #if (defined(CFG_EBC_PB1AP) && defined(CFG_EBC_PB1CR) && !(CFG_INIT_DCACHE_CS == 1))
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	mtebc(pb1ap, CFG_EBC_PB1AP);
    	mtebc(pb1cr, CFG_EBC_PB1CR);
    #endif
    
    
    #if (defined(CFG_EBC_PB2AP) && defined(CFG_EBC_PB2CR) && !(CFG_INIT_DCACHE_CS == 2))
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	mtebc(pb2ap, CFG_EBC_PB2AP);
    	mtebc(pb2cr, CFG_EBC_PB2CR);
    #endif
    
    
    #if (defined(CFG_EBC_PB3AP) && defined(CFG_EBC_PB3CR) && !(CFG_INIT_DCACHE_CS == 3))
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	mtebc(pb3ap, CFG_EBC_PB3AP);
    	mtebc(pb3cr, CFG_EBC_PB3CR);
    #endif
    
    
    #if (defined(CFG_EBC_PB4AP) && defined(CFG_EBC_PB4CR) && !(CFG_INIT_DCACHE_CS == 4))
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	mtebc(pb4ap, CFG_EBC_PB4AP);
    	mtebc(pb4cr, CFG_EBC_PB4CR);
    #endif
    
    
    #if (defined(CFG_EBC_PB5AP) && defined(CFG_EBC_PB5CR) && !(CFG_INIT_DCACHE_CS == 5))
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	mtebc(pb5ap, CFG_EBC_PB5AP);
    	mtebc(pb5cr, CFG_EBC_PB5CR);
    #endif
    
    
    #if (defined(CFG_EBC_PB6AP) && defined(CFG_EBC_PB6CR) && !(CFG_INIT_DCACHE_CS == 6))
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	mtebc(pb6ap, CFG_EBC_PB6AP);
    	mtebc(pb6cr, CFG_EBC_PB6CR);
    #endif
    
    
    #if (defined(CFG_EBC_PB7AP) && defined(CFG_EBC_PB7CR) && !(CFG_INIT_DCACHE_CS == 7))
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	mtebc(pb7ap, CFG_EBC_PB7AP);
    	mtebc(pb7cr, CFG_EBC_PB7CR);
    #endif
    
    #if defined(CONFIG_WATCHDOG)
    	unsigned long val;
    
    	val = mfspr(tcr);
    
    #if defined(CONFIG_440EP) || defined(CONFIG_440GR)
    
    	val |= 0xb8000000;      /* generate system reset after 1.34 seconds */
    #else
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	val |= 0xf0000000;      /* generate system reset after 2.684 seconds */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	mtspr(tcr, val);
    
    	val = mfspr(tsr);
    	val |= 0x80000000;      /* enable watchdog timer */
    	mtspr(tsr, val);
    
    	reset_4xx_watchdog();
    #endif /* CONFIG_WATCHDOG */
    }
    
    /*
     * initialize higher level parts of CPU like time base and timers
     */
    int cpu_init_r (void)
    {
    
    Stefan Roese's avatar
    Stefan Roese committed
    #if defined(CONFIG_405GP)  || defined(CONFIG_405EP)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	bd_t *bd = gd->bd;
    	unsigned long reg;
    
    Stefan Roese's avatar
    Stefan Roese committed
    #if defined(CONFIG_405GP)
    
    Stefan Roese's avatar
    Stefan Roese committed
    #endif
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    #ifdef CFG_INIT_DCACHE_CS
    	/*
    	 * Flush and invalidate dcache, then disable CS for temporary stack.
    	 * Afterwards, this CS can be used for other purposes
    	 */
    	dcache_disable();   /* flush and invalidate dcache */
    	mtebc(PBxAP, 0);
    	mtebc(PBxCR, 0);    /* disable CS for temporary stack */
    
    #if (defined(PBxAP_VAL) && defined(PBxCR_VAL))
    	/*
    	 * Write new value into CS register
    	 */
    	mtebc(PBxAP, PBxAP_VAL);
    	mtebc(PBxCR, PBxCR_VAL);
    #endif
    #endif /* CFG_INIT_DCACHE_CS */
    
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	/*
    	 * Write Ethernetaddress into on-chip register
    	 */
    	reg = 0x00000000;
    	reg |= bd->bi_enetaddr[0];           /* set high address */
    	reg = reg << 8;
    	reg |= bd->bi_enetaddr[1];
    	out32 (EMAC_IAH, reg);
    
    	reg = 0x00000000;
    	reg |= bd->bi_enetaddr[2];           /* set low address  */
    	reg = reg << 8;
    	reg |= bd->bi_enetaddr[3];
    	reg = reg << 8;
    	reg |= bd->bi_enetaddr[4];
    	reg = reg << 8;
    	reg |= bd->bi_enetaddr[5];
    	out32 (EMAC_IAL, reg);
    
    Stefan Roese's avatar
    Stefan Roese committed
    #if defined(CONFIG_405GP)
    
    	/*
    	 * Set edge conditioning circuitry on PPC405GPr
    	 * for compatibility to existing PPC405GP designs.
    	 */
    
    	if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
    
    Stefan Roese's avatar
    Stefan Roese committed
    #endif  /* defined(CONFIG_405GP) */
    #endif  /* defined(CONFIG_405GP) || defined(CONFIG_405EP) */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	return (0);
    }