summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2015-12-08 08:28:58 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2015-12-08 08:28:58 +0100
commitfab8198323d88ec061032b406b0dc4a874096d60 (patch)
tree5a8accda636ce2a2f9b71f67eefedd7f43c8c357
parent3c40bc8c26beac31ada80efa99b60d49b27da64a (diff)
parent3c8f016d9b78f12602b5485152abfdbd2674b790 (diff)
downloadbarebox-fab8198323d88ec061032b406b0dc4a874096d60.tar.gz
barebox-fab8198323d88ec061032b406b0dc4a874096d60.tar.xz
Merge branch 'for-next/socfpga'
-rw-r--r--arch/arm/mach-socfpga/generic.c34
-rw-r--r--drivers/firmware/socfpga.c46
2 files changed, 66 insertions, 14 deletions
diff --git a/arch/arm/mach-socfpga/generic.c b/arch/arm/mach-socfpga/generic.c
index 234dc52145..2d4afd0a7a 100644
--- a/arch/arm/mach-socfpga/generic.c
+++ b/arch/arm/mach-socfpga/generic.c
@@ -10,6 +10,7 @@
#include <linux/stat.h>
#include <asm/memory.h>
#include <mach/system-manager.h>
+#include <mach/reset-manager.h>
#include <mach/socfpga-regs.h>
#include <mach/nic301.h>
@@ -55,16 +56,43 @@ static int socfpga_detect_sdram(void)
return 0;
}
-static int socfpga_init(void)
+/* Some initialization for the EMAC */
+static void socfpga_init_emac(void)
{
- uint32_t val;
+ uint32_t rst, val;
+
+ /* No need for this without network support, e.g. xloader build */
+ if (!IS_ENABLED(CONFIG_NET))
+ return;
+
+ /* According to Cyclone V datasheet, 17-60 "EMAC HPS Interface
+ * Initialization", changing PHYSEL should be done with EMAC in reset
+ * via permodrst. */
- /* Clearing emac0 PHY interface select to 0 */
+ /* Everything, except L4WD0/1, is out of reset via socfpga_lowlevel_init() */
+ rst = readl(CYCLONE5_RSTMGR_ADDRESS + RESET_MGR_PER_MOD_RESET_OFS);
+ rst |= RSTMGR_PERMODRST_EMAC0 | RSTMGR_PERMODRST_EMAC1;
+ writel(rst, CYCLONE5_RSTMGR_ADDRESS + RESET_MGR_PER_MOD_RESET_OFS);
+
+ /* Set emac0/1 PHY interface select to RGMII. We could read phy-mode
+ * from the device tree, if it was desired to support interfaces other
+ * than RGMII. */
val = readl(CONFIG_SYSMGR_EMAC_CTRL);
+ val &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB);
val &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB);
+ val |= SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII << SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB;
val |= SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII << SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB;
writel(val, CONFIG_SYSMGR_EMAC_CTRL);
+ /* Take emac0 and emac1 out of reset */
+ rst &= ~(RSTMGR_PERMODRST_EMAC0 | RSTMGR_PERMODRST_EMAC1);
+ writel(rst, CYCLONE5_RSTMGR_ADDRESS + RESET_MGR_PER_MOD_RESET_OFS);
+}
+
+static int socfpga_init(void)
+{
+ socfpga_init_emac();
+
writel(SYSMGR_SDMMC_CTRL_DRVSEL(3) | SYSMGR_SDMMC_CTRL_SMPLSEL(0),
SYSMGR_SDMMCGRP_CTRL_REG);
diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 14a7a14c64..159644bbfb 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -79,9 +79,10 @@
struct fpgamgr {
struct firmware_handler fh;
- struct device_d *dev;
+ struct device_d dev;
void __iomem *regs;
void __iomem *regs_data;
+ int programmed;
};
/* Get the FPGA mode */
@@ -303,12 +304,12 @@ static int fpgamgr_program_start(struct firmware_handler *fh)
/* unmap the bridges from NIC-301 */
writel(0x1, CYCLONE5_L3REGS_ADDRESS);
- dev_dbg(mgr->dev, "start programming...\n");
+ dev_dbg(&mgr->dev, "start programming...\n");
/* initialize the FPGA Manager */
status = fpgamgr_program_init(mgr);
if (status) {
- dev_err(mgr->dev, "program init failed with: %s\n",
+ dev_err(&mgr->dev, "program init failed with: %s\n",
strerror(-status));
return status;
}
@@ -356,27 +357,27 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
/* Ensure the FPGA entering config done */
status = fpgamgr_program_poll_cd(mgr);
if (status) {
- dev_err(mgr->dev, "poll for config done failed with: %s\n",
+ dev_err(&mgr->dev, "poll for config done failed with: %s\n",
strerror(-status));
return status;
}
- dev_dbg(mgr->dev, "waiting for init phase...\n");
+ dev_dbg(&mgr->dev, "waiting for init phase...\n");
/* Ensure the FPGA entering init phase */
status = fpgamgr_program_poll_initphase(mgr);
if (status) {
- dev_err(mgr->dev, "poll for init phase failed with: %s\n",
+ dev_err(&mgr->dev, "poll for init phase failed with: %s\n",
strerror(-status));
return status;
}
- dev_dbg(mgr->dev, "waiting for user mode...\n");
+ dev_dbg(&mgr->dev, "waiting for user mode...\n");
/* Ensure the FPGA entering user mode */
status = fpgamgr_program_poll_usermode(mgr);
if (status) {
- dev_err(mgr->dev, "poll for user mode with: %s\n",
+ dev_err(&mgr->dev, "poll for user mode with: %s\n",
strerror(-status));
return status;
}
@@ -384,12 +385,21 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
return 0;
}
+/* Get current programmed state of fpga and put in "programmed" parameter */
+static int programmed_get(struct param_d *p, void *priv)
+{
+ struct fpgamgr *mgr = priv;
+ mgr->programmed = fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE;
+ return 0;
+}
+
static int fpgamgr_probe(struct device_d *dev)
{
struct fpgamgr *mgr;
struct firmware_handler *fh;
const char *alias = of_alias_get(dev->device_node);
const char *model = NULL;
+ struct param_d *p;
int ret;
dev_dbg(dev, "Probing FPGA firmware programmer\n");
@@ -422,17 +432,31 @@ static int fpgamgr_probe(struct device_d *dev)
fh->model = xstrdup(model);
fh->dev = dev;
- mgr->dev = dev;
-
dev_dbg(dev, "Registering FPGA firmware programmer\n");
+ mgr->dev.id = DEVICE_ID_SINGLE;
+ strcpy(mgr->dev.name, "fpga");
+ mgr->dev.parent = dev;
+ ret = register_device(&mgr->dev);
+ if (ret)
+ goto out;
+
+ p = dev_add_param_bool(&mgr->dev, "programmed", NULL, programmed_get, &mgr->programmed, mgr);
+ if (IS_ERR(p)) {
+ ret = PTR_ERR(p);
+ goto out_unreg;
+ }
+
+ fh->dev = &mgr->dev;
ret = firmwaremgr_register(fh);
if (ret != 0) {
free(mgr);
- goto out;
+ goto out_unreg;
}
return 0;
+out_unreg:
+ unregister_device(&mgr->dev);
out:
free(fh->id);
free(mgr);