summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ddr/fsl/ctrl_regs.c77
-rw-r--r--drivers/ddr/fsl/ddr4_dimm_params.c3
-rw-r--r--drivers/ddr/fsl/fsl_ddr_gen4.c169
-rw-r--r--drivers/ddr/fsl/interactive.c56
-rw-r--r--drivers/ddr/fsl/lc_common_dimm_params.c5
-rw-r--r--drivers/ddr/fsl/main.c2
-rw-r--r--drivers/ddr/fsl/options.c7
-rw-r--r--drivers/ddr/fsl/util.c28
-rw-r--r--drivers/i2c/mxc_i2c.c17
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/fsl_debug_server.c246
-rw-r--r--drivers/misc/fsl_ifc.c21
-rw-r--r--drivers/mmc/fsl_esdhc.c36
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c64
-rw-r--r--drivers/mtd/nand/fsl_ifc_spl.c25
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/e1000.c8
-rw-r--r--drivers/net/fm/eth.c2
-rw-r--r--drivers/net/fm/memac.c2
-rw-r--r--drivers/net/fm/memac_phy.c62
-rw-r--r--drivers/net/fsl-mc/Makefile6
-rw-r--r--drivers/net/fsl-mc/dpbp.c102
-rw-r--r--drivers/net/fsl-mc/dpio/Makefile9
-rw-r--r--drivers/net/fsl-mc/dpio/dpio.c102
-rw-r--r--drivers/net/fsl-mc/dpio/qbman_portal.c593
-rw-r--r--drivers/net/fsl-mc/dpio/qbman_portal.h157
-rw-r--r--drivers/net/fsl-mc/dpio/qbman_private.h169
-rw-r--r--drivers/net/fsl-mc/dpio/qbman_sys.h290
-rw-r--r--drivers/net/fsl-mc/dpmng.c65
-rw-r--r--drivers/net/fsl-mc/dpni.c506
-rw-r--r--drivers/net/fsl-mc/dprc.c283
-rw-r--r--drivers/net/fsl-mc/fsl_dpmng_cmd.h32
-rw-r--r--drivers/net/fsl-mc/mc.c702
-rw-r--r--drivers/net/fsl-mc/mc_sys.c6
-rw-r--r--drivers/net/ldpaa_eth/Makefile9
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.c710
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.h149
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_wriop.c146
-rw-r--r--drivers/net/ldpaa_eth/ls2085a.c83
-rw-r--r--drivers/net/phy/cortina.c4
-rw-r--r--drivers/net/vsc9953.c2
-rw-r--r--drivers/pci/pcie_layerscape.c52
-rw-r--r--drivers/qe/qe.c82
-rw-r--r--drivers/qe/qe.h6
-rw-r--r--drivers/usb/host/ehci-fsl.c16
45 files changed, 4785 insertions, 329 deletions
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 391925751a..8367c95cf8 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -313,7 +313,10 @@ static void set_timing_cfg_0(const unsigned int ctrl_num,
#ifdef CONFIG_SYS_FSL_DDR4
/* tXP=max(4nCK, 6ns) */
int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */
- trwt_mclk = 2;
+ unsigned int data_rate = get_ddr_freq(ctrl_num);
+
+ /* for faster clock, need more time for data setup */
+ trwt_mclk = (data_rate/1000000 > 1900) ? 3 : 2;
twrt_mclk = 1;
act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
pre_pd_exit_mclk = act_pd_exit_mclk;
@@ -338,7 +341,7 @@ static void set_timing_cfg_0(const unsigned int ctrl_num,
*/
txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
- ip_rev = fsl_ddr_get_version();
+ ip_rev = fsl_ddr_get_version(ctrl_num);
if (ip_rev >= 0x40700) {
/*
* MRS_CYC = max(tMRD, tMOD)
@@ -544,7 +547,7 @@ static void set_timing_cfg_1(const unsigned int ctrl_num,
* we need set extend bit for it at
* TIMING_CFG_3[EXT_CASLAT]
*/
- if (fsl_ddr_get_version() <= 0x40400)
+ if (fsl_ddr_get_version(ctrl_num) <= 0x40400)
caslat_ctrl = 2 * cas_latency - 1;
else
caslat_ctrl = (cas_latency - 1) << 1;
@@ -1113,16 +1116,32 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
int i;
unsigned short esdmode4 = 0; /* Extended SDRAM mode 4 */
unsigned short esdmode5; /* Extended SDRAM mode 5 */
+ int rtt_park = 0;
- esdmode5 = 0x00000400; /* Data mask enabled */
+ if (ddr->cs[0].config & SDRAM_CS_CONFIG_EN) {
+ esdmode5 = 0x00000500; /* Data mask enable, RTT_PARK CS0 */
+ rtt_park = 1;
+ } else {
+ esdmode5 = 0x00000400; /* Data mask enabled */
+ }
ddr->ddr_sdram_mode_9 = (0
| ((esdmode4 & 0xffff) << 16)
| ((esdmode5 & 0xffff) << 0)
);
+
+ /* only mode_9 use 0x500, others use 0x400 */
+
debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9);
if (unq_mrs_en) { /* unique mode registers are supported */
for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (!rtt_park &&
+ (ddr->cs[i].config & SDRAM_CS_CONFIG_EN)) {
+ esdmode5 |= 0x00000500; /* RTT_PARK */
+ rtt_park = 1;
+ } else {
+ esdmode5 = 0x00000400;
+ }
switch (i) {
case 1:
ddr->ddr_sdram_mode_11 = (0
@@ -1970,31 +1989,41 @@ static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr,
const dimm_params_t *dimm_params)
{
unsigned int acc_ecc_en = (ddr->ddr_sdram_cfg >> 2) & 0x1;
+ int i;
+
+ for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+ if (dimm_params[i].n_ranks)
+ break;
+ }
+ if (i >= CONFIG_DIMM_SLOTS_PER_CTLR) {
+ puts("DDR error: no DIMM found!\n");
+ return;
+ }
- ddr->dq_map_0 = ((dimm_params->dq_mapping[0] & 0x3F) << 26) |
- ((dimm_params->dq_mapping[1] & 0x3F) << 20) |
- ((dimm_params->dq_mapping[2] & 0x3F) << 14) |
- ((dimm_params->dq_mapping[3] & 0x3F) << 8) |
- ((dimm_params->dq_mapping[4] & 0x3F) << 2);
+ ddr->dq_map_0 = ((dimm_params[i].dq_mapping[0] & 0x3F) << 26) |
+ ((dimm_params[i].dq_mapping[1] & 0x3F) << 20) |
+ ((dimm_params[i].dq_mapping[2] & 0x3F) << 14) |
+ ((dimm_params[i].dq_mapping[3] & 0x3F) << 8) |
+ ((dimm_params[i].dq_mapping[4] & 0x3F) << 2);
- ddr->dq_map_1 = ((dimm_params->dq_mapping[5] & 0x3F) << 26) |
- ((dimm_params->dq_mapping[6] & 0x3F) << 20) |
- ((dimm_params->dq_mapping[7] & 0x3F) << 14) |
- ((dimm_params->dq_mapping[10] & 0x3F) << 8) |
- ((dimm_params->dq_mapping[11] & 0x3F) << 2);
+ ddr->dq_map_1 = ((dimm_params[i].dq_mapping[5] & 0x3F) << 26) |
+ ((dimm_params[i].dq_mapping[6] & 0x3F) << 20) |
+ ((dimm_params[i].dq_mapping[7] & 0x3F) << 14) |
+ ((dimm_params[i].dq_mapping[10] & 0x3F) << 8) |
+ ((dimm_params[i].dq_mapping[11] & 0x3F) << 2);
- ddr->dq_map_2 = ((dimm_params->dq_mapping[12] & 0x3F) << 26) |
- ((dimm_params->dq_mapping[13] & 0x3F) << 20) |
- ((dimm_params->dq_mapping[14] & 0x3F) << 14) |
- ((dimm_params->dq_mapping[15] & 0x3F) << 8) |
- ((dimm_params->dq_mapping[16] & 0x3F) << 2);
+ ddr->dq_map_2 = ((dimm_params[i].dq_mapping[12] & 0x3F) << 26) |
+ ((dimm_params[i].dq_mapping[13] & 0x3F) << 20) |
+ ((dimm_params[i].dq_mapping[14] & 0x3F) << 14) |
+ ((dimm_params[i].dq_mapping[15] & 0x3F) << 8) |
+ ((dimm_params[i].dq_mapping[16] & 0x3F) << 2);
/* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */
- ddr->dq_map_3 = ((dimm_params->dq_mapping[17] & 0x3F) << 26) |
- ((dimm_params->dq_mapping[8] & 0x3F) << 20) |
+ ddr->dq_map_3 = ((dimm_params[i].dq_mapping[17] & 0x3F) << 26) |
+ ((dimm_params[i].dq_mapping[8] & 0x3F) << 20) |
(acc_ecc_en ? 0 :
- (dimm_params->dq_mapping[9] & 0x3F) << 14) |
- dimm_params->dq_mapping_ors;
+ (dimm_params[i].dq_mapping[9] & 0x3F) << 14) |
+ dimm_params[i].dq_mapping_ors;
debug("FSLDDR: dq_map_0 = 0x%08x\n", ddr->dq_map_0);
debug("FSLDDR: dq_map_1 = 0x%08x\n", ddr->dq_map_1);
@@ -2357,7 +2386,7 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
set_ddr_cdr1(ddr, popts);
set_ddr_cdr2(ddr, popts);
set_ddr_sdram_cfg(ddr, popts, common_dimm);
- ip_rev = fsl_ddr_get_version();
+ ip_rev = fsl_ddr_get_version(ctrl_num);
if (ip_rev > 0x40400)
unq_mrs_en = 1;
diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c
index bbfb4ee417..42834ca7b2 100644
--- a/drivers/ddr/fsl/ddr4_dimm_params.c
+++ b/drivers/ddr/fsl/ddr4_dimm_params.c
@@ -135,7 +135,8 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num,
if (spd->mem_type) {
if (spd->mem_type != SPD_MEMTYPE_DDR4) {
- printf("DIMM %u: is not a DDR4 SPD.\n", dimm_number);
+ printf("Ctrl %u DIMM %u: is not a DDR4 SPD.\n",
+ ctrl_num, dimm_number);
return 1;
}
} else {
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index d9fce7d2f3..49e4688351 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2014-2015 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -11,6 +11,22 @@
#include <fsl_immap.h>
#include <fsl_ddr.h>
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)
+{
+ int timeout = 1000;
+
+ ddr_out32(ptr, value);
+
+ while (ddr_in32(ptr) & bits) {
+ udelay(100);
+ timeout--;
+ }
+ if (timeout <= 0)
+ puts("Error: A007865 wait for clear timeout.\n");
+}
+#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */
+
#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
#endif
@@ -36,6 +52,16 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
defined(CONFIG_SYS_FSL_ERRATUM_A008514)
u32 *eddrtqcr1;
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+ u32 temp32, mr6;
+#endif
+#ifdef CONFIG_FSL_DDR_BIST
+ u32 mtcr, err_detect, err_sbe;
+ u32 cs0_bnds, cs1_bnds, cs2_bnds, cs3_bnds, cs0_config;
+#endif
+#ifdef CONFIG_FSL_DDR_BIST
+ char buffer[CONFIG_SYS_CBSIZE];
+#endif
switch (ctrl_num) {
case 0:
@@ -214,6 +240,21 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_setbits32(ddr->debug[28], 0x9 << 20);
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+ /* Part 1 of 2 */
+ /* This erraum only applies to verion 5.2.0 */
+ if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
+ /* Disable DRAM VRef training */
+ ddr_out32(&ddr->ddr_cdr2,
+ regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN);
+ /* Disable deskew */
+ ddr_out32(&ddr->debug[28], 0x400);
+ /* Disable D_INIT */
+ ddr_out32(&ddr->sdram_cfg_2,
+ regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+ ddr_out32(&ddr->debug[25], 0x9000);
+ }
+#endif
/*
* For RDIMMs, JEDEC spec requires clocks to be stable before reset is
* deasserted. Clocks start when any chip select is enabled and clock
@@ -261,6 +302,66 @@ step2:
mb();
isb();
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+ /* Part 2 of 2 */
+ /* This erraum only applies to verion 5.2.0 */
+ if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
+ /* Wait for idle */
+ timeout = 200;
+ while (!(ddr_in32(&ddr->debug[1]) & 0x2) &&
+ (timeout > 0)) {
+ udelay(100);
+ timeout--;
+ }
+ if (timeout <= 0) {
+ printf("Controler %d timeout, debug_2 = %x\n",
+ ctrl_num, ddr_in32(&ddr->debug[1]));
+ }
+ /* Set VREF */
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN))
+ continue;
+
+ mr6 = (regs->ddr_sdram_mode_10 >> 16) |
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL(i) |
+ MD_CNTL_MD_SEL(6) |
+ 0x00200000;
+ temp32 = mr6 | 0xc0;
+ set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+ temp32, MD_CNTL_MD_EN);
+ udelay(1);
+ debug("MR6 = 0x%08x\n", temp32);
+ temp32 = mr6 | 0xf0;
+ set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+ temp32, MD_CNTL_MD_EN);
+ udelay(1);
+ debug("MR6 = 0x%08x\n", temp32);
+ temp32 = mr6 | 0x70;
+ set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+ temp32, MD_CNTL_MD_EN);
+ udelay(1);
+ debug("MR6 = 0x%08x\n", temp32);
+ }
+ ddr_out32(&ddr->sdram_md_cntl, 0);
+ ddr_out32(&ddr->debug[28], 0); /* Enable deskew */
+ ddr_out32(&ddr->debug[1], 0x400); /* restart deskew */
+ /* wait for idle */
+ timeout = 200;
+ while (!(ddr_in32(&ddr->debug[1]) & 0x2) &&
+ (timeout > 0)) {
+ udelay(100);
+ timeout--;
+ }
+ if (timeout <= 0) {
+ printf("Controler %d timeout, debug_2 = %x\n",
+ ctrl_num, ddr_in32(&ddr->debug[1]));
+ }
+ /* Restore D_INIT */
+ ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ }
+#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */
+
total_gb_size_per_controller = 0;
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
if (!(regs->cs[i].config & 0x80000000))
@@ -309,4 +410,70 @@ step2:
ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
}
#endif
+
+#ifdef CONFIG_FSL_DDR_BIST
+#define BIST_PATTERN1 0xFFFFFFFF
+#define BIST_PATTERN2 0x0
+#define BIST_CR 0x80010000
+#define BIST_CR_EN 0x80000000
+#define BIST_CR_STAT 0x00000001
+#define CTLR_INTLV_MASK 0x20000000
+ /* Perform build-in test on memory. Three-way interleaving is not yet
+ * supported by this code. */
+ if (getenv_f("ddr_bist", buffer, CONFIG_SYS_CBSIZE) >= 0) {
+ puts("Running BIST test. This will take a while...");
+ cs0_config = ddr_in32(&ddr->cs0_config);
+ if (cs0_config & CTLR_INTLV_MASK) {
+ cs0_bnds = ddr_in32(&cs0_bnds);
+ cs1_bnds = ddr_in32(&cs1_bnds);
+ cs2_bnds = ddr_in32(&cs2_bnds);
+ cs3_bnds = ddr_in32(&cs3_bnds);
+ /* set bnds to non-interleaving */
+ ddr_out32(&cs0_bnds, (cs0_bnds & 0xfffefffe) >> 1);
+ ddr_out32(&cs1_bnds, (cs1_bnds & 0xfffefffe) >> 1);
+ ddr_out32(&cs2_bnds, (cs2_bnds & 0xfffefffe) >> 1);
+ ddr_out32(&cs3_bnds, (cs3_bnds & 0xfffefffe) >> 1);
+ }
+ ddr_out32(&ddr->mtp1, BIST_PATTERN1);
+ ddr_out32(&ddr->mtp2, BIST_PATTERN1);
+ ddr_out32(&ddr->mtp3, BIST_PATTERN2);
+ ddr_out32(&ddr->mtp4, BIST_PATTERN2);
+ ddr_out32(&ddr->mtp5, BIST_PATTERN1);
+ ddr_out32(&ddr->mtp6, BIST_PATTERN1);
+ ddr_out32(&ddr->mtp7, BIST_PATTERN2);
+ ddr_out32(&ddr->mtp8, BIST_PATTERN2);
+ ddr_out32(&ddr->mtp9, BIST_PATTERN1);
+ ddr_out32(&ddr->mtp10, BIST_PATTERN2);
+ mtcr = BIST_CR;
+ ddr_out32(&ddr->mtcr, mtcr);
+ timeout = 100;
+ while (timeout > 0 && (mtcr & BIST_CR_EN)) {
+ mdelay(1000);
+ timeout--;
+ mtcr = ddr_in32(&ddr->mtcr);
+ }
+ if (timeout <= 0)
+ puts("Timeout\n");
+ else
+ puts("Done\n");
+ err_detect = ddr_in32(&ddr->err_detect);
+ err_sbe = ddr_in32(&ddr->err_sbe);
+ if (mtcr & BIST_CR_STAT) {
+ printf("BIST test failed on controller %d.\n",
+ ctrl_num);
+ }
+ if (err_detect || (err_sbe & 0xffff)) {
+ printf("ECC error detected on controller %d.\n",
+ ctrl_num);
+ }
+
+ if (cs0_config & CTLR_INTLV_MASK) {
+ /* restore bnds registers */
+ ddr_out32(&cs0_bnds, cs0_bnds);
+ ddr_out32(&cs1_bnds, cs1_bnds);
+ ddr_out32(&cs2_bnds, cs2_bnds);
+ ddr_out32(&cs3_bnds, cs3_bnds);
+ }
+ }
+#endif
}
diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c
index 32ba6d820b..d23e6e5b97 100644
--- a/drivers/ddr/fsl/interactive.c
+++ b/drivers/ddr/fsl/interactive.c
@@ -205,6 +205,8 @@ static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
#define DIMM_PARM(x) {#x, offsetof(dimm_params_t, x), \
sizeof((dimm_params_t *)0)->x, 0}
+#define DIMM_PARM_HEX(x) {#x, offsetof(dimm_params_t, x), \
+ sizeof((dimm_params_t *)0)->x, 1}
static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
unsigned int ctrl_num,
@@ -220,6 +222,7 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
DIMM_PARM(primary_sdram_width),
DIMM_PARM(ec_sdram_width),
DIMM_PARM(registered_dimm),
+ DIMM_PARM(mirrored_dimm),
DIMM_PARM(device_width),
DIMM_PARM(n_row_addr),
@@ -274,7 +277,27 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
DIMM_PARM(tdqsq_max_ps),
DIMM_PARM(tqhs_ps),
#endif
-
+#ifdef CONFIG_SYS_FSL_DDR4
+ DIMM_PARM_HEX(dq_mapping[0]),
+ DIMM_PARM_HEX(dq_mapping[1]),
+ DIMM_PARM_HEX(dq_mapping[2]),
+ DIMM_PARM_HEX(dq_mapping[3]),
+ DIMM_PARM_HEX(dq_mapping[4]),
+ DIMM_PARM_HEX(dq_mapping[5]),
+ DIMM_PARM_HEX(dq_mapping[6]),
+ DIMM_PARM_HEX(dq_mapping[7]),
+ DIMM_PARM_HEX(dq_mapping[8]),
+ DIMM_PARM_HEX(dq_mapping[9]),
+ DIMM_PARM_HEX(dq_mapping[10]),
+ DIMM_PARM_HEX(dq_mapping[11]),
+ DIMM_PARM_HEX(dq_mapping[12]),
+ DIMM_PARM_HEX(dq_mapping[13]),
+ DIMM_PARM_HEX(dq_mapping[14]),
+ DIMM_PARM_HEX(dq_mapping[15]),
+ DIMM_PARM_HEX(dq_mapping[16]),
+ DIMM_PARM_HEX(dq_mapping[17]),
+ DIMM_PARM(dq_mapping_ors),
+#endif
DIMM_PARM(rank_density),
DIMM_PARM(capacity),
DIMM_PARM(base_address),
@@ -296,6 +319,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
DIMM_PARM(primary_sdram_width),
DIMM_PARM(ec_sdram_width),
DIMM_PARM(registered_dimm),
+ DIMM_PARM(mirrored_dimm),
DIMM_PARM(device_width),
DIMM_PARM(n_row_addr),
@@ -314,6 +338,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
DIMM_PARM(tckmax_ps),
DIMM_PARM(caslat_x),
+ DIMM_PARM_HEX(caslat_x),
DIMM_PARM(taa_ps),
DIMM_PARM(caslat_x_minus_1),
DIMM_PARM(caslat_x_minus_2),
@@ -322,6 +347,9 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
DIMM_PARM(trcd_ps),
DIMM_PARM(trp_ps),
DIMM_PARM(tras_ps),
+#if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3)
+ DIMM_PARM(tfaw_ps),
+#endif
#ifdef CONFIG_SYS_FSL_DDR4
DIMM_PARM(trfc1_ps),
DIMM_PARM(trfc2_ps),
@@ -347,6 +375,27 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
DIMM_PARM(tdqsq_max_ps),
DIMM_PARM(tqhs_ps),
#endif
+#ifdef CONFIG_SYS_FSL_DDR4
+ DIMM_PARM_HEX(dq_mapping[0]),
+ DIMM_PARM_HEX(dq_mapping[1]),
+ DIMM_PARM_HEX(dq_mapping[2]),
+ DIMM_PARM_HEX(dq_mapping[3]),
+ DIMM_PARM_HEX(dq_mapping[4]),
+ DIMM_PARM_HEX(dq_mapping[5]),
+ DIMM_PARM_HEX(dq_mapping[6]),
+ DIMM_PARM_HEX(dq_mapping[7]),
+ DIMM_PARM_HEX(dq_mapping[8]),
+ DIMM_PARM_HEX(dq_mapping[9]),
+ DIMM_PARM_HEX(dq_mapping[10]),
+ DIMM_PARM_HEX(dq_mapping[11]),
+ DIMM_PARM_HEX(dq_mapping[12]),
+ DIMM_PARM_HEX(dq_mapping[13]),
+ DIMM_PARM_HEX(dq_mapping[14]),
+ DIMM_PARM_HEX(dq_mapping[15]),
+ DIMM_PARM_HEX(dq_mapping[16]),
+ DIMM_PARM_HEX(dq_mapping[17]),
+ DIMM_PARM(dq_mapping_ors),
+#endif
};
static const unsigned int n_opts = ARRAY_SIZE(options);
@@ -463,7 +512,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
CTRL_OPTIONS_CS(3, odt_rd_cfg),
CTRL_OPTIONS_CS(3, odt_wr_cfg),
#endif
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
CTRL_OPTIONS_CS(0, odt_rtt_norm),
CTRL_OPTIONS_CS(0, odt_rtt_wr),
#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
@@ -753,7 +802,7 @@ static void print_memctl_options(const memctl_options_t *popts)
CTRL_OPTIONS_CS(3, odt_rd_cfg),
CTRL_OPTIONS_CS(3, odt_wr_cfg),
#endif
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
CTRL_OPTIONS_CS(0, odt_rtt_norm),
CTRL_OPTIONS_CS(0, odt_rtt_wr),
#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
@@ -795,6 +844,7 @@ static void print_memctl_options(const memctl_options_t *popts)
CTRL_OPTIONS(twot_en),
CTRL_OPTIONS(threet_en),
CTRL_OPTIONS(registered_dimm_en),
+ CTRL_OPTIONS(mirrored_dimm),
CTRL_OPTIONS(ap_en),
CTRL_OPTIONS(x4_en),
CTRL_OPTIONS(bstopre),
diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c
index b295344c4d..b12eeb9f01 100644
--- a/drivers/ddr/fsl/lc_common_dimm_params.c
+++ b/drivers/ddr/fsl/lc_common_dimm_params.c
@@ -22,7 +22,7 @@ compute_cas_latency(const unsigned int ctrl_num,
unsigned int common_caslat;
unsigned int caslat_actual;
unsigned int retry = 16;
- unsigned int tmp;
+ unsigned int tmp = ~0;
const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
#ifdef CONFIG_SYS_FSL_DDR3
const unsigned int taamax = 20000;
@@ -31,8 +31,7 @@ compute_cas_latency(const unsigned int ctrl_num,
#endif
/* compute the common CAS latency supported between slots */
- tmp = dimm_params[0].caslat_x;
- for (i = 1; i < number_of_dimms; i++) {
+ for (i = 0; i < number_of_dimms; i++) {
if (dimm_params[i].n_ranks)
tmp &= dimm_params[i].caslat_x;
}
diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c
index b72b24290e..fa223834f2 100644
--- a/drivers/ddr/fsl/main.c
+++ b/drivers/ddr/fsl/main.c
@@ -453,7 +453,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
retval = compute_dimm_parameters(
i, spd, pdimm, j);
#ifdef CONFIG_SYS_DDR_RAW_TIMING
- if (!i && !j && retval) {
+ if (!j && retval) {
printf("SPD error on controller %d! "
"Trying fallback to raw timing "
"calculation\n", i);
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index 5beb11b02b..3b30fa284c 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -728,7 +728,12 @@ unsigned int populate_memctl_options(int all_dimms_registered,
/* Choose ddr controller address mirror mode */
#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
- popts->mirrored_dimm = pdimm[0].mirrored_dimm;
+ for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+ if (pdimm[i].n_ranks) {
+ popts->mirrored_dimm = pdimm[i].mirrored_dimm;
+ break;
+ }
+ }
#endif
/* Global Timing Parameters. */
diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c
index 664081b1b8..ce55aea1b4 100644
--- a/drivers/ddr/fsl/util.c
+++ b/drivers/ddr/fsl/util.c
@@ -23,12 +23,34 @@
#define ULL_8FS 0xFFFFFFFFULL
-u32 fsl_ddr_get_version(void)
+u32 fsl_ddr_get_version(unsigned int ctrl_num)
{
struct ccsr_ddr __iomem *ddr;
u32 ver_major_minor_errata;
- ddr = (void *)_DDR_ADDR;
+ switch (ctrl_num) {
+ case 0:
+ ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
+ break;
+#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
+ case 1:
+ ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR;
+ break;
+#endif
+#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+ case 2:
+ ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR;
+ break;
+#endif
+#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+ case 3:
+ ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR;
+ break;
+#endif
+ default:
+ printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num);
+ return 0;
+ }
ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8;
ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8;
@@ -212,7 +234,7 @@ void print_ddr_info(unsigned int start_ctrl)
/* Calculate CAS latency based on timing cfg values */
cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
- if (fsl_ddr_get_version() <= 0x40400)
+ if (fsl_ddr_get_version(0) <= 0x40400)
cas_lat += 1;
else
cas_lat += 2;
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index fc5ee35a1a..42782cb1ac 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -114,6 +114,9 @@ static u16 i2c_clk_div[50][2] = {
#ifndef CONFIG_SYS_MXC_I2C3_SPEED
#define CONFIG_SYS_MXC_I2C3_SPEED 100000
#endif
+#ifndef CONFIG_SYS_MXC_I2C4_SPEED
+#define CONFIG_SYS_MXC_I2C4_SPEED 100000
+#endif
#ifndef CONFIG_SYS_MXC_I2C1_SLAVE
#define CONFIG_SYS_MXC_I2C1_SLAVE 0
@@ -124,6 +127,9 @@ static u16 i2c_clk_div[50][2] = {
#ifndef CONFIG_SYS_MXC_I2C3_SLAVE
#define CONFIG_SYS_MXC_I2C3_SLAVE 0
#endif
+#ifndef CONFIG_SYS_MXC_I2C4_SLAVE
+#define CONFIG_SYS_MXC_I2C4_SLAVE 0
+#endif
/*
@@ -543,12 +549,17 @@ U_BOOT_I2C_ADAP_COMPLETE(mxc1, mxc_i2c_init, mxc_i2c_probe,
mxc_i2c_set_bus_speed,
CONFIG_SYS_MXC_I2C2_SPEED,
CONFIG_SYS_MXC_I2C2_SLAVE, 1)
-#if defined(CONFIG_MX31) || defined(CONFIG_MX35) ||\
- defined(CONFIG_MX51) || defined(CONFIG_MX53) ||\
- defined(CONFIG_MX6) || defined(CONFIG_LS102XA)
+#ifdef CONFIG_SYS_I2C_MXC_I2C3
U_BOOT_I2C_ADAP_COMPLETE(mxc2, mxc_i2c_init, mxc_i2c_probe,
mxc_i2c_read, mxc_i2c_write,
mxc_i2c_set_bus_speed,
CONFIG_SYS_MXC_I2C3_SPEED,
CONFIG_SYS_MXC_I2C3_SLAVE, 2)
#endif
+#ifdef CONFIG_SYS_I2C_MXC_I2C4
+U_BOOT_I2C_ADAP_COMPLETE(mxc3, mxc_i2c_init, mxc_i2c_probe,
+ mxc_i2c_read, mxc_i2c_write,
+ mxc_i2c_set_bus_speed,
+ CONFIG_SYS_MXC_I2C4_SPEED,
+ CONFIG_SYS_MXC_I2C4_SLAVE, 3)
+#endif
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 842209a2ec..25630c3f2b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o
obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
+obj-$(CONFIG_FSL_DEBUG_SERVER) += fsl_debug_server.o
obj-$(CONFIG_FSL_IIM) += fsl_iim.o
obj-$(CONFIG_GPIO_LED) += gpio_led.o
obj-$(CONFIG_I2C_EEPROM) += i2c_eeprom.o
diff --git a/drivers/misc/fsl_debug_server.c b/drivers/misc/fsl_debug_server.c
new file mode 100644
index 0000000000..e080fe6132
--- /dev/null
+++ b/drivers/misc/fsl_debug_server.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch-fsl-lsch3/immap_lsch3.h>
+
+#include <fsl_debug_server.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+static int debug_server_ver_info_maj, debug_server_ver_info_min;
+
+/**
+ * Copying Debug Server firmware to DDR
+ */
+static int debug_server_copy_image(const char *title, u64 image_addr,
+ u32 image_size, u64 debug_server_ram_addr)
+{
+ debug("%s copied to address %p\n", title,
+ (void *)debug_server_ram_addr);
+ memcpy((void *)debug_server_ram_addr, (void *)image_addr, image_size);
+
+ return 0;
+}
+
+/**
+ * Debug Server FIT image parser checks if the image is in FIT
+ * format, verifies integrity of the image and calculates
+ * raw image address and size values.
+ *
+ * Returns 0 if success and -1 if any of the above mentioned
+ * task fail.
+ **/
+int debug_server_parse_firmware_fit_image(const void **raw_image_addr,
+ size_t *raw_image_size)
+{
+ int format;
+ void *fit_hdr;
+ int node_offset;
+ const void *data;
+ size_t size;
+ const char *uname = "firmware";
+ char *desc;
+ char *debug_server_ver_info;
+ char *debug_server_ver_info_major, *debug_server_ver_info_minor;
+
+ /* Check if the image is in NOR flash */
+#ifdef CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR
+ fit_hdr = (void *)CONFIG_SYS_DEBUG_SERVER_FW_ADDR;
+#else
+#error "CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR not defined"
+#endif
+
+ /* Check if Image is in FIT format */
+ format = genimg_get_format(fit_hdr);
+ if (format != IMAGE_FORMAT_FIT) {
+ printf("Error! Not a FIT image\n");
+ goto out_error;
+ }
+
+ if (!fit_check_format(fit_hdr)) {
+ printf("Error! Bad FIT image format\n");
+ goto out_error;
+ }
+
+ node_offset = fit_image_get_node(fit_hdr, uname);
+ if (node_offset < 0) {
+ printf("Error! Can not find %s subimage\n", uname);
+ goto out_error;
+ }
+
+ /* Verify Debug Server firmware image */
+ if (!fit_image_verify(fit_hdr, node_offset)) {
+ printf("Error! Bad Debug Server firmware hash");
+ goto out_error;
+ }
+
+ if (fit_get_desc(fit_hdr, node_offset, &desc) < 0) {
+ printf("Error! Failed to get Debug Server fw description");
+ goto out_error;
+ }
+
+ debug_server_ver_info = strstr(desc, "Version");
+ debug_server_ver_info_major = strtok(debug_server_ver_info, ".");
+ debug_server_ver_info_minor = strtok(NULL, ".");
+
+ debug_server_ver_info_maj =
+ simple_strtoul(debug_server_ver_info_major, NULL, 10);
+ debug_server_ver_info_min =
+ simple_strtoul(debug_server_ver_info_minor, NULL, 10);
+
+ /* Debug server version checking */
+ if ((debug_server_ver_info_maj < DEBUG_SERVER_VER_MAJOR) ||
+ (debug_server_ver_info_min < DEBUG_SERVER_VER_MINOR)) {
+ printf("Debug server FW mismatches the min version required\n");
+ printf("Expected:%d.%d, Got %d.%d\n",
+ DEBUG_SERVER_VER_MAJOR, DEBUG_SERVER_VER_MINOR,
+ debug_server_ver_info_maj,
+ debug_server_ver_info_min);
+ goto out_error;
+ }
+
+ /* Get address and size of raw image */
+ fit_image_get_data(fit_hdr, node_offset, &data, &size);
+
+ *raw_image_addr = data;
+ *raw_image_size = size;
+
+ return 0;
+
+out_error:
+ return -1;
+}
+
+/**
+ * Return the actual size of the Debug Server private DRAM block.
+ *
+ * NOTE: For now this function always returns the minimum required size,
+ * However, in the future, the actual size may be obtained from an environment
+ * variable.
+ */
+unsigned long debug_server_get_dram_block_size(void)
+{
+ return CONFIG_SYS_DEBUG_SERVER_DRAM_BLOCK_MIN_SIZE;
+}
+
+int debug_server_init(void)
+{
+ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ int error, timeout = CONFIG_SYS_DEBUG_SERVER_TIMEOUT;
+ int debug_server_boot_status;
+ u64 debug_server_ram_addr, debug_server_ram_size;
+ const void *raw_image_addr;
+ size_t raw_image_size = 0;
+
+ debug("debug_server_init called\n");
+ /*
+ * The Debug Server private DRAM block was already carved at the end of
+ * DRAM by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
+ */
+ debug_server_ram_size = debug_server_get_dram_block_size();
+ if (gd->bd->bi_dram[1].start)
+ debug_server_ram_addr =
+ gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
+ else
+ debug_server_ram_addr =
+ gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
+
+ error = debug_server_parse_firmware_fit_image(&raw_image_addr,
+ &raw_image_size);
+ if (error != 0)
+ goto out;
+
+ debug("debug server (ram addr = 0x%llx, ram size = 0x%llx)\n",
+ debug_server_ram_addr, debug_server_ram_size);
+ /*
+ * Load the Debug Server FW at the beginning of the Debug Server
+ * private DRAM block:
+ */
+ debug_server_copy_image("Debug Server Firmware",
+ (u64)raw_image_addr, raw_image_size,
+ debug_server_ram_addr);
+
+ /* flush dcache */
+ flush_dcache_range((unsigned long)debug_server_ram_addr,
+ (unsigned long)debug_server_ram_addr +
+ (unsigned long)debug_server_ram_size);
+
+ /*
+ * Tell SP that the Debug Server FW is about to be launched. Before that
+ * populate the following:
+ * 1. Write the size allocated to SP Memory region into Bits {31:16} of
+ * SCRATCHRW5.
+ * 2. Write the start address of the SP memory regions into
+ * SCRATCHRW5 (Bits {15:0}, contain most significant bits, Bits
+ * {47:32} of the SP Memory Region physical start address
+ * (SoC address)) and SCRATCHRW6 (Bits {31:0}).
+ * 3. To know the Debug Server FW boot status, set bit 0 of SCRATCHRW11
+ * to 1. The Debug Server sets this to 0 to indicate a
+ * successul boot.
+ * 4. Wakeup SP by writing 0x1F to VSG GIC reg VIGR2.
+ */
+
+ /* 512 MB */
+ out_le32(&gur->scratchrw[5 - 1],
+ (u32)((u64)debug_server_ram_addr >> 32) | (0x000D << 16));
+ out_le32(&gur->scratchrw[6 - 1],
+ ((u32)debug_server_ram_addr) & 0xFFFFFFFF);
+
+ out_le32(&gur->scratchrw[11 - 1], DEBUG_SERVER_INIT_STATUS);
+ /* Allow the changes to reflect in GUR block */
+ mb();
+
+ /*
+ * Program VGIC to raise an interrupt to SP
+ */
+ out_le32(CONFIG_SYS_FSL_SP_VSG_GIC_VIGR2, 0x1F);
+ /* Allow the changes to reflect in VIGR2 */
+ mb();
+
+ dmb();
+ debug("Polling for Debug server to launch ...\n");
+
+ while (1) {
+ debug_server_boot_status = in_le32(&gur->scratchrw[11 - 1]);
+ if (!(debug_server_boot_status & DEBUG_SERVER_INIT_STATUS_MASK))
+ break;
+
+ udelay(1); /* throttle polling */
+ if (timeout-- <= 0)
+ break;
+ }
+
+ if (timeout <= 0) {
+ printf("Debug Server FW timed out (boot status: 0x%x)\n",
+ debug_server_boot_status);
+ error = -ETIMEDOUT;
+ goto out;
+ }
+
+ if (debug_server_boot_status & DEBUG_SERVER_INIT_STATUS_MASK) {
+ printf("Debug server FW error'ed out (boot status: 0x%x)\n",
+ debug_server_boot_status);
+ error = -ENODEV;
+ goto out;
+ }
+
+ printf("Debug server booted\n");
+ printf("Detected firmware %d.%d, (boot status: 0x0%x)\n",
+ debug_server_ver_info_maj, debug_server_ver_info_min,
+ debug_server_boot_status);
+
+out:
+ if (error != 0)
+ debug_server_boot_status = -error;
+ else
+ debug_server_boot_status = 0;
+
+ return debug_server_boot_status;
+}
+
diff --git a/drivers/misc/fsl_ifc.c b/drivers/misc/fsl_ifc.c
index 3902e9ff53..a33efdb3b3 100644
--- a/drivers/misc/fsl_ifc.c
+++ b/drivers/misc/fsl_ifc.c
@@ -168,4 +168,25 @@ void init_final_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR0_FINAL
set_ifc_cspr(IFC_CS0, CONFIG_SYS_CSPR0_FINAL);
#endif
+#ifdef CONFIG_SYS_AMASK0_FINAL
+ set_ifc_amask(IFC_CS0, CONFIG_SYS_AMASK0);
+#endif
+#ifdef CONFIG_SYS_CSPR1_FINAL
+ set_ifc_cspr(IFC_CS1, CONFIG_SYS_CSPR1_FINAL);
+#endif
+#ifdef CONFIG_SYS_AMASK1_FINAL
+ set_ifc_amask(IFC_CS1, CONFIG_SYS_AMASK1_FINAL);
+#endif
+#ifdef CONFIG_SYS_CSPR2_FINAL
+ set_ifc_cspr(IFC_CS2, CONFIG_SYS_CSPR2_FINAL);
+#endif
+#ifdef CONFIG_SYS_AMASK2_FINAL
+ set_ifc_amask(IFC_CS2, CONFIG_SYS_AMASK2);
+#endif
+#ifdef CONFIG_SYS_CSPR3_FINAL
+ set_ifc_cspr(IFC_CS3, CONFIG_SYS_CSPR3_FINAL);
+#endif
+#ifdef CONFIG_SYS_AMASK3_FINAL
+ set_ifc_amask(IFC_CS3, CONFIG_SYS_AMASK3);
+#endif
}
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index db4d251923..10ec216d2c 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -105,7 +105,8 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
else if (cmd->resp_type & MMC_RSP_PRESENT)
xfertyp |= XFERTYP_RSPTYP_48;
-#if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || defined(CONFIG_LS102XA)
+#if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || \
+ defined(CONFIG_LS102XA) || defined(CONFIG_LS2085A)
if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
xfertyp |= XFERTYP_CMDTYP_ABORT;
#endif
@@ -183,7 +184,9 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
int timeout;
struct fsl_esdhc_cfg *cfg = mmc->priv;
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
-
+#ifdef CONFIG_LS2085A
+ dma_addr_t addr;
+#endif
uint wml_value;
wml_value = data->blocksize/4;
@@ -194,8 +197,16 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
+#ifdef CONFIG_LS2085A
+ addr = virt_to_phys((void *)(data->dest));
+ if (upper_32_bits(addr))
+ printf("Error found for upper 32 bits\n");
+ else
+ esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
+#else
esdhc_write32(&regs->dsaddr, (u32)data->dest);
#endif
+#endif
} else {
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
flush_dcache_range((ulong)data->src,
@@ -212,8 +223,16 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
wml_value << 16);
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
+#ifdef CONFIG_LS2085A
+ addr = virt_to_phys((void *)(data->src));
+ if (upper_32_bits(addr))
+ printf("Error found for upper 32 bits\n");
+ else
+ esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
+#else
esdhc_write32(&regs->dsaddr, (u32)data->src);
#endif
+#endif
}
esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
@@ -259,10 +278,23 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
static void check_and_invalidate_dcache_range
(struct mmc_cmd *cmd,
struct mmc_data *data) {
+#ifdef CONFIG_LS2085A
+ unsigned start = 0;
+#else
unsigned start = (unsigned)data->dest ;
+#endif
unsigned size = roundup(ARCH_DMA_MINALIGN,
data->blocks*data->blocksize);
unsigned end = start+size ;
+#ifdef CONFIG_LS2085A
+ dma_addr_t addr;
+
+ addr = virt_to_phys((void *)(data->dest));
+ if (upper_32_bits(addr))
+ printf("Error found for upper 32 bits\n");
+ else
+ start = lower_32_bits(addr);
+#endif
invalidate_dcache_range(start, end);
}
#endif
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 7903eebd53..79fa88b22f 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -46,7 +46,7 @@ struct fsl_ifc_ctrl {
struct fsl_ifc_mtd *chips[MAX_BANKS];
/* device info */
- struct fsl_ifc *regs;
+ struct fsl_ifc regs;
uint8_t __iomem *addr; /* Address of assigned IFC buffer */
unsigned int cs_nand; /* On which chipsel NAND is connected */
unsigned int page; /* Last page written to / read from */
@@ -225,7 +225,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
struct nand_chip *chip = mtd->priv;
struct fsl_ifc_mtd *priv = chip->priv;
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
+ struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
int buf_num;
ctrl->page = page_addr;
@@ -289,10 +289,10 @@ static int fsl_ifc_run_command(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_ifc_mtd *priv = chip->priv;
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
+ struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
u32 time_start;
- u32 eccstat[4] = {0};
+ u32 eccstat[8] = {0};
int i;
/* set the chip select for NAND Transaction */
@@ -325,8 +325,15 @@ static int fsl_ifc_run_command(struct mtd_info *mtd)
int sector = bufnum * chip->ecc.steps;
int sector_end = sector + chip->ecc.steps - 1;
- for (i = sector / 4; i <= sector_end / 4; i++)
+ for (i = sector / 4; i <= sector_end / 4; i++) {
+ if (i >= ARRAY_SIZE(eccstat)) {
+ printf("%s: eccstat too small for %d\n",
+ __func__, i);
+ return -EIO;
+ }
+
eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
+ }
for (i = sector; i <= sector_end; i++) {
errors = check_read_ecc(mtd, ctrl, eccstat, i);
@@ -362,7 +369,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
{
struct fsl_ifc_mtd *priv = chip->priv;
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
+ struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
/* Program FIR/IFC_NAND_FCR0 for Small/Large page */
if (mtd->writesize > 512) {
@@ -400,7 +407,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
struct nand_chip *chip = mtd->priv;
struct fsl_ifc_mtd *priv = chip->priv;
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
+ struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
/* clear the read buffer */
ctrl->read_bytes = 0;
@@ -690,7 +697,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_ifc_mtd *priv = chip->priv;
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
+ struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
u32 nand_fsr;
if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
@@ -747,24 +754,33 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
static void fsl_ifc_ctrl_init(void)
{
+ uint32_t ver = 0;
ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
if (!ifc_ctrl)
return;
- ifc_ctrl->regs = IFC_BASE_ADDR;
+ ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR;
+
+ ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev);
+ if (ver >= FSL_IFC_V2_0_0)
+ ifc_ctrl->regs.rregs =
+ (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
+ else
+ ifc_ctrl->regs.rregs =
+ (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
/* clear event registers */
- ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U);
- ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
+ ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U);
+ ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
/* Enable error and event for any detected errors */
- ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en,
+ ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en,
IFC_NAND_EVTER_EN_OPC_EN |
IFC_NAND_EVTER_EN_PGRDCMPL_EN |
IFC_NAND_EVTER_EN_FTOER_EN |
IFC_NAND_EVTER_EN_WPER_EN);
- ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0);
+ ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0);
}
static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
@@ -773,7 +789,7 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
static int fsl_ifc_sram_init(uint32_t ver)
{
- struct fsl_ifc *ifc = ifc_ctrl->regs;
+ struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
uint32_t ncfgr = 0;
u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
@@ -799,13 +815,13 @@ static int fsl_ifc_sram_init(uint32_t ver)
cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
/* Save CSOR and CSOR_ext */
- csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor);
- csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
+ csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
+ csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext);
/* chage PageSize 8K and SpareSize 1K*/
csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
- ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
- ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
+ ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k);
+ ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400);
/* READID */
ifc_out32(&ifc->ifc_nand.nand_fir0,
@@ -845,8 +861,8 @@ static int fsl_ifc_sram_init(uint32_t ver)
ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
/* Restore CSOR and CSOR_ext */
- ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
- ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
+ ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor);
+ ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext);
return 0;
}
@@ -857,6 +873,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
struct nand_chip *nand;
struct fsl_ifc_mtd *priv;
struct nand_ecclayout *layout;
+ struct fsl_ifc_fcm *gregs = NULL;
uint32_t cspr = 0, csor = 0, ver = 0;
int ret = 0;
@@ -872,14 +889,15 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
priv->ctrl = ifc_ctrl;
priv->vbase = addr;
+ gregs = ifc_ctrl->regs.gregs;
/* Find which chip select it is connected to.
*/
for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
phys_addr_t phys_addr = virt_to_phys(addr);
- cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
- csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
+ cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr);
+ csor = ifc_in32(&gregs->csor_cs[priv->bank].csor);
if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
(cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
@@ -998,7 +1016,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
nand->ecc.mode = NAND_ECC_SOFT;
}
- ver = ifc_in32(&ifc_ctrl->regs->ifc_rev);
+ ver = ifc_in32(&gregs->ifc_rev);
if (ver >= FSL_IFC_V1_1_0)
ret = fsl_ifc_sram_init(ver);
if (ret)
diff --git a/drivers/mtd/nand/fsl_ifc_spl.c b/drivers/mtd/nand/fsl_ifc_spl.c
index fb827c5e74..fccbfb5129 100644
--- a/drivers/mtd/nand/fsl_ifc_spl.c
+++ b/drivers/mtd/nand/fsl_ifc_spl.c
@@ -48,11 +48,25 @@ static inline int check_read_ecc(uchar *buf, u32 *eccstat,
return 0;
}
+static inline struct fsl_ifc_runtime *runtime_regs_address(void)
+{
+ struct fsl_ifc regs = {(void *)CONFIG_SYS_IFC_ADDR, NULL};
+ int ver = 0;
+
+ ver = ifc_in32(&regs.gregs->ifc_rev);
+ if (ver >= FSL_IFC_V2_0_0)
+ regs.rregs = (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
+ else
+ regs.rregs = (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
+
+ return regs.rregs;
+}
+
static inline void nand_wait(uchar *buf, int bufnum, int page_size)
{
- struct fsl_ifc *ifc = IFC_BASE_ADDR;
+ struct fsl_ifc_runtime *ifc = runtime_regs_address();
u32 status;
- u32 eccstat[4];
+ u32 eccstat[8];
int bufperpage = page_size / 512;
int bufnum_end, i;
@@ -90,7 +104,8 @@ static inline int bad_block(uchar *marker, int port_size)
int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
{
- struct fsl_ifc *ifc = IFC_BASE_ADDR;
+ struct fsl_ifc_fcm *gregs = (void *)CONFIG_SYS_IFC_ADDR;
+ struct fsl_ifc_runtime *ifc = NULL;
uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
int page_size;
int port_size;
@@ -107,6 +122,8 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
int pg_no;
uchar *dst = vdst;
+ ifc = runtime_regs_address();
+
/* Get NAND Flash configuration */
csor = CONFIG_SYS_NAND_CSOR;
cspr = CONFIG_SYS_NAND_CSPR;
@@ -130,7 +147,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
bad_marker = 5;
}
- ver = ifc_in32(&ifc->ifc_rev);
+ ver = ifc_in32(&gregs->ifc_rev);
if (ver >= FSL_IFC_V2_0_0)
bufnum_mask = (bufnum_mask * 2) + 1;
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f24443df71..150470c24b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -69,4 +69,6 @@ obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/
+obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
+obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
obj-$(CONFIG_VSC9953) += vsc9953.o
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 2d66690226..96e6bb0824 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -2174,7 +2174,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
DEBUGOUT("Error, did not detect valid phy.\n");
return ret_val;
}
- DEBUGOUT("Phy ID = %x \n", hw->phy_id);
+ DEBUGOUT("Phy ID = %x\n", hw->phy_id);
/* Set PHY to class A mode (if necessary) */
ret_val = e1000_set_phy_mode(hw);
@@ -3485,11 +3485,11 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
* some "sticky" (latched) bits.
*/
if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
- DEBUGOUT("PHY Read Error \n");
+ DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
- DEBUGOUT("PHY Read Error \n");
+ DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
@@ -5152,7 +5152,7 @@ e1000_poll(struct eth_device *nic)
if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD)
return 0;
- /*DEBUGOUT("recv: packet len=%d \n", rd->length); */
+ /* DEBUGOUT("recv: packet len=%d\n", rd->length); */
/* Packet received, make sure the data are re-loaded from RAM. */
len = le32_to_cpu(rd->length);
invalidate_dcache_range((unsigned long)packet,
diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c
index 55e76a7d88..d7a37f39a8 100644
--- a/drivers/net/fm/eth.c
+++ b/drivers/net/fm/eth.c
@@ -15,7 +15,7 @@
#include <phy.h>
#include <asm/fsl_dtsec.h>
#include <asm/fsl_tgec.h>
-#include <asm/fsl_memac.h>
+#include <fsl_memac.h>
#include "fm.h"
diff --git a/drivers/net/fm/memac.c b/drivers/net/fm/memac.c
index 60e898cd7c..81a64bf656 100644
--- a/drivers/net/fm/memac.c
+++ b/drivers/net/fm/memac.c
@@ -12,7 +12,7 @@
#include <phy.h>
#include <asm/types.h>
#include <asm/io.h>
-#include <asm/fsl_memac.h>
+#include <fsl_memac.h>
#include "fm.h"
diff --git a/drivers/net/fm/memac_phy.c b/drivers/net/fm/memac_phy.c
index a155d8930b..4ab78e6c25 100644
--- a/drivers/net/fm/memac_phy.c
+++ b/drivers/net/fm/memac_phy.c
@@ -10,9 +10,28 @@
#include <miiphy.h>
#include <phy.h>
#include <asm/io.h>
-#include <asm/fsl_memac.h>
+#include <fsl_memac.h>
#include <fm_eth.h>
+#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
+#define memac_out_32(a, v) out_le32(a, v)
+#define memac_clrbits_32(a, v) clrbits_le32(a, v)
+#define memac_setbits_32(a, v) setbits_le32(a, v)
+#else
+#define memac_out_32(a, v) out_be32(a, v)
+#define memac_clrbits_32(a, v) clrbits_be32(a, v)
+#define memac_setbits_32(a, v) setbits_be32(a, v)
+#endif
+
+static u32 memac_in_32(u32 *reg)
+{
+#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
+ return in_le32(reg);
+#else
+ return in_be32(reg);
+#endif
+}
+
/*
* Write value to the PHY for this device to the register at regnum, waiting
* until the write is done before it returns. All PHY configuration has to be
@@ -28,31 +47,31 @@ int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
if (dev_addr == MDIO_DEVAD_NONE) {
c45 = 0; /* clause 22 */
dev_addr = regnum & 0x1f;
- clrbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+ memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
} else
- setbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+ memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
/* Wait till the bus is free */
- while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+ while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
;
/* Set the port and dev addr */
mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
- out_be32(&regs->mdio_ctl, mdio_ctl);
+ memac_out_32(&regs->mdio_ctl, mdio_ctl);
/* Set the register address */
if (c45)
- out_be32(&regs->mdio_addr, regnum & 0xffff);
+ memac_out_32(&regs->mdio_addr, regnum & 0xffff);
/* Wait till the bus is free */
- while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+ while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
;
/* Write the value to the register */
- out_be32(&regs->mdio_data, MDIO_DATA(value));
+ memac_out_32(&regs->mdio_data, MDIO_DATA(value));
/* Wait till the MDIO write is complete */
- while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
+ while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
;
return 0;
@@ -75,39 +94,39 @@ int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
return 0xffff;
c45 = 0; /* clause 22 */
dev_addr = regnum & 0x1f;
- clrbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+ memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
} else
- setbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+ memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
/* Wait till the bus is free */
- while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+ while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
;
/* Set the Port and Device Addrs */
mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
- out_be32(&regs->mdio_ctl, mdio_ctl);
+ memac_out_32(&regs->mdio_ctl, mdio_ctl);
/* Set the register address */
if (c45)
- out_be32(&regs->mdio_addr, regnum & 0xffff);
+ memac_out_32(&regs->mdio_addr, regnum & 0xffff);
/* Wait till the bus is free */
- while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+ while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
;
/* Initiate the read */
mdio_ctl |= MDIO_CTL_READ;
- out_be32(&regs->mdio_ctl, mdio_ctl);
+ memac_out_32(&regs->mdio_ctl, mdio_ctl);
/* Wait till the MDIO write is complete */
- while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
+ while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
;
/* Return all Fs if nothing was there */
- if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
+ if (memac_in_32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
return 0xffff;
- return in_be32(&regs->mdio_data) & 0xffff;
+ return memac_in_32(&regs->mdio_data) & 0xffff;
}
int memac_mdio_reset(struct mii_dev *bus)
@@ -143,8 +162,9 @@ int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
* like T2080QDS, this bit default is '0', which leads to MDIO failure
* on XAUI PHY, so set this bit definitely.
*/
- setbits_be32(&((struct memac_mdio_controller *)info->regs)->mdio_stat,
- MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
+ memac_setbits_32(
+ &((struct memac_mdio_controller *)info->regs)->mdio_stat,
+ MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
return mdio_register(bus);
}
diff --git a/drivers/net/fsl-mc/Makefile b/drivers/net/fsl-mc/Makefile
index 206ac6be07..7563a5fdd3 100644
--- a/drivers/net/fsl-mc/Makefile
+++ b/drivers/net/fsl-mc/Makefile
@@ -7,4 +7,8 @@
# Layerscape MC driver
obj-y += mc.o \
mc_sys.o \
- dpmng.o
+ dpmng.o \
+ dprc.o \
+ dpbp.o \
+ dpni.o
+obj-y += dpio/
diff --git a/drivers/net/fsl-mc/dpbp.c b/drivers/net/fsl-mc/dpbp.c
new file mode 100644
index 0000000000..3853e58ef9
--- /dev/null
+++ b/drivers/net/fsl-mc/dpbp.c
@@ -0,0 +1,102 @@
+/*
+ * Freescale Layerscape MC I/O wrapper
+ *
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
+ * Author: German Rivera <German.Rivera@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <fsl-mc/fsl_mc_sys.h>
+#include <fsl-mc/fsl_mc_cmd.h>
+#include <fsl-mc/fsl_dpbp.h>
+
+int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
+ MC_CMD_PRI_LOW, 0);
+ DPBP_CMD_OPEN(cmd, dpbp_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+ return err;
+}
+
+int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, MC_CMD_PRI_HIGH,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, MC_CMD_PRI_LOW,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_disable(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_reset(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_get_attributes(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dpbp_attr *attr)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPBP_RSP_GET_ATTRIBUTES(cmd, attr);
+
+ return 0;
+}
diff --git a/drivers/net/fsl-mc/dpio/Makefile b/drivers/net/fsl-mc/dpio/Makefile
new file mode 100644
index 0000000000..1ccefc0db2
--- /dev/null
+++ b/drivers/net/fsl-mc/dpio/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2014 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+# Layerscape MC DPIO driver
+obj-y += dpio.o \
+ qbman_portal.o
diff --git a/drivers/net/fsl-mc/dpio/dpio.c b/drivers/net/fsl-mc/dpio/dpio.c
new file mode 100644
index 0000000000..b07eff7e3c
--- /dev/null
+++ b/drivers/net/fsl-mc/dpio/dpio.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013-2015 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <fsl-mc/fsl_mc_sys.h>
+#include <fsl-mc/fsl_mc_cmd.h>
+#include <fsl-mc/fsl_dpio.h>
+
+int dpio_open(struct fsl_mc_io *mc_io, int dpio_id, uint16_t *token)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN,
+ MC_CMD_PRI_LOW, 0);
+ DPIO_CMD_OPEN(cmd, dpio_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+ return 0;
+}
+
+int dpio_close(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE,
+ MC_CMD_PRI_HIGH, token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpio_enable(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpio_disable(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE,
+ MC_CMD_PRI_LOW,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpio_reset(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpio_get_attributes(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dpio_attr *attr)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR,
+ MC_CMD_PRI_LOW,
+ token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPIO_RSP_GET_ATTR(cmd, attr);
+
+ return 0;
+}
diff --git a/drivers/net/fsl-mc/dpio/qbman_portal.c b/drivers/net/fsl-mc/dpio/qbman_portal.c
new file mode 100644
index 0000000000..dd2a7deee5
--- /dev/null
+++ b/drivers/net/fsl-mc/dpio/qbman_portal.c
@@ -0,0 +1,593 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "qbman_portal.h"
+
+/* QBMan portal management command codes */
+#define QBMAN_MC_ACQUIRE 0x30
+#define QBMAN_WQCHAN_CONFIGURE 0x46
+
+/* CINH register offsets */
+#define QBMAN_CINH_SWP_EQAR 0x8c0
+#define QBMAN_CINH_SWP_DCAP 0xac0
+#define QBMAN_CINH_SWP_SDQCR 0xb00
+#define QBMAN_CINH_SWP_RAR 0xcc0
+
+/* CENA register offsets */
+#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((uint32_t)(n) << 6))
+#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((uint32_t)(n) << 6))
+#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((uint32_t)(n) << 6))
+#define QBMAN_CENA_SWP_CR 0x600
+#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((uint32_t)(vb) >> 1))
+#define QBMAN_CENA_SWP_VDQCR 0x780
+
+/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */
+#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0xff) >> 6)
+
+/*******************************/
+/* Pre-defined attribute codes */
+/*******************************/
+
+struct qb_attr_code code_generic_verb = QB_CODE(0, 0, 7);
+struct qb_attr_code code_generic_rslt = QB_CODE(0, 8, 8);
+
+/*************************/
+/* SDQCR attribute codes */
+/*************************/
+
+/* we put these here because at least some of them are required by
+ * qbman_swp_init() */
+struct qb_attr_code code_sdqcr_dct = QB_CODE(0, 24, 2);
+struct qb_attr_code code_sdqcr_fc = QB_CODE(0, 29, 1);
+struct qb_attr_code code_sdqcr_tok = QB_CODE(0, 16, 8);
+#define CODE_SDQCR_DQSRC(n) QB_CODE(0, n, 1)
+enum qbman_sdqcr_dct {
+ qbman_sdqcr_dct_null = 0,
+ qbman_sdqcr_dct_prio_ics,
+ qbman_sdqcr_dct_active_ics,
+ qbman_sdqcr_dct_active
+};
+enum qbman_sdqcr_fc {
+ qbman_sdqcr_fc_one = 0,
+ qbman_sdqcr_fc_up_to_3 = 1
+};
+
+/*********************************/
+/* Portal constructor/destructor */
+/*********************************/
+
+/* Software portals should always be in the power-on state when we initialise,
+ * due to the CCSR-based portal reset functionality that MC has. */
+struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
+{
+ int ret;
+ struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL);
+
+ if (!p)
+ return NULL;
+ p->desc = d;
+#ifdef QBMAN_CHECKING
+ p->mc.check = swp_mc_can_start;
+#endif
+ p->mc.valid_bit = QB_VALID_BIT;
+ p->sdq = 0;
+ qb_attr_code_encode(&code_sdqcr_dct, &p->sdq, qbman_sdqcr_dct_prio_ics);
+ qb_attr_code_encode(&code_sdqcr_fc, &p->sdq, qbman_sdqcr_fc_up_to_3);
+ qb_attr_code_encode(&code_sdqcr_tok, &p->sdq, 0xbb);
+ p->vdq.busy = 0; /* TODO: convert to atomic_t */
+ p->vdq.valid_bit = QB_VALID_BIT;
+ p->dqrr.next_idx = 0;
+ p->dqrr.valid_bit = QB_VALID_BIT;
+ ret = qbman_swp_sys_init(&p->sys, d);
+ if (ret) {
+ free(p);
+ printf("qbman_swp_sys_init() failed %d\n", ret);
+ return NULL;
+ }
+ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_SDQCR, p->sdq);
+ return p;
+}
+
+/***********************/
+/* Management commands */
+/***********************/
+
+/*
+ * Internal code common to all types of management commands.
+ */
+
+void *qbman_swp_mc_start(struct qbman_swp *p)
+{
+ void *ret;
+#ifdef QBMAN_CHECKING
+ BUG_ON(p->mc.check != swp_mc_can_start);
+#endif
+ ret = qbman_cena_write_start(&p->sys, QBMAN_CENA_SWP_CR);
+#ifdef QBMAN_CHECKING
+ if (!ret)
+ p->mc.check = swp_mc_can_submit;
+#endif
+ return ret;
+}
+
+void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb)
+{
+ uint32_t *v = cmd;
+#ifdef QBMAN_CHECKING
+ BUG_ON(!p->mc.check != swp_mc_can_submit);
+#endif
+ lwsync();
+ /* TBD: "|=" is going to hurt performance. Need to move as many fields
+ * out of word zero, and for those that remain, the "OR" needs to occur
+ * at the caller side. This debug check helps to catch cases where the
+ * caller wants to OR but has forgotten to do so. */
+ BUG_ON((*v & cmd_verb) != *v);
+ *v = cmd_verb | p->mc.valid_bit;
+ qbman_cena_write_complete(&p->sys, QBMAN_CENA_SWP_CR, cmd);
+ /* TODO: add prefetch support for GPP */
+#ifdef QBMAN_CHECKING
+ p->mc.check = swp_mc_can_poll;
+#endif
+}
+
+void *qbman_swp_mc_result(struct qbman_swp *p)
+{
+ uint32_t *ret, verb;
+#ifdef QBMAN_CHECKING
+ BUG_ON(p->mc.check != swp_mc_can_poll);
+#endif
+ ret = qbman_cena_read(&p->sys, QBMAN_CENA_SWP_RR(p->mc.valid_bit));
+ /* Remove the valid-bit - command completed iff the rest is non-zero */
+ verb = ret[0] & ~QB_VALID_BIT;
+ if (!verb)
+ return NULL;
+#ifdef QBMAN_CHECKING
+ p->mc.check = swp_mc_can_start;
+#endif
+ p->mc.valid_bit ^= QB_VALID_BIT;
+ return ret;
+}
+
+/***********/
+/* Enqueue */
+/***********/
+
+/* These should be const, eventually */
+static struct qb_attr_code code_eq_cmd = QB_CODE(0, 0, 2);
+static struct qb_attr_code code_eq_orp_en = QB_CODE(0, 2, 1);
+static struct qb_attr_code code_eq_tgt_id = QB_CODE(2, 0, 24);
+/* static struct qb_attr_code code_eq_tag = QB_CODE(3, 0, 32); */
+static struct qb_attr_code code_eq_qd_en = QB_CODE(0, 4, 1);
+static struct qb_attr_code code_eq_qd_bin = QB_CODE(4, 0, 16);
+static struct qb_attr_code code_eq_qd_pri = QB_CODE(4, 16, 4);
+static struct qb_attr_code code_eq_rsp_stash = QB_CODE(5, 16, 1);
+static struct qb_attr_code code_eq_rsp_lo = QB_CODE(6, 0, 32);
+static struct qb_attr_code code_eq_rsp_hi = QB_CODE(7, 0, 32);
+
+enum qbman_eq_cmd_e {
+ /* No enqueue, primarily for plugging ORP gaps for dropped frames */
+ qbman_eq_cmd_empty,
+ /* DMA an enqueue response once complete */
+ qbman_eq_cmd_respond,
+ /* DMA an enqueue response only if the enqueue fails */
+ qbman_eq_cmd_respond_reject
+};
+
+void qbman_eq_desc_clear(struct qbman_eq_desc *d)
+{
+ memset(d, 0, sizeof(*d));
+}
+
+void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success)
+{
+ uint32_t *cl = qb_cl(d);
+
+ qb_attr_code_encode(&code_eq_orp_en, cl, 0);
+ qb_attr_code_encode(&code_eq_cmd, cl,
+ respond_success ? qbman_eq_cmd_respond :
+ qbman_eq_cmd_respond_reject);
+}
+
+void qbman_eq_desc_set_response(struct qbman_eq_desc *d,
+ dma_addr_t storage_phys,
+ int stash)
+{
+ uint32_t *cl = qb_cl(d);
+
+ qb_attr_code_encode(&code_eq_rsp_lo, cl, lower32(storage_phys));
+ qb_attr_code_encode(&code_eq_rsp_hi, cl, upper32(storage_phys));
+ qb_attr_code_encode(&code_eq_rsp_stash, cl, !!stash);
+}
+
+
+void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid,
+ uint32_t qd_bin, uint32_t qd_prio)
+{
+ uint32_t *cl = qb_cl(d);
+
+ qb_attr_code_encode(&code_eq_qd_en, cl, 1);
+ qb_attr_code_encode(&code_eq_tgt_id, cl, qdid);
+ qb_attr_code_encode(&code_eq_qd_bin, cl, qd_bin);
+ qb_attr_code_encode(&code_eq_qd_pri, cl, qd_prio);
+}
+
+#define EQAR_IDX(eqar) ((eqar) & 0x7)
+#define EQAR_VB(eqar) ((eqar) & 0x80)
+#define EQAR_SUCCESS(eqar) ((eqar) & 0x100)
+
+int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
+ const struct qbman_fd *fd)
+{
+ uint32_t *p;
+ const uint32_t *cl = qb_cl(d);
+ uint32_t eqar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_EQAR);
+ debug("EQAR=%08x\n", eqar);
+ if (!EQAR_SUCCESS(eqar))
+ return -EBUSY;
+ p = qbman_cena_write_start(&s->sys,
+ QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
+ word_copy(&p[1], &cl[1], 7);
+ word_copy(&p[8], fd, sizeof(*fd) >> 2);
+ lwsync();
+ /* Set the verb byte, have to substitute in the valid-bit */
+ p[0] = cl[0] | EQAR_VB(eqar);
+ qbman_cena_write_complete(&s->sys,
+ QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)),
+ p);
+ return 0;
+}
+
+/***************************/
+/* Volatile (pull) dequeue */
+/***************************/
+
+/* These should be const, eventually */
+static struct qb_attr_code code_pull_dct = QB_CODE(0, 0, 2);
+static struct qb_attr_code code_pull_dt = QB_CODE(0, 2, 2);
+static struct qb_attr_code code_pull_rls = QB_CODE(0, 4, 1);
+static struct qb_attr_code code_pull_stash = QB_CODE(0, 5, 1);
+static struct qb_attr_code code_pull_numframes = QB_CODE(0, 8, 4);
+static struct qb_attr_code code_pull_token = QB_CODE(0, 16, 8);
+static struct qb_attr_code code_pull_dqsource = QB_CODE(1, 0, 24);
+static struct qb_attr_code code_pull_rsp_lo = QB_CODE(2, 0, 32);
+static struct qb_attr_code code_pull_rsp_hi = QB_CODE(3, 0, 32);
+
+enum qb_pull_dt_e {
+ qb_pull_dt_channel,
+ qb_pull_dt_workqueue,
+ qb_pull_dt_framequeue
+};
+
+void qbman_pull_desc_clear(struct qbman_pull_desc *d)
+{
+ memset(d, 0, sizeof(*d));
+}
+
+void qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
+ struct ldpaa_dq *storage,
+ dma_addr_t storage_phys,
+ int stash)
+{
+ uint32_t *cl = qb_cl(d);
+
+ /* Squiggle the pointer 'storage' into the extra 2 words of the
+ * descriptor (which aren't copied to the hw command) */
+ *(void **)&cl[4] = storage;
+ if (!storage) {
+ qb_attr_code_encode(&code_pull_rls, cl, 0);
+ return;
+ }
+ qb_attr_code_encode(&code_pull_rls, cl, 1);
+ qb_attr_code_encode(&code_pull_stash, cl, !!stash);
+ qb_attr_code_encode(&code_pull_rsp_lo, cl, lower32(storage_phys));
+ qb_attr_code_encode(&code_pull_rsp_hi, cl, upper32(storage_phys));
+}
+
+void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, uint8_t numframes)
+{
+ uint32_t *cl = qb_cl(d);
+
+ BUG_ON(!numframes || (numframes > 16));
+ qb_attr_code_encode(&code_pull_numframes, cl,
+ (uint32_t)(numframes - 1));
+}
+
+void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token)
+{
+ uint32_t *cl = qb_cl(d);
+
+ qb_attr_code_encode(&code_pull_token, cl, token);
+}
+
+void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid)
+{
+ uint32_t *cl = qb_cl(d);
+
+ qb_attr_code_encode(&code_pull_dct, cl, 1);
+ qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_framequeue);
+ qb_attr_code_encode(&code_pull_dqsource, cl, fqid);
+}
+
+int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)
+{
+ uint32_t *p;
+ uint32_t *cl = qb_cl(d);
+
+ /* TODO: convert to atomic_t */
+ if (s->vdq.busy)
+ return -EBUSY;
+ s->vdq.busy = 1;
+ s->vdq.storage = *(void **)&cl[4];
+ s->vdq.token = qb_attr_code_decode(&code_pull_token, cl);
+ p = qbman_cena_write_start(&s->sys, QBMAN_CENA_SWP_VDQCR);
+ word_copy(&p[1], &cl[1], 3);
+ lwsync();
+ /* Set the verb byte, have to substitute in the valid-bit */
+ p[0] = cl[0] | s->vdq.valid_bit;
+ s->vdq.valid_bit ^= QB_VALID_BIT;
+ qbman_cena_write_complete(&s->sys, QBMAN_CENA_SWP_VDQCR, p);
+ return 0;
+}
+
+/****************/
+/* Polling DQRR */
+/****************/
+
+static struct qb_attr_code code_dqrr_verb = QB_CODE(0, 0, 8);
+static struct qb_attr_code code_dqrr_response = QB_CODE(0, 0, 7);
+static struct qb_attr_code code_dqrr_stat = QB_CODE(0, 8, 8);
+
+#define QBMAN_DQRR_RESPONSE_DQ 0x60
+#define QBMAN_DQRR_RESPONSE_FQRN 0x21
+#define QBMAN_DQRR_RESPONSE_FQRNI 0x22
+#define QBMAN_DQRR_RESPONSE_FQPN 0x24
+#define QBMAN_DQRR_RESPONSE_FQDAN 0x25
+#define QBMAN_DQRR_RESPONSE_CDAN 0x26
+#define QBMAN_DQRR_RESPONSE_CSCN_MEM 0x27
+#define QBMAN_DQRR_RESPONSE_CGCU 0x28
+#define QBMAN_DQRR_RESPONSE_BPSCN 0x29
+#define QBMAN_DQRR_RESPONSE_CSCN_WQ 0x2a
+
+
+/* NULL return if there are no unconsumed DQRR entries. Returns a DQRR entry
+ * only once, so repeated calls can return a sequence of DQRR entries, without
+ * requiring they be consumed immediately or in any particular order. */
+const struct ldpaa_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
+{
+ uint32_t verb;
+ uint32_t response_verb;
+ const struct ldpaa_dq *dq = qbman_cena_read(&s->sys,
+ QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
+ const uint32_t *p = qb_cl(dq);
+
+ verb = qb_attr_code_decode(&code_dqrr_verb, p);
+ /* If the valid-bit isn't of the expected polarity, nothing there */
+ if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
+ qbman_cena_invalidate_prefetch(&s->sys,
+ QBMAN_CENA_SWP_DQRR(
+ s->dqrr.next_idx));
+ return NULL;
+ }
+ /* There's something there. Move "next_idx" attention to the next ring
+ * entry (and prefetch it) before returning what we found. */
+ s->dqrr.next_idx++;
+ s->dqrr.next_idx &= 3; /* Wrap around at 4 */
+ /* TODO: it's possible to do all this without conditionals, optimise it
+ * later. */
+ if (!s->dqrr.next_idx)
+ s->dqrr.valid_bit ^= QB_VALID_BIT;
+ /* VDQCR "no longer busy" hook - if VDQCR shows "busy" and this is a
+ * VDQCR result, mark it as non-busy. */
+ if (s->vdq.busy) {
+ uint32_t flags = ldpaa_dq_flags(dq);
+
+ response_verb = qb_attr_code_decode(&code_dqrr_response, &verb);
+ if ((response_verb == QBMAN_DQRR_RESPONSE_DQ) &&
+ (flags & LDPAA_DQ_STAT_VOLATILE))
+ s->vdq.busy = 0;
+ }
+ qbman_cena_invalidate_prefetch(&s->sys,
+ QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
+ return dq;
+}
+
+/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */
+void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct ldpaa_dq *dq)
+{
+ qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq));
+}
+
+/*********************************/
+/* Polling user-provided storage */
+/*********************************/
+
+void qbman_dq_entry_set_oldtoken(struct ldpaa_dq *dq,
+ unsigned int num_entries,
+ uint8_t oldtoken)
+{
+ memset(dq, oldtoken, num_entries * sizeof(*dq));
+}
+
+int qbman_dq_entry_has_newtoken(struct qbman_swp *s,
+ const struct ldpaa_dq *dq,
+ uint8_t newtoken)
+{
+ /* To avoid converting the little-endian DQ entry to host-endian prior
+ * to us knowing whether there is a valid entry or not (and run the
+ * risk of corrupting the incoming hardware LE write), we detect in
+ * hardware endianness rather than host. This means we need a different
+ * "code" depending on whether we are BE or LE in software, which is
+ * where DQRR_TOK_OFFSET comes in... */
+ static struct qb_attr_code code_dqrr_tok_detect =
+ QB_CODE(0, DQRR_TOK_OFFSET, 8);
+ /* The user trying to poll for a result treats "dq" as const. It is
+ * however the same address that was provided to us non-const in the
+ * first place, for directing hardware DMA to. So we can cast away the
+ * const because it is mutable from our perspective. */
+ uint32_t *p = qb_cl((struct ldpaa_dq *)dq);
+ uint32_t token;
+
+ token = qb_attr_code_decode(&code_dqrr_tok_detect, &p[1]);
+ if (token != newtoken)
+ return 0;
+
+ /* Only now do we convert from hardware to host endianness. Also, as we
+ * are returning success, the user has promised not to call us again, so
+ * there's no risk of us converting the endianness twice... */
+ make_le32_n(p, 16);
+
+ /* VDQCR "no longer busy" hook - not quite the same as DQRR, because the
+ * fact "VDQCR" shows busy doesn't mean that the result we're looking at
+ * is from the same command. Eg. we may be looking at our 10th dequeue
+ * result from our first VDQCR command, yet the second dequeue command
+ * could have been kicked off already, after seeing the 1st result. Ie.
+ * the result we're looking at is not necessarily proof that we can
+ * reset "busy". We instead base the decision on whether the current
+ * result is sitting at the first 'storage' location of the busy
+ * command. */
+ if (s->vdq.busy && (s->vdq.storage == dq))
+ s->vdq.busy = 0;
+ return 1;
+}
+
+/********************************/
+/* Categorising dequeue entries */
+/********************************/
+
+static inline int __qbman_dq_entry_is_x(const struct ldpaa_dq *dq, uint32_t x)
+{
+ const uint32_t *p = qb_cl(dq);
+ uint32_t response_verb = qb_attr_code_decode(&code_dqrr_response, p);
+
+ return response_verb == x;
+}
+
+int qbman_dq_entry_is_DQ(const struct ldpaa_dq *dq)
+{
+ return __qbman_dq_entry_is_x(dq, QBMAN_DQRR_RESPONSE_DQ);
+}
+
+/*********************************/
+/* Parsing frame dequeue results */
+/*********************************/
+
+/* These APIs assume qbman_dq_entry_is_DQ() is TRUE */
+
+uint32_t ldpaa_dq_flags(const struct ldpaa_dq *dq)
+{
+ const uint32_t *p = qb_cl(dq);
+
+ return qb_attr_code_decode(&code_dqrr_stat, p);
+}
+
+const struct dpaa_fd *ldpaa_dq_fd(const struct ldpaa_dq *dq)
+{
+ const uint32_t *p = qb_cl(dq);
+
+ return (const struct dpaa_fd *)&p[8];
+}
+
+/******************/
+/* Buffer release */
+/******************/
+
+/* These should be const, eventually */
+/* static struct qb_attr_code code_release_num = QB_CODE(0, 0, 3); */
+static struct qb_attr_code code_release_set_me = QB_CODE(0, 5, 1);
+static struct qb_attr_code code_release_bpid = QB_CODE(0, 16, 16);
+
+void qbman_release_desc_clear(struct qbman_release_desc *d)
+{
+ uint32_t *cl;
+
+ memset(d, 0, sizeof(*d));
+ cl = qb_cl(d);
+ qb_attr_code_encode(&code_release_set_me, cl, 1);
+}
+
+void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint32_t bpid)
+{
+ uint32_t *cl = qb_cl(d);
+
+ qb_attr_code_encode(&code_release_bpid, cl, bpid);
+}
+
+#define RAR_IDX(rar) ((rar) & 0x7)
+#define RAR_VB(rar) ((rar) & 0x80)
+#define RAR_SUCCESS(rar) ((rar) & 0x100)
+
+int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
+ const uint64_t *buffers, unsigned int num_buffers)
+{
+ uint32_t *p;
+ const uint32_t *cl = qb_cl(d);
+ uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR);
+ debug("RAR=%08x\n", rar);
+ if (!RAR_SUCCESS(rar))
+ return -EBUSY;
+ BUG_ON(!num_buffers || (num_buffers > 7));
+ /* Start the release command */
+ p = qbman_cena_write_start(&s->sys,
+ QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
+ /* Copy the caller's buffer pointers to the command */
+ u64_to_le32_copy(&p[2], buffers, num_buffers);
+ lwsync();
+ /* Set the verb byte, have to substitute in the valid-bit and the number
+ * of buffers. */
+ p[0] = cl[0] | RAR_VB(rar) | num_buffers;
+ qbman_cena_write_complete(&s->sys,
+ QBMAN_CENA_SWP_RCR(RAR_IDX(rar)),
+ p);
+ return 0;
+}
+
+/*******************/
+/* Buffer acquires */
+/*******************/
+
+/* These should be const, eventually */
+static struct qb_attr_code code_acquire_bpid = QB_CODE(0, 16, 16);
+static struct qb_attr_code code_acquire_num = QB_CODE(1, 0, 3);
+static struct qb_attr_code code_acquire_r_num = QB_CODE(1, 0, 3);
+
+int qbman_swp_acquire(struct qbman_swp *s, uint32_t bpid, uint64_t *buffers,
+ unsigned int num_buffers)
+{
+ uint32_t *p;
+ uint32_t verb, rslt, num;
+
+ BUG_ON(!num_buffers || (num_buffers > 7));
+
+ /* Start the management command */
+ p = qbman_swp_mc_start(s);
+
+ if (!p)
+ return -EBUSY;
+
+ /* Encode the caller-provided attributes */
+ qb_attr_code_encode(&code_acquire_bpid, p, bpid);
+ qb_attr_code_encode(&code_acquire_num, p, num_buffers);
+
+ /* Complete the management command */
+ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_MC_ACQUIRE);
+
+ /* Decode the outcome */
+ verb = qb_attr_code_decode(&code_generic_verb, p);
+ rslt = qb_attr_code_decode(&code_generic_rslt, p);
+ num = qb_attr_code_decode(&code_acquire_r_num, p);
+ BUG_ON(verb != QBMAN_MC_ACQUIRE);
+
+ /* Determine success or failure */
+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) {
+ printf("Acquire buffers from BPID 0x%x failed, code=0x%02x\n",
+ bpid, rslt);
+ return -EIO;
+ }
+ BUG_ON(num > num_buffers);
+ /* Copy the acquired buffers to the caller's array */
+ u64_from_le32_copy(buffers, &p[2], num);
+ return (int)num;
+}
diff --git a/drivers/net/fsl-mc/dpio/qbman_portal.h b/drivers/net/fsl-mc/dpio/qbman_portal.h
new file mode 100644
index 0000000000..bb67c3bd06
--- /dev/null
+++ b/drivers/net/fsl-mc/dpio/qbman_portal.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "qbman_private.h"
+#include <fsl-mc/fsl_qbman_portal.h>
+#include <fsl-mc/fsl_dpaa_fd.h>
+
+/* All QBMan command and result structures use this "valid bit" encoding */
+#define QB_VALID_BIT ((uint32_t)0x80)
+
+/* Management command result codes */
+#define QBMAN_MC_RSLT_OK 0xf0
+
+/* --------------------- */
+/* portal data structure */
+/* --------------------- */
+
+struct qbman_swp {
+ const struct qbman_swp_desc *desc;
+ /* The qbman_sys (ie. arch/OS-specific) support code can put anything it
+ * needs in here. */
+ struct qbman_swp_sys sys;
+ /* Management commands */
+ struct {
+#ifdef QBMAN_CHECKING
+ enum swp_mc_check {
+ swp_mc_can_start, /* call __qbman_swp_mc_start() */
+ swp_mc_can_submit, /* call __qbman_swp_mc_submit() */
+ swp_mc_can_poll, /* call __qbman_swp_mc_result() */
+ } check;
+#endif
+ uint32_t valid_bit; /* 0x00 or 0x80 */
+ } mc;
+ /* Push dequeues */
+ uint32_t sdq;
+ /* Volatile dequeues */
+ struct {
+ /* VDQCR supports a "1 deep pipeline", meaning that if you know
+ * the last-submitted command is already executing in the
+ * hardware (as evidenced by at least 1 valid dequeue result),
+ * you can write another dequeue command to the register, the
+ * hardware will start executing it as soon as the
+ * already-executing command terminates. (This minimises latency
+ * and stalls.) With that in mind, this "busy" variable refers
+ * to whether or not a command can be submitted, not whether or
+ * not a previously-submitted command is still executing. In
+ * other words, once proof is seen that the previously-submitted
+ * command is executing, "vdq" is no longer "busy". TODO:
+ * convert this to "atomic_t" so that it is thread-safe (without
+ * locking). */
+ int busy;
+ uint32_t valid_bit; /* 0x00 or 0x80 */
+ /* We need to determine when vdq is no longer busy. This depends
+ * on whether the "busy" (last-submitted) dequeue command is
+ * targetting DQRR or main-memory, and detected is based on the
+ * presence of the dequeue command's "token" showing up in
+ * dequeue entries in DQRR or main-memory (respectively). Debug
+ * builds will, when submitting vdq commands, verify that the
+ * dequeue result location is not already equal to the command's
+ * token value. */
+ struct ldpaa_dq *storage; /* NULL if DQRR */
+ uint32_t token;
+ } vdq;
+ /* DQRR */
+ struct {
+ uint32_t next_idx;
+ uint32_t valid_bit;
+ } dqrr;
+};
+
+/* -------------------------- */
+/* portal management commands */
+/* -------------------------- */
+
+/* Different management commands all use this common base layer of code to issue
+ * commands and poll for results. The first function returns a pointer to where
+ * the caller should fill in their MC command (though they should ignore the
+ * verb byte), the second function commits merges in the caller-supplied command
+ * verb (which should not include the valid-bit) and submits the command to
+ * hardware, and the third function checks for a completed response (returns
+ * non-NULL if only if the response is complete). */
+void *qbman_swp_mc_start(struct qbman_swp *p);
+void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb);
+void *qbman_swp_mc_result(struct qbman_swp *p);
+
+/* Wraps up submit + poll-for-result */
+static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd,
+ uint32_t cmd_verb)
+{
+ int loopvar;
+
+ qbman_swp_mc_submit(swp, cmd, cmd_verb);
+ DBG_POLL_START(loopvar);
+ do {
+ DBG_POLL_CHECK(loopvar);
+ cmd = qbman_swp_mc_result(swp);
+ } while (!cmd);
+ return cmd;
+}
+
+/* ------------ */
+/* qb_attr_code */
+/* ------------ */
+
+/* This struct locates a sub-field within a QBMan portal (CENA) cacheline which
+ * is either serving as a configuration command or a query result. The
+ * representation is inherently little-endian, as the indexing of the words is
+ * itself little-endian in nature and layerscape is little endian for anything
+ * that crosses a word boundary too (64-bit fields are the obvious examples).
+ */
+struct qb_attr_code {
+ unsigned int word; /* which uint32_t[] array member encodes the field */
+ unsigned int lsoffset; /* encoding offset from ls-bit */
+ unsigned int width; /* encoding width. (bool must be 1.) */
+};
+
+/* Macros to define codes */
+#define QB_CODE(a, b, c) { a, b, c}
+
+/* decode a field from a cacheline */
+static inline uint32_t qb_attr_code_decode(const struct qb_attr_code *code,
+ const uint32_t *cacheline)
+{
+ return d32_uint32_t(code->lsoffset, code->width, cacheline[code->word]);
+}
+
+/* encode a field to a cacheline */
+static inline void qb_attr_code_encode(const struct qb_attr_code *code,
+ uint32_t *cacheline, uint32_t val)
+{
+ cacheline[code->word] =
+ r32_uint32_t(code->lsoffset, code->width, cacheline[code->word])
+ | e32_uint32_t(code->lsoffset, code->width, val);
+}
+
+/* ---------------------- */
+/* Descriptors/cachelines */
+/* ---------------------- */
+
+/* To avoid needless dynamic allocation, the driver API often gives the caller
+ * a "descriptor" type that the caller can instantiate however they like.
+ * Ultimately though, it is just a cacheline of binary storage (or something
+ * smaller when it is known that the descriptor doesn't need all 64 bytes) for
+ * holding pre-formatted pieces of harware commands. The performance-critical
+ * code can then copy these descriptors directly into hardware command
+ * registers more efficiently than trying to construct/format commands
+ * on-the-fly. The API user sees the descriptor as an array of 32-bit words in
+ * order for the compiler to know its size, but the internal details are not
+ * exposed. The following macro is used within the driver for converting *any*
+ * descriptor pointer to a usable array pointer. The use of a macro (instead of
+ * an inline) is necessary to work with different descriptor types and to work
+ * correctly with const and non-const inputs (and similarly-qualified outputs).
+ */
+#define qb_cl(d) (&(d)->dont_manipulate_directly[0])
diff --git a/drivers/net/fsl-mc/dpio/qbman_private.h b/drivers/net/fsl-mc/dpio/qbman_private.h
new file mode 100644
index 0000000000..2d2556b755
--- /dev/null
+++ b/drivers/net/fsl-mc/dpio/qbman_private.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/* Perform extra checking */
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/compat.h>
+#include <malloc.h>
+#include <fsl-mc/fsl_qbman_base.h>
+
+#define QBMAN_CHECKING
+
+/* Any time there is a register interface which we poll on, this provides a
+ * "break after x iterations" scheme for it. It's handy for debugging, eg.
+ * where you don't want millions of lines of log output from a polling loop
+ * that won't, because such things tend to drown out the earlier log output
+ * that might explain what caused the problem. (NB: put ";" after each macro!)
+ * TODO: we should probably remove this once we're done sanitising the
+ * simulator...
+ */
+#define DBG_POLL_START(loopvar) (loopvar = 10)
+#define DBG_POLL_CHECK(loopvar) \
+ do {if (!(loopvar--)) BUG_ON(NULL == "DBG_POLL_CHECK"); } while (0)
+
+/* For CCSR or portal-CINH registers that contain fields at arbitrary offsets
+ * and widths, these macro-generated encode/decode/isolate/remove inlines can
+ * be used.
+ *
+ * Eg. to "d"ecode a 14-bit field out of a register (into a "uint16_t" type),
+ * where the field is located 3 bits "up" from the least-significant bit of the
+ * register (ie. the field location within the 32-bit register corresponds to a
+ * mask of 0x0001fff8), you would do;
+ * uint16_t field = d32_uint16_t(3, 14, reg_value);
+ *
+ * Or to "e"ncode a 1-bit boolean value (input type is "int", zero is FALSE,
+ * non-zero is TRUE, so must convert all non-zero inputs to 1, hence the "!!"
+ * operator) into a register at bit location 0x00080000 (19 bits "in" from the
+ * LS bit), do;
+ * reg_value |= e32_int(19, 1, !!field);
+ *
+ * If you wish to read-modify-write a register, such that you leave the 14-bit
+ * field as-is but have all other fields set to zero, then "i"solate the 14-bit
+ * value using;
+ * reg_value = i32_uint16_t(3, 14, reg_value);
+ *
+ * Alternatively, you could "r"emove the 1-bit boolean field (setting it to
+ * zero) but leaving all other fields as-is;
+ * reg_val = r32_int(19, 1, reg_value);
+ *
+ */
+#define MAKE_MASK32(width) (width == 32 ? 0xffffffff : \
+ (uint32_t)((1 << width) - 1))
+#define DECLARE_CODEC32(t) \
+static inline uint32_t e32_##t(uint32_t lsoffset, uint32_t width, t val) \
+{ \
+ BUG_ON(width > (sizeof(t) * 8)); \
+ return ((uint32_t)val & MAKE_MASK32(width)) << lsoffset; \
+} \
+static inline t d32_##t(uint32_t lsoffset, uint32_t width, uint32_t val) \
+{ \
+ BUG_ON(width > (sizeof(t) * 8)); \
+ return (t)((val >> lsoffset) & MAKE_MASK32(width)); \
+} \
+static inline uint32_t i32_##t(uint32_t lsoffset, uint32_t width, \
+ uint32_t val) \
+{ \
+ BUG_ON(width > (sizeof(t) * 8)); \
+ return e32_##t(lsoffset, width, d32_##t(lsoffset, width, val)); \
+} \
+static inline uint32_t r32_##t(uint32_t lsoffset, uint32_t width, \
+ uint32_t val) \
+{ \
+ BUG_ON(width > (sizeof(t) * 8)); \
+ return ~(MAKE_MASK32(width) << lsoffset) & val; \
+}
+DECLARE_CODEC32(uint32_t)
+DECLARE_CODEC32(uint16_t)
+DECLARE_CODEC32(uint8_t)
+DECLARE_CODEC32(int)
+
+ /*********************/
+ /* Debugging assists */
+ /*********************/
+
+static inline void __hexdump(unsigned long start, unsigned long end,
+ unsigned long p, size_t sz, const unsigned char *c)
+{
+ while (start < end) {
+ unsigned int pos = 0;
+ char buf[64];
+ int nl = 0;
+
+ pos += sprintf(buf + pos, "%08lx: ", start);
+ do {
+ if ((start < p) || (start >= (p + sz)))
+ pos += sprintf(buf + pos, "..");
+ else
+ pos += sprintf(buf + pos, "%02x", *(c++));
+ if (!(++start & 15)) {
+ buf[pos++] = '\n';
+ nl = 1;
+ } else {
+ nl = 0;
+ if (!(start & 1))
+ buf[pos++] = ' ';
+ if (!(start & 3))
+ buf[pos++] = ' ';
+ }
+ } while (start & 15);
+ if (!nl)
+ buf[pos++] = '\n';
+ buf[pos] = '\0';
+ debug("%s", buf);
+ }
+}
+static inline void hexdump(const void *ptr, size_t sz)
+{
+ unsigned long p = (unsigned long)ptr;
+ unsigned long start = p & ~(unsigned long)15;
+ unsigned long end = (p + sz + 15) & ~(unsigned long)15;
+ const unsigned char *c = ptr;
+
+ __hexdump(start, end, p, sz, c);
+}
+
+#if defined(__BIG_ENDIAN)
+#define DQRR_TOK_OFFSET 0
+#else
+#define DQRR_TOK_OFFSET 24
+#endif
+
+/* Similarly-named functions */
+#define upper32(a) upper_32_bits(a)
+#define lower32(a) lower_32_bits(a)
+
+ /****************/
+ /* arch assists */
+ /****************/
+
+static inline void dcbz(void *ptr)
+{
+ uint32_t *p = ptr;
+ BUG_ON((unsigned long)ptr & 63);
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ p[3] = 0;
+ p[4] = 0;
+ p[5] = 0;
+ p[6] = 0;
+ p[7] = 0;
+ p[8] = 0;
+ p[9] = 0;
+ p[10] = 0;
+ p[11] = 0;
+ p[12] = 0;
+ p[13] = 0;
+ p[14] = 0;
+ p[15] = 0;
+}
+
+#define lwsync()
+
+#include "qbman_sys.h"
diff --git a/drivers/net/fsl-mc/dpio/qbman_sys.h b/drivers/net/fsl-mc/dpio/qbman_sys.h
new file mode 100644
index 0000000000..235d641bd4
--- /dev/null
+++ b/drivers/net/fsl-mc/dpio/qbman_sys.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/* qbman_sys_decl.h and qbman_sys.h are the two platform-specific files in the
+ * driver. They are only included via qbman_private.h, which is itself a
+ * platform-independent file and is included by all the other driver source.
+ *
+ * qbman_sys_decl.h is included prior to all other declarations and logic, and
+ * it exists to provide compatibility with any linux interfaces our
+ * single-source driver code is dependent on (eg. kmalloc). Ie. this file
+ * provides linux compatibility.
+ *
+ * This qbman_sys.h header, on the other hand, is included *after* any common
+ * and platform-neutral declarations and logic in qbman_private.h, and exists to
+ * implement any platform-specific logic of the qbman driver itself. Ie. it is
+ * *not* to provide linux compatibility.
+ */
+
+/* Trace the 3 different classes of read/write access to QBMan. #undef as
+ * required. */
+#undef QBMAN_CCSR_TRACE
+#undef QBMAN_CINH_TRACE
+#undef QBMAN_CENA_TRACE
+
+/* Temporarily define this to get around the fact that cache enabled mapping is
+ * not working right now. Will remove this after uboot could map the cache
+ * enabled portal memory.
+ */
+#define QBMAN_CINH_ONLY
+
+static inline void word_copy(void *d, const void *s, unsigned int cnt)
+{
+ uint32_t *dd = d;
+ const uint32_t *ss = s;
+
+ while (cnt--)
+ *(dd++) = *(ss++);
+}
+
+/* Currently, the CENA support code expects each 32-bit word to be written in
+ * host order, and these are converted to hardware (little-endian) order on
+ * command submission. However, 64-bit quantities are must be written (and read)
+ * as two 32-bit words with the least-significant word first, irrespective of
+ * host endianness. */
+static inline void u64_to_le32_copy(void *d, const uint64_t *s,
+ unsigned int cnt)
+{
+ uint32_t *dd = d;
+ const uint32_t *ss = (const uint32_t *)s;
+
+ while (cnt--) {
+ /* TBD: the toolchain was choking on the use of 64-bit types up
+ * until recently so this works entirely with 32-bit variables.
+ * When 64-bit types become usable again, investigate better
+ * ways of doing this. */
+#if defined(__BIG_ENDIAN)
+ *(dd++) = ss[1];
+ *(dd++) = ss[0];
+ ss += 2;
+#else
+ *(dd++) = *(ss++);
+ *(dd++) = *(ss++);
+#endif
+ }
+}
+static inline void u64_from_le32_copy(uint64_t *d, const void *s,
+ unsigned int cnt)
+{
+ const uint32_t *ss = s;
+ uint32_t *dd = (uint32_t *)d;
+
+ while (cnt--) {
+#if defined(__BIG_ENDIAN)
+ dd[1] = *(ss++);
+ dd[0] = *(ss++);
+ dd += 2;
+#else
+ *(dd++) = *(ss++);
+ *(dd++) = *(ss++);
+#endif
+ }
+}
+
+/* Convert a host-native 32bit value into little endian */
+#if defined(__BIG_ENDIAN)
+static inline uint32_t make_le32(uint32_t val)
+{
+ return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
+ ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
+}
+#else
+#define make_le32(val) (val)
+#endif
+static inline void make_le32_n(uint32_t *val, unsigned int num)
+{
+ while (num--) {
+ *val = make_le32(*val);
+ val++;
+ }
+}
+
+ /******************/
+ /* Portal access */
+ /******************/
+struct qbman_swp_sys {
+ /* On GPP, the sys support for qbman_swp is here. The CENA region isi
+ * not an mmap() of the real portal registers, but an allocated
+ * place-holder, because the actual writes/reads to/from the portal are
+ * marshalled from these allocated areas using QBMan's "MC access
+ * registers". CINH accesses are atomic so there's no need for a
+ * place-holder. */
+ void *cena;
+ void __iomem *addr_cena;
+ void __iomem *addr_cinh;
+};
+
+/* P_OFFSET is (ACCESS_CMD,0,12) - offset within the portal
+ * C is (ACCESS_CMD,12,1) - is inhibited? (0==CENA, 1==CINH)
+ * SWP_IDX is (ACCESS_CMD,16,10) - Software portal index
+ * P is (ACCESS_CMD,28,1) - (0==special portal, 1==any portal)
+ * T is (ACCESS_CMD,29,1) - Command type (0==READ, 1==WRITE)
+ * E is (ACCESS_CMD,31,1) - Command execute (1 to issue, poll for 0==complete)
+ */
+
+static inline void qbman_cinh_write(struct qbman_swp_sys *s, uint32_t offset,
+ uint32_t val)
+{
+ __raw_writel(val, s->addr_cinh + offset);
+#ifdef QBMAN_CINH_TRACE
+ pr_info("qbman_cinh_write(%p:0x%03x) 0x%08x\n",
+ s->addr_cinh, offset, val);
+#endif
+}
+
+static inline uint32_t qbman_cinh_read(struct qbman_swp_sys *s, uint32_t offset)
+{
+ uint32_t reg = __raw_readl(s->addr_cinh + offset);
+
+#ifdef QBMAN_CINH_TRACE
+ pr_info("qbman_cinh_read(%p:0x%03x) 0x%08x\n",
+ s->addr_cinh, offset, reg);
+#endif
+ return reg;
+}
+
+static inline void *qbman_cena_write_start(struct qbman_swp_sys *s,
+ uint32_t offset)
+{
+ void *shadow = s->cena + offset;
+
+#ifdef QBMAN_CENA_TRACE
+ pr_info("qbman_cena_write_start(%p:0x%03x) %p\n",
+ s->addr_cena, offset, shadow);
+#endif
+ BUG_ON(offset & 63);
+ dcbz(shadow);
+ return shadow;
+}
+
+static inline void qbman_cena_write_complete(struct qbman_swp_sys *s,
+ uint32_t offset, void *cmd)
+{
+ const uint32_t *shadow = cmd;
+ int loop;
+
+#ifdef QBMAN_CENA_TRACE
+ pr_info("qbman_cena_write_complete(%p:0x%03x) %p\n",
+ s->addr_cena, offset, shadow);
+ hexdump(cmd, 64);
+#endif
+ for (loop = 15; loop >= 0; loop--)
+#ifdef QBMAN_CINH_ONLY
+ __raw_writel(shadow[loop], s->addr_cinh +
+ offset + loop * 4);
+#else
+ __raw_writel(shadow[loop], s->addr_cena +
+ offset + loop * 4);
+#endif
+}
+
+static inline void *qbman_cena_read(struct qbman_swp_sys *s, uint32_t offset)
+{
+ uint32_t *shadow = s->cena + offset;
+ unsigned int loop;
+
+#ifdef QBMAN_CENA_TRACE
+ pr_info("qbman_cena_read(%p:0x%03x) %p\n",
+ s->addr_cena, offset, shadow);
+#endif
+
+ for (loop = 0; loop < 16; loop++)
+#ifdef QBMAN_CINH_ONLY
+ shadow[loop] = __raw_readl(s->addr_cinh + offset
+ + loop * 4);
+#else
+ shadow[loop] = __raw_readl(s->addr_cena + offset
+ + loop * 4);
+#endif
+#ifdef QBMAN_CENA_TRACE
+ hexdump(shadow, 64);
+#endif
+ return shadow;
+}
+
+static inline void qbman_cena_invalidate_prefetch(struct qbman_swp_sys *s,
+ uint32_t offset)
+{
+}
+
+ /******************/
+ /* Portal support */
+ /******************/
+
+/* The SWP_CFG portal register is special, in that it is used by the
+ * platform-specific code rather than the platform-independent code in
+ * qbman_portal.c. So use of it is declared locally here. */
+#define QBMAN_CINH_SWP_CFG 0xd00
+
+/* For MC portal use, we always configure with
+ * DQRR_MF is (SWP_CFG,20,3) - DQRR max fill (<- 0x4)
+ * EST is (SWP_CFG,16,3) - EQCR_CI stashing threshold (<- 0x0)
+ * RPM is (SWP_CFG,12,2) - RCR production notification mode (<- 0x3)
+ * DCM is (SWP_CFG,10,2) - DQRR consumption notification mode (<- 0x2)
+ * EPM is (SWP_CFG,8,2) - EQCR production notification mode (<- 0x3)
+ * SD is (SWP_CFG,5,1) - memory stashing drop enable (<- FALSE)
+ * SP is (SWP_CFG,4,1) - memory stashing priority (<- TRUE)
+ * SE is (SWP_CFG,3,1) - memory stashing enable (<- 0x0)
+ * DP is (SWP_CFG,2,1) - dequeue stashing priority (<- TRUE)
+ * DE is (SWP_CFG,1,1) - dequeue stashing enable (<- 0x0)
+ * EP is (SWP_CFG,0,1) - EQCR_CI stashing priority (<- FALSE)
+ */
+static inline uint32_t qbman_set_swp_cfg(uint8_t max_fill, uint8_t wn,
+ uint8_t est, uint8_t rpm, uint8_t dcm,
+ uint8_t epm, int sd, int sp, int se,
+ int dp, int de, int ep)
+{
+ uint32_t reg;
+
+ reg = e32_uint8_t(20, 3, max_fill) | e32_uint8_t(16, 3, est) |
+ e32_uint8_t(12, 2, rpm) | e32_uint8_t(10, 2, dcm) |
+ e32_uint8_t(8, 2, epm) | e32_int(5, 1, sd) |
+ e32_int(4, 1, sp) | e32_int(3, 1, se) | e32_int(2, 1, dp) |
+ e32_int(1, 1, de) | e32_int(0, 1, ep) | e32_uint8_t(14, 1, wn);
+ return reg;
+}
+
+static inline int qbman_swp_sys_init(struct qbman_swp_sys *s,
+ const struct qbman_swp_desc *d)
+{
+ uint32_t reg;
+
+ s->addr_cena = d->cena_bar;
+ s->addr_cinh = d->cinh_bar;
+ s->cena = (void *)valloc(CONFIG_SYS_PAGE_SIZE);
+ memset((void *)s->cena, 0x00, CONFIG_SYS_PAGE_SIZE);
+ if (!s->cena) {
+ printf("Could not allocate page for cena shadow\n");
+ return -1;
+ }
+
+#ifdef QBMAN_CHECKING
+ /* We should never be asked to initialise for a portal that isn't in
+ * the power-on state. (Ie. don't forget to reset portals when they are
+ * decommissioned!)
+ */
+ reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG);
+ BUG_ON(reg);
+#endif
+#ifdef QBMAN_CINH_ONLY
+ reg = qbman_set_swp_cfg(4, 1, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0);
+#else
+ reg = qbman_set_swp_cfg(4, 0, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0);
+#endif
+ qbman_cinh_write(s, QBMAN_CINH_SWP_CFG, reg);
+ reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG);
+ if (!reg) {
+ printf("The portal is not enabled!\n");
+ free(s->cena);
+ return -1;
+ }
+ return 0;
+}
+
+static inline void qbman_swp_sys_finish(struct qbman_swp_sys *s)
+{
+ free((void *)s->cena);
+}
diff --git a/drivers/net/fsl-mc/dpmng.c b/drivers/net/fsl-mc/dpmng.c
index cc14c7b755..01ee1126a9 100644
--- a/drivers/net/fsl-mc/dpmng.c
+++ b/drivers/net/fsl-mc/dpmng.c
@@ -1,4 +1,4 @@
-/* Copyright 2014 Freescale Semiconductor Inc.
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -26,66 +26,3 @@ int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info)
return 0;
}
-
-int dpmng_reset_aiop(struct fsl_mc_io *mc_io, int container_id,
- int aiop_tile_id)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RESET_AIOP,
- MC_CMD_PRI_LOW, 0);
- DPMNG_CMD_RESET_AIOP(cmd, container_id, aiop_tile_id);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dpmng_load_aiop(struct fsl_mc_io *mc_io,
- int container_id,
- int aiop_tile_id,
- uint64_t img_iova,
- uint32_t img_size)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMNG_CMDID_LOAD_AIOP,
- MC_CMD_PRI_LOW,
- 0);
- DPMNG_CMD_LOAD_AIOP(cmd, container_id, aiop_tile_id, img_size,
- img_iova);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dpmng_run_aiop(struct fsl_mc_io *mc_io,
- int container_id,
- int aiop_tile_id,
- const struct dpmng_aiop_run_cfg *cfg)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RUN_AIOP,
- MC_CMD_PRI_LOW,
- 0);
- DPMNG_CMD_RUN_AIOP(cmd, container_id, aiop_tile_id, cfg);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dpmng_reset_mc_portal(struct fsl_mc_io *mc_io)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RESET_MC_PORTAL,
- MC_CMD_PRI_LOW,
- 0);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
diff --git a/drivers/net/fsl-mc/dpni.c b/drivers/net/fsl-mc/dpni.c
new file mode 100644
index 0000000000..b384401295
--- /dev/null
+++ b/drivers/net/fsl-mc/dpni.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2013-2015 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <fsl-mc/fsl_mc_sys.h>
+#include <fsl-mc/fsl_mc_cmd.h>
+#include <fsl-mc/fsl_dpni.h>
+
+int dpni_open(struct fsl_mc_io *mc_io, int dpni_id, uint16_t *token)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN,
+ MC_CMD_PRI_LOW, 0);
+ DPNI_CMD_OPEN(cmd, dpni_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+ return 0;
+}
+
+int dpni_close(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE,
+ MC_CMD_PRI_HIGH, token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_pools(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const struct dpni_pools_cfg *cfg)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS,
+ MC_CMD_PRI_LOW,
+ token);
+ DPNI_CMD_SET_POOLS(cmd, cfg);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_enable(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_disable(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE,
+ MC_CMD_PRI_LOW,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_reset(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_attributes(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dpni_attr *attr)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR,
+ MC_CMD_PRI_LOW,
+ token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_ATTR(cmd, attr);
+
+ return 0;
+}
+
+int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dpni_buffer_layout *layout)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_BUFFER_LAYOUT,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout);
+
+ return 0;
+}
+
+int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const struct dpni_buffer_layout *layout)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_BUFFER_LAYOUT,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dpni_buffer_layout *layout)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_BUFFER_LAYOUT,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout);
+
+ return 0;
+}
+
+int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const struct dpni_buffer_layout *layout)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_BUFFER_LAYOUT,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dpni_buffer_layout *layout)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout);
+
+ return 0;
+}
+
+int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const struct dpni_buffer_layout *layout)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_qdid(struct fsl_mc_io *mc_io, uint16_t token, uint16_t *qdid)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID,
+ MC_CMD_PRI_LOW,
+ token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_QDID(cmd, *qdid);
+
+ return 0;
+}
+
+int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ uint16_t *data_offset)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_DATA_OFFSET,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_TX_DATA_OFFSET(cmd, *data_offset);
+
+ return 0;
+}
+
+int dpni_get_counter(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ enum dpni_counter counter,
+ uint64_t *value)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_COUNTER,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_GET_COUNTER(cmd, counter);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_COUNTER(cmd, *value);
+
+ return 0;
+}
+
+int dpni_set_counter(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ enum dpni_counter counter,
+ uint64_t value)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_COUNTER,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_SET_COUNTER(cmd, counter, value);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dpni_link_cfg *cfg)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_SET_LINK_CFG(cmd, cfg);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_link_state(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dpni_link_state *state)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_LINK_STATE(cmd, state);
+
+ return 0;
+}
+
+
+int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const uint8_t mac_addr[6])
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ uint8_t mac_addr[6])
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr);
+
+ return 0;
+}
+
+int dpni_add_mac_addr(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const uint8_t mac_addr[6])
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_remove_mac_addr(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const uint8_t mac_addr[6])
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_tx_flow(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ uint16_t *flow_id,
+ const struct dpni_tx_flow_cfg *cfg)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_FLOW,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_SET_TX_FLOW(cmd, *flow_id, cfg);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_SET_TX_FLOW(cmd, *flow_id);
+
+ return 0;
+}
+
+int dpni_get_tx_flow(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ uint16_t flow_id,
+ struct dpni_tx_flow_attr *attr)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_FLOW,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_GET_TX_FLOW(cmd, flow_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_TX_FLOW(cmd, attr);
+
+ return 0;
+}
+
+int dpni_set_rx_flow(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ uint8_t tc_id,
+ uint16_t flow_id,
+ const struct dpni_queue_cfg *cfg)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FLOW,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_rx_flow(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ uint8_t tc_id,
+ uint16_t flow_id,
+ struct dpni_queue_attr *attr)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_FLOW,
+ MC_CMD_PRI_LOW, token);
+ DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPNI_RSP_GET_RX_FLOW(cmd, attr);
+
+ return 0;
+}
diff --git a/drivers/net/fsl-mc/dprc.c b/drivers/net/fsl-mc/dprc.c
new file mode 100644
index 0000000000..d481200243
--- /dev/null
+++ b/drivers/net/fsl-mc/dprc.c
@@ -0,0 +1,283 @@
+/*
+ * Freescale Layerscape MC I/O wrapper
+ *
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
+ * Author: German Rivera <German.Rivera@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <fsl-mc/fsl_mc_sys.h>
+#include <fsl-mc/fsl_mc_cmd.h>
+#include <fsl-mc/fsl_dprc.h>
+
+int dprc_get_container_id(struct fsl_mc_io *mc_io, int *container_id)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
+ MC_CMD_PRI_LOW, 0);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPRC_RSP_GET_CONTAINER_ID(cmd, *container_id);
+
+ return 0;
+}
+
+int dprc_open(struct fsl_mc_io *mc_io, int container_id, uint16_t *token)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, MC_CMD_PRI_LOW,
+ 0);
+ DPRC_CMD_OPEN(cmd, container_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+ return 0;
+}
+
+int dprc_close(struct fsl_mc_io *mc_io, uint16_t token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, MC_CMD_PRI_HIGH,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_reset_container(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ int child_container_id)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
+ MC_CMD_PRI_LOW, token);
+ DPRC_CMD_RESET_CONTAINER(cmd, child_container_id);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_attributes(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ struct dprc_attributes *attr)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
+ MC_CMD_PRI_LOW,
+ token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPRC_RSP_GET_ATTRIBUTES(cmd, attr);
+
+ return 0;
+}
+
+int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
+ MC_CMD_PRI_LOW, token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPRC_RSP_GET_OBJ_COUNT(cmd, *obj_count);
+
+ return 0;
+}
+
+int dprc_get_obj(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ int obj_index,
+ struct dprc_obj_desc *obj_desc)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
+ MC_CMD_PRI_LOW,
+ token);
+ DPRC_CMD_GET_OBJ(cmd, obj_index);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPRC_RSP_GET_OBJ(cmd, obj_desc);
+
+ return 0;
+}
+
+int dprc_get_res_count(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ char *type,
+ int *res_count)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ *res_count = 0;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
+ MC_CMD_PRI_LOW, token);
+ DPRC_CMD_GET_RES_COUNT(cmd, type);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPRC_RSP_GET_RES_COUNT(cmd, *res_count);
+
+ return 0;
+}
+
+int dprc_get_res_ids(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ char *type,
+ struct dprc_res_ids_range_desc *range_desc)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS,
+ MC_CMD_PRI_LOW, token);
+ DPRC_CMD_GET_RES_IDS(cmd, range_desc, type);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPRC_RSP_GET_RES_IDS(cmd, range_desc);
+
+ return 0;
+}
+
+int dprc_get_obj_region(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ char *obj_type,
+ int obj_id,
+ uint8_t region_index,
+ struct dprc_region_desc *region_desc)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
+ MC_CMD_PRI_LOW, token);
+ DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPRC_RSP_GET_OBJ_REGION(cmd, region_desc);
+
+ return 0;
+}
+
+int dprc_connect(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const struct dprc_endpoint *endpoint1,
+ const struct dprc_endpoint *endpoint2)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT,
+ MC_CMD_PRI_LOW,
+ token);
+ DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_disconnect(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const struct dprc_endpoint *endpoint)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT,
+ MC_CMD_PRI_LOW,
+ token);
+ DPRC_CMD_DISCONNECT(cmd, endpoint);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_connection(struct fsl_mc_io *mc_io,
+ uint16_t token,
+ const struct dprc_endpoint *endpoint1,
+ struct dprc_endpoint *endpoint2,
+ int *state)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION,
+ MC_CMD_PRI_LOW,
+ token);
+ DPRC_CMD_GET_CONNECTION(cmd, endpoint1);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ DPRC_RSP_GET_CONNECTION(cmd, endpoint2, *state);
+
+ return 0;
+}
diff --git a/drivers/net/fsl-mc/fsl_dpmng_cmd.h b/drivers/net/fsl-mc/fsl_dpmng_cmd.h
index c9fe021f45..33f84f39bb 100644
--- a/drivers/net/fsl-mc/fsl_dpmng_cmd.h
+++ b/drivers/net/fsl-mc/fsl_dpmng_cmd.h
@@ -1,4 +1,4 @@
-/* Copyright 2014 Freescale Semiconductor Inc.
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -7,10 +7,6 @@
/* Command IDs */
#define DPMNG_CMDID_GET_VERSION 0x831
-#define DPMNG_CMDID_RESET_AIOP 0x832
-#define DPMNG_CMDID_LOAD_AIOP 0x833
-#define DPMNG_CMDID_RUN_AIOP 0x834
-#define DPMNG_CMDID_RESET_MC_PORTAL 0x835
/* cmd, param, offset, width, type, arg_name */
#define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \
@@ -20,30 +16,4 @@ do { \
MC_RSP_OP(cmd, 1, 0, 32, uint32_t, mc_ver_info->minor); \
} while (0)
-/* cmd, param, offset, width, type, arg_name */
-#define DPMNG_CMD_RESET_AIOP(cmd, container_id, aiop_tile_id) \
-do { \
- MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \
- MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \
-} while (0)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMNG_CMD_LOAD_AIOP(cmd, container_id, aiop_tile_id, img_size, \
- img_iova) \
-do { \
- MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \
- MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \
- MC_CMD_OP(cmd, 1, 0, 32, uint32_t, img_size); \
- MC_CMD_OP(cmd, 2, 0, 64, uint64_t, img_iova); \
-} while (0)
-
-/* cmd, param, offset, width, type, arg_name */
-#define DPMNG_CMD_RUN_AIOP(cmd, container_id, aiop_tile_id, cfg) \
-do { \
- MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \
- MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \
- MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->cores_mask); \
- MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options); \
-} while (0)
-
#endif /* __FSL_DPMNG_CMD_H */
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index 74b0085301..c5c44bcab0 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -3,16 +3,75 @@
*
* SPDX-License-Identifier: GPL-2.0+
*/
-
#include <errno.h>
#include <asm/io.h>
#include <fsl-mc/fsl_mc.h>
#include <fsl-mc/fsl_mc_sys.h>
+#include <fsl-mc/fsl_mc_private.h>
#include <fsl-mc/fsl_dpmng.h>
+#include <fsl_debug_server.h>
+#include <fsl-mc/fsl_dprc.h>
+#include <fsl-mc/fsl_dpio.h>
+#include <fsl-mc/fsl_qbman_portal.h>
+
+#define MC_RAM_BASE_ADDR_ALIGNMENT (512UL * 1024 * 1024)
+#define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
+#define MC_RAM_SIZE_ALIGNMENT (256UL * 1024 * 1024)
+
+#define MC_MEM_SIZE_ENV_VAR "mcmemsize"
+#define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
DECLARE_GLOBAL_DATA_PTR;
static int mc_boot_status;
+struct fsl_mc_io *dflt_mc_io = NULL;
+uint16_t dflt_dprc_handle = 0;
+struct fsl_dpbp_obj *dflt_dpbp = NULL;
+struct fsl_dpio_obj *dflt_dpio = NULL;
+uint16_t dflt_dpio_handle = 0;
+
+#ifdef DEBUG
+void dump_ram_words(const char *title, void *addr)
+{
+ int i;
+ uint32_t *words = addr;
+
+ printf("Dumping beginning of %s (%p):\n", title, addr);
+ for (i = 0; i < 16; i++)
+ printf("%#x ", words[i]);
+ printf("\n");
+}
+
+void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
+{
+ printf("MC CCSR registers:\n"
+ "reg_gcr1 %#x\n"
+ "reg_gsr %#x\n"
+ "reg_sicbalr %#x\n"
+ "reg_sicbahr %#x\n"
+ "reg_sicapr %#x\n"
+ "reg_mcfbalr %#x\n"
+ "reg_mcfbahr %#x\n"
+ "reg_mcfapr %#x\n"
+ "reg_psr %#x\n",
+ mc_ccsr_regs->reg_gcr1,
+ mc_ccsr_regs->reg_gsr,
+ mc_ccsr_regs->reg_sicbalr,
+ mc_ccsr_regs->reg_sicbahr,
+ mc_ccsr_regs->reg_sicapr,
+ mc_ccsr_regs->reg_mcfbalr,
+ mc_ccsr_regs->reg_mcfbahr,
+ mc_ccsr_regs->reg_mcfapr,
+ mc_ccsr_regs->reg_psr);
+}
+#else
+
+#define dump_ram_words(title, addr)
+#define dump_mc_ccsr_regs(mc_ccsr_regs)
+
+#endif /* DEBUG */
+
+#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
/**
* Copying MC firmware or DPL image to DDR
*/
@@ -21,6 +80,7 @@ static int mc_copy_image(const char *title,
{
debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
+ flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
return 0;
}
@@ -82,23 +142,254 @@ int parse_mc_firmware_fit_image(const void **raw_image_addr,
return 0;
}
+#endif
+
+/*
+ * Calculates the values to be used to specify the address range
+ * for the MC private DRAM block, in the MCFBALR/MCFBAHR registers.
+ * It returns the highest 512MB-aligned address within the given
+ * address range, in '*aligned_base_addr', and the number of 256 MiB
+ * blocks in it, in 'num_256mb_blocks'.
+ */
+static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr,
+ size_t mc_ram_size,
+ u64 *aligned_base_addr,
+ u8 *num_256mb_blocks)
+{
+ u64 addr;
+ u16 num_blocks;
+
+ if (mc_ram_size % MC_RAM_SIZE_ALIGNMENT != 0) {
+ printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
+ mc_ram_size);
+ return -EINVAL;
+ }
+
+ num_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
+ if (num_blocks < 1 || num_blocks > 0xff) {
+ printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
+ mc_ram_size);
+ return -EINVAL;
+ }
+
+ addr = (mc_private_ram_start_addr + mc_ram_size - 1) &
+ MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
+
+ if (addr < mc_private_ram_start_addr) {
+ printf("fsl-mc: ERROR: bad start address %#llx\n",
+ mc_private_ram_start_addr);
+ return -EFAULT;
+ }
+
+ *aligned_base_addr = addr;
+ *num_256mb_blocks = num_blocks;
+ return 0;
+}
+
+static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size)
+{
+ u64 mc_dpc_offset;
+#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
+ int error;
+ void *dpc_fdt_hdr;
+ int dpc_size;
+#endif
+
+#ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
+ BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
+ CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
+
+ mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
+#else
+#error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
+#endif
+
+ /*
+ * Load the MC DPC blob in the MC private DRAM block:
+ */
+#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
+ printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
+#else
+ /*
+ * Get address and size of the DPC blob stored in flash:
+ */
+#ifdef CONFIG_SYS_LS_MC_DPC_IN_NOR
+ dpc_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPC_ADDR;
+#else
+#error "No CONFIG_SYS_LS_MC_DPC_IN_xxx defined"
+#endif
+
+ error = fdt_check_header(dpc_fdt_hdr);
+ if (error != 0) {
+ /*
+ * Don't return with error here, since the MC firmware can
+ * still boot without a DPC
+ */
+ printf("fsl-mc: WARNING: No DPC image found\n");
+ return 0;
+ }
+
+ dpc_size = fdt_totalsize(dpc_fdt_hdr);
+ if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
+ printf("fsl-mc: ERROR: Bad DPC image (too large: %d)\n",
+ dpc_size);
+ return -EINVAL;
+ }
+
+ mc_copy_image("MC DPC blob",
+ (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
+#endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
+
+ dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
+ return 0;
+}
-int mc_init(bd_t *bis)
+static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size)
+{
+ u64 mc_dpl_offset;
+#ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
+ int error;
+ void *dpl_fdt_hdr;
+ int dpl_size;
+#endif
+
+#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
+ BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
+ CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
+
+ mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
+#else
+#error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
+#endif
+
+ /*
+ * Load the MC DPL blob in the MC private DRAM block:
+ */
+#ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
+ printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
+#else
+ /*
+ * Get address and size of the DPL blob stored in flash:
+ */
+#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR
+ dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR;
+#else
+#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined"
+#endif
+
+ error = fdt_check_header(dpl_fdt_hdr);
+ if (error != 0) {
+ printf("fsl-mc: ERROR: Bad DPL image (bad header)\n");
+ return error;
+ }
+
+ dpl_size = fdt_totalsize(dpl_fdt_hdr);
+ if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
+ printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n",
+ dpl_size);
+ return -EINVAL;
+ }
+
+ mc_copy_image("MC DPL blob",
+ (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
+#endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
+
+ dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
+ return 0;
+}
+
+/**
+ * Return the MC boot timeout value in milliseconds
+ */
+static unsigned long get_mc_boot_timeout_ms(void)
+{
+ unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
+
+ char *timeout_ms_env_var = getenv(MC_BOOT_TIMEOUT_ENV_VAR);
+
+ if (timeout_ms_env_var) {
+ timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
+ if (timeout_ms == 0) {
+ printf("fsl-mc: WARNING: Invalid value for \'"
+ MC_BOOT_TIMEOUT_ENV_VAR
+ "\' environment variable: %lu\n",
+ timeout_ms);
+
+ timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
+ }
+ }
+
+ return timeout_ms;
+}
+
+static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
+{
+ u32 reg_gsr;
+ u32 mc_fw_boot_status;
+ unsigned long timeout_ms = get_mc_boot_timeout_ms();
+ struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
+
+ dmb();
+ debug("Polling mc_ccsr_regs->reg_gsr ...\n");
+ assert(timeout_ms > 0);
+ for (;;) {
+ udelay(1000); /* throttle polling */
+ reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
+ mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
+ if (mc_fw_boot_status & 0x1)
+ break;
+
+ timeout_ms--;
+ if (timeout_ms == 0)
+ break;
+ }
+
+ if (timeout_ms == 0) {
+ if (booting_mc)
+ printf("fsl-mc: timeout booting management complex firmware\n");
+ else
+ printf("fsl-mc: timeout deploying data path layout\n");
+
+ /* TODO: Get an error status from an MC CCSR register */
+ return -ETIMEDOUT;
+ }
+
+ if (mc_fw_boot_status != 0x1) {
+ /*
+ * TODO: Identify critical errors from the GSR register's FS
+ * field and for those errors, set error to -ENODEV or other
+ * appropriate errno, so that the status property is set to
+ * failure in the fsl,dprc device tree node.
+ */
+ if (booting_mc) {
+ printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n",
+ reg_gsr);
+ } else {
+ printf("fsl-mc: WARNING: Data path layout deployed with error (GSR: %#x)\n",
+ reg_gsr);
+ }
+ }
+
+ *final_reg_gsr = reg_gsr;
+ return 0;
+}
+
+int mc_init(void)
{
int error = 0;
- int timeout = 200000;
+ int portal_id = 0;
struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
u64 mc_ram_addr;
- u64 mc_dpl_offset;
u32 reg_gsr;
- u32 mc_fw_boot_status;
- void *dpl_fdt_hdr;
- int dpl_size;
+ u32 reg_mcfbalr;
+#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
const void *raw_image_addr;
size_t raw_image_size = 0;
- struct fsl_mc_io mc_io;
- int portal_id;
+#endif
struct mc_version mc_ver_info;
+ u64 mc_ram_aligned_base_addr;
+ u8 mc_ram_num_256mb_blocks;
+ size_t mc_ram_size = mc_get_dram_block_size();
/*
* The MC private DRAM block was already carved at the end of DRAM
@@ -112,6 +403,20 @@ int mc_init(bd_t *bis)
gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
}
+#ifdef CONFIG_FSL_DEBUG_SERVER
+ /*
+ * FIXME: I don't think this is right. See get_dram_size_to_hide()
+ */
+ mc_ram_addr -= debug_server_get_dram_block_size();
+#endif
+
+ error = calculate_mc_private_ram_params(mc_ram_addr,
+ mc_ram_size,
+ &mc_ram_aligned_base_addr,
+ &mc_ram_num_256mb_blocks);
+ if (error != 0)
+ goto out;
+
/*
* Management Complex cores should be held at reset out of POR.
* U-boot should be the first software to touch MC. To be safe,
@@ -127,6 +432,9 @@ int mc_init(bd_t *bis)
out_le32(&mc_ccsr_regs->reg_gcr1, 0);
dmb();
+#ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
+ printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
+#else
error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size);
if (error != 0)
goto out;
@@ -135,83 +443,34 @@ int mc_init(bd_t *bis)
*/
mc_copy_image("MC Firmware",
(u64)raw_image_addr, raw_image_size, mc_ram_addr);
-
- /*
- * Get address and size of the DPL blob stored in flash:
- */
-#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR
- dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR;
-#else
-#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined"
#endif
+ dump_ram_words("firmware", (void *)mc_ram_addr);
- error = fdt_check_header(dpl_fdt_hdr);
- if (error != 0) {
- printf("fsl-mc: ERROR: Bad DPL image (bad header)\n");
- goto out;
- }
-
- dpl_size = fdt_totalsize(dpl_fdt_hdr);
- if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
- printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n",
- dpl_size);
- error = -EINVAL;
+ error = load_mc_dpc(mc_ram_addr, mc_ram_size);
+ if (error != 0)
goto out;
- }
- /*
- * Calculate offset in the MC private DRAM block at which the MC DPL
- * blob is to be placed:
- */
-#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
- BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
- CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
-
- mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
-#else
- mc_dpl_offset = mc_get_dram_block_size() -
- roundup(CONFIG_SYS_LS_MC_DPL_MAX_LENGTH, 4096);
-
- if ((mc_dpl_offset & 0x3) != 0 || mc_dpl_offset > 0xffffffff) {
- printf("%s: Invalid MC DPL offset: %llu\n",
- __func__, mc_dpl_offset);
- error = -EINVAL;
+ error = load_mc_dpl(mc_ram_addr, mc_ram_size);
+ if (error != 0)
goto out;
- }
-#endif
-
- /*
- * Load the MC DPL blob at the far end of the MC private DRAM block:
- *
- * TODO: Should we place the DPL at a different location to match
- * assumptions of MC firmware about its memory layout?
- */
- mc_copy_image("MC DPL blob",
- (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
+ dump_mc_ccsr_regs(mc_ccsr_regs);
/*
- * Tell MC where the MC Firmware image was loaded in DDR:
+ * Tell MC what is the address range of the DRAM block assigned to it:
*/
- out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr);
- out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32));
+ reg_mcfbalr = (u32)mc_ram_aligned_base_addr |
+ (mc_ram_num_256mb_blocks - 1);
+ out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
+ out_le32(&mc_ccsr_regs->reg_mcfbahr,
+ (u32)(mc_ram_aligned_base_addr >> 32));
out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK);
/*
- * Tell MC where the DPL blob was loaded in DDR, by indicating
- * its offset relative to the beginning of the DDR block
- * allocated to the MC firmware. The MC firmware is responsible
- * for checking that there is no overlap between the DPL blob
- * and the runtime heap and stack of the MC firmware itself.
- *
- * NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of
- * the GSR MC CCSR register. So, this offset is assumed to be 4-byte
- * aligned.
- * Care must be taken not to write 1s into bits 31 and 30 of the GSR in
- * this case as the SoC COP or PIC will be signaled.
+ * Tell the MC that we want delayed DPL deployment.
*/
- out_le32(&mc_ccsr_regs->reg_gsr, (u32)(mc_dpl_offset >> 2));
+ out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
printf("\nfsl-mc: Booting Management Complex ...\n");
@@ -219,38 +478,9 @@ int mc_init(bd_t *bis)
* Deassert reset and release MC core 0 to run
*/
out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
- dmb();
- debug("Polling mc_ccsr_regs->reg_gsr ...\n");
-
- for (;;) {
- reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
- mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
- if (mc_fw_boot_status & 0x1)
- break;
-
- udelay(1000); /* throttle polling */
- if (timeout-- <= 0)
- break;
- }
-
- if (timeout <= 0) {
- printf("fsl-mc: timeout booting management complex firmware\n");
-
- /* TODO: Get an error status from an MC CCSR register */
- error = -ETIMEDOUT;
+ error = wait_for_mc(true, &reg_gsr);
+ if (error != 0)
goto out;
- }
-
- if (mc_fw_boot_status != 0x1) {
- /*
- * TODO: Identify critical errors from the GSR register's FS
- * field and for those errors, set error to -ENODEV or other
- * appropriate errno, so that the status property is set to
- * failure in the fsl,dprc device tree node.
- */
- printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n",
- reg_gsr);
- }
/*
* TODO: need to obtain the portal_id for the root container from the
@@ -259,13 +489,20 @@ int mc_init(bd_t *bis)
portal_id = 0;
/*
- * Check that the MC firmware is responding portal commands:
+ * Initialize the global default MC portal
+ * And check that the MC firmware is responding portal commands:
*/
- mc_io.mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
+ dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
+ if (!dflt_mc_io) {
+ printf(" No memory: malloc() failed\n");
+ return -ENOMEM;
+ }
+
+ dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
- portal_id, mc_io.mmio_regs);
+ portal_id, dflt_mc_io->mmio_regs);
- error = mc_get_version(&mc_io, &mc_ver_info);
+ error = mc_get_version(dflt_mc_io, &mc_ver_info);
if (error != 0) {
printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
error);
@@ -282,7 +519,16 @@ int mc_init(bd_t *bis)
printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
- mc_fw_boot_status);
+ reg_gsr & GSR_FS_MASK);
+
+ /*
+ * Tell the MC to deploy the DPL:
+ */
+ out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
+ printf("\nfsl-mc: Deploying data path layout ...\n");
+ error = wait_for_mc(false, &reg_gsr);
+ if (error != 0)
+ goto out;
out:
if (error != 0)
mc_boot_status = -error;
@@ -299,12 +545,242 @@ int get_mc_boot_status(void)
/**
* Return the actual size of the MC private DRAM block.
- *
- * NOTE: For now this function always returns the minimum required size,
- * However, in the future, the actual size may be obtained from an environment
- * variable.
*/
unsigned long mc_get_dram_block_size(void)
{
- return CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
+ unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
+
+ char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR);
+
+ if (dram_block_size_env_var) {
+ dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
+ 10);
+
+ if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
+ printf("fsl-mc: WARNING: Invalid value for \'"
+ MC_MEM_SIZE_ENV_VAR
+ "\' environment variable: %lu\n",
+ dram_block_size);
+
+ dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
+ }
+ }
+
+ return dram_block_size;
+}
+
+int dpio_init(struct dprc_obj_desc obj_desc)
+{
+ struct qbman_swp_desc p_des;
+ struct dpio_attr attr;
+ int err = 0;
+
+ dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
+ if (!dflt_dpio) {
+ printf(" No memory: malloc() failed\n");
+ return -ENOMEM;
+ }
+
+ dflt_dpio->dpio_id = obj_desc.id;
+
+ err = dpio_open(dflt_mc_io, obj_desc.id, &dflt_dpio_handle);
+ if (err) {
+ printf("dpio_open() failed\n");
+ goto err_open;
+ }
+
+ err = dpio_get_attributes(dflt_mc_io, dflt_dpio_handle, &attr);
+ if (err) {
+ printf("dpio_get_attributes() failed %d\n", err);
+ goto err_get_attr;
+ }
+
+ err = dpio_enable(dflt_mc_io, dflt_dpio_handle);
+ if (err) {
+ printf("dpio_enable() failed %d\n", err);
+ goto err_get_enable;
+ }
+ debug("ce_paddr=0x%llx, ci_paddr=0x%llx, portalid=%d, prios=%d\n",
+ attr.qbman_portal_ce_paddr,
+ attr.qbman_portal_ci_paddr,
+ attr.qbman_portal_id,
+ attr.num_priorities);
+
+ p_des.cena_bar = (void *)attr.qbman_portal_ce_paddr;
+ p_des.cinh_bar = (void *)attr.qbman_portal_ci_paddr;
+
+ dflt_dpio->sw_portal = qbman_swp_init(&p_des);
+ if (dflt_dpio->sw_portal == NULL) {
+ printf("qbman_swp_init() failed\n");
+ goto err_get_swp_init;
+ }
+ return 0;
+
+err_get_swp_init:
+err_get_enable:
+ dpio_disable(dflt_mc_io, dflt_dpio_handle);
+err_get_attr:
+ dpio_close(dflt_mc_io, dflt_dpio_handle);
+err_open:
+ free(dflt_dpio);
+ return err;
+}
+
+int dpbp_init(struct dprc_obj_desc obj_desc)
+{
+ dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
+ if (!dflt_dpbp) {
+ printf(" No memory: malloc() failed\n");
+ return -ENOMEM;
+ }
+ dflt_dpbp->dpbp_attr.id = obj_desc.id;
+
+ return 0;
+}
+
+int dprc_init_container_obj(struct dprc_obj_desc obj_desc, uint16_t dprc_handle)
+{
+ int error = 0, state = 0;
+ struct dprc_endpoint dpni_endpoint, dpmac_endpoint;
+ if (!strcmp(obj_desc.type, "dpbp")) {
+ if (!dflt_dpbp) {
+ error = dpbp_init(obj_desc);
+ if (error < 0)
+ printf("dpbp_init failed\n");
+ }
+ } else if (!strcmp(obj_desc.type, "dpio")) {
+ if (!dflt_dpio) {
+ error = dpio_init(obj_desc);
+ if (error < 0)
+ printf("dpio_init failed\n");
+ }
+ } else if (!strcmp(obj_desc.type, "dpni")) {
+ strcpy(dpni_endpoint.type, obj_desc.type);
+ dpni_endpoint.id = obj_desc.id;
+ error = dprc_get_connection(dflt_mc_io, dprc_handle,
+ &dpni_endpoint, &dpmac_endpoint, &state);
+ if (!strcmp(dpmac_endpoint.type, "dpmac"))
+ error = ldpaa_eth_init(obj_desc);
+ if (error < 0)
+ printf("ldpaa_eth_init failed\n");
+ }
+
+ return error;
+}
+
+int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i)
+{
+ int error = 0;
+ struct dprc_obj_desc obj_desc;
+
+ memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc));
+
+ error = dprc_get_obj(dflt_mc_io, dprc_handle,
+ i, &obj_desc);
+ if (error < 0) {
+ printf("dprc_get_obj(i=%d) failed: %d\n",
+ i, error);
+ return error;
+ }
+
+ if (!strcmp(obj_desc.type, obj_type)) {
+ debug("Discovered object: type %s, id %d, req %s\n",
+ obj_desc.type, obj_desc.id, obj_type);
+
+ error = dprc_init_container_obj(obj_desc, dprc_handle);
+ if (error < 0) {
+ printf("dprc_init_container_obj(i=%d) failed: %d\n",
+ i, error);
+ return error;
+ }
+ }
+
+ return error;
+}
+
+int fsl_mc_ldpaa_init(bd_t *bis)
+{
+ int i, error = 0;
+ int dprc_opened = 0, container_id;
+ int num_child_objects = 0;
+
+ error = mc_init();
+ if (error < 0)
+ goto error;
+
+ error = dprc_get_container_id(dflt_mc_io, &container_id);
+ if (error < 0) {
+ printf("dprc_get_container_id() failed: %d\n", error);
+ goto error;
+ }
+
+ debug("fsl-mc: Container id=0x%x\n", container_id);
+
+ error = dprc_open(dflt_mc_io, container_id, &dflt_dprc_handle);
+ if (error < 0) {
+ printf("dprc_open() failed: %d\n", error);
+ goto error;
+ }
+ dprc_opened = true;
+
+ error = dprc_get_obj_count(dflt_mc_io,
+ dflt_dprc_handle,
+ &num_child_objects);
+ if (error < 0) {
+ printf("dprc_get_obj_count() failed: %d\n", error);
+ goto error;
+ }
+ debug("Total child in container %d = %d\n", container_id,
+ num_child_objects);
+
+ if (num_child_objects != 0) {
+ /*
+ * Discover objects currently in the DPRC container in the MC:
+ */
+ for (i = 0; i < num_child_objects; i++)
+ error = dprc_scan_container_obj(dflt_dprc_handle,
+ "dpbp", i);
+
+ for (i = 0; i < num_child_objects; i++)
+ error = dprc_scan_container_obj(dflt_dprc_handle,
+ "dpio", i);
+
+ for (i = 0; i < num_child_objects; i++)
+ error = dprc_scan_container_obj(dflt_dprc_handle,
+ "dpni", i);
+ }
+error:
+ if (dprc_opened)
+ dprc_close(dflt_mc_io, dflt_dprc_handle);
+
+ return error;
+}
+
+void fsl_mc_ldpaa_exit(bd_t *bis)
+{
+ int err;
+
+ if (get_mc_boot_status() == 0) {
+ err = dpio_disable(dflt_mc_io, dflt_dpio_handle);
+ if (err < 0) {
+ printf("dpio_disable() failed: %d\n", err);
+ return;
+ }
+ err = dpio_reset(dflt_mc_io, dflt_dpio_handle);
+ if (err < 0) {
+ printf("dpio_reset() failed: %d\n", err);
+ return;
+ }
+ err = dpio_close(dflt_mc_io, dflt_dpio_handle);
+ if (err < 0) {
+ printf("dpio_close() failed: %d\n", err);
+ return;
+ }
+
+ free(dflt_dpio);
+ free(dflt_dpbp);
+ }
+
+ if (dflt_mc_io)
+ free(dflt_mc_io);
}
diff --git a/drivers/net/fsl-mc/mc_sys.c b/drivers/net/fsl-mc/mc_sys.c
index 7c8e003ad0..3fc1f98341 100644
--- a/drivers/net/fsl-mc/mc_sys.c
+++ b/drivers/net/fsl-mc/mc_sys.c
@@ -1,7 +1,7 @@
/*
* Freescale Layerscape MC I/O wrapper
*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
* Author: German Rivera <German.Rivera@freescale.com>
*
* SPDX-License-Identifier: GPL-2.0+
@@ -32,7 +32,7 @@ int mc_send_command(struct fsl_mc_io *mc_io,
struct mc_command *cmd)
{
enum mc_cmd_status status;
- int timeout = 2000;
+ int timeout = 6000;
mc_write_command(mc_io->mmio_regs, cmd);
@@ -52,7 +52,7 @@ int mc_send_command(struct fsl_mc_io *mc_io,
if (status != MC_CMD_STATUS_OK) {
printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n",
mc_io->mmio_regs,
- (unsigned int)MC_CMD_HDR_READ_AUTHID(cmd->header),
+ (unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header),
(unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header),
(unsigned int)status);
diff --git a/drivers/net/ldpaa_eth/Makefile b/drivers/net/ldpaa_eth/Makefile
new file mode 100644
index 0000000000..c37633f3ed
--- /dev/null
+++ b/drivers/net/ldpaa_eth/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2014 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += ldpaa_wriop.o
+obj-y += ldpaa_eth.o
+obj-$(CONFIG_LS2085A) += ls2085a.o
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c
new file mode 100644
index 0000000000..d4be1bada9
--- /dev/null
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/types.h>
+#include <malloc.h>
+#include <net.h>
+#include <hwconfig.h>
+#include <phy.h>
+#include <linux/compat.h>
+
+#include "ldpaa_eth.h"
+
+#undef CONFIG_PHYLIB
+static int init_phy(struct eth_device *dev)
+{
+ /*TODO for external PHY */
+
+ return 0;
+}
+
+static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
+ const struct dpaa_fd *fd)
+{
+ u64 fd_addr;
+ uint16_t fd_offset;
+ uint32_t fd_length;
+ struct ldpaa_fas *fas;
+ uint32_t status, err;
+ struct qbman_release_desc releasedesc;
+ struct qbman_swp *swp = dflt_dpio->sw_portal;
+
+ fd_addr = ldpaa_fd_get_addr(fd);
+ fd_offset = ldpaa_fd_get_offset(fd);
+ fd_length = ldpaa_fd_get_len(fd);
+
+ debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
+
+ if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
+ /* Read the frame annotation status word and check for errors */
+ fas = (struct ldpaa_fas *)
+ ((uint8_t *)(fd_addr) +
+ priv->buf_layout.private_data_size);
+ status = le32_to_cpu(fas->status);
+ if (status & LDPAA_ETH_RX_ERR_MASK) {
+ printf("Rx frame error(s): 0x%08x\n",
+ status & LDPAA_ETH_RX_ERR_MASK);
+ goto error;
+ } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
+ printf("Unsupported feature in bitmask: 0x%08x\n",
+ status & LDPAA_ETH_RX_UNSUPP_MASK);
+ goto error;
+ }
+ }
+
+ debug("Rx frame: To Upper layer\n");
+ net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
+ fd_length);
+
+error:
+ flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
+ qbman_release_desc_clear(&releasedesc);
+ qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
+ do {
+ /* Release buffer into the QBMAN */
+ err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
+ } while (err == -EBUSY);
+ return;
+}
+
+static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
+{
+ struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
+ const struct ldpaa_dq *dq;
+ const struct dpaa_fd *fd;
+ int i = 5, err = 0, status, loop = 20;
+ static struct qbman_pull_desc pulldesc;
+ struct qbman_swp *swp = dflt_dpio->sw_portal;
+
+ while (--i) {
+ qbman_pull_desc_clear(&pulldesc);
+ qbman_pull_desc_set_numframes(&pulldesc, 1);
+ qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
+
+ err = qbman_swp_pull(swp, &pulldesc);
+ if (err < 0) {
+ printf("Dequeue frames error:0x%08x\n", err);
+ continue;
+ }
+
+ do {
+ loop--;
+ dq = qbman_swp_dqrr_next(swp);
+
+ if (!loop)
+ break;
+ } while (!dq);
+
+ if (dq) {
+ /* Check for valid frame. If not sent a consume
+ * confirmation to QBMAN otherwise give it to NADK
+ * application and then send consume confirmation to
+ * QBMAN.
+ */
+ status = (uint8_t)ldpaa_dq_flags(dq);
+ if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
+ debug("Dequeue RX frames:");
+ debug("No frame delivered\n");
+
+ qbman_swp_dqrr_consume(swp, dq);
+ break;
+ }
+
+ fd = ldpaa_dq_fd(dq);
+
+ /* Obtain FD and process it */
+ ldpaa_eth_rx(priv, fd);
+ qbman_swp_dqrr_consume(swp, dq);
+ break;
+ }
+ }
+
+ return err;
+}
+
+static void ldpaa_eth_tx_conf(struct ldpaa_eth_priv *priv,
+ const struct dpaa_fd *fd)
+{
+ uint64_t fd_addr;
+ struct ldpaa_fas *fas;
+ uint32_t status, err;
+ struct qbman_release_desc releasedesc;
+ struct qbman_swp *swp = dflt_dpio->sw_portal;
+
+ fd_addr = ldpaa_fd_get_addr(fd);
+
+
+ debug("TX Conf frame:data addr=0x%p\n", (u64 *)fd_addr);
+
+ /* Check the status from the Frame Annotation */
+ if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
+ fas = (struct ldpaa_fas *)
+ ((uint8_t *)(fd_addr) +
+ priv->buf_layout.private_data_size);
+ status = le32_to_cpu(fas->status);
+ if (status & LDPAA_ETH_TXCONF_ERR_MASK) {
+ printf("TxConf frame error(s): 0x%08x\n",
+ status & LDPAA_ETH_TXCONF_ERR_MASK);
+ }
+ }
+
+ qbman_release_desc_clear(&releasedesc);
+ qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
+ do {
+ /* Release buffer into the QBMAN */
+ err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
+ } while (err == -EBUSY);
+}
+
+static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv)
+{
+ const struct ldpaa_dq *dq;
+ const struct dpaa_fd *fd;
+ int err = 0;
+ int i = 5, status, loop = 20;
+ static struct qbman_pull_desc pulldesc;
+ struct qbman_swp *swp = dflt_dpio->sw_portal;
+
+ while (--i) {
+ qbman_pull_desc_clear(&pulldesc);
+ qbman_pull_desc_set_numframes(&pulldesc, 1);
+ qbman_pull_desc_set_fq(&pulldesc, priv->tx_conf_fqid);
+
+ err = qbman_swp_pull(swp, &pulldesc);
+ if (err < 0) {
+ printf("Dequeue TX conf frames error:0x%08x\n", err);
+ continue;
+ }
+
+ do {
+ loop--;
+ dq = qbman_swp_dqrr_next(swp);
+
+ if (!loop)
+ break;
+ } while (!dq);
+
+ if (dq) {
+ /* Check for valid frame. If not sent a consume
+ * confirmation to QBMAN otherwise give it to NADK
+ * application and then send consume confirmation to
+ * QBMAN.
+ */
+ status = (uint8_t)ldpaa_dq_flags(dq);
+ if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
+ debug("Dequeue TX conf frames:");
+ debug("No frame is delivered\n");
+
+ qbman_swp_dqrr_consume(swp, dq);
+ break;
+ }
+ fd = ldpaa_dq_fd(dq);
+
+ ldpaa_eth_tx_conf(priv, fd);
+ qbman_swp_dqrr_consume(swp, dq);
+ break;
+ }
+ }
+
+ return err;
+}
+
+static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
+{
+ struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
+ struct dpaa_fd fd;
+ u64 buffer_start;
+ int data_offset, err;
+ struct qbman_swp *swp = dflt_dpio->sw_portal;
+ struct qbman_eq_desc ed;
+
+ /* Setup the FD fields */
+ memset(&fd, 0, sizeof(fd));
+
+ data_offset = priv->tx_data_offset;
+
+ do {
+ err = qbman_swp_acquire(dflt_dpio->sw_portal,
+ dflt_dpbp->dpbp_attr.bpid,
+ &buffer_start, 1);
+ } while (err == -EBUSY);
+
+ if (err < 0) {
+ printf("qbman_swp_acquire() failed\n");
+ return -ENOMEM;
+ }
+
+ debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
+
+ memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
+
+ flush_dcache_range(buffer_start, buffer_start +
+ LDPAA_ETH_RX_BUFFER_SIZE);
+
+ ldpaa_fd_set_addr(&fd, (u64)buffer_start);
+ ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
+ ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
+ ldpaa_fd_set_len(&fd, len);
+
+ fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
+ LDPAA_FD_CTRL_PTV1;
+
+ qbman_eq_desc_clear(&ed);
+ qbman_eq_desc_set_no_orp(&ed, 0);
+ qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
+ err = qbman_swp_enqueue(swp, &ed, (const struct qbman_fd *)(&fd));
+ if (err < 0)
+ printf("error enqueueing Tx frame\n");
+
+ mdelay(1);
+
+ err = ldpaa_eth_pull_dequeue_tx_conf(priv);
+ if (err < 0)
+ printf("error Tx Conf frame\n");
+
+ return err;
+}
+
+static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
+{
+ struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
+ struct dpni_queue_attr rx_queue_attr;
+ struct dpni_tx_flow_attr tx_flow_attr;
+ uint8_t mac_addr[6];
+ int err;
+
+ if (net_dev->state == ETH_STATE_ACTIVE)
+ return 0;
+
+ /* DPNI initialization */
+ err = ldpaa_dpni_setup(priv);
+ if (err < 0)
+ goto err_dpni_setup;
+
+ err = ldpaa_dpbp_setup();
+ if (err < 0)
+ goto err_dpbp_setup;
+
+ /* DPNI binding DPBP */
+ err = ldpaa_dpni_bind(priv);
+ if (err)
+ goto err_bind;
+
+ err = dpni_get_primary_mac_addr(dflt_mc_io, priv->dpni_handle,
+ mac_addr);
+ if (err) {
+ printf("dpni_get_primary_mac_addr() failed\n");
+ return err;
+ }
+
+ memcpy(net_dev->enetaddr, mac_addr, 0x6);
+
+ /* setup the MAC address */
+ if (net_dev->enetaddr[0] & 0x01) {
+ printf("%s: MacAddress is multcast address\n", __func__);
+ return 1;
+ }
+
+#ifdef CONFIG_PHYLIB
+ /* TODO Check this path */
+ err = phy_startup(priv->phydev);
+ if (err) {
+ printf("%s: Could not initialize\n", priv->phydev->dev->name);
+ return err;
+ }
+#else
+ priv->phydev->speed = SPEED_1000;
+ priv->phydev->link = 1;
+ priv->phydev->duplex = DUPLEX_FULL;
+#endif
+
+ err = dpni_enable(dflt_mc_io, priv->dpni_handle);
+ if (err < 0) {
+ printf("dpni_enable() failed\n");
+ return err;
+ }
+
+ /* TODO: support multiple Rx flows */
+ err = dpni_get_rx_flow(dflt_mc_io, priv->dpni_handle, 0, 0,
+ &rx_queue_attr);
+ if (err) {
+ printf("dpni_get_rx_flow() failed\n");
+ goto err_rx_flow;
+ }
+
+ priv->rx_dflt_fqid = rx_queue_attr.fqid;
+
+ err = dpni_get_qdid(dflt_mc_io, priv->dpni_handle, &priv->tx_qdid);
+ if (err) {
+ printf("dpni_get_qdid() failed\n");
+ goto err_qdid;
+ }
+
+ err = dpni_get_tx_flow(dflt_mc_io, priv->dpni_handle, priv->tx_flow_id,
+ &tx_flow_attr);
+ if (err) {
+ printf("dpni_get_tx_flow() failed\n");
+ goto err_tx_flow;
+ }
+
+ priv->tx_conf_fqid = tx_flow_attr.conf_err_attr.queue_attr.fqid;
+
+ if (!priv->phydev->link)
+ printf("%s: No link.\n", priv->phydev->dev->name);
+
+ return priv->phydev->link ? 0 : -1;
+
+err_tx_flow:
+err_qdid:
+err_rx_flow:
+ dpni_disable(dflt_mc_io, priv->dpni_handle);
+err_bind:
+ ldpaa_dpbp_free();
+err_dpbp_setup:
+ dpni_close(dflt_mc_io, priv->dpni_handle);
+err_dpni_setup:
+ return err;
+}
+
+static void ldpaa_eth_stop(struct eth_device *net_dev)
+{
+ struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
+ int err = 0;
+
+ if ((net_dev->state == ETH_STATE_PASSIVE) ||
+ (net_dev->state == ETH_STATE_INIT))
+ return;
+ /* Stop Tx and Rx traffic */
+ err = dpni_disable(dflt_mc_io, priv->dpni_handle);
+ if (err < 0)
+ printf("dpni_disable() failed\n");
+
+#ifdef CONFIG_PHYLIB
+ phy_shutdown(priv->phydev);
+#endif
+
+ ldpaa_dpbp_free();
+ dpni_reset(dflt_mc_io, priv->dpni_handle);
+ dpni_close(dflt_mc_io, priv->dpni_handle);
+}
+
+static void ldpaa_dpbp_drain_cnt(int count)
+{
+ uint64_t buf_array[7];
+ void *addr;
+ int ret, i;
+
+ BUG_ON(count > 7);
+
+ do {
+ ret = qbman_swp_acquire(dflt_dpio->sw_portal,
+ dflt_dpbp->dpbp_attr.bpid,
+ buf_array, count);
+ if (ret < 0) {
+ printf("qbman_swp_acquire() failed\n");
+ return;
+ }
+ for (i = 0; i < ret; i++) {
+ addr = (void *)buf_array[i];
+ debug("Free: buffer addr =0x%p\n", addr);
+ free(addr);
+ }
+ } while (ret);
+}
+
+static void ldpaa_dpbp_drain(void)
+{
+ int i;
+ for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
+ ldpaa_dpbp_drain_cnt(7);
+}
+
+static int ldpaa_bp_add_7(uint16_t bpid)
+{
+ uint64_t buf_array[7];
+ u8 *addr;
+ int i;
+ struct qbman_release_desc rd;
+
+ for (i = 0; i < 7; i++) {
+ addr = memalign(L1_CACHE_BYTES, LDPAA_ETH_RX_BUFFER_SIZE);
+ if (!addr) {
+ printf("addr allocation failed\n");
+ goto err_alloc;
+ }
+ memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
+ flush_dcache_range((u64)addr,
+ (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
+
+ buf_array[i] = (uint64_t)addr;
+ debug("Release: buffer addr =0x%p\n", addr);
+ }
+
+release_bufs:
+ /* In case the portal is busy, retry until successful.
+ * This function is guaranteed to succeed in a reasonable amount
+ * of time.
+ */
+
+ do {
+ mdelay(1);
+ qbman_release_desc_clear(&rd);
+ qbman_release_desc_set_bpid(&rd, bpid);
+ } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
+
+ return i;
+
+err_alloc:
+ if (i)
+ goto release_bufs;
+
+ return 0;
+}
+
+static int ldpaa_dpbp_seed(uint16_t bpid)
+{
+ int i;
+ int count;
+
+ for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
+ count = ldpaa_bp_add_7(bpid);
+ if (count < 7)
+ printf("Buffer Seed= %d\n", count);
+ }
+
+ return 0;
+}
+
+static int ldpaa_dpbp_setup(void)
+{
+ int err;
+
+ err = dpbp_open(dflt_mc_io, dflt_dpbp->dpbp_attr.id,
+ &dflt_dpbp->dpbp_handle);
+ if (err) {
+ printf("dpbp_open() failed\n");
+ goto err_open;
+ }
+
+ err = dpbp_enable(dflt_mc_io, dflt_dpbp->dpbp_handle);
+ if (err) {
+ printf("dpbp_enable() failed\n");
+ goto err_enable;
+ }
+
+ err = dpbp_get_attributes(dflt_mc_io, dflt_dpbp->dpbp_handle,
+ &dflt_dpbp->dpbp_attr);
+ if (err) {
+ printf("dpbp_get_attributes() failed\n");
+ goto err_get_attr;
+ }
+
+ err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
+ if (err) {
+ printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
+ dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
+ goto err_seed;
+ }
+
+ return 0;
+
+err_seed:
+err_get_attr:
+ dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle);
+err_enable:
+ dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle);
+err_open:
+ return err;
+}
+
+static void ldpaa_dpbp_free(void)
+{
+ ldpaa_dpbp_drain();
+ dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle);
+ dpbp_reset(dflt_mc_io, dflt_dpbp->dpbp_handle);
+ dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle);
+}
+
+static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
+{
+ int err;
+
+ /* and get a handle for the DPNI this interface is associate with */
+ err = dpni_open(dflt_mc_io, priv->dpni_id, &priv->dpni_handle);
+ if (err) {
+ printf("dpni_open() failed\n");
+ goto err_open;
+ }
+
+ err = dpni_get_attributes(dflt_mc_io, priv->dpni_handle,
+ &priv->dpni_attrs);
+ if (err) {
+ printf("dpni_get_attributes() failed (err=%d)\n", err);
+ goto err_get_attr;
+ }
+
+ /* Configure our buffers' layout */
+ priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
+ DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
+ DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
+ priv->buf_layout.pass_parser_result = true;
+ priv->buf_layout.pass_frame_status = true;
+ priv->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
+ /* ...rx, ... */
+ err = dpni_set_rx_buffer_layout(dflt_mc_io, priv->dpni_handle,
+ &priv->buf_layout);
+ if (err) {
+ printf("dpni_set_rx_buffer_layout() failed");
+ goto err_buf_layout;
+ }
+
+ /* ... tx, ... */
+ priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PARSER_RESULT;
+ err = dpni_set_tx_buffer_layout(dflt_mc_io, priv->dpni_handle,
+ &priv->buf_layout);
+ if (err) {
+ printf("dpni_set_tx_buffer_layout() failed");
+ goto err_buf_layout;
+ }
+
+ /* ... tx-confirm. */
+ priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
+ err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, priv->dpni_handle,
+ &priv->buf_layout);
+ if (err) {
+ printf("dpni_set_tx_conf_buffer_layout() failed");
+ goto err_buf_layout;
+ }
+
+ /* Now that we've set our tx buffer layout, retrieve the minimum
+ * required tx data offset.
+ */
+ err = dpni_get_tx_data_offset(dflt_mc_io, priv->dpni_handle,
+ &priv->tx_data_offset);
+ if (err) {
+ printf("dpni_get_tx_data_offset() failed\n");
+ goto err_data_offset;
+ }
+
+ /* Warn in case TX data offset is not multiple of 64 bytes. */
+ WARN_ON(priv->tx_data_offset % 64);
+
+ /* Accomodate SWA space. */
+ priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
+ debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
+
+ return 0;
+
+err_data_offset:
+err_buf_layout:
+err_get_attr:
+ dpni_close(dflt_mc_io, priv->dpni_handle);
+err_open:
+ return err;
+}
+
+static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
+{
+ struct dpni_pools_cfg pools_params;
+ struct dpni_tx_flow_cfg dflt_tx_flow;
+ int err = 0;
+
+ pools_params.num_dpbp = 1;
+ pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
+ pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
+ err = dpni_set_pools(dflt_mc_io, priv->dpni_handle, &pools_params);
+ if (err) {
+ printf("dpni_set_pools() failed\n");
+ return err;
+ }
+
+ priv->tx_flow_id = DPNI_NEW_FLOW_ID;
+ memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
+
+ err = dpni_set_tx_flow(dflt_mc_io, priv->dpni_handle,
+ &priv->tx_flow_id, &dflt_tx_flow);
+ if (err) {
+ printf("dpni_set_tx_flow() failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int ldpaa_eth_netdev_init(struct eth_device *net_dev)
+{
+ int err;
+ struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
+
+ sprintf(net_dev->name, "DPNI%d", priv->dpni_id);
+
+ net_dev->iobase = 0;
+ net_dev->init = ldpaa_eth_open;
+ net_dev->halt = ldpaa_eth_stop;
+ net_dev->send = ldpaa_eth_tx;
+ net_dev->recv = ldpaa_eth_pull_dequeue_rx;
+/*
+ TODO: PHY MDIO information
+ priv->bus = info->bus;
+ priv->phyaddr = info->phy_addr;
+ priv->enet_if = info->enet_if;
+*/
+
+ if (init_phy(net_dev))
+ return 0;
+
+ err = eth_register(net_dev);
+ if (err < 0) {
+ printf("eth_register() = %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+int ldpaa_eth_init(struct dprc_obj_desc obj_desc)
+{
+ struct eth_device *net_dev = NULL;
+ struct ldpaa_eth_priv *priv = NULL;
+ int err = 0;
+
+
+ /* Net device */
+ net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
+ if (!net_dev) {
+ printf("eth_device malloc() failed\n");
+ return -ENOMEM;
+ }
+ memset(net_dev, 0, sizeof(struct eth_device));
+
+ /* alloc the ldpaa ethernet private struct */
+ priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
+ if (!priv) {
+ printf("ldpaa_eth_priv malloc() failed\n");
+ return -ENOMEM;
+ }
+ memset(priv, 0, sizeof(struct ldpaa_eth_priv));
+
+ net_dev->priv = (void *)priv;
+ priv->net_dev = (struct eth_device *)net_dev;
+ priv->dpni_id = obj_desc.id;
+
+ err = ldpaa_eth_netdev_init(net_dev);
+ if (err)
+ goto err_netdev_init;
+
+ debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
+ return 0;
+
+err_netdev_init:
+ free(priv);
+ net_dev->priv = NULL;
+ free(net_dev);
+
+ return err;
+}
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h
new file mode 100644
index 0000000000..3107ab6cff
--- /dev/null
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __LDPAA_ETH_H
+#define __LDPAA_ETH_H
+
+#include <linux/netdevice.h>
+#include <fsl-mc/fsl_mc.h>
+#include <fsl-mc/fsl_dpaa_fd.h>
+#include <fsl-mc/fsl_dprc.h>
+#include <fsl-mc/fsl_dpni.h>
+#include <fsl-mc/fsl_dpbp.h>
+#include <fsl-mc/fsl_dpio.h>
+#include <fsl-mc/fsl_qbman_portal.h>
+#include <fsl-mc/fsl_mc_private.h>
+
+
+enum ldpaa_eth_type {
+ LDPAA_ETH_1G_E,
+ LDPAA_ETH_10G_E,
+};
+
+/* Arbitrary values for now, but we'll need to tune */
+#define LDPAA_ETH_NUM_BUFS (2 * 7)
+#define LDPAA_ETH_REFILL_THRESH (LDPAA_ETH_NUM_BUFS/2)
+#define LDPAA_ETH_RX_BUFFER_SIZE 2048
+
+/* Hardware requires alignment for ingress/egress buffer addresses
+ * and ingress buffer lengths.
+ */
+#define LDPAA_ETH_BUF_ALIGN 64
+
+/* So far we're only accomodating a skb backpointer in the frame's
+ * software annotation, but the hardware options are either 0 or 64.
+ */
+#define LDPAA_ETH_SWA_SIZE 64
+
+/* Annotation valid bits in FD FRC */
+#define LDPAA_FD_FRC_FASV 0x8000
+#define LDPAA_FD_FRC_FAEADV 0x4000
+#define LDPAA_FD_FRC_FAPRV 0x2000
+#define LDPAA_FD_FRC_FAIADV 0x1000
+#define LDPAA_FD_FRC_FASWOV 0x0800
+#define LDPAA_FD_FRC_FAICFDV 0x0400
+
+/* Annotation bits in FD CTRL */
+#define LDPAA_FD_CTRL_ASAL 0x00020000 /* ASAL = 128 */
+#define LDPAA_FD_CTRL_PTA 0x00800000
+#define LDPAA_FD_CTRL_PTV1 0x00400000
+
+/* TODO: we may want to move this and other WRIOP related defines
+ * to a separate header
+ */
+/* Frame annotation status */
+struct ldpaa_fas {
+ u8 reserved;
+ u8 ppid;
+ __le16 ifpid;
+ __le32 status;
+} __packed;
+
+/* Debug frame, otherwise supposed to be discarded */
+#define LDPAA_ETH_FAS_DISC 0x80000000
+/* MACSEC frame */
+#define LDPAA_ETH_FAS_MS 0x40000000
+#define LDPAA_ETH_FAS_PTP 0x08000000
+/* Ethernet multicast frame */
+#define LDPAA_ETH_FAS_MC 0x04000000
+/* Ethernet broadcast frame */
+#define LDPAA_ETH_FAS_BC 0x02000000
+#define LDPAA_ETH_FAS_KSE 0x00040000
+#define LDPAA_ETH_FAS_EOFHE 0x00020000
+#define LDPAA_ETH_FAS_MNLE 0x00010000
+#define LDPAA_ETH_FAS_TIDE 0x00008000
+#define LDPAA_ETH_FAS_PIEE 0x00004000
+/* Frame length error */
+#define LDPAA_ETH_FAS_FLE 0x00002000
+/* Frame physical error; our favourite pastime */
+#define LDPAA_ETH_FAS_FPE 0x00001000
+#define LDPAA_ETH_FAS_PTE 0x00000080
+#define LDPAA_ETH_FAS_ISP 0x00000040
+#define LDPAA_ETH_FAS_PHE 0x00000020
+#define LDPAA_ETH_FAS_BLE 0x00000010
+/* L3 csum validation performed */
+#define LDPAA_ETH_FAS_L3CV 0x00000008
+/* L3 csum error */
+#define LDPAA_ETH_FAS_L3CE 0x00000004
+/* L4 csum validation performed */
+#define LDPAA_ETH_FAS_L4CV 0x00000002
+/* L4 csum error */
+#define LDPAA_ETH_FAS_L4CE 0x00000001
+/* These bits always signal errors */
+#define LDPAA_ETH_RX_ERR_MASK (LDPAA_ETH_FAS_DISC | \
+ LDPAA_ETH_FAS_KSE | \
+ LDPAA_ETH_FAS_EOFHE | \
+ LDPAA_ETH_FAS_MNLE | \
+ LDPAA_ETH_FAS_TIDE | \
+ LDPAA_ETH_FAS_PIEE | \
+ LDPAA_ETH_FAS_FLE | \
+ LDPAA_ETH_FAS_FPE | \
+ LDPAA_ETH_FAS_PTE | \
+ LDPAA_ETH_FAS_ISP | \
+ LDPAA_ETH_FAS_PHE | \
+ LDPAA_ETH_FAS_BLE | \
+ LDPAA_ETH_FAS_L3CE | \
+ LDPAA_ETH_FAS_L4CE)
+/* Unsupported features in the ingress */
+#define LDPAA_ETH_RX_UNSUPP_MASK LDPAA_ETH_FAS_MS
+/* TODO trim down the bitmask; not all of them apply to Tx-confirm */
+#define LDPAA_ETH_TXCONF_ERR_MASK (LDPAA_ETH_FAS_KSE | \
+ LDPAA_ETH_FAS_EOFHE | \
+ LDPAA_ETH_FAS_MNLE | \
+ LDPAA_ETH_FAS_TIDE)
+
+struct ldpaa_eth_priv {
+ struct eth_device *net_dev;
+ int dpni_id;
+ uint16_t dpni_handle;
+ struct dpni_attr dpni_attrs;
+ /* Insofar as the MC is concerned, we're using one layout on all 3 types
+ * of buffers (Rx, Tx, Tx-Conf).
+ */
+ struct dpni_buffer_layout buf_layout;
+ uint16_t tx_data_offset;
+
+ uint32_t rx_dflt_fqid;
+ uint16_t tx_qdid;
+ uint32_t tx_conf_fqid;
+ uint16_t tx_flow_id;
+
+ enum ldpaa_eth_type type; /* 1G or 10G ethernet */
+ struct phy_device *phydev;
+};
+
+extern struct fsl_mc_io *dflt_mc_io;
+extern struct fsl_dpbp_obj *dflt_dpbp;
+extern struct fsl_dpio_obj *dflt_dpio;
+
+static void ldpaa_dpbp_drain_cnt(int count);
+static void ldpaa_dpbp_drain(void);
+static int ldpaa_dpbp_seed(uint16_t bpid);
+static void ldpaa_dpbp_free(void);
+static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv);
+static int ldpaa_dpbp_setup(void);
+static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv);
+#endif /* __LDPAA_H */
diff --git a/drivers/net/ldpaa_eth/ldpaa_wriop.c b/drivers/net/ldpaa_eth/ldpaa_wriop.c
new file mode 100644
index 0000000000..926057a8ad
--- /dev/null
+++ b/drivers/net/ldpaa_eth/ldpaa_wriop.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/types.h>
+#include <malloc.h>
+#include <net.h>
+#include <linux/compat.h>
+#include <asm/arch/fsl_serdes.h>
+#include <fsl-mc/ldpaa_wriop.h>
+
+struct wriop_dpmac_info dpmac_info[NUM_WRIOP_PORTS];
+
+__weak phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtc)
+{
+ return PHY_INTERFACE_MODE_NONE;
+}
+
+void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl)
+{
+ phy_interface_t enet_if;
+ int index = dpmac_id + sd * 8;
+
+ dpmac_info[index].enabled = 0;
+ dpmac_info[index].id = 0;
+ dpmac_info[index].enet_if = PHY_INTERFACE_MODE_NONE;
+
+ enet_if = wriop_dpmac_enet_if(index, lane_prtcl);
+ if (enet_if != PHY_INTERFACE_MODE_NONE) {
+ dpmac_info[index].enabled = 1;
+ dpmac_info[index].id = index;
+ dpmac_info[index].enet_if = enet_if;
+ }
+}
+
+/*TODO what it do */
+static int wriop_dpmac_to_index(int dpmac_id)
+{
+ int i;
+
+ for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
+ if (dpmac_info[i].id == dpmac_id)
+ return i;
+ }
+
+ return -1;
+}
+
+void wriop_disable_dpmac(int dpmac_id)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return;
+
+ dpmac_info[i].enabled = 0;
+ wriop_dpmac_disable(dpmac_id);
+}
+
+void wriop_enable_dpmac(int dpmac_id)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return;
+
+ dpmac_info[i].enabled = 1;
+ wriop_dpmac_enable(dpmac_id);
+}
+
+void wriop_set_mdio(int dpmac_id, struct mii_dev *bus)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return;
+
+ dpmac_info[i].bus = bus;
+}
+
+struct mii_dev *wriop_get_mdio(int dpmac_id)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return NULL;
+
+ return dpmac_info[i].bus;
+}
+
+void wriop_set_phy_address(int dpmac_id, int address)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return;
+
+ dpmac_info[i].phy_addr = address;
+}
+
+int wriop_get_phy_address(int dpmac_id)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return -1;
+
+ return dpmac_info[i].phy_addr;
+}
+
+void wriop_set_phy_dev(int dpmac_id, struct phy_device *phydev)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return;
+
+ dpmac_info[i].phydev = phydev;
+}
+
+struct phy_device *wriop_get_phy_dev(int dpmac_id)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return NULL;
+
+ return dpmac_info[i].phydev;
+}
+
+phy_interface_t wriop_get_enet_if(int dpmac_id)
+{
+ int i = wriop_dpmac_to_index(dpmac_id);
+
+ if (i == -1)
+ return PHY_INTERFACE_MODE_NONE;
+
+ if (dpmac_info[i].enabled)
+ return dpmac_info[i].enet_if;
+
+ return PHY_INTERFACE_MODE_NONE;
+}
diff --git a/drivers/net/ldpaa_eth/ls2085a.c b/drivers/net/ldpaa_eth/ls2085a.c
new file mode 100644
index 0000000000..6b7960a000
--- /dev/null
+++ b/drivers/net/ldpaa_eth/ls2085a.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <phy.h>
+#include <fsl-mc/ldpaa_wriop.h>
+#include <asm/io.h>
+#include <asm/arch-fsl-lsch3/immap_lsch3.h>
+#include <asm/arch/fsl_serdes.h>
+#include <fsl-mc/ldpaa_wriop.h>
+
+u32 dpmac_to_devdisr[] = {
+ [WRIOP1_DPMAC1] = FSL_CHASSIS3_DEVDISR2_DPMAC1,
+ [WRIOP1_DPMAC2] = FSL_CHASSIS3_DEVDISR2_DPMAC2,
+ [WRIOP1_DPMAC3] = FSL_CHASSIS3_DEVDISR2_DPMAC3,
+ [WRIOP1_DPMAC4] = FSL_CHASSIS3_DEVDISR2_DPMAC4,
+ [WRIOP1_DPMAC5] = FSL_CHASSIS3_DEVDISR2_DPMAC5,
+ [WRIOP1_DPMAC6] = FSL_CHASSIS3_DEVDISR2_DPMAC6,
+ [WRIOP1_DPMAC7] = FSL_CHASSIS3_DEVDISR2_DPMAC7,
+ [WRIOP1_DPMAC8] = FSL_CHASSIS3_DEVDISR2_DPMAC8,
+ [WRIOP1_DPMAC9] = FSL_CHASSIS3_DEVDISR2_DPMAC9,
+ [WRIOP1_DPMAC10] = FSL_CHASSIS3_DEVDISR2_DPMAC10,
+ [WRIOP1_DPMAC11] = FSL_CHASSIS3_DEVDISR2_DPMAC11,
+ [WRIOP1_DPMAC12] = FSL_CHASSIS3_DEVDISR2_DPMAC12,
+ [WRIOP1_DPMAC13] = FSL_CHASSIS3_DEVDISR2_DPMAC13,
+ [WRIOP1_DPMAC14] = FSL_CHASSIS3_DEVDISR2_DPMAC14,
+ [WRIOP1_DPMAC15] = FSL_CHASSIS3_DEVDISR2_DPMAC15,
+ [WRIOP1_DPMAC16] = FSL_CHASSIS3_DEVDISR2_DPMAC16,
+ [WRIOP1_DPMAC17] = FSL_CHASSIS3_DEVDISR2_DPMAC17,
+ [WRIOP1_DPMAC18] = FSL_CHASSIS3_DEVDISR2_DPMAC18,
+ [WRIOP1_DPMAC19] = FSL_CHASSIS3_DEVDISR2_DPMAC19,
+ [WRIOP1_DPMAC20] = FSL_CHASSIS3_DEVDISR2_DPMAC20,
+ [WRIOP1_DPMAC21] = FSL_CHASSIS3_DEVDISR2_DPMAC21,
+ [WRIOP1_DPMAC22] = FSL_CHASSIS3_DEVDISR2_DPMAC22,
+ [WRIOP1_DPMAC23] = FSL_CHASSIS3_DEVDISR2_DPMAC23,
+ [WRIOP1_DPMAC24] = FSL_CHASSIS3_DEVDISR2_DPMAC24,
+};
+
+static int is_device_disabled(int dpmac_id)
+{
+ struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+ u32 devdisr2 = in_le32(&gur->devdisr2);
+
+ return dpmac_to_devdisr[dpmac_id] & devdisr2;
+}
+
+void wriop_dpmac_disable(int dpmac_id)
+{
+ struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+
+ setbits_le32(&gur->devdisr2, dpmac_to_devdisr[dpmac_id]);
+}
+
+void wriop_dpmac_enable(int dpmac_id)
+{
+ struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+
+ clrbits_le32(&gur->devdisr2, dpmac_to_devdisr[dpmac_id]);
+}
+
+phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtcl)
+{
+ enum srds_prtcl;
+
+ if (is_device_disabled(dpmac_id + 1))
+ return PHY_INTERFACE_MODE_NONE;
+
+ if (lane_prtcl >= SGMII1 && lane_prtcl <= SGMII16)
+ return PHY_INTERFACE_MODE_SGMII;
+
+ if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8)
+ return PHY_INTERFACE_MODE_XGMII;
+
+ if (lane_prtcl >= XAUI1 && lane_prtcl <= XAUI2)
+ return PHY_INTERFACE_MODE_XGMII;
+
+ if (lane_prtcl >= QSGMII_A && lane_prtcl <= QSGMII_D)
+ return PHY_INTERFACE_MODE_QSGMII;
+
+ return PHY_INTERFACE_MODE_NONE;
+}
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index 254f056df4..3a2b3bba99 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -186,8 +186,8 @@ void cs4340_upload_firmware(struct phy_device *phydev)
while (*addr != 0x0a) {
line_temp[i++] = *addr++;
if (0x50 < i) {
- printf("Not found Cortina PHY ucode at 0x%x\n",
- CONFIG_CORTINA_FW_ADDR);
+ printf("Not found Cortina PHY ucode at 0x%p\n",
+ (char *)CONFIG_CORTINA_FW_ADDR);
return;
}
}
diff --git a/drivers/net/vsc9953.c b/drivers/net/vsc9953.c
index 9fc3c18ba2..fed7358448 100644
--- a/drivers/net/vsc9953.c
+++ b/drivers/net/vsc9953.c
@@ -9,7 +9,7 @@
#include <asm/io.h>
#include <asm/fsl_serdes.h>
#include <fm_eth.h>
-#include <asm/fsl_memac.h>
+#include <fsl_memac.h>
#include <vsc9953.h>
static struct vsc9953_info vsc9953_l2sw = {
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c
index bcad8f2aec..402c5193e0 100644
--- a/drivers/pci/pcie_layerscape.c
+++ b/drivers/pci/pcie_layerscape.c
@@ -11,7 +11,6 @@
#include <asm/io.h>
#include <errno.h>
#include <malloc.h>
-#include <asm/pcie_layerscape.h>
#ifndef CONFIG_SYS_PCI_MEMORY_BUS
#define CONFIG_SYS_PCI_MEMORY_BUS CONFIG_SYS_SDRAM_BASE
@@ -50,11 +49,20 @@
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
+/* LUT registers */
+#define PCIE_LUT_BASE 0x80000
+#define PCIE_LUT_DBG 0x7FC
+
+#define PCIE_DBI_RO_WR_EN 0x8bc
+
#define PCIE_LINK_CAP 0x7c
#define PCIE_LINK_SPEED_MASK 0xf
#define PCIE_LINK_STA 0x82
-#define PCIE_DBI_SIZE (4 * 1024) /* 4K */
+#define LTSSM_STATE_MASK 0x3f
+#define LTSSM_PCIE_L0 0x11 /* L0 state */
+
+#define PCIE_DBI_SIZE 0x100000 /* 1M */
struct ls_pcie {
int idx;
@@ -104,8 +112,6 @@ struct ls_pcie_info {
/* PEX1/2 Misc Ports Status Register */
#define LTSSM_STATE_SHIFT 20
-#define LTSSM_STATE_MASK 0x3f
-#define LTSSM_PCIE_L0 0x11 /* L0 state */
static int ls_pcie_link_state(struct ls_pcie *pcie)
{
@@ -122,18 +128,18 @@ static int ls_pcie_link_state(struct ls_pcie *pcie)
return 1;
}
#else
-#define PCIE_LDBG 0x7FC
-
static int ls_pcie_link_state(struct ls_pcie *pcie)
{
u32 state;
- state = readl(pcie->dbi + PCIE_LDBG);
- if (state)
- return 1;
+ state = readl(pcie->dbi + PCIE_LUT_BASE + PCIE_LUT_DBG) &
+ LTSSM_STATE_MASK;
+ if (state < LTSSM_PCIE_L0) {
+ debug("....PCIe link error. LTSSM=0x%02x.\n", state);
+ return 0;
+ }
- debug("....PCIe link error.\n");
- return 0;
+ return 1;
}
#endif
@@ -149,7 +155,11 @@ static int ls_pcie_link_up(struct ls_pcie *pcie)
/* Try to download speed to gen1 */
cap = readl(pcie->dbi + PCIE_LINK_CAP);
writel((cap & (~PCIE_LINK_SPEED_MASK)) | 1, pcie->dbi + PCIE_LINK_CAP);
- udelay(2000);
+ /*
+ * Notice: the following delay has critical impact on link training
+ * if too short (<30ms) the link doesn't get up.
+ */
+ mdelay(100);
state = ls_pcie_link_state(pcie);
if (state)
return state;
@@ -251,6 +261,10 @@ static int ls_pcie_addr_valid(struct pci_controller *hose, pci_dev_t d)
if (PCI_DEV(d) > 0)
return -EINVAL;
+ /* Controller does not support multi-function in RC mode */
+ if ((PCI_BUS(d) == hose->first_busno) && (PCI_FUNC(d) > 0))
+ return -EINVAL;
+
return 0;
}
@@ -327,8 +341,12 @@ static void ls_pcie_setup_ctrl(struct ls_pcie *pcie,
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0);
/* program correct class for RC */
+ writel(1, pcie->dbi + PCIE_DBI_RO_WR_EN);
pci_hose_write_config_word(hose, dev, PCI_CLASS_DEVICE,
PCI_CLASS_BRIDGE_PCI);
+#ifndef CONFIG_LS102XA
+ writel(0, pcie->dbi + PCIE_DBI_RO_WR_EN);
+#endif
}
int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
@@ -417,9 +435,9 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
}
/* Print the negotiated PCIe link width */
- pci_hose_read_config_word(hose, dev, PCIE_LINK_STA, &temp16);
- printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4,
- (temp16 & 0xf), info->regs);
+ pci_hose_read_config_word(hose, pdev, PCIE_LINK_STA, &temp16);
+ printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4,
+ (temp16 & 0xf), info->regs);
if (ep_mode)
return busno;
@@ -486,7 +504,7 @@ static void ft_pcie_ls_setup(void *blob, const char *pci_compat,
fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
}
-void ft_pcie_setup(void *blob, bd_t *bd)
+void ft_pci_setup(void *blob, bd_t *bd)
{
#ifdef CONFIG_PCIE1
ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE1_ADDR, PCIE1);
@@ -506,7 +524,7 @@ void ft_pcie_setup(void *blob, bd_t *bd)
}
#else
-void ft_pcie_setup(void *blob, bd_t *bd)
+void ft_pci_setup(void *blob, bd_t *bd)
{
}
#endif
diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c
index d24651b5ba..84e1433d9e 100644
--- a/drivers/qe/qe.c
+++ b/drivers/qe/qe.c
@@ -196,6 +196,18 @@ void u_qe_init(void)
}
#endif
+#ifdef CONFIG_U_QE
+void u_qe_resume(void)
+{
+ qe_map_t *qe_immrr;
+ uint qe_base = CONFIG_SYS_IMMR + QE_IMMR_OFFSET; /* QE immr base */
+ qe_immrr = (qe_map_t *)qe_base;
+
+ u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr);
+ out_be32(&qe_immrr->iram.iready, QE_IRAM_READY);
+}
+#endif
+
void qe_reset(void)
{
qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
@@ -580,6 +592,76 @@ int u_qe_upload_firmware(const struct qe_firmware *firmware)
}
#endif
+#ifdef CONFIG_U_QE
+int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
+{
+ unsigned int i;
+ unsigned int j;
+ const struct qe_header *hdr;
+ const u32 *code;
+#ifdef CONFIG_DEEP_SLEEP
+#ifdef CONFIG_PPC
+ ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#else
+ struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+#endif
+#endif
+
+ if (!firmware)
+ return -EINVAL;
+
+ hdr = &firmware->header;
+
+ /* Check the magic */
+ if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
+ (hdr->magic[2] != 'F')) {
+#ifdef CONFIG_DEEP_SLEEP
+ setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
+#endif
+ return -EPERM;
+ }
+
+ /*
+ * If the microcode calls for it, split the I-RAM.
+ */
+ if (!firmware->split) {
+ out_be16(&qe_immrr->cp.cercr,
+ in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
+ }
+
+ /* Loop through each microcode. */
+ for (i = 0; i < firmware->count; i++) {
+ const struct qe_microcode *ucode = &firmware->microcode[i];
+
+ /* Upload a microcode if it's present */
+ if (!ucode->code_offset)
+ return 0;
+
+ code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
+
+ /* Use auto-increment */
+ out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
+ QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
+
+ for (i = 0; i < be32_to_cpu(ucode->count); i++)
+ out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
+
+ /* Program the traps for this processor */
+ for (j = 0; j < 16; j++) {
+ u32 trap = be32_to_cpu(ucode->traps[j]);
+
+ if (trap)
+ out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
+ }
+
+ /* Enable traps */
+ out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
+ }
+
+ return 0;
+}
+#endif
+
struct qe_firmware_info *qe_get_firmware_info(void)
{
return qe_firmware_uploaded ? &qe_firmware_info : NULL;
diff --git a/drivers/qe/qe.h b/drivers/qe/qe.h
index 33878f897b..77b18e928f 100644
--- a/drivers/qe/qe.h
+++ b/drivers/qe/qe.h
@@ -11,6 +11,9 @@
#define __QE_H__
#include "common.h"
+#ifdef CONFIG_U_QE
+#include <linux/immap_qe.h>
+#endif
#define QE_NUM_OF_BRGS 16
#define UCC_MAX_NUM 8
@@ -288,6 +291,9 @@ void qe_reset(void);
#ifdef CONFIG_U_QE
void u_qe_init(void);
int u_qe_upload_firmware(const struct qe_firmware *firmware);
+void u_qe_resume(void);
+int u_qe_firmware_resume(const struct qe_firmware *firmware,
+ qe_map_t *qe_immrr);
#endif
#endif /* __QE_H__ */
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 5d4288d38f..2dca5244be 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -259,10 +259,11 @@ static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum,
void fdt_fixup_dr_usb(void *blob, bd_t *bd)
{
static const char * const modes[] = { "host", "peripheral", "otg" };
- static const char * const phys[] = { "ulpi", "utmi" };
+ static const char * const phys[] = { "ulpi", "utmi", "utmi_dual" };
int usb_erratum_a006261_off = -1;
int usb_erratum_a007075_off = -1;
int usb_erratum_a007792_off = -1;
+ int usb_erratum_a005697_off = -1;
int usb_mode_off = -1;
int usb_phy_off = -1;
char str[5];
@@ -303,6 +304,9 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd)
dr_phy_type = phys[phy_idx];
}
+ if (has_dual_phy())
+ dr_phy_type = phys[2];
+
usb_mode_off = fdt_fixup_usb_mode_phy_type(blob,
dr_mode_type, NULL,
usb_mode_off);
@@ -325,6 +329,7 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd)
if (usb_erratum_a006261_off < 0)
return;
}
+
if (has_erratum_a007075()) {
usb_erratum_a007075_off = fdt_fixup_usb_erratum
(blob,
@@ -333,6 +338,7 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd)
if (usb_erratum_a007075_off < 0)
return;
}
+
if (has_erratum_a007792()) {
usb_erratum_a007792_off = fdt_fixup_usb_erratum
(blob,
@@ -341,6 +347,14 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd)
if (usb_erratum_a007792_off < 0)
return;
}
+ if (has_erratum_a005697()) {
+ usb_erratum_a005697_off = fdt_fixup_usb_erratum
+ (blob,
+ "fsl,usb-erratum-a005697",
+ usb_erratum_a005697_off);
+ if (usb_erratum_a005697_off < 0)
+ return;
+ }
}
}
#endif
OpenPOWER on IntegriCloud