diff mbox

[U-Boot,25/35] arm: socfpga: fpga: Add SoCFPGA FPGA programming interface

Message ID 1410779188-6880-26-git-send-email-marex@denx.de
State Superseded
Delegated to: Marek Vasut
Headers show

Commit Message

Marek Vasut Sept. 15, 2014, 11:06 a.m. UTC
From: Pavel Machek <pavel@denx.de>

Add code necessary to program the FPGA part of SoCFPGA from U-Boot
with an RBF blob. This patch also integrates the code into the
FPGA driver framework in U-Boot so it can be used via the 'fpga'
command.

Signed-off-by: Pavel Machek <pavel@denx.de>
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chin Liang See <clsee@altera.com>
Cc: Dinh Nguyen <dinguyen@altera.com>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>
Cc: Tom Rini <trini@ti.com>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Pavel Machek <pavel@denx.de>
---
 arch/arm/cpu/armv7/socfpga/Makefile              |   3 +-
 arch/arm/cpu/armv7/socfpga/fpga_manager.c        | 354 +++++++++++++++++++++++
 arch/arm/cpu/armv7/socfpga/misc.c                |  37 +++
 arch/arm/include/asm/arch-socfpga/fpga_manager.h |  77 +++++
 drivers/fpga/altera.c                            |  21 ++
 include/altera.h                                 |   1 +
 6 files changed, 492 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/cpu/armv7/socfpga/fpga_manager.c
 create mode 100644 arch/arm/include/asm/arch-socfpga/fpga_manager.h

Comments

Wolfgang Denk Sept. 15, 2014, 3:41 p.m. UTC | #1
Dear Marek Vasut,

In message <1410779188-6880-26-git-send-email-marex@denx.de> you wrote:
> From: Pavel Machek <pavel@denx.de>
> 
> Add code necessary to program the FPGA part of SoCFPGA from U-Boot
> with an RBF blob. This patch also integrates the code into the
> FPGA driver framework in U-Boot so it can be used via the 'fpga'
> command.
...
> +/* Get the FPGA mode */
> +static int fpgamgr_get_mode(void)
> +{
> +	unsigned long val;
> +	val = readl(&fpgamgr_regs->stat);
> +	return val & FPGAMGRREGS_STAT_MODE_MASK;
> +}

Please always separate declarations and code by a blank line (please
fix globally).

Best regards,

Wolfgang Denk
Michal Simek Sept. 16, 2014, 9:42 a.m. UTC | #2
On 09/15/2014 01:06 PM, Marek Vasut wrote:
> From: Pavel Machek <pavel@denx.de>
> 
> Add code necessary to program the FPGA part of SoCFPGA from U-Boot
> with an RBF blob. This patch also integrates the code into the
> FPGA driver framework in U-Boot so it can be used via the 'fpga'
> command.
> 
> Signed-off-by: Pavel Machek <pavel@denx.de>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Chin Liang See <clsee@altera.com>
> Cc: Dinh Nguyen <dinguyen@altera.com>
> Cc: Albert Aribaud <albert.u.boot@aribaud.net>
> Cc: Tom Rini <trini@ti.com>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Pavel Machek <pavel@denx.de>
> ---
>  arch/arm/cpu/armv7/socfpga/Makefile              |   3 +-
>  arch/arm/cpu/armv7/socfpga/fpga_manager.c        | 354 +++++++++++++++++++++++

We have drivers/fpga and you should move this driver there to be visible for others.
Maybe also nios can use this driver with some changes.

