From patchwork Tue May 15 14:10:53 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Longchamp X-Patchwork-Id: 159341 X-Patchwork-Delegate: prafulla@marvell.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 753A7B6F62 for ; Wed, 16 May 2012 00:26:16 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5555F280CE; Tue, 15 May 2012 16:25:14 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yYcqiS0ZwSFG; Tue, 15 May 2012 16:25:14 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 37F3A280F2; Tue, 15 May 2012 16:22:37 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5713528097 for ; Tue, 15 May 2012 16:21:32 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nX3d+3V1QG8S for ; Tue, 15 May 2012 16:21:31 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail.ch.keymile.com (mail.ch.keymile.com [193.17.201.103]) by theia.denx.de (Postfix) with SMTP id 36298280A0 for ; Tue, 15 May 2012 16:21:26 +0200 (CEST) Received: from SRVCHBER1212.ch.keymile.net ([172.31.32.9]) by eSafe SMTP Relay 1334159602; Tue, 15 May 2012 16:11:07 +0200 Received: from chber1-10533x.ch.keymile.net ([172.31.40.3]) by SRVCHBER1212.ch.keymile.net with Microsoft SMTPSVC(6.0.3790.4675); Tue, 15 May 2012 16:11:06 +0200 From: Valentin Longchamp To: To: prafulla@marvell.com, holger.brunck@keymile.com Date: Tue, 15 May 2012 16:10:53 +0200 Message-Id: <1337091064-30561-17-git-send-email-valentin.longchamp@keymile.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1337091064-30561-1-git-send-email-valentin.longchamp@keymile.com> References: <1337091064-30561-1-git-send-email-valentin.longchamp@keymile.com> X-OriginalArrivalTime: 15 May 2012 14:11:06.0906 (UTC) FILETIME=[91FF37A0:01CD32A4] X-ESAFE-STATUS: [srvchber1306.keymile.net] Mail allowed Cc: Valentin Longchamp , Gerlando@theia.denx.de, u-boot@lists.denx.de, Holger Brunck , Falauto Subject: [U-Boot] [PATCH v4 16/27] arm/km: enable BOCO2 FPGA download support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de This adds a first support of the FPGA download for a PCIe FPGA based on the BOCO2 CPLD. This takes place in 3 steps, all done accessing the SPICTRL reg of the BOCO2: 1) start the FPGA config with an access to the FPGA_PROG bit 2) later in the boot sequence, wait for the FPGA_DONE bit to toggle to 1 for the end of the FPGA configuration (with a timeout) 3) reset the FPGA 4) finally remove the access to its config EEPROM from the FPGA so that the CPU can update the FPGA configuration when the kernel is running The boards with a PCIe FPGA but without BOCO2 still are supported. The config option name is CONFIG_KM_FPGA_CONFIG Signed-off-by: Valentin Longchamp Signed-off-by: Holger Brunck cc: Gerlando Falauto cc: Prafulla Wadaskar --- board/keymile/common/common.h | 6 + board/keymile/km_arm/Makefile | 4 + board/keymile/km_arm/fpga_config.c | 212 ++++++++++++++++++++++++++++++++++++ board/keymile/km_arm/km_arm.c | 21 +++- boards.cfg | 2 +- include/configs/km/km_arm.h | 3 + include/configs/km_kirkwood.h | 8 +- 7 files changed, 246 insertions(+), 10 deletions(-) create mode 100644 board/keymile/km_arm/fpga_config.c diff --git a/board/keymile/common/common.h b/board/keymile/common/common.h index 49225b8..c58e565 100644 --- a/board/keymile/common/common.h +++ b/board/keymile/common/common.h @@ -131,6 +131,12 @@ int ext_switch_reg_write(const char *devname, u8 phy_addr, u8 port, int ext_switch_reg_read(const char *devname, u8 phy_addr, u8 port, u8 reg, u16 *data); + +int trigger_fpga_config(void); +int wait_for_fpga_config(void); +int fpga_reset(void); +int toggle_eeprom_spi_bus(void); + int set_km_env(void); int fdt_set_node_and_value(void *blob, char *nodename, diff --git a/board/keymile/km_arm/Makefile b/board/keymile/km_arm/Makefile index 06079e9..bd824e2 100644 --- a/board/keymile/km_arm/Makefile +++ b/board/keymile/km_arm/Makefile @@ -31,6 +31,10 @@ LIB = $(obj)lib$(BOARD).o COBJS := $(BOARD).o ../common/common.o ../common/ivm.o +ifdef CONFIG_KM_FPGA_CONFIG +COBJS += fpga_config.o +endif + ifdef CONFIG_KM_MANAGED_SW_ADDR COBJS += managed_switch.o endif diff --git a/board/keymile/km_arm/fpga_config.c b/board/keymile/km_arm/fpga_config.c new file mode 100644 index 0000000..4356b9a --- /dev/null +++ b/board/keymile/km_arm/fpga_config.c @@ -0,0 +1,212 @@ +/* + * (C) Copyright 2012 + * Valentin Lontgchamp, Keymile AG, valentin.longchamp@keymile.com + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include + +/* GPIO Pin from kirkwood connected to PROGRAM_B pin of the xilinx FPGA */ +#define KM_XLX_PROGRAM_B_PIN 39 + +#define BOCO_ADDR 0x10 + +#define ID_REG 0x00 +#define BOCO2_ID 0x5b + +static int check_boco2(void) +{ + int ret; + u8 id; + + ret = i2c_read(BOCO_ADDR, ID_REG, 1, &id, 1); + if (ret) { + printf("%s: error reading the BOCO id !!\n", __func__); + return ret; + } + + return (id == BOCO2_ID); +} + +static int boco_clear_bits(u8 reg, u8 flags) +{ + int ret; + u8 regval; + + /* give access to the EEPROM from FPGA */ + ret = i2c_read(BOCO_ADDR, reg, 1, ®val, 1); + if (ret) { + printf("%s: error reading the BOCO @%#x !!\n", + __func__, reg); + return ret; + } + regval &= ~flags; + ret = i2c_write(BOCO_ADDR, reg, 1, ®val, 1); + if (ret) { + printf("%s: error writing the BOCO @%#x !!\n", + __func__, reg); + return ret; + } + + return 0; +} + +static int boco_set_bits(u8 reg, u8 flags) +{ + int ret; + u8 regval; + + /* give access to the EEPROM from FPGA */ + ret = i2c_read(BOCO_ADDR, reg, 1, ®val, 1); + if (ret) { + printf("%s: error reading the BOCO @%#x !!\n", + __func__, reg); + return ret; + } + regval |= flags; + ret = i2c_write(BOCO_ADDR, reg, 1, ®val, 1); + if (ret) { + printf("%s: error writing the BOCO @%#x !!\n", + __func__, reg); + return ret; + } + + return 0; +} + +#define SPI_REG 0x06 +#define CFG_EEPROM 0x02 +#define FPGA_PROG 0x04 +#define FPGA_DONE 0x20 + +int trigger_fpga_config(void) +{ + int ret = 0; + + if (check_boco2()) { + /* we have a BOCO2, this has to be triggered here */ + + /* make sure the FPGA_can access the EEPROM */ + ret = boco_clear_bits(SPI_REG, CFG_EEPROM); + if (ret) + return ret; + + /* trigger the config start */ + ret = boco_clear_bits(SPI_REG, FPGA_PROG); + if (ret) + return ret; + + /* small delay for the pulse */ + udelay(10); + + /* up signal for pulse end */ + ret = boco_set_bits(SPI_REG, FPGA_PROG); + if (ret) + return ret; + + } else { + /* we do it the old way, with the gpio pin */ + kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1); + kw_gpio_direction_output(KM_XLX_PROGRAM_B_PIN, 0); + /* small delay for the pulse */ + udelay(10); + kw_gpio_direction_input(KM_XLX_PROGRAM_B_PIN); + } + + return 0; +} + +int wait_for_fpga_config(void) +{ + int ret = 0; + u8 spictrl; + u32 timeout = 20000; + + if (!check_boco2()) { + /* we do not have BOCO2, this is not really used */ + return 0; + } + + printf("PCIe FPGA config:"); + do { + ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &spictrl, 1); + if (ret) { + printf("%s: error reading the BOCO spictrl !!\n", + __func__); + return ret; + } + if (timeout-- == 0) { + printf(" FPGA_DONE timeout\n"); + return -EFAULT; + } + udelay(10); + } while (!(spictrl & FPGA_DONE)); + + printf(" done\n"); + + return 0; +} + +#define PRST1 0x4 +#define BRIDGE_RST 0x4 + +int fpga_reset(void) +{ + int ret = 0; + + if (!check_boco2()) { + /* we do not have BOCO2, this is not really used */ + return 0; + } + + ret = boco_clear_bits(PRST1, BRIDGE_RST); + if (ret) + return ret; + + /* small delay for the pulse */ + udelay(10); + + ret = boco_set_bits(PRST1, BRIDGE_RST); + if (ret) + return ret; + + return 0; +} + +/* the FPGA was configured, we configure the BOCO2 so that the EEPROM + * is available from the Bobcat SPI bus */ +int toggle_eeprom_spi_bus(void) +{ + int ret = 0; + + if (!check_boco2()) { + /* we do not have BOCO2, this is not really used */ + return 0; + } + + ret = boco_set_bits(SPI_REG, CFG_EEPROM); + if (ret) + return ret; + + return 0; +} + diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c index c7d65b5..89d7df6 100644 --- a/board/keymile/km_arm/km_arm.c +++ b/board/keymile/km_arm/km_arm.c @@ -266,12 +266,6 @@ int board_early_init_f(void) kw_gpio_set_valid(KM_KIRKWOOD_ENV_WP, 38); kw_gpio_direction_output(KM_KIRKWOOD_ENV_WP, 1); #endif -#if defined(CONFIG_KM_RECONFIG_XLX) - /* trigger the reconfiguration of the xilinx fpga */ - kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1); - kw_gpio_direction_output(KM_XLX_PROGRAM_B_PIN, 0); - kw_gpio_direction_input(KM_XLX_PROGRAM_B_PIN); -#endif return 0; } @@ -280,6 +274,21 @@ int board_init(void) /* address of boot parameters */ gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100; +#if defined(CONFIG_KM_FPGA_CONFIG) + trigger_fpga_config(); +#endif + + return 0; +} + +int board_late_init(void) +{ +#if defined(CONFIG_KM_FPGA_CONFIG) + wait_for_fpga_config(); + fpga_reset(); + toggle_eeprom_spi_bus(); +#endif + return 0; } diff --git a/boards.cfg b/boards.cfg index c2c1789..619bed0 100644 --- a/boards.cfg +++ b/boards.cfg @@ -138,7 +138,7 @@ enbw_cmc arm arm926ejs enbw_cmc enbw calimain arm arm926ejs calimain omicron davinci dns325 arm arm926ejs - d-link kirkwood km_kirkwood arm arm926ejs km_arm keymile kirkwood km_kirkwood:KM_KIRKWOOD,KM_DISABLE_PCI -km_kirkwood_pci arm arm926ejs km_arm keymile kirkwood km_kirkwood:KM_KIRKWOOD_PCI,KM_RECONFIG_XLX +km_kirkwood_pci arm arm926ejs km_arm keymile kirkwood km_kirkwood:KM_KIRKWOOD_PCI,KM_FPGA_CONFIG kmnusa arm arm926ejs km_arm keymile kirkwood km_kirkwood:KM_NUSA mgcoge3un arm arm926ejs km_arm keymile kirkwood km_kirkwood:KM_MGCOGE3UN kmcoge5un arm arm926ejs km_arm keymile kirkwood km_kirkwood:KMCOGE5UN diff --git a/include/configs/km/km_arm.h b/include/configs/km/km_arm.h index 56d5971..547b579 100644 --- a/include/configs/km/km_arm.h +++ b/include/configs/km/km_arm.h @@ -307,4 +307,7 @@ int get_scl(void); #define CONFIG_POST_EXTERNAL_WORD_FUNCS #define CONFIG_CMD_DIAG +/* we do the whole PCIe FPGA config stuff here */ +#define BOARD_LATE_INIT + #endif /* _CONFIG_KM_ARM_H */ diff --git a/include/configs/km_kirkwood.h b/include/configs/km_kirkwood.h index 059fdbc..7d38413 100644 --- a/include/configs/km_kirkwood.h +++ b/include/configs/km_kirkwood.h @@ -175,10 +175,12 @@ MVGBE_SET_MII_SPEED_TO_100) #endif -/* GPIO Pin from kirkwood connected to PROGRAM_B pin of the xilinx FPGA */ -#define KM_XLX_PROGRAM_B_PIN 39 - #ifdef CONFIG_KM_DISABLE_PCI #undef CONFIG_KIRKWOOD_PCIE_INIT #endif + +#ifndef CONFIG_KM_FPGA_CONFIG +#undef BOARD_LATE_INIT +#endif + #endif /* _CONFIG_KM_KIRKWOOD */