diff options
Diffstat (limited to 'board')
| -rw-r--r-- | board/spear/x600/Makefile | 47 | ||||
| -rw-r--r-- | board/spear/x600/fpga.c | 280 | ||||
| -rw-r--r-- | board/spear/x600/fpga.h | 23 | ||||
| -rw-r--r-- | board/spear/x600/x600.c | 124 | 
4 files changed, 474 insertions, 0 deletions
| diff --git a/board/spear/x600/Makefile b/board/spear/x600/Makefile new file mode 100644 index 000000000..8c4e7e298 --- /dev/null +++ b/board/spear/x600/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000-2004 +# 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 $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(BOARD).o + +ifndef CONFIG_SPL_BUILD +COBJS	:= fpga.o $(BOARD).o +endif +SOBJS	:= + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) $(SOBJS) +	$(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/spear/x600/fpga.c b/board/spear/x600/fpga.c new file mode 100644 index 000000000..85eb31be7 --- /dev/null +++ b/board/spear/x600/fpga.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2012 Stefan Roese <sr@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 <spartan3.h> +#include <command.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_misc.h> +#include <asm/arch/spr_ssp.h> + +/* + * FPGA program pin configuration on X600: + * + * Only PROG and DONE are connected to GPIOs. INIT is not connected to the + * SoC at all. And CLOCK and DATA are connected to the SSP2 port. We use + * 16bit serial writes via this SSP port to write the data bits into the + * FPGA. + */ +#define CONFIG_SYS_FPGA_PROG		2 +#define CONFIG_SYS_FPGA_DONE		3 + +/* + * Set the active-low FPGA reset signal. + */ +static void fpga_reset(int assert) +{ +	/* +	 * On x600 we have no means to toggle the FPGA reset signal +	 */ +	debug("%s:%d: RESET (%d)\n", __func__, __LINE__, assert); +} + +/* + * Set the FPGA's active-low SelectMap program line to the specified level + */ +static int fpga_pgm_fn(int assert, int flush, int cookie) +{ +	debug("%s:%d: FPGA PROG (%d)\n", __func__, __LINE__, assert); + +	gpio_set_value(CONFIG_SYS_FPGA_PROG, assert); + +	return assert; +} + +/* + * Test the state of the active-low FPGA INIT line.  Return 1 on INIT + * asserted (low). + */ +static int fpga_init_fn(int cookie) +{ +	static int state; + +	debug("%s:%d: init (state=%d)\n", __func__, __LINE__, state); + +	/* +	 * On x600, the FPGA INIT signal is not connected to the SoC. +	 * We can't read the INIT status. Let's return the "correct" +	 * INIT signal state generated via a local state-machine. +	 */ +	if (++state == 1) { +		return 1; +	} else { +		state = 0; +		return 0; +	} +} + +/* + * Test the state of the active-high FPGA DONE pin + */ +static int fpga_done_fn(int cookie) +{ +	struct ssp_regs *ssp = (struct ssp_regs *)CONFIG_SSP2_BASE; + +	/* +	 * Wait for Tx-FIFO to become empty before looking for DONE +	 */ +	while (!(readl(&ssp->sspsr) & SSPSR_TFE)) +		; + +	if (gpio_get_value(CONFIG_SYS_FPGA_DONE)) +		return 1; +	else +		return 0; +} + +/* + * FPGA pre-configuration function. Just make sure that + * FPGA reset is asserted to keep the FPGA from starting up after + * configuration. + */ +static int fpga_pre_config_fn(int cookie) +{ +	debug("%s:%d: FPGA pre-configuration\n", __func__, __LINE__); +	fpga_reset(TRUE); + +	return 0; +} + +/* + * FPGA post configuration function. Blip the FPGA reset line and then see if + * the FPGA appears to be running. + */ +static int fpga_post_config_fn(int cookie) +{ +	int rc = 0; + +	debug("%s:%d: FPGA post configuration\n", __func__, __LINE__); + +	fpga_reset(TRUE); +	udelay(100); +	fpga_reset(FALSE); +	udelay(100); + +	return rc; +} + +static int fpga_clk_fn(int assert_clk, int flush, int cookie) +{ +	/* +	 * No dedicated clock signal on x600 (data & clock generated) +	 * in SSP interface. So we don't have to do anything here. +	 */ +	return assert_clk; +} + +static int fpga_wr_fn(int assert_write, int flush, int cookie) +{ +	struct ssp_regs *ssp = (struct ssp_regs *)CONFIG_SSP2_BASE; +	static int count; +	static u16 data; + +	/* +	 * First collect 16 bits of data +	 */ +	data = data << 1; +	if (assert_write) +		data |= 1; + +	/* +	 * If 16 bits are not available, return for more bits +	 */ +	count++; +	if (count != 16) +		return assert_write; + +	count = 0; + +	/* +	 * Wait for Tx-FIFO to become ready +	 */ +	while (!(readl(&ssp->sspsr) & SSPSR_TNF)) +		; + +	/* Send 16 bits to FPGA via SSP bus */ +	writel(data, &ssp->sspdr); + +	return assert_write; +} + +static Xilinx_Spartan3_Slave_Serial_fns x600_fpga_fns = { +	fpga_pre_config_fn, +	fpga_pgm_fn, +	fpga_clk_fn, +	fpga_init_fn, +	fpga_done_fn, +	fpga_wr_fn, +	fpga_post_config_fn, +}; + +static Xilinx_desc fpga[CONFIG_FPGA_COUNT] = { +	XILINX_XC3S1200E_DESC(slave_serial, &x600_fpga_fns, 0) +}; + +/* + * Initialize the SelectMap interface.  We assume that the mode and the + * initial state of all of the port pins have already been set! + */ +static void fpga_serialslave_init(void) +{ +	debug("%s:%d: Initialize serial slave interface\n", __func__, __LINE__); +	fpga_pgm_fn(FALSE, FALSE, 0);	/* make sure program pin is inactive */ +} + +static int expi_setup(int freq) +{ +	struct misc_regs *misc = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; +	int pll2_m, pll2_n, pll2_p, expi_x, expi_y; + +	pll2_m = (freq * 2) / 1000; +	pll2_n = 15; +	pll2_p = 1; +	expi_x = 1; +	expi_y = 2; + +	/* +	 * Disable reset, Low compression, Disable retiming, Enable Expi, +	 * Enable soft reset, DMA, PLL2, Internal +	 */ +	writel(EXPI_CLK_CFG_LOW_COMPR | EXPI_CLK_CFG_CLK_EN | EXPI_CLK_CFG_RST | +	       EXPI_CLK_SYNT_EN | EXPI_CLK_CFG_SEL_PLL2 | +	       EXPI_CLK_CFG_INT_CLK_EN | (expi_y << 16) | (expi_x << 24), +	       &misc->expi_clk_cfg); + +	/* +	 * 6 uA, Internal feedback, 1st order, Non-dithered, Sample Parameters, +	 * Enable PLL2, Disable reset +	 */ +	writel((pll2_m << 24) | (pll2_p << 8) | (pll2_n), &misc->pll2_frq); +	writel(PLL2_CNTL_6UA | PLL2_CNTL_SAMPLE | PLL2_CNTL_ENABLE | +	       PLL2_CNTL_RESETN | PLL2_CNTL_LOCK, &misc->pll2_cntl); + +	/* +	 * Disable soft reset +	 */ +	clrbits_le32(&misc->expi_clk_cfg, EXPI_CLK_CFG_RST); + +	return 0; +} + +/* + * Initialize the fpga + */ +int x600_init_fpga(void) +{ +	struct ssp_regs *ssp = (struct ssp_regs *)CONFIG_SSP2_BASE; +	struct misc_regs *misc = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + +	/* Enable SSP2 clock */ +	writel(readl(&misc->periph1_clken) | MISC_SSP2ENB | MISC_GPIO4ENB, +	       &misc->periph1_clken); + +	/* Set EXPI clock to 45 MHz */ +	expi_setup(45000); + +	/* Configure GPIO directions */ +	gpio_direction_output(CONFIG_SYS_FPGA_PROG, 0); +	gpio_direction_input(CONFIG_SYS_FPGA_DONE); + +	writel(SSPCR0_DSS_16BITS, &ssp->sspcr0); +	writel(SSPCR1_SSE, &ssp->sspcr1); + +	/* +	 * Set lowest prescale divisor value (CPSDVSR) of 2 for max download +	 * speed. +	 * +	 * Actual data clock rate is: 80MHz / (CPSDVSR * (SCR + 1)) +	 * With CPSDVSR at 2 and SCR at 0, the maximume clock rate is 40MHz. +	 */ +	writel(2, &ssp->sspcpsr); + +	fpga_init(); +	fpga_serialslave_init(); + +	debug("%s:%d: Adding fpga 0\n", __func__, __LINE__); +	fpga_add(fpga_xilinx, &fpga[0]); + +	return 0; +} diff --git a/board/spear/x600/fpga.h b/board/spear/x600/fpga.h new file mode 100644 index 000000000..2b1855716 --- /dev/null +++ b/board/spear/x600/fpga.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2012 Stefan Roese <sr@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 + */ + +int x600_init_fpga(void); diff --git a/board/spear/x600/x600.c b/board/spear/x600/x600.c new file mode 100644 index 000000000..96ec0ad8a --- /dev/null +++ b/board/spear/x600/x600.c @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2009 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * Copyright (C) 2012 Stefan Roese <sr@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 <nand.h> +#include <netdev.h> +#include <phy.h> +#include <rtc.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_defs.h> +#include <asm/arch/spr_misc.h> +#include <linux/mtd/fsmc_nand.h> +#include "fpga.h" + +static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE]; + +int board_init(void) +{ +	/* +	 * X600 is equipped with an M41T82 RTC. This RTC has the +	 * HT bit (Halt Update), which needs to be cleared upon +	 * power-up. Otherwise the RTC is halted. +	 */ +	rtc_reset(); + +	return spear_board_init(MACH_TYPE_SPEAR600); +} + +int board_late_init(void) +{ +	/* +	 * Monitor and env protection on by default +	 */ +	flash_protect(FLAG_PROTECT_SET, +		      CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE + +		      CONFIG_SYS_SPL_LEN + CONFIG_SYS_MONITOR_LEN + +		      2 * CONFIG_ENV_SECT_SIZE - 1, +		      &flash_info[0]); + +	/* Init FPGA subsystem */ +	x600_init_fpga(); + +	return 0; +} + +/* + * board_nand_init - Board specific NAND initialization + * @nand:	mtd private chip structure + * + * Called by nand_init_chip to initialize the board specific functions + */ + +void board_nand_init(void) +{ +	struct misc_regs *const misc_regs_p = +		(struct misc_regs *)CONFIG_SPEAR_MISCBASE; +	struct nand_chip *nand = &nand_chip[0]; + +	if (!(readl(&misc_regs_p->auto_cfg_reg) & MISC_NANDDIS)) +		fsmc_nand_init(nand); +} + +int designware_board_phy_init(struct eth_device *dev, int phy_addr, +	int (*mii_write)(struct eth_device *, u8, u8, u16), +	int dw_reset_phy(struct eth_device *)) +{ +	/* Extended PHY control 1, select GMII */ +	mii_write(dev, phy_addr, 23, 0x0020); + +	/* Software reset necessary after GMII mode selction */ +	dw_reset_phy(dev); + +	/* Enable extended page register access */ +	mii_write(dev, phy_addr, 31, 0x0001); + +	/* 17e: Enhanced LED behavior, needs to be written twice */ +	mii_write(dev, phy_addr, 17, 0x09ff); +	mii_write(dev, phy_addr, 17, 0x09ff); + +	/* 16e: Enhanced LED method select */ +	mii_write(dev, phy_addr, 16, 0xe0ea); + +	/* Disable extended page register access */ +	mii_write(dev, phy_addr, 31, 0x0000); + +	/* Enable clock output pin */ +	mii_write(dev, phy_addr, 18, 0x0049); + +	return 0; +} + +int board_eth_init(bd_t *bis) +{ +	int ret = 0; + +	if (designware_initialize(0, CONFIG_SPEAR_ETHBASE, CONFIG_PHY_ADDR, +				  PHY_INTERFACE_MODE_GMII) >= 0) +		ret++; + +	return ret; +} |