diff options
Diffstat (limited to 'board/armadeus/apf27/apf27.c')
| -rw-r--r-- | board/armadeus/apf27/apf27.c | 256 | 
1 files changed, 256 insertions, 0 deletions
| diff --git a/board/armadeus/apf27/apf27.c b/board/armadeus/apf27/apf27.c new file mode 100644 index 000000000..30e720d16 --- /dev/null +++ b/board/armadeus/apf27/apf27.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2008-2013 Eric Jarrige <eric.jarrige@armadeus.org> + * + * based on the files by + * Sascha Hauer, Pengutronix + * + * SPDX-License-Identifier:    GPL-2.0+ + */ + +#include <common.h> +#include <environment.h> +#include <jffs2/jffs2.h> +#include <nand.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/gpio.h> +#include <asm/gpio.h> +#include <asm/errno.h> +#include "apf27.h" +#include "crc.h" +#include "fpga.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Fuse bank 1 row 8 is "reserved for future use" and therefore available for + * customer use. The APF27 board uses this fuse to store the board revision: + * 0: initial board revision + * 1: first revision - Presence of the second RAM chip on the board is blown in + *     fuse bank 1 row 9  bit 0 - No hardware change + * N: to be defined + */ +static u32 get_board_rev(void) +{ +	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; + +	return readl(&iim->bank[1].fuse_regs[8]); +} + +/* + * Fuse bank 1 row 9 is "reserved for future use" and therefore available for + * customer use. The APF27 board revision 1 uses the bit 0 to permanently store + * the presence of the second RAM chip + * 0: AFP27 with 1 RAM of 64 MiB + * 1: AFP27 with 2 RAM chips of 64 MiB each (128MB) + */ +static int get_num_ram_bank(void) +{ +	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; +	int nr_dram_banks = 1; + +	if ((get_board_rev() > 0) && (CONFIG_NR_DRAM_BANKS > 1)) +		nr_dram_banks += readl(&iim->bank[1].fuse_regs[9]) & 0x01; +	else +		nr_dram_banks = CONFIG_NR_DRAM_POPULATED; + +	return nr_dram_banks; +} + +static void apf27_port_init(int port, u32 gpio_dr, u32 ocr1, u32 ocr2, +			    u32 iconfa1, u32 iconfa2, u32 iconfb1, u32 iconfb2, +			    u32 icr1, u32 icr2, u32 imr, u32 gpio_dir, u32 gpr, +			    u32 puen, u32 gius) +{ +	struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE; + +	writel(gpio_dr,   ®s->port[port].gpio_dr); +	writel(ocr1,      ®s->port[port].ocr1); +	writel(ocr2,      ®s->port[port].ocr2); +	writel(iconfa1,   ®s->port[port].iconfa1); +	writel(iconfa2,   ®s->port[port].iconfa2); +	writel(iconfb1,   ®s->port[port].iconfb1); +	writel(iconfb2,   ®s->port[port].iconfb2); +	writel(icr1,      ®s->port[port].icr1); +	writel(icr2,      ®s->port[port].icr2); +	writel(imr,       ®s->port[port].imr); +	writel(gpio_dir,  ®s->port[port].gpio_dir); +	writel(gpr,       ®s->port[port].gpr); +	writel(puen,      ®s->port[port].puen); +	writel(gius,      ®s->port[port].gius); +} + +#define APF27_PORT_INIT(n) apf27_port_init(PORT##n, ACFG_DR_##n##_VAL,	  \ +	ACFG_OCR1_##n##_VAL, ACFG_OCR2_##n##_VAL, ACFG_ICFA1_##n##_VAL,	  \ +	ACFG_ICFA2_##n##_VAL, ACFG_ICFB1_##n##_VAL, ACFG_ICFB2_##n##_VAL, \ +	ACFG_ICR1_##n##_VAL, ACFG_ICR2_##n##_VAL, ACFG_IMR_##n##_VAL,	  \ +	ACFG_DDIR_##n##_VAL, ACFG_GPR_##n##_VAL, ACFG_PUEN_##n##_VAL,	  \ +	ACFG_GIUS_##n##_VAL) + +static void apf27_iomux_init(void) +{ +	APF27_PORT_INIT(A); +	APF27_PORT_INIT(B); +	APF27_PORT_INIT(C); +	APF27_PORT_INIT(D); +	APF27_PORT_INIT(E); +	APF27_PORT_INIT(F); +} + +static int apf27_devices_init(void) +{ +	int i; +	unsigned int mode[] = { +		PC5_PF_I2C2_DATA, +		PC6_PF_I2C2_CLK, +		PD17_PF_I2C_DATA, +		PD18_PF_I2C_CLK, +	}; + +	for (i = 0; i < ARRAY_SIZE(mode); i++) +		imx_gpio_mode(mode[i]); + +#ifdef CONFIG_MXC_UART +	mx27_uart1_init_pins(); +#endif + +#ifdef CONFIG_FEC_MXC +	mx27_fec_init_pins(); +#endif + +#ifdef CONFIG_MXC_MMC +	mx27_sd2_init_pins(); +	imx_gpio_mode((GPIO_PORTF | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 16)); +	gpio_request(PC_PWRON, "pc_pwron"); +	gpio_set_value(PC_PWRON, 1); +#endif +	return 0; +} + +static void apf27_setup_csx(void) +{ +	struct weim_regs *weim = (struct weim_regs *)IMX_WEIM_BASE; + +	writel(ACFG_CS0U_VAL, &weim->cs0u); +	writel(ACFG_CS0L_VAL, &weim->cs0l); +	writel(ACFG_CS0A_VAL, &weim->cs0a); + +	writel(ACFG_CS1U_VAL, &weim->cs1u); +	writel(ACFG_CS1L_VAL, &weim->cs1l); +	writel(ACFG_CS1A_VAL, &weim->cs1a); + +	writel(ACFG_CS2U_VAL, &weim->cs2u); +	writel(ACFG_CS2L_VAL, &weim->cs2l); +	writel(ACFG_CS2A_VAL, &weim->cs2a); + +	writel(ACFG_CS3U_VAL, &weim->cs3u); +	writel(ACFG_CS3L_VAL, &weim->cs3l); +	writel(ACFG_CS3A_VAL, &weim->cs3a); + +	writel(ACFG_CS4U_VAL, &weim->cs4u); +	writel(ACFG_CS4L_VAL, &weim->cs4l); +	writel(ACFG_CS4A_VAL, &weim->cs4a); + +	writel(ACFG_CS5U_VAL, &weim->cs5u); +	writel(ACFG_CS5L_VAL, &weim->cs5l); +	writel(ACFG_CS5A_VAL, &weim->cs5a); + +	writel(ACFG_EIM_VAL, &weim->eim); +} + +static void apf27_setup_port(void) +{ +	struct system_control_regs *system = +		(struct system_control_regs *)IMX_SYSTEM_CTL_BASE; + +	writel(ACFG_FMCR_VAL, &system->fmcr); +} + +int board_init(void) +{ +	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; + +	apf27_setup_csx(); +	apf27_setup_port(); +	apf27_iomux_init(); +	apf27_devices_init(); +#if defined(CONFIG_FPGA) +	APF27_init_fpga(); +#endif + + +	return 0; +} + +int dram_init(void) +{ +	gd->ram_size = get_ram_size((void *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); +	if (get_num_ram_bank() > 1) +		gd->ram_size += get_ram_size((void *)PHYS_SDRAM_2, +					     PHYS_SDRAM_2_SIZE); + +	return 0; +} + +void dram_init_banksize(void) +{ +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1; +	gd->bd->bi_dram[0].size  = get_ram_size((void *)PHYS_SDRAM_1, +						PHYS_SDRAM_1_SIZE); +	gd->bd->bi_dram[1].start = PHYS_SDRAM_2; +	if (get_num_ram_bank() > 1) +		gd->bd->bi_dram[1].size = get_ram_size((void *)PHYS_SDRAM_2, +					     PHYS_SDRAM_2_SIZE); +	else +		gd->bd->bi_dram[1].size = 0; +} + +ulong board_get_usable_ram_top(ulong total_size) +{ +	ulong ramtop; + +	if (get_num_ram_bank() > 1) +		ramtop = PHYS_SDRAM_2 + get_ram_size((void *)PHYS_SDRAM_2, +						     PHYS_SDRAM_2_SIZE); +	else +		ramtop = PHYS_SDRAM_1 + get_ram_size((void *)PHYS_SDRAM_1, +						     PHYS_SDRAM_1_SIZE); + +	return ramtop; +} + +int checkboard(void) +{ +	printf("Board: Armadeus APF27 revision %d\n", get_board_rev()); +	return 0; +} + +#ifdef CONFIG_SPL_BUILD +inline void hang(void) +{ +	for (;;) +		; +} + +void board_init_f(ulong bootflag) +{ +	/* +	 * copy ourselves from where we are running to where we were +	 * linked at. Use ulong pointers as all addresses involved +	 * are 4-byte-aligned. +	 */ +	ulong *start_ptr, *end_ptr, *link_ptr, *run_ptr, *dst; +	asm volatile ("ldr %0, =_start" : "=r"(start_ptr)); +	asm volatile ("ldr %0, =_end" : "=r"(end_ptr)); +	asm volatile ("ldr %0, =board_init_f" : "=r"(link_ptr)); +	asm volatile ("adr %0, board_init_f" : "=r"(run_ptr)); +	for (dst = start_ptr; dst < end_ptr; dst++) +		*dst = *(dst+(run_ptr-link_ptr)); + +	/* +	 * branch to nand_boot's link-time address. +	 */ +	asm volatile("ldr pc, =nand_boot"); +} +#endif /* CONFIG_SPL_BUILD */ |