Commit e47e7650 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev
Browse files

nand spl support

parent 8220fd36
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -40,9 +40,11 @@ config TARGET_ELPHEL393
endchoice
endchoice


config SYS_BOARD
config SYS_BOARD
	default "elphel393" if TARGET_ELPHEL393
	default "zynq"
	default "zynq"


config SYS_VENDOR
config SYS_VENDOR
	default "elphel" if TARGET_ELPHEL393
	default "xilinx"
	default "xilinx"


config SYS_SOC
config SYS_SOC
+299 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (c) 2013 Xilinx Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <asm/io.h>
#include <malloc.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/clk.h>

#define SLCR_LOCK_MAGIC		0x767B
#define SLCR_UNLOCK_MAGIC	0xDF0D

#define SLCR_QSPI_ENABLE		0x02
#define SLCR_QSPI_ENABLE_MASK		0x03
#define SLCR_NAND_L2_SEL		0x10
#define SLCR_NAND_L2_SEL_MASK		0x1F

#define SLCR_USB_L1_SEL			0x04

#define SLCR_IDCODE_MASK	0x1F000
#define SLCR_IDCODE_SHIFT	12

/*
 * zynq_slcr_mio_get_status - Get the status of MIO peripheral.
 *
 * @peri_name: Name of the peripheral for checking MIO status
 * @get_pins: Pointer to array of get pin for this peripheral
 * @num_pins: Number of pins for this peripheral
 * @mask: Mask value
 * @check_val: Required check value to get the status of  periph
 */
struct zynq_slcr_mio_get_status {
	const char *peri_name;
	const int *get_pins;
	int num_pins;
	u32 mask;
	u32 check_val;
};

static const int qspi0_pins[] = {
	1, 2, 3, 4, 5, 6
};

static const int qspi1_cs_pin[] = {
	0
};

static const int qspi1_pins[] = {
	9, 10, 11, 12, 13
};

static const int qspi0_dio_pins[] = {
	1, 2, 3, 6
};

static const int qspi1_cs_dio_pin[] = {
	0
};

static const int qspi1_dio_pins[] = {
	9, 10, 11
};


static const int nand8_pins[] = {
	0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
};

static const int nand16_pins[] = {
	16, 17, 18, 19, 20, 21, 22, 23
};

static const int usb0_pins[] = {
	28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
};

static const int usb1_pins[] = {
	40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};

static const struct zynq_slcr_mio_get_status mio_periphs[] = {
	{
		"qspi0",
		qspi0_pins,
		ARRAY_SIZE(qspi0_pins),
		SLCR_QSPI_ENABLE_MASK,
		SLCR_QSPI_ENABLE,
	},
	{
		"qspi1_cs",
		qspi1_cs_pin,
		ARRAY_SIZE(qspi1_cs_pin),
		SLCR_QSPI_ENABLE_MASK,
		SLCR_QSPI_ENABLE,
	},
	{
		"qspi1",
		qspi1_pins,
		ARRAY_SIZE(qspi1_pins),
		SLCR_QSPI_ENABLE_MASK,
		SLCR_QSPI_ENABLE,
	},
	{
		"qspi0_dio",
		qspi0_dio_pins,
		ARRAY_SIZE(qspi0_dio_pins),
		SLCR_QSPI_ENABLE_MASK,
		SLCR_QSPI_ENABLE,
	},
	{
		"qspi1_cs_dio",
		qspi1_cs_dio_pin,
		ARRAY_SIZE(qspi1_cs_dio_pin),
		SLCR_QSPI_ENABLE_MASK,
		SLCR_QSPI_ENABLE,
	},
	{
		"qspi1_dio",
		qspi1_dio_pins,
		ARRAY_SIZE(qspi1_dio_pins),
		SLCR_QSPI_ENABLE_MASK,
		SLCR_QSPI_ENABLE,
	},
	{
		"nand8",
		nand8_pins,
		ARRAY_SIZE(nand8_pins),
		SLCR_NAND_L2_SEL_MASK,
		SLCR_NAND_L2_SEL,
	},
	{
		"nand16",
		nand16_pins,
		ARRAY_SIZE(nand16_pins),
		SLCR_NAND_L2_SEL_MASK,
		SLCR_NAND_L2_SEL,
	},
	{
		"usb0",
		usb0_pins,
		ARRAY_SIZE(usb0_pins),
		SLCR_USB_L1_SEL,
		SLCR_USB_L1_SEL,
	},
	{
		"usb1",
		usb1_pins,
		ARRAY_SIZE(usb1_pins),
		SLCR_USB_L1_SEL,
		SLCR_USB_L1_SEL,
	},
};

static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */

void zynq_slcr_lock(void)
{
	if (!slcr_lock) {
		writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock);
		slcr_lock = 1;
	}
}

void zynq_slcr_unlock(void)
{
	if (slcr_lock) {
		writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock);
		slcr_lock = 0;
	}
}