Thanks,
Michal
Marek Vasut Sept. 16, 2014, 10:12 a.m. UTC | #3
On Tuesday, September 16, 2014 at 11:42:00 AM, Michal Simek wrote:
> On 09/15/2014 01:06 PM, Marek Vasut wrote:
> > From: Pavel Machek <pavel@denx.de>
> > 
> > Add code necessary to program the FPGA part of SoCFPGA from U-Boot
> > with an RBF blob. This patch also integrates the code into the
> > FPGA driver framework in U-Boot so it can be used via the 'fpga'
> > command.
> > 
> > Signed-off-by: Pavel Machek <pavel@denx.de>
> > Signed-off-by: Marek Vasut <marex@denx.de>
> > Cc: Chin Liang See <clsee@altera.com>
> > Cc: Dinh Nguyen <dinguyen@altera.com>
> > Cc: Albert Aribaud <albert.u.boot@aribaud.net>
> > Cc: Tom Rini <trini@ti.com>
> > Cc: Wolfgang Denk <wd@denx.de>
> > Cc: Pavel Machek <pavel@denx.de>
> > ---
> > 
> >  arch/arm/cpu/armv7/socfpga/Makefile              |   3 +-
> >  arch/arm/cpu/armv7/socfpga/fpga_manager.c        | 354
> >  +++++++++++++++++++++++
> 
> We have drivers/fpga and you should move this driver there to be visible
> for others. Maybe also nios can use this driver with some changes.

Good point about the move, but how could NIOS possibly use this ?

Best regards,
Marek Vasut
Michal Simek Sept. 16, 2014, 10:33 a.m. UTC | #4
On 09/16/2014 12:12 PM, Marek Vasut wrote:
> On Tuesday, September 16, 2014 at 11:42:00 AM, Michal Simek wrote:
>> On 09/15/2014 01:06 PM, Marek Vasut wrote:
>>> From: Pavel Machek <pavel@denx.de>
>>>
>>> Add code necessary to program the FPGA part of SoCFPGA from U-Boot
>>> with an RBF blob. This patch also integrates the code into the
>>> FPGA driver framework in U-Boot so it can be used via the 'fpga'
>>> command.
>>>
>>> Signed-off-by: Pavel Machek <pavel@denx.de>
>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>> Cc: Chin Liang See <clsee@altera.com>
>>> Cc: Dinh Nguyen <dinguyen@altera.com>
>>> Cc: Albert Aribaud <albert.u.boot@aribaud.net>
>>> Cc: Tom Rini <trini@ti.com>
>>> Cc: Wolfgang Denk <wd@denx.de>
>>> Cc: Pavel Machek <pavel@denx.de>
>>> ---
>>>
>>>  arch/arm/cpu/armv7/socfpga/Makefile              |   3 +-
>>>  arch/arm/cpu/armv7/socfpga/fpga_manager.c        | 354
>>>  +++++++++++++++++++++++
>>
>> We have drivers/fpga and you should move this driver there to be visible
>> for others. Maybe also nios can use this driver with some changes.
> 
> Good point about the move, but how could NIOS possibly use this ?

I don't know the architecture but I expect that this fpga_manager
can also work with partial bitstream.
It means the flow is.
1. load full bitstream with NIOS
2. NIOS become security manager and own this driver
3. NIOS is able to load partial bitstreams via this device.

Not sure if this realistic flow on socfpga but this is possible to do
on our fpga.
That's why IMHO this driver should be in drivers/fpga.

Also look at my xilinx fpga changes I have done recently and
you should change that altera code to look the same and remove
that ugly ifdef mess.

Thanks,
Michal
Marek Vasut Sept. 16, 2014, 6:18 p.m. UTC | #5
On Monday, September 15, 2014 at 05:41:51 PM, Wolfgang Denk wrote:
> Dear Marek Vasut,
> 
> In message <1410779188-6880-26-git-send-email-marex@denx.de> you wrote:
> > From: Pavel Machek <pavel@denx.de>
> > 
> > Add code necessary to program the FPGA part of SoCFPGA from U-Boot
> > with an RBF blob. This patch also integrates the code into the
> > FPGA driver framework in U-Boot so it can be used via the 'fpga'
> > command.
> 
> ...
> 
> > +/* Get the FPGA mode */
> > +static int fpgamgr_get_mode(void)
> > +{
> > +	unsigned long val;
> > +	val = readl(&fpgamgr_regs->stat);
> > +	return val & FPGAMGRREGS_STAT_MODE_MASK;
> > +}
> 
> Please always separate declarations and code by a blank line (please
> fix globally).

