diff options
Diffstat (limited to 'arch/arm/cpu/armv7/exynos/spl_boot.c')
| -rw-r--r-- | arch/arm/cpu/armv7/exynos/spl_boot.c | 126 | 
1 files changed, 123 insertions, 3 deletions
| diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c index 3651c0085..ade45fd5d 100644 --- a/arch/arm/cpu/armv7/exynos/spl_boot.c +++ b/arch/arm/cpu/armv7/exynos/spl_boot.c @@ -10,8 +10,11 @@  #include <asm/arch/clock.h>  #include <asm/arch/clk.h>  #include <asm/arch/dmc.h> +#include <asm/arch/periph.h> +#include <asm/arch/pinmux.h>  #include <asm/arch/power.h>  #include <asm/arch/spl.h> +#include <asm/arch/spi.h>  #include "common_setup.h"  #include "clock_init.h" @@ -59,6 +62,121 @@ static int config_branch_prediction(int set_cr_z)  }  #endif +#ifdef CONFIG_SPI_BOOTING +static void spi_rx_tx(struct exynos_spi *regs, int todo, +			void *dinp, void const *doutp, int i) +{ +	uint *rxp = (uint *)(dinp + (i * (32 * 1024))); +	int rx_lvl, tx_lvl; +	uint out_bytes, in_bytes; + +	out_bytes = todo; +	in_bytes = todo; +	setbits_le32(®s->ch_cfg, SPI_CH_RST); +	clrbits_le32(®s->ch_cfg, SPI_CH_RST); +	writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); + +	while (in_bytes) { +		uint32_t spi_sts; +		int temp; + +		spi_sts = readl(®s->spi_sts); +		rx_lvl = ((spi_sts >> 15) & 0x7f); +		tx_lvl = ((spi_sts >> 6) & 0x7f); +		while (tx_lvl < 32 && out_bytes) { +			temp = 0xffffffff; +			writel(temp, ®s->tx_data); +			out_bytes -= 4; +			tx_lvl += 4; +		} +		while (rx_lvl >= 4 && in_bytes) { +			temp = readl(®s->rx_data); +			if (rxp) +				*rxp++ = temp; +			in_bytes -= 4; +			rx_lvl -= 4; +		} +	} +} + +/* + * Copy uboot from spi flash to RAM + * + * @parma uboot_size	size of u-boot to copy + * @param uboot_addr	address in u-boot to copy + */ +static void exynos_spi_copy(unsigned int uboot_size, unsigned int uboot_addr) +{ +	int upto, todo; +	int i, timeout = 100; +	struct exynos_spi *regs = (struct exynos_spi *)CONFIG_ENV_SPI_BASE; + +	set_spi_clk(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ +	/* set the spi1 GPIO */ +	exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); + +	/* set pktcnt and enable it */ +	writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); +	/* set FB_CLK_SEL */ +	writel(SPI_FB_DELAY_180, ®s->fb_clk); +	/* set CH_WIDTH and BUS_WIDTH as word */ +	setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | +					SPI_MODE_BUS_WIDTH_WORD); +	clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ + +	/* clear rx and tx channel if set priveously */ +	clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); + +	setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | +			SPI_RX_BYTE_SWAP | +			SPI_RX_HWORD_SWAP); + +	/* do a soft reset */ +	setbits_le32(®s->ch_cfg, SPI_CH_RST); +	clrbits_le32(®s->ch_cfg, SPI_CH_RST); + +	/* now set rx and tx channel ON */ +	setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); +	clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ + +	/* Send read instruction (0x3h) followed by a 24 bit addr */ +	writel((SF_READ_DATA_CMD << 24) | SPI_FLASH_UBOOT_POS, ®s->tx_data); + +	/* waiting for TX done */ +	while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)) { +		if (!timeout) { +			debug("SPI TIMEOUT\n"); +			break; +		} +		timeout--; +	} + +	for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) { +		todo = min(uboot_size - upto, (1 << 15)); +		spi_rx_tx(regs, todo, (void *)(uboot_addr), +			  (void *)(SPI_FLASH_UBOOT_POS), i); +	} + +	setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ + +	/* +	 * Let put controller mode to BYTE as +	 * SPI driver does not support WORD mode yet +	 */ +	clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | +					SPI_MODE_BUS_WIDTH_WORD); +	writel(0, ®s->swap_cfg); + +	/* +	 * Flush spi tx, rx fifos and reset the SPI controller +	 * and clear rx/tx channel +	 */ +	clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); +	clrbits_le32(®s->ch_cfg, SPI_CH_RST); +	clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); +} +#endif +  /*  * Copy U-boot from mmc to RAM:  * COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains @@ -70,6 +188,9 @@ void copy_uboot_to_ram(void)  	u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL;  	u32 offset = 0, size = 0; +#ifdef CONFIG_SPI_BOOTING +	struct spl_machine_param *param = spl_get_machine_params(); +#endif  #ifdef CONFIG_SUPPORT_EMMC_BOOT  	u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst);  	void (*end_bootop_from_emmc)(void); @@ -91,9 +212,8 @@ void copy_uboot_to_ram(void)  	switch (bootmode) {  #ifdef CONFIG_SPI_BOOTING  	case BOOT_MODE_SERIAL: -		offset = SPI_FLASH_UBOOT_POS; -		size = CONFIG_BL2_SIZE; -		copy_bl2 = get_irom_func(SPI_INDEX); +		/* Customised function to copy u-boot from SF */ +		exynos_spi_copy(param->uboot_size, CONFIG_SYS_TEXT_BASE);  		break;  #endif  	case BOOT_MODE_MMC: |