/* Reset the entire system */
void zynq_slcr_cpu_reset(void)
{
	/*
	 * Unlock the SLCR then reset the system.
	 * Note that this seems to require raw i/o
	 * functions or there's a lockup?
	 */
	zynq_slcr_unlock();

	/*
	 * Clear 0x0F000000 bits of reboot status register to workaround
	 * the FSBL not loading the bitstream after soft-reboot
	 * This is a temporary solution until we know more.
	 */
	clrbits_le32(&slcr_base->reboot_status, 0xF000000);

	writel(1, &slcr_base->pss_rst_ctrl);
}

/* Setup clk for network */
void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
{
	int ret;

	zynq_slcr_unlock();

	if (gem_id > 1) {
		printf("Non existing GEM id %d\n", gem_id);
		goto out;
	}

	ret = zynq_clk_set_rate(gem0_clk + gem_id, clk_rate);
	if (ret)
		goto out;

	if (gem_id) {
		/* Configure GEM_RCLK_CTRL */
		writel(1, &slcr_base->gem1_rclk_ctrl);
	} else {
		/* Configure GEM_RCLK_CTRL */
		writel(1, &slcr_base->gem0_rclk_ctrl);
	}
	udelay(100000);
out:
	zynq_slcr_lock();
}

void zynq_slcr_devcfg_disable(void)
{
	u32 reg_val;

	zynq_slcr_unlock();

	/* Disable AXI interface by asserting FPGA resets */
	writel(0xF, &slcr_base->fpga_rst_ctrl);

	/* Disable Level shifters before setting PS-PL */
	reg_val = readl(&slcr_base->lvl_shftr_en);
	reg_val &= ~0xF;
	writel(reg_val, &slcr_base->lvl_shftr_en);

	/* Set Level Shifters DT618760 */
	writel(0xA, &slcr_base->lvl_shftr_en);

	zynq_slcr_lock();
}

void zynq_slcr_devcfg_enable(void)
{
	zynq_slcr_unlock();

	/* Set Level Shifters DT618760 */
	writel(0xF, &slcr_base->lvl_shftr_en);

	/* Enable AXI interface by de-asserting FPGA resets */
	writel(0x0, &slcr_base->fpga_rst_ctrl);

	zynq_slcr_lock();
}

u32 zynq_slcr_get_boot_mode(void)
{
	/* Get the bootmode register value */
	printf("\nBOOTMODE CODE is %d\n",(u32)readl(&slcr_base->boot_mode));
	udelay(5000);
	return readl(&slcr_base->boot_mode);
}

u32 zynq_slcr_get_idcode(void)
{
	return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >>
							SLCR_IDCODE_SHIFT;
}

/*
 * zynq_slcr_get_mio_pin_status - Get the MIO pin status of peripheral.
 *
 * @periph: Name of the peripheral
 *
 * Returns count to indicate the number of pins configured for the
 * given @periph.
 */
int zynq_slcr_get_mio_pin_status(const char *periph)
{
	const struct zynq_slcr_mio_get_status *mio_ptr;
	int val, i, j;
	int mio = 0;

	for (i = 0; i < ARRAY_SIZE(mio_periphs); i++) {
		if (strcmp(periph, mio_periphs[i].peri_name) == 0) {
			mio_ptr = &mio_periphs[i];
			for (j = 0; j < mio_ptr->num_pins; j++) {
				val = readl(&slcr_base->mio_pin
						[mio_ptr->get_pins[j]]);
				if ((val & mio_ptr->mask) == mio_ptr->check_val)
					mio++;
			}
			break;
		}
	}

	return mio;
}
+48 −49
Original line number Original line Diff line number Diff line
@@ -5,7 +5,9 @@
 */
 */


#include <common.h>
#include <common.h>
#include <asm/io.h>
#include <fdtdec.h>
#include <fpga.h>
#include <mmc.h>
#include <netdev.h>
#include <netdev.h>
#include <zynqpl.h>
#include <zynqpl.h>
#include <asm/arch/hardware.h>
#include <asm/arch/hardware.h>
@@ -15,20 +17,22 @@ DECLARE_GLOBAL_DATA_PTR;


#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
Xilinx_desc fpga;
static xilinx_desc fpga;


/* It can be done differently */
/* It can be done differently */
Xilinx_desc fpga010 = XILINX_XC7Z010_DESC(0x10);
static xilinx_desc fpga010 = XILINX_XC7Z010_DESC(0x10);
Xilinx_desc fpga015 = XILINX_XC7Z015_DESC(0x15);
static xilinx_desc fpga015 = XILINX_XC7Z015_DESC(0x15);
Xilinx_desc fpga020 = XILINX_XC7Z020_DESC(0x20);
static xilinx_desc fpga020 = XILINX_XC7Z020_DESC(0x20);
Xilinx_desc fpga030 = XILINX_XC7Z030_DESC(0x30);
static xilinx_desc fpga030 = XILINX_XC7Z030_DESC(0x30);
Xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45);
static xilinx_desc fpga035 = XILINX_XC7Z035_DESC(0x35);
Xilinx_desc fpga100 = XILINX_XC7Z100_DESC(0x100);
static xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45);
static xilinx_desc fpga100 = XILINX_XC7Z100_DESC(0x100);
#endif
#endif