Done, thank you!

Best regards,
Marek Vasut
Marek Vasut Sept. 16, 2014, 8:15 p.m. UTC | #6
On Tuesday, September 16, 2014 at 12:33:02 PM, Michal Simek wrote:
> On 09/16/2014 12:12 PM, Marek Vasut wrote:
> > On Tuesday, September 16, 2014 at 11:42:00 AM, Michal Simek wrote:
> >> On 09/15/2014 01:06 PM, Marek Vasut wrote:
> >>> From: Pavel Machek <pavel@denx.de>
> >>> 
> >>> Add code necessary to program the FPGA part of SoCFPGA from U-Boot
> >>> with an RBF blob. This patch also integrates the code into the
> >>> FPGA driver framework in U-Boot so it can be used via the 'fpga'
> >>> command.
> >>> 
> >>> Signed-off-by: Pavel Machek <pavel@denx.de>
> >>> Signed-off-by: Marek Vasut <marex@denx.de>
> >>> Cc: Chin Liang See <clsee@altera.com>
> >>> Cc: Dinh Nguyen <dinguyen@altera.com>
> >>> Cc: Albert Aribaud <albert.u.boot@aribaud.net>
> >>> Cc: Tom Rini <trini@ti.com>
> >>> Cc: Wolfgang Denk <wd@denx.de>
> >>> Cc: Pavel Machek <pavel@denx.de>
> >>> ---
> >>> 
> >>>  arch/arm/cpu/armv7/socfpga/Makefile              |   3 +-
> >>>  arch/arm/cpu/armv7/socfpga/fpga_manager.c        | 354
> >>>  +++++++++++++++++++++++
> >> 
> >> We have drivers/fpga and you should move this driver there to be visible
> >> for others. Maybe also nios can use this driver with some changes.
> > 
> > Good point about the move, but how could NIOS possibly use this ?
> 
> I don't know the architecture but I expect that this fpga_manager
> can also work with partial bitstream.
> It means the flow is.
> 1. load full bitstream with NIOS
> 2. NIOS become security manager and own this driver
> 3. NIOS is able to load partial bitstreams via this device.
> 
> Not sure if this realistic flow on socfpga but this is possible to do
> on our fpga.
> That's why IMHO this driver should be in drivers/fpga.
> 
> Also look at my xilinx fpga changes I have done recently and
> you should change that altera code to look the same and remove
> that ugly ifdef mess.

I did clean that up to a certain degree. It was truly hideous. Who's picking up 
the patches for drivers/fpga/ nowadays ?

Best regards,
Marek Vasut
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/socfpga/Makefile b/arch/arm/cpu/armv7/socfpga/Makefile
index eb33f2c..8b6e108 100644
--- a/arch/arm/cpu/armv7/socfpga/Makefile
+++ b/arch/arm/cpu/armv7/socfpga/Makefile
@@ -8,5 +8,6 @@ 
 #
 
 obj-y	:= lowlevel_init.o
-obj-y	+= misc.o timer.o reset_manager.o system_manager.o clock_manager.o
+obj-y	+= misc.o timer.o reset_manager.o system_manager.o clock_manager.o \
+	   fpga_manager.o
 obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o scan_manager.o
diff --git a/arch/arm/cpu/armv7/socfpga/fpga_manager.c b/arch/arm/cpu/armv7/socfpga/fpga_manager.c
new file mode 100644
index 0000000..38d48f8
--- /dev/null
+++ b/arch/arm/cpu/armv7/socfpga/fpga_manager.c
@@ -0,0 +1,354 @@ 
+/*
+ * Copyright (C) 2012 Altera Corporation <www.altera.com>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/fpga_manager.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Timeout count */
+#define FPGA_TIMEOUT_CNT		0x1000000
+
+static struct socfpga_fpga_manager *fpgamgr_regs =
+	(struct socfpga_fpga_manager *)SOCFPGA_FPGAMGRREGS_ADDRESS;
+static struct socfpga_system_manager *sysmgr_regs =
+	(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
+
+/* Check whether FPGA Init_Done signal is high */
+static int is_fpgamgr_initdone_high(void)
+{
+	unsigned long val;
+	val = readl(&fpgamgr_regs->gpio_ext_porta);
+	return val & FPGAMGRREGS_MON_GPIO_EXT_PORTA_ID_MASK;
+}
+
+/* Get the FPGA mode */
+static int fpgamgr_get_mode(void)
+{
+	unsigned long val;
+	val = readl(&fpgamgr_regs->stat);
+	return val & FPGAMGRREGS_STAT_MODE_MASK;
+}
+
+/* Check whether FPGA is ready to be accessed */
+int fpgamgr_test_fpga_ready(void)
+{
+	/* Check for init done signal */
+	if (!is_fpgamgr_initdone_high())
+		return 0;
+
+	/* Check again to avoid false glitches */
+	if (!is_fpgamgr_initdone_high())
+		return 0;
+
+	if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_USERMODE)
+		return 0;
+
+	return 1;
+}
+
+/* Poll until FPGA is ready to be accessed or timeout occurred */
+int fpgamgr_poll_fpga_ready(void)
+{
+	unsigned long i;
+
+	/* If FPGA is blank, wait till WD invoke warm reset */
+	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+		/* check for init done signal */
+		if (!is_fpgamgr_initdone_high())
+			continue;
+		/* check again to avoid false glitches */
+		if (!is_fpgamgr_initdone_high())
+			continue;
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Set CD ratio */
+static void fpgamgr_set_cd_ratio(unsigned long ratio)
+{
+	clrsetbits_le32(&fpgamgr_regs->ctrl,
+			0x3 << FPGAMGRREGS_CTRL_CDRATIO_LSB,
+			(ratio & 0x3) << FPGAMGRREGS_CTRL_CDRATIO_LSB);
+}
+
+static int fpgamgr_dclkcnt_set(unsigned long cnt)
+{
+	unsigned long i;
+
+	/* Clear any existing done status */
+	if (readl(&fpgamgr_regs->dclkstat))
+		writel(0x1, &fpgamgr_regs->dclkstat);
+
+	/* Write the dclkcnt */
+	writel(cnt, &fpgamgr_regs->dclkcnt);
+
+	/* Wait till the dclkcnt done */
+	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+		if (!readl(&fpgamgr_regs->dclkstat))
+			continue;
+
+		writel(0x1, &fpgamgr_regs->dclkstat);
+		return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+/* Start the FPGA programming by initialize the FPGA Manager */
+static int fpgamgr_program_init(void)
+{
+	unsigned long msel, i;
+
+	/* Get the MSEL value */
+	msel = readl(&fpgamgr_regs->stat);
+	msel &= FPGAMGRREGS_STAT_MSEL_MASK;
+	msel >>= FPGAMGRREGS_STAT_MSEL_LSB;
+
+	/*
+	 * Set the cfg width
+	 * If MSEL[3] = 1, cfg width = 32 bit
+	 */
+	if (msel & 0x8) {
+		setbits_le32(&fpgamgr_regs->ctrl,
+			     FPGAMGRREGS_CTRL_CFGWDTH_MASK);
+
+		/* To determine the CD ratio */
+		/* MSEL[1:0] = 0, CD Ratio = 1 */
+		if ((msel & 0x3) == 0x0)
+			fpgamgr_set_cd_ratio(CDRATIO_x1);
+		/* MSEL[1:0] = 1, CD Ratio = 4 */
+		else if ((msel & 0x3) == 0x1)
+			fpgamgr_set_cd_ratio(CDRATIO_x4);
+		/* MSEL[1:0] = 2, CD Ratio = 8 */
+		else if ((msel & 0x3) == 0x2)
+			fpgamgr_set_cd_ratio(CDRATIO_x8);
+
+	} else {	/* MSEL[3] = 0 */
+		clrbits_le32(&fpgamgr_regs->ctrl,
+			     FPGAMGRREGS_CTRL_CFGWDTH_MASK);
+
+		/* To determine the CD ratio */
+		/* MSEL[1:0] = 0, CD Ratio = 1 */
+		if ((msel & 0x3) == 0x0)
+			fpgamgr_set_cd_ratio(CDRATIO_x1);
+		/* MSEL[1:0] = 1, CD Ratio = 2 */
+		else if ((msel & 0x3) == 0x1)
+			fpgamgr_set_cd_ratio(CDRATIO_x2);
+		/* MSEL[1:0] = 2, CD Ratio = 4 */
+		else if ((msel & 0x3) == 0x2)
+			fpgamgr_set_cd_ratio(CDRATIO_x4);
+	}
+
+	/* To enable FPGA Manager configuration */
+	clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCE_MASK);
+
+	/* To enable FPGA Manager drive over configuration line */
+	setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
+
+	/* Put FPGA into reset phase */
+	setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
+
+	/* (1) wait until FPGA enter reset phase */
+	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+		if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_RESETPHASE)
+			break;
+	}
+
+	/* If not in reset state, return error */
+	if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_RESETPHASE) {
+		puts("FPGA: Could not reset\n");
+		return -1;
+	}
+
+	/* Release FPGA from reset phase */
+	clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
+
+	/* (2) wait until FPGA enter configuration phase */
+	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+		if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_CFGPHASE)
+			break;
+	}
+
+	/* If not in configuration state, return error */
+	if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_CFGPHASE) {
+		puts("FPGA: Could not configure\n");
+		return -2;
+	}
+
+	/* Clear all interrupts in CB Monitor */
+	writel(0xFFF, &fpgamgr_regs->gpio_porta_eoi);
+
+	/* Enable AXI configuration */
+	setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
+
+	return 0;
+}
+
+/* Write the RBF data to FPGA Manager */
+static noinline void fpgamgr_program_write(const unsigned long *rbf_data,
+	unsigned long rbf_size)
+{
+	uint32_t src = (uint32_t)rbf_data;
+	uint32_t dst = SOCFPGA_FPGAMGRDATA_ADDRESS;
+
+	/* Number of loops for 32-byte long copying. */
+	uint32_t loops32 = rbf_size / 32;
+	/* Number of loops for 4-byte long copying + trailing bytes */
+	uint32_t loops4 = DIV_ROUND_UP(rbf_size % 32, 4);
+
+	asm volatile(
+		"1:	ldmia	%0!,	{r0-r7}\n"
+		"	stmia	%1!,	{r0-r7}\n"
+		"	sub	%1,	#32\n"
+		"	subs	%2,	#1\n"
+		"	bne	1b\n"
+		"2:	ldr	%2,	[%0],	#4\n"
+		"	str	%2,	[%1]\n"
+		"	subs	%3,	#1\n"
+		"	bne	2b\n"
+		: "+r"(src), "+r"(dst), "+r"(loops32), "+r"(loops4) :
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "cc");
+}
+
+/* Ensure the FPGA entering config done */
+static int fpgamgr_program_poll_cd(void)
+{
+	const uint32_t mask = FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK |
+			      FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK;
+	unsigned long reg, i;
+
+	/* (3) wait until full config done */
+	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+		reg = readl(&fpgamgr_regs->gpio_ext_porta);
+
+		/* Config error */
+		if (!(reg & mask)) {
+			printf("FPGA: Configuration error.\n");
+			return -3;
+		}
+
+		/* Config done without error */
+		if (reg & mask)
+			break;
+	}
+
+	/* Timeout happened, return error */
+	if (i == FPGA_TIMEOUT_CNT) {
+		printf("FPGA: Timeout waiting for program.\n");
+		return -4;
+	}
+
+	/* Disable AXI configuration */
+	clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
+
+	return 0;
+}
+
+/* Ensure the FPGA entering init phase */
+static int fpgamgr_program_poll_initphase(void)
+{
+	unsigned long i;
+
+	/* Additional clocks for the CB to enter initialization phase */
+	if (fpgamgr_dclkcnt_set(0x4))
+		return -5;
+
+	/* (4) wait until FPGA enter init phase or user mode */
+	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+		if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_INITPHASE)
+			break;
+		if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
+			break;
+	}
+
+	/* If not in configuration state, return error */
+	if (i == FPGA_TIMEOUT_CNT)
+		return -6;
+
+	return 0;
+}
+
+/* Ensure the FPGA entering user mode */
+static int fpgamgr_program_poll_usermode(void)
+{
+	unsigned long i;
+
+	/* Additional clocks for the CB to exit initialization phase */
+	if (fpgamgr_dclkcnt_set(0x5000))
+		return -7;
+
+	/* (5) wait until FPGA enter user mode */
+	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+		if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
+			break;
+	}
+	/* If not in configuration state, return error */
+	if (i == FPGA_TIMEOUT_CNT)
+		return -8;
+
+	/* To release FPGA Manager drive over configuration line */
+	clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
+
+	return 0;
+}
+
+/*
+ * FPGA Manager to program the FPGA. This is the interface used by FPGA driver.
+ * Return 0 for sucess, non-zero for error.
+ */
+int fpgamgr_program_fpga(const unsigned long *rbf_data, unsigned long rbf_size)
+{
+	unsigned long status;
+
+	if ((uint32_t)rbf_data & 0x3) {
+		puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
+		return -EINVAL;
+	}
+
+	/* Prior programming the FPGA, all bridges need to be shut off */
+
+	/* Disable all signals from hps peripheral controller to fpga */
+	writel(0, &sysmgr_regs->fpgaintfgrp_module);
+
+	/* Disable all signals from FPGA to HPS SDRAM */
+#define SDR_CTRLGRP_FPGAPORTRST_ADDRESS	0x5080
+	writel(0, SOCFPGA_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS);
+
+	/* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
+	socfpga_bridges_reset(1);
+
+	/* Unmap the bridges from NIC-301 */
+	writel(0x1, SOCFPGA_L3REGS_ADDRESS);
+
+	/* Initialize the FPGA Manager */
+	status = fpgamgr_program_init();
+	if (status)
+		return status;
+
+	/* Write the RBF data to FPGA Manager */
+	fpgamgr_program_write(rbf_data, rbf_size);
+
+	/* Ensure the FPGA entering config done */
+	status = fpgamgr_program_poll_cd();
+	if (status)
+		return status;
+
+	/* Ensure the FPGA entering init phase */
+	status = fpgamgr_program_poll_initphase();
+	if (status)
+		return status;
+
+	/* Ensure the FPGA entering user mode */
+	return fpgamgr_program_poll_usermode();
+}
diff --git a/arch/arm/cpu/armv7/socfpga/misc.c b/arch/arm/cpu/armv7/socfpga/misc.c
index 51be55c..8e25f09 100644
--- a/arch/arm/cpu/armv7/socfpga/misc.c
+++ b/arch/arm/cpu/armv7/socfpga/misc.c
@@ -6,6 +6,7 @@ 
 
 #include <common.h>
 #include <asm/io.h>