int board_init(void)
int board_init(void)
{
{
#ifdef CONFIG_FPGA
#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
	u32 idcode;
	u32 idcode;


	idcode = zynq_slcr_get_idcode();
	idcode = zynq_slcr_get_idcode();
@@ -46,6 +50,9 @@ int board_init(void)
	case XILINX_ZYNQ_7030:
	case XILINX_ZYNQ_7030:
		fpga = fpga030;
		fpga = fpga030;
		break;
		break;
	case XILINX_ZYNQ_7035:
		fpga = fpga035;
		break;
	case XILINX_ZYNQ_7045:
	case XILINX_ZYNQ_7045:
		fpga = fpga045;
		fpga = fpga045;
		break;
		break;
@@ -55,34 +62,27 @@ int board_init(void)
	}
	}
#endif
#endif


	/* temporary hack to clear pending irqs before Linux as it
	 * will hang Linux
	 */
	writel(0x26d, 0xe0001014);

#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
	fpga_init();
	fpga_init();
	fpga_add(fpga_xilinx, &fpga);
	fpga_add(fpga_xilinx, &fpga);
#endif
#endif

	return 0;
	return 0;
}
}


int board_late_init(void)
int board_late_init(void)
{
{
	switch ((zynq_slcr_get_boot_mode()) & ZYNQ_BM_MASK) {
	switch ((zynq_slcr_get_boot_mode()) & ZYNQ_BM_MASK) {
	case ZYNQ_BM_QSPI:
		setenv("modeboot", "qspiboot");
		break;
	case ZYNQ_BM_NAND:
		setenv("modeboot", "nandboot");
		break;
	case ZYNQ_BM_NOR:
	case ZYNQ_BM_NOR:
		setenv("modeboot", "norboot");
		setenv("modeboot", "norboot");
		break;
		break;
	case ZYNQ_BM_SD:
	case ZYNQ_BM_SD:
		setenv("modeboot", "sdboot");
		setenv("modeboot", "sdboot");
		break;
		break;
	case ZYNQ_BM_NAND:
		setenv("modeboot", "nandboot");
		break;
	case ZYNQ_BM_JTAG:
	case ZYNQ_BM_JTAG:
		setenv("modeboot", "jtagboot");
		setenv("modeboot", "jtagboot");
		break;
		break;
@@ -94,6 +94,14 @@ int board_late_init(void)
	return 0;
	return 0;
}
}


#ifdef CONFIG_DISPLAY_BOARDINFO
int checkboard(void)
{
	puts("Board: Elphel 10393\n");
	return 0;
}
#endif

int board_eth_init(bd_t *bis)
int board_eth_init(bd_t *bis)
{
{
	u32 ret = 0;
	u32 ret = 0;
@@ -113,42 +121,33 @@ int board_eth_init(bd_t *bis)
# endif
# endif
	ret |= xilinx_emaclite_initialize(bis, XILINX_EMACLITE_BASEADDR,
	ret |= xilinx_emaclite_initialize(bis, XILINX_EMACLITE_BASEADDR,
			txpp, rxpp);
			txpp, rxpp);
#endif

#if defined(CONFIG_ZYNQ_GEM)
# if defined(CONFIG_ZYNQ_GEM0)
	ret |= zynq_gem_initialize(bis, ZYNQ_GEM_BASEADDR0,
						CONFIG_ZYNQ_GEM_PHY_ADDR0, 0);
# endif
# if defined(CONFIG_ZYNQ_GEM1)
	ret |= zynq_gem_initialize(bis, ZYNQ_GEM_BASEADDR1,
						CONFIG_ZYNQ_GEM_PHY_ADDR1, 0);
# endif
#endif
#endif
	return ret;
	return ret;
}
}


#ifdef CONFIG_CMD_MMC
int board_mmc_init(bd_t *bd)
{
	int ret = 0;

#if defined(CONFIG_ZYNQ_SDHCI)
# if defined(CONFIG_ZYNQ_SDHCI0)
	ret = zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR0);
# endif
# if defined(CONFIG_ZYNQ_SDHCI1)
	ret |= zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR1);
# endif
#endif
	return ret;
}
#endif

int dram_init(void)
int dram_init(void)
{
{
#if CONFIG_IS_ENABLED(OF_CONTROL)
	int node;
	fdt_addr_t addr;
	fdt_size_t size;
	const void *blob = gd->fdt_blob;

	node = fdt_node_offset_by_prop_value(blob, -1, "device_type",
					     "memory", 7);
	if (node == -FDT_ERR_NOTFOUND) {
		debug("ZYNQ DRAM: Can't get memory node\n");
		return -1;
	}
	addr = fdtdec_get_addr_size(blob, node, "reg", &size);
	if (addr == FDT_ADDR_T_NONE || size == 0) {
		debug("ZYNQ DRAM: Can't get base address or size\n");
		return -1;
	}
	gd->ram_size = size;
#else
	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;

#endif
	zynq_ddrc_init();
	zynq_ddrc_init();


	return 0;
	return 0;