+#include <altera.h>
 #include <miiphy.h>
 #include <netdev.h>
 #include <asm/arch/reset_manager.h>
@@ -93,8 +94,44 @@  int overwrite_console(void)
 }
 #endif
 
+#ifdef CONFIG_FPGA
+/*
+ * FPGA programming support for SoC FPGA Cyclone V
+ */
+static Altera_desc altera_fpga[] = {
+	{
+		/* Family */
+		Altera_SoCFPGA,
+		/* Interface type */
+		fast_passive_parallel,
+		/* No limitation as additional data will be ignored */
+		-1,
+		/* No device function table */
+		NULL,
+		/* Base interface address specified in driver */
+		NULL,
+		/* No cookie implementation */
+		0
+	},
+};
+
+/* add device descriptor to FPGA device table */
+static void socfpga_fpga_add(void)
+{
+	int i;
+	fpga_init();
+	for (i = 0; i < ARRAY_SIZE(altera_fpga); i++)
+		fpga_add(fpga_altera, &altera_fpga[i]);
+}
+#else
+static inline void socfpga_fpga_add(void) {}
+#endif
+
 int misc_init_r(void)
 {
+	/* Add device descriptor to FPGA device table */
+	socfpga_fpga_add();
+
 	/* This is needed, otherwise kernel is rebooted by watchdog. */
 	watchdog_disable();
 
diff --git a/arch/arm/include/asm/arch-socfpga/fpga_manager.h b/arch/arm/include/asm/arch-socfpga/fpga_manager.h
new file mode 100644
index 0000000..4812591
--- /dev/null
+++ b/arch/arm/include/asm/arch-socfpga/fpga_manager.h
@@ -0,0 +1,77 @@ 
+/*
+ * Copyright (C) 2012 Altera Corporation <www.altera.com>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ */
+
+#ifndef	_FPGA_MANAGER_H_
+#define	_FPGA_MANAGER_H_
+
+struct socfpga_fpga_manager {
+	/* FPGA Manager Module */
+	u32	stat;			/* 0x00 */
+	u32	ctrl;
+	u32	dclkcnt;
+	u32	dclkstat;
+	u32	gpo;			/* 0x10 */
+	u32	gpi;
+	u32	misci;			/* 0x18 */
+	u32	_pad_0x1c_0x82c[517];
+
+	/* Configuration Monitor (MON) Registers */
+	u32	gpio_inten;		/* 0x830 */
+	u32	gpio_intmask;
+	u32	gpio_inttype_level;
+	u32	gpio_int_polarity;
+	u32	gpio_intstatus;		/* 0x840 */
+	u32	gpio_raw_intstatus;
+	u32	_pad_0x848;
+	u32	gpio_porta_eoi;
+	u32	gpio_ext_porta;		/* 0x850 */
+	u32	_pad_0x854_0x85c[3];
+	u32	gpio_1s_sync;		/* 0x860 */
+	u32	_pad_0x864_0x868[2];
+	u32	gpio_ver_id_code;
+	u32	gpio_config_reg2;	/* 0x870 */
+	u32	gpio_config_reg1;
+};
+
+#define FPGAMGRREGS_STAT_MODE_MASK		0x7
+#define FPGAMGRREGS_STAT_MSEL_MASK		0xf8
+#define FPGAMGRREGS_STAT_MSEL_LSB		3
+
+#define FPGAMGRREGS_CTRL_CFGWDTH_MASK		0x200
+#define FPGAMGRREGS_CTRL_AXICFGEN_MASK		0x100
+#define FPGAMGRREGS_CTRL_NCONFIGPULL_MASK	0x4
+#define FPGAMGRREGS_CTRL_NCE_MASK		0x2
+#define FPGAMGRREGS_CTRL_EN_MASK		0x1
+#define FPGAMGRREGS_CTRL_CDRATIO_LSB		6
+
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_CRC_MASK	0x8
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_ID_MASK	0x4
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK	0x2
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK	0x1
+
+/* FPGA Mode */
+#define FPGAMGRREGS_MODE_FPGAOFF		0x0
+#define FPGAMGRREGS_MODE_RESETPHASE		0x1
+#define FPGAMGRREGS_MODE_CFGPHASE		0x2
+#define FPGAMGRREGS_MODE_INITPHASE		0x3
+#define FPGAMGRREGS_MODE_USERMODE		0x4
+#define FPGAMGRREGS_MODE_UNKNOWN		0x5
+
+/* FPGA CD Ratio Value */
+#define CDRATIO_x1				0x0
+#define CDRATIO_x2				0x1
+#define CDRATIO_x4				0x2
+#define CDRATIO_x8				0x3
+
+/* SoCFPGA support functions */
+int fpgamgr_test_fpga_ready(void);
+int fpgamgr_poll_fpga_ready(void);
+
+/* FPGA driver API function */
+int fpgamgr_program_fpga(const unsigned long *rbf_data, unsigned long rbf_size);
+
+#endif /* _FPGA_MANAGER_H_ */
diff --git a/drivers/fpga/altera.c b/drivers/fpga/altera.c
index 6e34a8e..d20b7be 100644
--- a/drivers/fpga/altera.c
+++ b/drivers/fpga/altera.c
@@ -1,4 +1,7 @@ 
 /*
+ * (C) Copyright 2013
+ * Altera Corporation <www.altera.com>
+ *
  * (C) Copyright 2003
  * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
  *
@@ -14,6 +17,9 @@ 
 #include <common.h>
 #include <ACEX1K.h>
 #include <stratixII.h>
+#if defined(CONFIG_FPGA_SOCFPGA)
+#include <asm/arch/fpga_manager.h>
+#endif
 
 /* Define FPGA_DEBUG to get debug printf's */
 /* #define FPGA_DEBUG */
@@ -59,6 +65,13 @@  int altera_load(Altera_desc *desc, const void *buf, size_t bsize)
 			ret_val = StratixII_load (desc, buf, bsize);
 			break;
 #endif
+#if defined(CONFIG_FPGA_SOCFPGA)
+		case Altera_SoCFPGA:
+			PRINTF("%s: Launching the SoC FPGA Loader...\n",
+			       __func__);
+			ret_val = fpgamgr_program_fpga(buf, bsize);
+			break;
+#endif
 		default:
 			printf ("%s: Unsupported family type, %d\n",
 					__FUNCTION__, desc->family);
@@ -94,6 +107,11 @@  int altera_dump(Altera_desc *desc, const void *buf, size_t bsize)
 			ret_val = StratixII_dump (desc, buf, bsize);
 			break;
 #endif
+		case Altera_SoCFPGA:
+			printf("%s: Unsupported due to security reason, %d\n",
+			       __func__, desc->family);
+			ret_val = FPGA_SUCCESS;
+			break;
 		default:
 			printf ("%s: Unsupported family type, %d\n",
 					__FUNCTION__, desc->family);
@@ -119,6 +137,9 @@  int altera_info( Altera_desc *desc )
 		case Altera_StratixII:
 			printf ("Stratix II\n");
 			break;
+		case Altera_SoCFPGA:
+			printf("SoC FPGA\n");
+			break;
 			/* Add new family types here */
 		default:
 			printf ("Unknown family type, %d\n", desc->family);
diff --git a/include/altera.h b/include/altera.h
index ae5f7ee..c7f78fc 100644
--- a/include/altera.h
+++ b/include/altera.h
@@ -27,6 +27,7 @@  typedef enum {			/* typedef Altera_Family */
 	Altera_ACEX1K,		/* ACEX1K Family */
 	Altera_CYC2,		/* CYCLONII Family */
 	Altera_StratixII,	/* StratixII Family */
+	Altera_SoCFPGA,		/* SoCFPGA Family */
 /* Add new models here */
 	max_altera_type		/* insert all new types before this */
 } Altera_Family;		/* end, typedef Altera_Family */