summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/Kconfig20
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/cpu.c55
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/fdt.c3
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c53
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/ppa.c143
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/soc.c4
-rw-r--r--arch/arm/dts/armada-7040-db.dts27
-rw-r--r--arch/arm/dts/armada-8040-db.dts16
-rw-r--r--arch/arm/dts/armada-cp110-master.dtsi37
-rw-r--r--arch/arm/dts/armada-cp110-slave.dtsi37
-rw-r--r--arch/arm/dts/fsl-ls1012a.dtsi2
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h8
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h9
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/ppa.h7
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch2.h63
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h (renamed from arch/arm/include/asm/arch-fsl-layerscape/ls2080a_stream_id.h)15
-rw-r--r--arch/arm/include/asm/arch-lpc32xx/i2c.h37
-rw-r--r--arch/arm/include/asm/armv8/sec_firmware.h4
-rw-r--r--arch/arm/include/asm/fsl_secure_boot.h8
-rw-r--r--board/freescale/common/fsl_validate.c88
-rw-r--r--board/freescale/ls1043ardb/ls1043ardb.c2
-rw-r--r--board/freescale/ls2080aqds/ls2080aqds.c13
-rw-r--r--board/freescale/ls2080ardb/ls2080ardb.c11
-rw-r--r--board/ge/bx50v3/bx50v3.c6
-rw-r--r--cmd/i2c.c10
-rw-r--r--cmd/tpm.c162
-rw-r--r--common/board_r.c1
-rw-r--r--common/fdt_support.c10
-rw-r--r--configs/A10-OLinuXino-Lime_defconfig4
-rw-r--r--configs/A20-OLinuXino-Lime2_defconfig4
-rw-r--r--configs/A20-OLinuXino-Lime_defconfig4
-rw-r--r--configs/A20-OLinuXino_MICRO_defconfig4
-rw-r--r--configs/ls1043ardb_nand_defconfig1
-rw-r--r--configs/ls1043ardb_sdcard_defconfig1
-rw-r--r--configs/ls1046ardb_emmc_defconfig1
-rw-r--r--configs/ls1046ardb_sdcard_defconfig1
-rw-r--r--configs/ls2080aqds_defconfig1
-rw-r--r--configs/ls2080ardb_defconfig1
-rw-r--r--configs/mvebu_db-88f7040_defconfig3
-rw-r--r--configs/mvebu_db-88f8040_defconfig3
-rw-r--r--doc/device-tree-bindings/net/fixed-link.txt30
-rw-r--r--drivers/i2c/Kconfig14
-rw-r--r--drivers/i2c/lpc32xx_i2c.c236
-rw-r--r--drivers/i2c/omap24xx_i2c.c66
-rw-r--r--drivers/i2c/omap24xx_i2c.h10
-rw-r--r--drivers/mmc/omap_hsmmc.c100
-rw-r--r--drivers/mtd/nand/nand.c17
-rw-r--r--drivers/net/Kconfig6
-rw-r--r--drivers/net/bcm-sf2-eth-gmac.c113
-rw-r--r--drivers/net/bcm-sf2-eth.h4
-rw-r--r--drivers/net/ldpaa_eth/ls2080a.c30
-rw-r--r--drivers/net/mvpp2.c1845
-rw-r--r--drivers/net/phy/Kconfig10
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/fixed.c82
-rw-r--r--drivers/net/phy/phy.c23
-rw-r--r--drivers/net/sunxi_emac.c19
-rw-r--r--drivers/pci/pci-uclass.c5
-rw-r--r--drivers/pci/pcie_layerscape.c42
-rw-r--r--drivers/pci/pcie_layerscape.h10
-rw-r--r--drivers/pci/pcie_layerscape_fixup.c94
-rw-r--r--drivers/pinctrl/Kconfig10
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/pinctrl-single.c142
-rw-r--r--drivers/reset/Kconfig8
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/sti-reset.c320
-rw-r--r--drivers/spi/fsl_qspi.c5
-rw-r--r--drivers/tpm/Kconfig15
-rw-r--r--dts/Makefile13
-rw-r--r--include/configs/ls1012a_common.h1
-rw-r--r--include/configs/ls1043a_common.h15
-rw-r--r--include/configs/ls1046a_common.h1
-rw-r--r--include/configs/ls1046aqds.h14
-rw-r--r--include/configs/ls2080a_common.h2
-rw-r--r--include/configs/ls2080aqds.h2
-rw-r--r--include/configs/ls2080ardb.h2
-rw-r--r--include/configs/mvebu_armada-8k.h8
-rw-r--r--include/fsl-mc/ldpaa_wriop.h1
-rw-r--r--include/fsl_validate.h24
-rw-r--r--include/linux/bitops.h1
-rw-r--r--include/nand.h1
-rw-r--r--include/phy.h9
-rw-r--r--include/tpm.h12
-rw-r--r--lib/fdtdec.c2
-rw-r--r--lib/tpm.c40
-rw-r--r--net/link_local.c2
-rw-r--r--tools/pblimage.c48
89 files changed, 3754 insertions, 583 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dacfe9a..e644ee3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1132,6 +1132,7 @@ config ARCH_STI
select DM_SERIAL
select BLK
select DM_MMC
+ select DM_RESET
help
Support for STMicroelectronics STiH407/10 SoC family.
This SoC is used on Linaro 96Board STiH410-B2260
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index a99b1c6..b24462b 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -73,6 +73,7 @@ config ARCH_LS2080A
select SYS_FSL_ERRATUM_A009803
select SYS_FSL_ERRATUM_A009942
select SYS_FSL_ERRATUM_A010165
+ select SYS_FSL_ERRATUM_A009203
select ARCH_EARLY_INIT_R
select BOARD_EARLY_INIT_F
@@ -134,6 +135,8 @@ config FSL_LS_PPA
choice
prompt "FSL Layerscape PPA firmware loading-media select"
depends on FSL_LS_PPA
+ default SYS_LS_PPA_FW_IN_MMC if SD_BOOT
+ default SYS_LS_PPA_FW_IN_NAND if NAND_BOOT
default SYS_LS_PPA_FW_IN_XIP
config SYS_LS_PPA_FW_IN_XIP
@@ -142,13 +145,27 @@ config SYS_LS_PPA_FW_IN_XIP
Say Y here if the PPA firmware locate at XIP flash, such
as NOR or QSPI flash.
+config SYS_LS_PPA_FW_IN_MMC
+ bool "eMMC or SD Card"
+ help
+ Say Y here if the PPA firmware locate at eMMC/SD card.
+
+config SYS_LS_PPA_FW_IN_NAND
+ bool "NAND"
+ help
+ Say Y here if the PPA firmware locate at NAND flash.
+
endchoice
config SYS_LS_PPA_FW_ADDR
hex "Address of PPA firmware loading from"
depends on FSL_LS_PPA
default 0x40500000 if SYS_LS_PPA_FW_IN_XIP && QSPI_BOOT
+ default 0x580a00000 if SYS_LS_PPA_FW_IN_XIP && ARCH_LS2080A
default 0x60500000 if SYS_LS_PPA_FW_IN_XIP
+ default 0x500000 if SYS_LS_PPA_FW_IN_MMC
+ default 0x500000 if SYS_LS_PPA_FW_IN_NAND
+
help
If the PPA firmware locate at XIP flash, such as NOR or
QSPI flash, this address is a directly memory-mapped.
@@ -307,6 +324,9 @@ config SYS_FSL_ERRATUM_A008585
config SYS_FSL_ERRATUM_A008850
bool
+config SYS_FSL_ERRATUM_A009203
+ bool
+
config SYS_FSL_ERRATUM_A009635
bool
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 7e66ee0..cebbb0f 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -89,6 +89,49 @@ static inline void early_mmu_setup(void)
set_sctlr(get_sctlr() | CR_M);
}
+static void fix_pcie_mmu_map(void)
+{
+#ifdef CONFIG_LS2080A
+ unsigned int i;
+ u32 svr, ver;
+ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+
+ svr = gur_in32(&gur->svr);
+ ver = SVR_SOC_VER(svr);
+
+ /* Fix PCIE base and size for LS2088A */
+ if ((ver == SVR_LS2088A) || (ver == SVR_LS2084A) ||
+ (ver == SVR_LS2048A) || (ver == SVR_LS2044A)) {
+ for (i = 0; i < ARRAY_SIZE(final_map); i++) {
+ switch (final_map[i].phys) {
+ case CONFIG_SYS_PCIE1_PHYS_ADDR:
+ final_map[i].phys = 0x2000000000ULL;
+ final_map[i].virt = 0x2000000000ULL;
+ final_map[i].size = 0x800000000ULL;
+ break;
+ case CONFIG_SYS_PCIE2_PHYS_ADDR:
+ final_map[i].phys = 0x2800000000ULL;
+ final_map[i].virt = 0x2800000000ULL;
+ final_map[i].size = 0x800000000ULL;
+ break;
+ case CONFIG_SYS_PCIE3_PHYS_ADDR:
+ final_map[i].phys = 0x3000000000ULL;
+ final_map[i].virt = 0x3000000000ULL;
+ final_map[i].size = 0x800000000ULL;
+ break;
+ case CONFIG_SYS_PCIE4_PHYS_ADDR:
+ final_map[i].phys = 0x3800000000ULL;
+ final_map[i].virt = 0x3800000000ULL;
+ final_map[i].size = 0x800000000ULL;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+#endif
+}
+
/*
* The final tables look similar to early tables, but different in detail.
* These tables are in DRAM. Sub tables are added to enable cache for
@@ -103,6 +146,9 @@ static inline void final_mmu_setup(void)
unsigned int el = current_el();
int index;
+ /* fix the final_map before filling in the block entries */
+ fix_pcie_mmu_map();
+
mem_map = final_map;
/* Update mapping for DDR to actual size */
@@ -436,7 +482,14 @@ int arch_early_init_r(void)
#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
- erratum_a009635();
+ u32 svr_dev_id;
+ /*
+ * erratum A009635 is valid only for LS2080A SoC and
+ * its personalitiesi
+ */
+ svr_dev_id = get_svr() >> 16;
+ if (svr_dev_id == SVR_DEV_LS2080A)
+ erratum_a009635();
#endif
#if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR)
erratum_a009942_check_cpo();
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
index 26d4a30..762a95b 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -387,8 +387,9 @@ void ft_cpu_setup(void *blob, bd_t *bd)
#ifdef CONFIG_SYS_DPAA_FMAN
fdt_fixup_fman_firmware(blob);
#endif
+#ifndef CONFIG_LS1012A
fsl_fdt_disable_usb(blob);
-
+#endif
#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
fdt_fixup_gic(blob);
#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
index 7faa86c..955e0b7 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
@@ -23,6 +23,11 @@ int xfi_dpmac[XFI8 + 1];
int sgmii_dpmac[SGMII16 + 1];
#endif
+__weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
+{
+ return;
+}
+
int is_serdes_configured(enum srds_prtcl device)
{
int ret = 0;
@@ -46,20 +51,22 @@ int is_serdes_configured(enum srds_prtcl device)
int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
{
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
- u32 cfg = gur_in32(&gur->rcwsr[28]);
+ u32 cfg = 0;
int i;
switch (sd) {
#ifdef CONFIG_SYS_FSL_SRDS_1
case FSL_SRDS_1:
- cfg &= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK;
- cfg >>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
+ cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]);
+ cfg &= FSL_CHASSIS3_SRDS1_PRTCL_MASK;
+ cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
break;
#endif
#ifdef CONFIG_SYS_FSL_SRDS_2
case FSL_SRDS_2:
- cfg &= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK;
- cfg >>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
+ cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
+ cfg &= FSL_CHASSIS3_SRDS2_PRTCL_MASK;
+ cfg >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT;
break;
#endif
default:
@@ -78,8 +85,8 @@ int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
return -ENODEV;
}
-void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
- u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
+void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask,
+ u32 sd_prctl_shift, u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
{
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
u32 cfg;
@@ -90,7 +97,7 @@ void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
- cfg = gur_in32(&gur->rcwsr[28]) & sd_prctl_mask;
+ cfg = gur_in32(&gur->rcwsr[rcwsr - 1]) & sd_prctl_mask;
cfg >>= sd_prctl_shift;
printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
@@ -106,28 +113,10 @@ void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
#ifdef CONFIG_FSL_MC_ENET
switch (lane_prtcl) {
case QSGMII_A:
- wriop_init_dpmac(sd, 5, (int)lane_prtcl);
- wriop_init_dpmac(sd, 6, (int)lane_prtcl);
- wriop_init_dpmac(sd, 7, (int)lane_prtcl);
- wriop_init_dpmac(sd, 8, (int)lane_prtcl);
- break;
case QSGMII_B:
- wriop_init_dpmac(sd, 1, (int)lane_prtcl);
- wriop_init_dpmac(sd, 2, (int)lane_prtcl);
- wriop_init_dpmac(sd, 3, (int)lane_prtcl);
- wriop_init_dpmac(sd, 4, (int)lane_prtcl);
- break;
case QSGMII_C:
- wriop_init_dpmac(sd, 13, (int)lane_prtcl);
- wriop_init_dpmac(sd, 14, (int)lane_prtcl);
- wriop_init_dpmac(sd, 15, (int)lane_prtcl);
- wriop_init_dpmac(sd, 16, (int)lane_prtcl);
- break;
case QSGMII_D:
- wriop_init_dpmac(sd, 9, (int)lane_prtcl);
- wriop_init_dpmac(sd, 10, (int)lane_prtcl);
- wriop_init_dpmac(sd, 11, (int)lane_prtcl);
- wriop_init_dpmac(sd, 12, (int)lane_prtcl);
+ wriop_init_dpmac_qsgmii(sd, (int)lane_prtcl);
break;
default:
if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8)
@@ -165,15 +154,17 @@ void fsl_serdes_init(void)
#ifdef CONFIG_SYS_FSL_SRDS_1
serdes_init(FSL_SRDS_1,
CONFIG_SYS_FSL_LSCH3_SERDES_ADDR,
- FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK,
- FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT,
+ FSL_CHASSIS3_SRDS1_REGSR,
+ FSL_CHASSIS3_SRDS1_PRTCL_MASK,
+ FSL_CHASSIS3_SRDS1_PRTCL_SHIFT,
serdes1_prtcl_map);
#endif
#ifdef CONFIG_SYS_FSL_SRDS_2
serdes_init(FSL_SRDS_2,
CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000,
- FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK,
- FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT,
+ FSL_CHASSIS3_SRDS2_REGSR,
+ FSL_CHASSIS3_SRDS2_PRTCL_MASK,
+ FSL_CHASSIS3_SRDS2_PRTCL_SHIFT,
serdes2_prtcl_map);
#endif
}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
index b68e87d..b35ad5f 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
+#include <malloc.h>
#include <config.h>
#include <errno.h>
#include <asm/system.h>
@@ -21,9 +22,17 @@
#include <fsl_validate.h>
#endif
+#ifdef CONFIG_SYS_LS_PPA_FW_IN_NAND
+#include <nand.h>
+#elif defined(CONFIG_SYS_LS_PPA_FW_IN_MMC)
+#include <mmc.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
int ppa_init(void)
{
- const void *ppa_fit_addr;
+ void *ppa_fit_addr;
u32 *boot_loc_ptr_l, *boot_loc_ptr_h;
int ret;
@@ -34,10 +43,137 @@ int ppa_init(void)
#ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP
ppa_fit_addr = (void *)CONFIG_SYS_LS_PPA_FW_ADDR;
+ debug("%s: PPA image load from XIP\n", __func__);
+#else /* !CONFIG_SYS_LS_PPA_FW_IN_XIP */
+ size_t fw_length, fdt_header_len = sizeof(struct fdt_header);
+
+ /* Copy PPA image from MMC/SD/NAND to allocated memory */
+#ifdef CONFIG_SYS_LS_PPA_FW_IN_MMC
+ struct mmc *mmc;
+ int dev = CONFIG_SYS_MMC_ENV_DEV;
+ struct fdt_header *fitp;
+ u32 cnt;
+ u32 blk = CONFIG_SYS_LS_PPA_FW_ADDR / 512;
+
+ debug("%s: PPA image load from eMMC/SD\n", __func__);
+
+ ret = mmc_initialize(gd->bd);
+ if (ret) {
+ printf("%s: mmc_initialize() failed\n", __func__);
+ return ret;
+ }
+ mmc = find_mmc_device(dev);
+ if (!mmc) {
+ printf("PPA: MMC cannot find device for PPA firmware\n");
+ return -ENODEV;
+ }
+
+ ret = mmc_init(mmc);
+ if (ret) {
+ printf("%s: mmc_init() failed\n", __func__);
+ return ret;
+ }
+
+ fitp = malloc(roundup(fdt_header_len, 512));
+ if (!fitp) {
+ printf("PPA: malloc failed for FIT header(size 0x%zx)\n",
+ roundup(fdt_header_len, 512));
+ return -ENOMEM;
+ }
+
+ cnt = DIV_ROUND_UP(fdt_header_len, 512);
+ debug("%s: MMC read PPA FIT header: dev # %u, block # %u, count %u\n",
+ __func__, dev, blk, cnt);
+ ret = mmc->block_dev.block_read(&mmc->block_dev, blk, cnt, fitp);
+ if (ret != cnt) {
+ free(fitp);
+ printf("MMC/SD read of PPA FIT header at offset 0x%x failed\n",
+ CONFIG_SYS_LS_PPA_FW_ADDR);
+ return -EIO;
+ }
+
+ /* flush cache after read */
+ flush_cache((ulong)fitp, cnt * 512);
+
+ ret = fdt_check_header(fitp);
+ if (ret) {
+ free(fitp);
+ printf("%s: fdt_check_header() failed\n", __func__);
+ return ret;
+ }
+
+ fw_length = fdt_totalsize(fitp);
+ free(fitp);
+
+ fw_length = roundup(fw_length, 512);
+ ppa_fit_addr = malloc(fw_length);
+ if (!ppa_fit_addr) {
+ printf("PPA: malloc failed for PPA image(size 0x%zx)\n",
+ fw_length);
+ return -ENOMEM;
+ }
+
+ cnt = DIV_ROUND_UP(fw_length, 512);
+ debug("%s: MMC read PPA FIT image: dev # %u, block # %u, count %u\n",
+ __func__, dev, blk, cnt);
+ ret = mmc->block_dev.block_read(&mmc->block_dev,
+ blk, cnt, ppa_fit_addr);
+ if (ret != cnt) {
+ free(ppa_fit_addr);
+ printf("MMC/SD read of PPA FIT header at offset 0x%x failed\n",
+ CONFIG_SYS_LS_PPA_FW_ADDR);
+ return -EIO;
+ }
+
+ /* flush cache after read */
+ flush_cache((ulong)ppa_fit_addr, cnt * 512);
+
+#elif defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
+ struct fdt_header fit;
+
+ debug("%s: PPA image load from NAND\n", __func__);
+
+ nand_init();
+ ret = nand_read(nand_info[0], (loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
+ &fdt_header_len, (u_char *)&fit);
+ if (ret == -EUCLEAN) {
+ printf("NAND read of PPA FIT header at offset 0x%x failed\n",
+ CONFIG_SYS_LS_PPA_FW_ADDR);
+ return -EIO;
+ }
+
+ ret = fdt_check_header(&fit);
+ if (ret) {
+ printf("%s: fdt_check_header() failed\n", __func__);
+ return ret;
+ }
+
+ fw_length = fdt_totalsize(&fit);
+
+ ppa_fit_addr = malloc(fw_length);
+ if (!ppa_fit_addr) {
+ printf("PPA: malloc failed for PPA image(size 0x%zx)\n",
+ fw_length);
+ return -ENOMEM;
+ }
+
+ ret = nand_read(nand_info[0], (loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
+ &fw_length, (u_char *)ppa_fit_addr);
+ if (ret == -EUCLEAN) {
+ free(ppa_fit_addr);
+ printf("NAND read of PPA firmware at offset 0x%x failed\n",
+ CONFIG_SYS_LS_PPA_FW_ADDR);
+ return -EIO;
+ }
+
+ /* flush cache after read */
+ flush_cache((ulong)ppa_fit_addr, fw_length);
#else
#error "No CONFIG_SYS_LS_PPA_FW_IN_xxx defined"
#endif
+#endif
+
#ifdef CONFIG_CHAIN_OF_TRUST
ppa_img_addr = (uintptr_t)ppa_fit_addr;
if (fsl_check_boot_mode_secure() != 0) {
@@ -65,5 +201,10 @@ int ppa_init(void)
boot_loc_ptr_l, boot_loc_ptr_h);
ret = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h);
+#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \
+ defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
+ free(ppa_fit_addr);
+#endif
+
return ret;
}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
index b54a937..9e3cdd7 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -152,6 +152,7 @@ static void erratum_rcw_src(void)
* This erratum requires setting glitch_en bit to enable
* digital glitch filter to improve clock stability.
*/
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009203
static void erratum_a009203(void)
{
u8 __iomem *ptr;
@@ -178,6 +179,7 @@ static void erratum_a009203(void)
#endif
#endif
}
+#endif
void bypass_smmu(void)
{
@@ -191,7 +193,9 @@ void fsl_lsch3_early_init_f(void)
{
erratum_rcw_src();
init_early_memctl_regs(); /* tighten IFC timing */
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009203
erratum_a009203();
+#endif
erratum_a008514();
erratum_a008336();
#ifdef CONFIG_CHAIN_OF_TRUST
diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts
index 63442df..84e0dbd 100644
--- a/arch/arm/dts/armada-7040-db.dts
+++ b/arch/arm/dts/armada-7040-db.dts
@@ -159,7 +159,7 @@
&cpm_comphy {
phy0 {
phy-type = <PHY_TYPE_SGMII2>;
- phy-speed = <PHY_SPEED_3_125G>;
+ phy-speed = <PHY_SPEED_1_25G>;
};
phy1 {
@@ -209,3 +209,28 @@
no-1-8-v;
non-removable;
};
+
+&cpm_mdio {
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+&cpm_ethernet {
+ status = "okay";
+};
+
+&cpm_eth1 {
+ status = "okay";
+ phy = <&phy0>;
+ phy-mode = "sgmii";
+};
+
+&cpm_eth2 {
+ status = "okay";
+ phy = <&phy1>;
+ phy-mode = "rgmii-id";
+};
diff --git a/arch/arm/dts/armada-8040-db.dts b/arch/arm/dts/armada-8040-db.dts
index 40def9d..f1f196f 100644
--- a/arch/arm/dts/armada-8040-db.dts
+++ b/arch/arm/dts/armada-8040-db.dts
@@ -283,3 +283,19 @@
&cps_utmi0 {
status = "okay";
};
+
+&cpm_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+&cpm_ethernet {
+ status = "okay";
+};
+
+&cpm_eth2 {
+ status = "okay";
+ phy = <&phy1>;
+ phy-mode = "rgmii-id";
+};
diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi
index 1f0edde..229046f 100644
--- a/arch/arm/dts/armada-cp110-master.dtsi
+++ b/arch/arm/dts/armada-cp110-master.dtsi
@@ -61,6 +61,43 @@
interrupt-parent = <&gic>;
ranges = <0x0 0x0 0xf2000000 0x2000000>;
+ cpm_ethernet: ethernet@0 {
+ compatible = "marvell,armada-7k-pp22";
+ reg = <0x0 0x100000>, <0x129000 0xb000>;
+ clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>, <&cpm_syscon0 1 5>;
+ clock-names = "pp_clk", "gop_clk", "mg_clk";
+ status = "disabled";
+ dma-coherent;
+
+ cpm_eth0: eth0 {
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <0>;
+ gop-port-id = <0>;
+ status = "disabled";
+ };
+
+ cpm_eth1: eth1 {
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <1>;
+ gop-port-id = <2>;
+ status = "disabled";
+ };
+
+ cpm_eth2: eth2 {
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <2>;
+ gop-port-id = <3>;
+ status = "disabled";
+ };
+ };
+
+ cpm_mdio: mdio@12a200 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "marvell,orion-mdio";
+ reg = <0x12a200 0x10>;
+ };
+
cpm_syscon0: system-controller@440000 {
compatible = "marvell,cp110-system-controller0",
"syscon";
diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi
index ff3fbed..5876391 100644
--- a/arch/arm/dts/armada-cp110-slave.dtsi
+++ b/arch/arm/dts/armada-cp110-slave.dtsi
@@ -61,6 +61,43 @@
interrupt-parent = <&gic>;
ranges = <0x0 0x0 0xf4000000 0x2000000>;
+ cps_ethernet: ethernet@0 {
+ compatible = "marvell,armada-7k-pp22";
+ reg = <0x0 0x100000>, <0x129000 0xb000>;
+ clocks = <&cps_syscon0 1 3>, <&cps_syscon0 1 9>, <&cps_syscon0 1 5>;
+ clock-names = "pp_clk", "gop_clk", "mg_clk";
+ status = "disabled";
+ dma-coherent;
+
+ cps_eth0: eth0 {
+ interrupts = <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <0>;
+ gop-port-id = <0>;
+ status = "disabled";
+ };
+
+ cps_eth1: eth1 {
+ interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <1>;
+ gop-port-id = <2>;
+ status = "disabled";
+ };
+
+ cps_eth2: eth2 {
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <2>;
+ gop-port-id = <3>;
+ status = "disabled";
+ };
+ };
+
+ cps_mdio: mdio@12a200 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "marvell,orion-mdio";
+ reg = <0x12a200 0x10>;
+ };
+
cps_syscon0: system-controller@440000 {
compatible = "marvell,cp110-system-controller0",
"syscon";
diff --git a/arch/arm/dts/fsl-ls1012a.dtsi b/arch/arm/dts/fsl-ls1012a.dtsi
index ed5ea54..23b3cec 100644
--- a/arch/arm/dts/fsl-ls1012a.dtsi
+++ b/arch/arm/dts/fsl-ls1012a.dtsi
@@ -114,7 +114,7 @@
reg = <0x0 0x1550000 0x0 0x10000>,
<0x0 0x40000000 0x0 0x4000000>;
reg-names = "QuadSPI", "QuadSPI-memory";
- num-cs = <2>;
+ num-cs = <1>;
big-endian;
status = "disabled";
};
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
index d9d948e..70181c5 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
@@ -48,10 +48,10 @@ enum srds_prtcl {
SGMII14,
SGMII15,
SGMII16,
- QSGMII_A, /* A indicates MACs 1-4 */
- QSGMII_B, /* B indicates MACs 5-8 */
- QSGMII_C, /* C indicates MACs 9-12 */
- QSGMII_D, /* D indicates MACs 12-16 */
+ QSGMII_A,
+ QSGMII_B,
+ QSGMII_C,
+ QSGMII_D,
SERDES_PRCTL_COUNT
};
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
index 08ea8fb..80c421f 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
@@ -230,10 +230,19 @@ struct ccsr_gur {
#define FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK 0x3f
#define FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT 18
#define FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK 0x3f
+
+#if defined(CONFIG_ARCH_LS2080A)
#define FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK 0x00FF0000
#define FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT 16
#define FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK 0xFF000000
#define FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT 24
+#define FSL_CHASSIS3_SRDS1_PRTCL_MASK FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK
+#define FSL_CHASSIS3_SRDS1_PRTCL_SHIFT FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT
+#define FSL_CHASSIS3_SRDS2_PRTCL_MASK FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK
+#define FSL_CHASSIS3_SRDS2_PRTCL_SHIFT FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT
+#define FSL_CHASSIS3_SRDS1_REGSR 29
+#define FSL_CHASSIS3_SRDS2_REGSR 29
+#endif
#define RCW_SB_EN_REG_INDEX 9
#define RCW_SB_EN_MASK 0x00000400
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/ppa.h b/arch/arm/include/asm/arch-fsl-layerscape/ppa.h
index 1f1442b..da4098e 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/ppa.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/ppa.h
@@ -7,10 +7,7 @@
#ifndef __FSL_PPA_H_
#define __FSL_PPA_H_
-#define SEC_FIRMWARE_FIT_IMAGE "firmware"
-#define SEC_FIRMEWARE_FIT_CNF_NAME "config@1"
-#define SEC_FIRMWARE_TARGET_EL 2
-
+#ifdef CONFIG_FSL_LS_PPA
int ppa_init(void);
-
+#endif
#endif
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch2.h b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch2.h
new file mode 100644
index 0000000..b326fe5
--- /dev/null
+++ b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch2.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ */
+#ifndef __FSL_STREAM_ID_H
+#define __FSL_STREAM_ID_H
+
+/*
+ * Stream IDs on Chassis-2 (for example ls1043a, ls1046a, ls1012) devices
+ * are not hardwired and are programmed by sw. There are a limited number
+ * of stream IDs available, and the partitioning of them is scenario
+ * dependent. This header defines the partitioning between legacy, PCI,
+ * and DPAA1 devices.
+ *
+ * This partitioning can be customized in this file depending
+ * on the specific hardware config:
+ *
+ * -non-PCI legacy, platform devices (USB, SDHC, SATA, DMA, QE etc)
+ * -all legacy devices get a unique stream ID assigned and programmed in
+ * their AMQR registers by u-boot
+ *
+ * -PCIe
+ * -there is a range of stream IDs set aside for PCI in this
+ * file. U-boot will scan the PCI bus and for each device discovered:
+ * -allocate a streamID
+ * -set a PEXn LUT table entry mapping 'requester ID' to 'stream ID'
+ * -set a msi-map entry in the PEXn controller node in the
+ * device tree (see Documentation/devicetree/bindings/pci/pci-msi.txt
+ * for more info on the msi-map definition)
+ * -set a iommu-map entry in the PEXn controller node in the
+ * device tree (see Documentation/devicetree/bindings/pci/pci-iommu.txt
+ * for more info on the iommu-map definition)
+ *
+ * -DPAA1
+ * - Stream ids for DPAA1 use are reserved for future usecase.
+ *
+ */
+
+
+#define FSL_INVALID_STREAM_ID 0
+
+/* legacy devices */
+#define FSL_USB1_STREAM_ID 1
+#define FSL_USB2_STREAM_ID 2
+#define FSL_USB3_STREAM_ID 3
+#define FSL_SDHC_STREAM_ID 4
+#define FSL_SATA_STREAM_ID 5
+#define FSL_QE_STREAM_ID 6
+#define FSL_QDMA_STREAM_ID 7
+#define FSL_EDMA_STREAM_ID 8
+#define FSL_ETR_STREAM_ID 9
+
+/* PCI - programmed in PEXn_LUT */
+#define FSL_PEX_STREAM_ID_START 11
+#define FSL_PEX_STREAM_ID_END 26
+
+/* DPAA1 - Stream-ID that can be programmed in DPAA1 h/w */
+#define FSL_DPAA1_STREAM_ID_START 27
+#define FSL_DPAA1_STREAM_ID_END 63
+
+#endif
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/ls2080a_stream_id.h b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h
index ee28323..d7d527d 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/ls2080a_stream_id.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/stream_id_lsch3.h
@@ -8,11 +8,11 @@
#define __FSL_STREAM_ID_H
/*
- * Stream IDs on ls2080a devices are not hardwired and are
- * programmed by sw. There are a limited number of stream IDs
- * available, and the partitioning of them is scenario dependent.
- * This header defines the partitioning between legacy, PCI,
- * and DPAA2 devices.
+ * Stream IDs on NXP Chassis-3 (for example ls2080a, ls1088a, ls2088a)
+ * devices are not hardwired and are programmed by sw. There are a limited
+ * number of stream IDs available, and the partitioning of them is scenario
+ * dependent. This header defines the partitioning between legacy,
+ * PCI, and DPAA2 devices.
*
* This partitioning can be customized in this file depending
* on the specific hardware config:
@@ -29,6 +29,9 @@
* -set a msi-map entry in the PEXn controller node in the
* device tree (see Documentation/devicetree/bindings/pci/pci-msi.txt
* for more info on the msi-map definition)
+ * -set a iommu-map entry in the PEXn controller node in the
+ * device tree (see Documentation/devicetree/bindings/pci/pci-iommu.txt
+ * for more info on the iommu-map definition)
*
* -DPAA2
* -u-boot will allocate a range of stream IDs to be used by the Management
@@ -36,7 +39,7 @@
* -the MC is responsible for allocating and setting up 'isolation context
* IDs (ICIDs) based on the allocated stream IDs for all DPAA2 devices.
*
- * On ls2080a SoCs stream IDs are programmed in AMQ registers (32-bits) for
+ * On Chasis-3 SoCs stream IDs are programmed in AMQ registers (32-bits) for
* each of the different bus masters. The relationship between
* the AMQ registers and stream IDs is defined in the table below:
* AMQ bit streamID bit
diff --git a/arch/arm/include/asm/arch-lpc32xx/i2c.h b/arch/arm/include/asm/arch-lpc32xx/i2c.h
new file mode 100644
index 0000000..5301d4c
--- /dev/null
+++ b/arch/arm/include/asm/arch-lpc32xx/i2c.h
@@ -0,0 +1,37 @@
+#ifndef _LPC32XX_I2C_H
+#define _LPC32XX_I2C_H
+
+#include <common.h>
+#include <asm/types.h>
+
+/* i2c register set */
+struct lpc32xx_i2c_base {
+ union {
+ u32 rx;
+ u32 tx;
+ };
+ u32 stat;
+ u32 ctrl;
+ u32 clk_hi;
+ u32 clk_lo;
+ u32 adr;
+ u32 rxfl;
+ u32 txfl;
+ u32 rxb;
+ u32 txb;
+ u32 stx;
+ u32 stxfl;
+};
+
+#ifdef CONFIG_DM_I2C
+enum {
+ I2C_0, I2C_1, I2C_2,
+};
+
+struct lpc32xx_i2c_dev {
+ struct lpc32xx_i2c_base *base;
+ int index;
+ uint speed;
+};
+#endif /* CONFIG_DM_I2C */
+#endif /* _LPC32XX_I2C_H */
diff --git a/arch/arm/include/asm/armv8/sec_firmware.h b/arch/arm/include/asm/armv8/sec_firmware.h
index 5ae00fa..bcdb1b0 100644
--- a/arch/arm/include/asm/armv8/sec_firmware.h
+++ b/arch/arm/include/asm/armv8/sec_firmware.h
@@ -7,10 +7,6 @@
#ifndef __SEC_FIRMWARE_H_
#define __SEC_FIRMWARE_H_
-#ifdef CONFIG_FSL_LS_PPA
-#include <asm/arch/ppa.h>
-#endif
-
int sec_firmware_init(const void *, u32 *, u32 *);
int _sec_firmware_entry(const void *, u32 *, u32 *);
bool sec_firmware_is_valid(const void *);
diff --git a/arch/arm/include/asm/fsl_secure_boot.h b/arch/arm/include/asm/fsl_secure_boot.h
index fd627c0..d98a1e8 100644
--- a/arch/arm/include/asm/fsl_secure_boot.h
+++ b/arch/arm/include/asm/fsl_secure_boot.h
@@ -38,11 +38,11 @@
* in boot ROM of the SoC.
* The feature is only applicable in case of NOR boot and is
* not applicable in case of RAMBOOT (NAND, SD, SPI).
+ * For LS, this feature is available for all device if IE Table
+ * is copied to XIP memory
+ * Also, for LS, ISBC doesn't verify this table.
*/
-#ifndef CONFIG_ESBC_HDR_LS
-/* Current Key EXT feature not available in LS ESBC Header */
#define CONFIG_FSL_ISBC_KEY_EXT
-#endif
#endif
@@ -112,6 +112,8 @@
#ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP
#ifdef CONFIG_LS1043A
#define CONFIG_SYS_LS_PPA_ESBC_ADDR 0x600c0000
+#elif defined(CONFIG_FSL_LSCH3)
+#define CONFIG_SYS_LS_PPA_ESBC_ADDR 0x580c40000
#endif
#else
#error "No CONFIG_SYS_LS_PPA_FW_IN_xxx defined"
diff --git a/board/freescale/common/fsl_validate.c b/board/freescale/common/fsl_validate.c
index 2b723a4..7396aa2 100644
--- a/board/freescale/common/fsl_validate.c
+++ b/board/freescale/common/fsl_validate.c
@@ -27,6 +27,10 @@
#define CHECK_KEY_LEN(key_len) (((key_len) == 2 * KEY_SIZE_BYTES / 4) || \
((key_len) == 2 * KEY_SIZE_BYTES / 2) || \
((key_len) == 2 * KEY_SIZE_BYTES))
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+/* Global data structure */
+static struct fsl_secboot_glb glb;
+#endif
/* This array contains DER value for SHA-256 */
static const u8 hash_identifier[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
@@ -60,7 +64,7 @@ self:
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
static u32 check_ie(struct fsl_secboot_img_priv *img)
{
- if (img->hdr.ie_flag)
+ if (img->hdr.ie_flag & IE_FLAG_MASK)
return 1;
return 0;
@@ -119,7 +123,21 @@ int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
}
#endif
-static int get_ie_info_addr(u32 *ie_addr)
+#if defined(CONFIG_ESBC_HDR_LS)
+static int get_ie_info_addr(uintptr_t *ie_addr)
+{
+ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ /* For LS-CH3, the address of IE Table is
+ * stated in Scratch13 and scratch14 of DCFG.
+ * Bootrom validates this table while validating uboot.
+ * DCFG is LE*/
+ *ie_addr = in_le32(&gur->scratchrw[SCRATCH_IE_HIGH_ADR - 1]);
+ *ie_addr = *ie_addr << 32;
+ *ie_addr |= in_le32(&gur->scratchrw[SCRATCH_IE_LOW_ADR - 1]);
+ return 0;
+}
+#else /* CONFIG_ESBC_HDR_LS */
+static int get_ie_info_addr(uintptr_t *ie_addr)
{
struct fsl_secboot_img_hdr *hdr;
struct fsl_secboot_sg_table *sg_tbl;
@@ -147,16 +165,17 @@ static int get_ie_info_addr(u32 *ie_addr)
/* IE Key Table is the first entry in the SG Table */
#if defined(CONFIG_MPC85xx)
- *ie_addr = (sg_tbl->src_addr & ~(CONFIG_SYS_PBI_FLASH_BASE)) +
- flash_base_addr;
+ *ie_addr = (uintptr_t)((sg_tbl->src_addr &
+ ~(CONFIG_SYS_PBI_FLASH_BASE)) +
+ flash_base_addr);
#else
- *ie_addr = sg_tbl->src_addr;
+ *ie_addr = (uintptr_t)sg_tbl->src_addr;
#endif
- debug("IE Table address is %x\n", *ie_addr);
+ debug("IE Table address is %lx\n", *ie_addr);
return 0;
}
-
+#endif /* CONFIG_ESBC_HDR_LS */
#endif
#ifdef CONFIG_KEY_REVOCATION
@@ -164,7 +183,10 @@ static int get_ie_info_addr(u32 *ie_addr)
static u32 check_srk(struct fsl_secboot_img_priv *img)
{
#ifdef CONFIG_ESBC_HDR_LS
- /* In LS, No SRK Flag as SRK is always present*/
+ /* In LS, No SRK Flag as SRK is always present if IE not present*/
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+ return !check_ie(img);
+#endif
return 1;
#else
if (img->hdr.len_kr.srk_table_flag & SRK_FLAG)
@@ -253,14 +275,29 @@ static u32 read_validate_single_key(struct fsl_secboot_img_priv *img)
#endif /* CONFIG_ESBC_HDR_LS */
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+
+static void install_ie_tbl(uintptr_t ie_tbl_addr,
+ struct fsl_secboot_img_priv *img)
+{
+ /* Copy IE tbl to Global Data */
+ memcpy(&glb.ie_tbl, (u8 *)ie_tbl_addr, sizeof(struct ie_key_info));
+ img->ie_addr = (uintptr_t)&glb.ie_tbl;
+ glb.ie_addr = img->ie_addr;
+}
+
static u32 read_validate_ie_tbl(struct fsl_secboot_img_priv *img)
{
struct fsl_secboot_img_hdr *hdr = &img->hdr;
u32 ie_key_len, ie_revoc_flag, ie_num;
struct ie_key_info *ie_info;
- if (get_ie_info_addr(&img->ie_addr))
- return ERROR_IE_TABLE_NOT_FOUND;
+ if (!img->ie_addr) {
+ if (get_ie_info_addr(&img->ie_addr))
+ return ERROR_IE_TABLE_NOT_FOUND;
+ else
+ install_ie_tbl(img->ie_addr, img);
+ }
+
ie_info = (struct ie_key_info *)(uintptr_t)img->ie_addr;
if (ie_info->num_keys == 0 || ie_info->num_keys > 32)
return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY;
@@ -786,6 +823,26 @@ static int calculate_cmp_img_sig(struct fsl_secboot_img_priv *img)
return 0;
}
+/* Function to initialize img priv and global data structure
+ */
+static int secboot_init(struct fsl_secboot_img_priv **img_ptr)
+{
+ *img_ptr = malloc(sizeof(struct fsl_secboot_img_priv));
+
+ struct fsl_secboot_img_priv *img = *img_ptr;
+
+ if (!img)
+ return -ENOMEM;
+ memset(img, 0, sizeof(struct fsl_secboot_img_priv));
+
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+ if (glb.ie_addr)
+ img->ie_addr = glb.ie_addr;
+#endif
+ return 0;
+}
+
+
/* haddr - Address of the header of image to be validated.
* arg_hash_str - Option hash string. If provided, this
* overrides the key hash in the SFP fuses.
@@ -839,12 +896,9 @@ int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
hash_cmd = 1;
}
- img = malloc(sizeof(struct fsl_secboot_img_priv));
-
- if (!img)
- return -1;
-
- memset(img, 0, sizeof(struct fsl_secboot_img_priv));
+ ret = secboot_init(&img);
+ if (ret)
+ goto exit;
/* Update the information in Private Struct */
hdr = &img->hdr;
@@ -899,5 +953,7 @@ int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
}
exit:
+ /* Free Img as it was malloc'ed*/
+ free(img);
return ret;
}
diff --git a/board/freescale/ls1043ardb/ls1043ardb.c b/board/freescale/ls1043ardb/ls1043ardb.c
index 2333843..728de2e 100644
--- a/board/freescale/ls1043ardb/ls1043ardb.c
+++ b/board/freescale/ls1043ardb/ls1043ardb.c
@@ -23,9 +23,7 @@
#ifdef CONFIG_U_QE
#include <fsl_qe.h>
#endif
-#ifdef CONFIG_FSL_LS_PPA
#include <asm/arch/ppa.h>
-#endif
DECLARE_GLOBAL_DATA_PTR;
diff --git a/board/freescale/ls2080aqds/ls2080aqds.c b/board/freescale/ls2080aqds/ls2080aqds.c
index 277013b..6da9c6c 100644
--- a/board/freescale/ls2080aqds/ls2080aqds.c
+++ b/board/freescale/ls2080aqds/ls2080aqds.c
@@ -19,6 +19,8 @@
#include <asm/arch/soc.h>
#include <hwconfig.h>
#include <fsl_sec.h>
+#include <asm/arch/ppa.h>
+
#include "../common/qixis.h"
#include "ls2080aqds_qixis.h"
@@ -225,6 +227,14 @@ int board_init(void)
select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
rtc_enable_32khz_output();
+#ifdef CONFIG_FSL_LS_PPA
+ ppa_init();
+#endif
+
+#ifdef CONFIG_FSL_CAAM
+ sec_init();
+#endif
+
return 0;
}
@@ -266,9 +276,6 @@ void detail_board_ddr_info(void)
#if defined(CONFIG_ARCH_MISC_INIT)
int arch_misc_init(void)
{
-#ifdef CONFIG_FSL_CAAM
- sec_init();
-#endif
return 0;
}
#endif
diff --git a/board/freescale/ls2080ardb/ls2080ardb.c b/board/freescale/ls2080ardb/ls2080ardb.c
index 4c01f56..ea05ec6 100644
--- a/board/freescale/ls2080ardb/ls2080ardb.c
+++ b/board/freescale/ls2080ardb/ls2080ardb.c
@@ -19,6 +19,7 @@
#include <i2c.h>
#include <asm/arch/mmu.h>
#include <asm/arch/soc.h>
+#include <asm/arch/ppa.h>
#include <fsl_sec.h>
#include "../common/qixis.h"
@@ -181,10 +182,17 @@ int board_init(void)
QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET_EN);
+#ifdef CONFIG_FSL_LS_PPA
+ ppa_init();
+#endif
+
#ifdef CONFIG_FSL_MC_ENET
/* invert AQR405 IRQ pins polarity */
out_le32(irq_ccsr + IRQCR_OFFSET / 4, AQR405_IRQ_MASK);
#endif
+#ifdef CONFIG_FSL_CAAM
+ sec_init();
+#endif
return 0;
}
@@ -223,9 +231,6 @@ void detail_board_ddr_info(void)
#if defined(CONFIG_ARCH_MISC_INIT)
int arch_misc_init(void)
{
-#ifdef CONFIG_FSL_CAAM
- sec_init();
-#endif
return 0;
}
#endif
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c
index 2fc1144..0acf655 100644
--- a/board/ge/bx50v3/bx50v3.c
+++ b/board/ge/bx50v3/bx50v3.c
@@ -103,8 +103,9 @@ static void setup_iomux_enet(void)
/* Reset AR8033 PHY */
gpio_direction_output(IMX_GPIO_NR(1, 28), 0);
- udelay(500);
+ mdelay(10);
gpio_set_value(IMX_GPIO_NR(1, 28), 1);
+ mdelay(1);
}
static iomux_v3_cfg_t const usdhc2_pads[] = {
@@ -306,7 +307,8 @@ static int mx6_rgmii_rework(struct phy_device *phydev)
/* set debug port address: SerDes Test and System Mode Control */
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
/* enable rgmii tx clock delay */
- phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
+ /* set the reserved bits to avoid board specific voltage peak issue*/
+ phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47);
return 0;
}
diff --git a/cmd/i2c.c b/cmd/i2c.c
index 473153f..3dd7c6b 100644
--- a/cmd/i2c.c
+++ b/cmd/i2c.c
@@ -151,6 +151,16 @@ static int cmd_i2c_set_bus_num(unsigned int busnum)
static int i2c_get_cur_bus(struct udevice **busp)
{
+#ifdef CONFIG_I2C_SET_DEFAULT_BUS_NUM
+ if (!i2c_cur_bus) {
+ if (cmd_i2c_set_bus_num(CONFIG_I2C_DEFAULT_BUS_NUMBER)) {
+ printf("Default I2C bus %d not found\n",
+ CONFIG_I2C_DEFAULT_BUS_NUMBER);
+ return -ENODEV;
+ }
+ }
+#endif
+
if (!i2c_cur_bus) {
puts("No I2C bus selected\n");
return -ENODEV;
diff --git a/cmd/tpm.c b/cmd/tpm.c
index 625fc43..0c4bc73 100644
--- a/cmd/tpm.c
+++ b/cmd/tpm.c
@@ -592,6 +592,45 @@ static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag,
return report_return_code(err);
}
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+static int do_tpm_load_key_by_sha1(cmd_tbl_t *cmdtp, int flag, int argc, char *
+ const argv[])
+{
+ uint32_t parent_handle = 0;
+ uint32_t key_len, key_handle, err;
+ uint8_t usage_auth[DIGEST_LENGTH];
+ uint8_t parent_hash[DIGEST_LENGTH];
+ void *key;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ parse_byte_string(argv[1], parent_hash, NULL);
+ key = (void *)simple_strtoul(argv[2], NULL, 0);
+ key_len = simple_strtoul(argv[3], NULL, 0);
+ if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
+ return CMD_RET_FAILURE;
+ parse_byte_string(argv[4], usage_auth, NULL);
+
+ err = tpm_find_key_sha1(usage_auth, parent_hash, &parent_handle);
+ if (err) {
+ printf("Could not find matching parent key (err = %d)\n", err);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Found parent key %08x\n", parent_handle);
+
+ err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
+ &key_handle);
+ if (!err) {
+ printf("Key handle is 0x%x\n", key_handle);
+ setenv_hex("key_handle", key_handle);
+ }
+
+ return report_return_code(err);
+}
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
{
@@ -652,31 +691,36 @@ static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
{
int type = 0;
- if (argc != 2)
+ if (argc != 3)
return CMD_RET_USAGE;
- if (strcasecmp(argv[1], "key"))
+ if (!strcasecmp(argv[1], "key"))
type = TPM_RT_KEY;
- else if (strcasecmp(argv[1], "auth"))
+ else if (!strcasecmp(argv[1], "auth"))
type = TPM_RT_AUTH;
- else if (strcasecmp(argv[1], "hash"))
+ else if (!strcasecmp(argv[1], "hash"))
type = TPM_RT_HASH;
- else if (strcasecmp(argv[1], "trans"))
+ else if (!strcasecmp(argv[1], "trans"))
type = TPM_RT_TRANS;
- else if (strcasecmp(argv[1], "context"))
+ else if (!strcasecmp(argv[1], "context"))
type = TPM_RT_CONTEXT;
- else if (strcasecmp(argv[1], "counter"))
+ else if (!strcasecmp(argv[1], "counter"))
type = TPM_RT_COUNTER;
- else if (strcasecmp(argv[1], "delegate"))
+ else if (!strcasecmp(argv[1], "delegate"))
type = TPM_RT_DELEGATE;
- else if (strcasecmp(argv[1], "daa_tpm"))
+ else if (!strcasecmp(argv[1], "daa_tpm"))
type = TPM_RT_DAA_TPM;
- else if (strcasecmp(argv[1], "daa_v0"))
+ else if (!strcasecmp(argv[1], "daa_v0"))
type = TPM_RT_DAA_V0;
- else if (strcasecmp(argv[1], "daa_v1"))
+ else if (!strcasecmp(argv[1], "daa_v1"))
type = TPM_RT_DAA_V1;
- if (strcasecmp(argv[2], "all")) {
+ if (!type) {
+ printf("Resource type %s unknown.\n", argv[1]);
+ return -1;
+ }
+
+ if (!strcasecmp(argv[2], "all")) {
uint16_t res_count;
uint8_t buf[288];
uint8_t *ptr;
@@ -686,8 +730,10 @@ static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
/* fetch list of already loaded resources in the TPM */
err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
sizeof(buf));
- if (err)
+ if (err) {
+ printf("tpm_get_capability returned error %d.\n", err);
return -1;
+ }
res_count = get_unaligned_be16(buf);
ptr = buf + 2;
for (i = 0; i < res_count; ++i, ptr += 4)
@@ -695,8 +741,10 @@ static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
} else {
uint32_t handle = simple_strtoul(argv[2], NULL, 0);
- if (!handle)
+ if (!handle) {
+ printf("Illegal resource handle %s\n", argv[2]);
return -1;
+ }
tpm_flush_specific(cpu_to_be32(handle), type);
}
@@ -704,6 +752,68 @@ static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
}
#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+#ifdef CONFIG_TPM_LIST_RESOURCES
+static int do_tpm_list(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ int type = 0;
+ uint16_t res_count;
+ uint8_t buf[288];
+ uint8_t *ptr;
+ int err;
+ uint i;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp(argv[1], "key"))
+ type = TPM_RT_KEY;
+ else if (!strcasecmp(argv[1], "auth"))
+ type = TPM_RT_AUTH;
+ else if (!strcasecmp(argv[1], "hash"))
+ type = TPM_RT_HASH;
+ else if (!strcasecmp(argv[1], "trans"))
+ type = TPM_RT_TRANS;
+ else if (!strcasecmp(argv[1], "context"))
+ type = TPM_RT_CONTEXT;
+ else if (!strcasecmp(argv[1], "counter"))
+ type = TPM_RT_COUNTER;
+ else if (!strcasecmp(argv[1], "delegate"))
+ type = TPM_RT_DELEGATE;
+ else if (!strcasecmp(argv[1], "daa_tpm"))
+ type = TPM_RT_DAA_TPM;
+ else if (!strcasecmp(argv[1], "daa_v0"))
+ type = TPM_RT_DAA_V0;
+ else if (!strcasecmp(argv[1], "daa_v1"))
+ type = TPM_RT_DAA_V1;
+
+ if (!type) {
+ printf("Resource type %s unknown.\n", argv[1]);
+ return -1;
+ }
+
+ /* fetch list of already loaded resources in the TPM */
+ err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
+ sizeof(buf));
+ if (err) {
+ printf("tpm_get_capability returned error %d.\n", err);
+ return -1;
+ }
+ res_count = get_unaligned_be16(buf);
+ ptr = buf + 2;
+
+ printf("Resources of type %s (%02x):\n", argv[1], type);
+ if (!res_count) {
+ puts("None\n");
+ } else {
+ for (i = 0; i < res_count; ++i, ptr += 4)
+ printf("Index %d: %08x\n", i, get_unaligned_be32(ptr));
+ }
+
+ return 0;
+}
+#endif /* CONFIG_TPM_LIST_RESOURCES */
+
#define MAKE_TPM_CMD_ENTRY(cmd) \
U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
@@ -756,6 +866,10 @@ static cmd_tbl_t tpm_commands[] = {
do_tpm_end_oiap, "", ""),
U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
do_tpm_load_key2_oiap, "", ""),
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+ U_BOOT_CMD_MKENT(load_key_by_sha1, 0, 1,
+ do_tpm_load_key_by_sha1, "", ""),
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
do_tpm_get_pub_key_oiap, "", ""),
#endif /* CONFIG_TPM_AUTH_SESSIONS */
@@ -763,6 +877,10 @@ static cmd_tbl_t tpm_commands[] = {
U_BOOT_CMD_MKENT(flush, 0, 1,
do_tpm_flush, "", ""),
#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+#ifdef CONFIG_TPM_LIST_RESOURCES
+ U_BOOT_CMD_MKENT(list, 0, 1,
+ do_tpm_list, "", ""),
+#endif /* CONFIG_TPM_LIST_RESOURCES */
};
static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -812,20 +930,34 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
" get_capability cap_area sub_cap addr count\n"
" - Read <count> bytes of TPM capability indexed by <cap_area> and\n"
" <sub_cap> to memory address <addr>.\n"
-#ifdef CONFIG_TPM_FLUSH_RESOURCES
+#if defined(CONFIG_TPM_FLUSH_RESOURCES) || defined(CONFIG_TPM_LIST_RESOURCES)
"Resource management functions\n"
+#endif
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
" flush resource_type id\n"
" - flushes a resource of type <resource_type> (may be one of key, auth,\n"
" hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
" and id <id> from the TPM. Use an <id> of \"all\" to flush all\n"
" resources of that type.\n"
#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+#ifdef CONFIG_TPM_LIST_RESOURCES
+" list resource_type\n"
+" - lists resources of type <resource_type> (may be one of key, auth,\n"
+" hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
+" contained in the TPM.\n"
+#endif /* CONFIG_TPM_LIST_RESOURCES */
#ifdef CONFIG_TPM_AUTH_SESSIONS
"Storage functions\n"
" loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
" - loads a key data from memory address <key_addr>, <key_len> bytes\n"
" into TPM using the parent key <parent_handle> with authorization\n"
" <usage_auth> (20 bytes hex string).\n"
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+" load_key_by_sha1 parent_hash key_addr key_len usage_auth\n"
+" - loads a key data from memory address <key_addr>, <key_len> bytes\n"
+" into TPM using the parent hash <parent_hash> (20 bytes hex string)\n"
+" with authorization <usage_auth> (20 bytes hex string).\n"
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
" get_pub_key_oiap key_handle usage_auth\n"
" - get the public key portion of a loaded key <key_handle> using\n"
" authorization <usage auth> (20 bytes hex string)\n"
diff --git a/common/board_r.c b/common/board_r.c
index 5c9e698..3344913 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -426,6 +426,7 @@ static int initr_nand(void)
{
puts("NAND: ");
nand_init();
+ printf("%lu MiB\n", nand_size() / 1024);
return 0;
}
#endif
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 55d4d6f..c6a76b7 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -482,7 +482,6 @@ void fdt_fixup_ethernet(void *fdt)
/* Cycle through all aliases */
for (prop = 0; ; prop++) {
const char *name;
- int len = strlen("ethernet");
/* FDT might have been edited, recompute the offset */
offset = fdt_first_property_offset(fdt,
@@ -495,8 +494,13 @@ void fdt_fixup_ethernet(void *fdt)
break;
path = fdt_getprop_by_offset(fdt, offset, &name, NULL);
- if (!strncmp(name, "ethernet", len)) {
- i = trailing_strtol(name);
+ if (!strncmp(name, "ethernet", 8)) {
+ /* Treat plain "ethernet" same as "ethernet0". */
+ if (!strcmp(name, "ethernet"))
+ i = 0;
+ else
+ i = trailing_strtol(name);
+
if (i != -1) {
if (i == 0)
strcpy(mac, "ethaddr");
diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
index 1cd3f1f..6634139 100644
--- a/configs/A10-OLinuXino-Lime_defconfig
+++ b/configs/A10-OLinuXino-Lime_defconfig
@@ -14,6 +14,10 @@ CONFIG_SPL_I2C_SUPPORT=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_FPGA is not set
+CONFIG_NET_ETHADDR_EEPROM=y
+CONFIG_NET_ETHADDR_EEPROM_I2C=y
+CONFIG_NET_ETHADDR_EEPROM_I2C_BUS=1
+CONFIG_I2C1_ENABLE=y
# CONFIG_SPL_DOS_PARTITION is not set
# CONFIG_SPL_ISO_PARTITION is not set
# CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index a4ade72..4c720b3 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -21,6 +21,10 @@ CONFIG_CMD_USB_MASS_STORAGE=y
# CONFIG_SPL_PARTITION_UUIDS is not set
CONFIG_DFU_RAM=y
CONFIG_ETH_DESIGNWARE=y
+CONFIG_NET_ETHADDR_EEPROM=y
+CONFIG_NET_ETHADDR_EEPROM_I2C=y
+CONFIG_NET_ETHADDR_EEPROM_I2C_BUS=1
+CONFIG_I2C1_ENABLE=y
CONFIG_AXP_ALDO3_VOLT=2800
CONFIG_AXP_ALDO4_VOLT=2800
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index 4fe4e4a..564ae25 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -16,6 +16,10 @@ CONFIG_SPL_I2C_SUPPORT=y
# CONFIG_SPL_ISO_PARTITION is not set
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_ETH_DESIGNWARE=y
+CONFIG_NET_ETHADDR_EEPROM=y
+CONFIG_NET_ETHADDR_EEPROM_I2C=y
+CONFIG_NET_ETHADDR_EEPROM_I2C_BUS=1
+CONFIG_I2C1_ENABLE=y
CONFIG_AXP_ALDO3_VOLT=2800
CONFIG_AXP_ALDO4_VOLT=2800
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index e1d91e3..93be13b 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -19,6 +19,10 @@ CONFIG_SPL_I2C_SUPPORT=y
# CONFIG_SPL_ISO_PARTITION is not set
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_ETH_DESIGNWARE=y
+CONFIG_NET_ETHADDR_EEPROM=y
+CONFIG_NET_ETHADDR_EEPROM_I2C=y
+CONFIG_NET_ETHADDR_EEPROM_I2C_BUS=1
+CONFIG_I2C1_ENABLE=y
CONFIG_AXP_ALDO3_VOLT=2800
CONFIG_AXP_ALDO4_VOLT=2800
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/ls1043ardb_nand_defconfig b/configs/ls1043ardb_nand_defconfig
index 4f4ae5a..ed429cb 100644
--- a/configs/ls1043ardb_nand_defconfig
+++ b/configs/ls1043ardb_nand_defconfig
@@ -9,6 +9,7 @@ CONFIG_SPL_WATCHDOG_SUPPORT=y
CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1043a-rdb"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
+CONFIG_FSL_LS_PPA=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT_PBL,SPL_FSL_PBL,NAND_BOOT"
CONFIG_NAND_BOOT=y
diff --git a/configs/ls1043ardb_sdcard_defconfig b/configs/ls1043ardb_sdcard_defconfig
index e57c42b..02b5b54 100644
--- a/configs/ls1043ardb_sdcard_defconfig
+++ b/configs/ls1043ardb_sdcard_defconfig
@@ -9,6 +9,7 @@ CONFIG_SPL_WATCHDOG_SUPPORT=y
CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1043a-rdb"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
+CONFIG_FSL_LS_PPA=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT_PBL,SPL_FSL_PBL,SD_BOOT"
CONFIG_SD_BOOT=y
diff --git a/configs/ls1046ardb_emmc_defconfig b/configs/ls1046ardb_emmc_defconfig
index 9beb050..711fc10 100644
--- a/configs/ls1046ardb_emmc_defconfig
+++ b/configs/ls1046ardb_emmc_defconfig
@@ -3,6 +3,7 @@ CONFIG_TARGET_LS1046ARDB=y
CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1046a-rdb"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
+CONFIG_FSL_LS_PPA=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT_PBL,SPL_FSL_PBL,EMMC_BOOT"
CONFIG_SD_BOOT=y
diff --git a/configs/ls1046ardb_sdcard_defconfig b/configs/ls1046ardb_sdcard_defconfig
index 032aab3..a3965f2 100644
--- a/configs/ls1046ardb_sdcard_defconfig
+++ b/configs/ls1046ardb_sdcard_defconfig
@@ -3,6 +3,7 @@ CONFIG_TARGET_LS1046ARDB=y
CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1046a-rdb"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
+CONFIG_FSL_LS_PPA=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT_PBL,SPL_FSL_PBL"
CONFIG_SD_BOOT=y
diff --git a/configs/ls2080aqds_defconfig b/configs/ls2080aqds_defconfig
index 0344d5f..fb9a3e4 100644
--- a/configs/ls2080aqds_defconfig
+++ b/configs/ls2080aqds_defconfig
@@ -1,5 +1,6 @@
CONFIG_ARM=y
CONFIG_TARGET_LS2080AQDS=y
+CONFIG_FSL_LS_PPA=y
CONFIG_DEFAULT_DEVICE_TREE="fsl-ls2080a-qds"
# CONFIG_SYS_MALLOC_F is not set
CONFIG_FIT=y
diff --git a/configs/ls2080ardb_defconfig b/configs/ls2080ardb_defconfig
index c4d8204..a1e552d 100644
--- a/configs/ls2080ardb_defconfig
+++ b/configs/ls2080ardb_defconfig
@@ -1,5 +1,6 @@
CONFIG_ARM=y
CONFIG_TARGET_LS2080ARDB=y
+CONFIG_FSL_LS_PPA=y
CONFIG_DEFAULT_DEVICE_TREE="fsl-ls2080a-rdb"
# CONFIG_SYS_MALLOC_F is not set
CONFIG_FIT=y
diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig
index f20158a..797eabb 100644
--- a/configs/mvebu_db-88f7040_defconfig
+++ b/configs/mvebu_db-88f7040_defconfig
@@ -47,7 +47,8 @@ CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
+CONFIG_PHY_MARVELL=y
+CONFIG_MVPP2=y
CONFIG_PCI=y
CONFIG_DM_PCI=y
CONFIG_PCIE_DW_MVEBU=y
diff --git a/configs/mvebu_db-88f8040_defconfig b/configs/mvebu_db-88f8040_defconfig
index 3611b84..046da09 100644
--- a/configs/mvebu_db-88f8040_defconfig
+++ b/configs/mvebu_db-88f8040_defconfig
@@ -47,7 +47,8 @@ CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
+CONFIG_PHY_MARVELL=y
+CONFIG_MVPP2=y
CONFIG_PCI=y
CONFIG_DM_PCI=y
CONFIG_PCIE_DW_MVEBU=y
diff --git a/doc/device-tree-bindings/net/fixed-link.txt b/doc/device-tree-bindings/net/fixed-link.txt
new file mode 100644
index 0000000..5829bd8
--- /dev/null
+++ b/doc/device-tree-bindings/net/fixed-link.txt
@@ -0,0 +1,30 @@
+Fixed link Device Tree binding
+------------------------------
+
+Some Ethernet MACs have a "fixed link", and are not connected to a
+normal MDIO-managed PHY device. For those situations, a Device Tree
+binding allows to describe a "fixed link".
+
+Such a fixed link situation is described by creating a 'fixed-link'
+sub-node of the Ethernet MAC device node, with the following
+properties:
+
+* 'speed' (integer, mandatory), to indicate the link speed. Accepted
+ values are 10, 100 and 1000
+* 'full-duplex' (boolean, optional), to indicate that full duplex is
+ used. When absent, half duplex is assumed.
+* 'pause' (boolean, optional), to indicate that pause should be
+ enabled.
+* 'asym-pause' (boolean, optional), to indicate that asym_pause should
+ be enabled.
+
+Examples:
+
+ethernet@0 {
+ ...
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ ...
+};
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 8ac7aaf..4e9afc1 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -49,6 +49,20 @@ config I2C_CROS_EC_LDO
avoid duplicating the logic in the TPS65090 regulator driver for
enabling/disabling an LDO.
+config I2C_SET_DEFAULT_BUS_NUM
+ bool "Set default I2C bus number"
+ depends on DM_I2C
+ help
+ Set default number of I2C bus to be accessed. This option provides
+ behaviour similar to old (i.e. pre DM) I2C bus driver.
+
+config I2C_DEFAULT_BUS_NUMBER
+ hex "I2C default bus number"
+ depends on I2C_SET_DEFAULT_BUS_NUM
+ default 0x0
+ help
+ Number of default I2C bus to use
+
config DM_I2C_GPIO
bool "Enable Driver Model for software emulated I2C bus driver"
depends on DM_I2C && DM_GPIO
diff --git a/drivers/i2c/lpc32xx_i2c.c b/drivers/i2c/lpc32xx_i2c.c
index b0167ab..661d031 100644
--- a/drivers/i2c/lpc32xx_i2c.c
+++ b/drivers/i2c/lpc32xx_i2c.c
@@ -5,9 +5,6 @@
* Written-by: Albert ARIBAUD - 3ADEV <albert.aribaud@3adev.fr>
*
* SPDX-License-Identifier: GPL-2.0+
- *
- * NOTE: This driver should be converted to driver model before June 2017.
- * Please see doc/driver-model/i2c-howto.txt for instructions.
*/
#include <common.h>
@@ -15,6 +12,9 @@
#include <i2c.h>
#include <linux/errno.h>
#include <asm/arch/clk.h>
+#include <asm/arch/i2c.h>
+#include <dm.h>
+#include <mapmem.h>
/*
* Provide default speed and slave if target did not
@@ -28,25 +28,6 @@
#define CONFIG_SYS_I2C_LPC32XX_SLAVE 0
#endif
-/* i2c register set */
-struct lpc32xx_i2c_registers {
- union {
- u32 rx;
- u32 tx;
- };
- u32 stat;
- u32 ctrl;
- u32 clk_hi;
- u32 clk_lo;
- u32 adr;
- u32 rxfl;
- u32 txfl;
- u32 rxb;
- u32 txb;
- u32 stx;
- u32 stxfl;
-};
-
/* TX register fields */
#define LPC32XX_I2C_TX_START 0x00000100
#define LPC32XX_I2C_TX_STOP 0x00000200
@@ -61,15 +42,17 @@ struct lpc32xx_i2c_registers {
#define LPC32XX_I2C_STAT_NAI 0x00000004
#define LPC32XX_I2C_STAT_TDI 0x00000001
-static struct lpc32xx_i2c_registers *lpc32xx_i2c[] = {
- (struct lpc32xx_i2c_registers *)I2C1_BASE,
- (struct lpc32xx_i2c_registers *)I2C2_BASE,
- (struct lpc32xx_i2c_registers *)(USB_BASE + 0x300)
+#ifndef CONFIG_DM_I2C
+static struct lpc32xx_i2c_base *lpc32xx_i2c[] = {
+ (struct lpc32xx_i2c_base *)I2C1_BASE,
+ (struct lpc32xx_i2c_base *)I2C2_BASE,
+ (struct lpc32xx_i2c_base *)(USB_BASE + 0x300)
};
+#endif
/* Set I2C bus speed */
-static unsigned int lpc32xx_i2c_set_bus_speed(struct i2c_adapter *adap,
- unsigned int speed)
+static unsigned int __i2c_set_bus_speed(struct lpc32xx_i2c_base *base,
+ unsigned int speed, unsigned int chip)
{
int half_period;
@@ -77,7 +60,7 @@ static unsigned int lpc32xx_i2c_set_bus_speed(struct i2c_adapter *adap,
return -EINVAL;
/* OTG I2C clock source and CLK registers are different */
- if (adap->hwadapnr == 2) {
+ if (chip == 2) {
half_period = (get_periph_clk_rate() / speed) / 2;
if (half_period > 0xFF)
return -EINVAL;
@@ -87,38 +70,35 @@ static unsigned int lpc32xx_i2c_set_bus_speed(struct i2c_adapter *adap,
return -EINVAL;
}
- writel(half_period, &lpc32xx_i2c[adap->hwadapnr]->clk_hi);
- writel(half_period, &lpc32xx_i2c[adap->hwadapnr]->clk_lo);
+ writel(half_period, &base->clk_hi);
+ writel(half_period, &base->clk_lo);
return 0;
}
/* I2C init called by cmd_i2c when doing 'i2c reset'. */
-static void _i2c_init(struct i2c_adapter *adap,
- int requested_speed, int slaveadd)
+static void __i2c_init(struct lpc32xx_i2c_base *base,
+ int requested_speed, int slaveadd, unsigned int chip)
{
- struct lpc32xx_i2c_registers *i2c = lpc32xx_i2c[adap->hwadapnr];
-
/* soft reset (auto-clears) */
- writel(LPC32XX_I2C_SOFT_RESET, &i2c->ctrl);
+ writel(LPC32XX_I2C_SOFT_RESET, &base->ctrl);
/* set HI and LO periods for half of the default speed */
- lpc32xx_i2c_set_bus_speed(adap, requested_speed);
+ __i2c_set_bus_speed(base, requested_speed, chip);
}
/* I2C probe called by cmd_i2c when doing 'i2c probe'. */
-static int lpc32xx_i2c_probe(struct i2c_adapter *adap, u8 dev)
+static int __i2c_probe_chip(struct lpc32xx_i2c_base *base, u8 dev)
{
- struct lpc32xx_i2c_registers *i2c = lpc32xx_i2c[adap->hwadapnr];
int stat;
/* Soft-reset the controller */
- writel(LPC32XX_I2C_SOFT_RESET, &i2c->ctrl);
- while (readl(&i2c->ctrl) & LPC32XX_I2C_SOFT_RESET)
+ writel(LPC32XX_I2C_SOFT_RESET, &base->ctrl);
+ while (readl(&base->ctrl) & LPC32XX_I2C_SOFT_RESET)
;
/* Addre slave for write with start before and stop after */
writel((dev<<1) | LPC32XX_I2C_TX_START | LPC32XX_I2C_TX_STOP,
- &i2c->tx);
+ &base->tx);
/* wait for end of transation */
- while (!((stat = readl(&i2c->stat)) & LPC32XX_I2C_STAT_TDI))
+ while (!((stat = readl(&base->stat)) & LPC32XX_I2C_STAT_TDI))
;
/* was there no acknowledge? */
return (stat & LPC32XX_I2C_STAT_NAI) ? -1 : 0;
@@ -128,20 +108,19 @@ static int lpc32xx_i2c_probe(struct i2c_adapter *adap, u8 dev)
* I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c
* Begin write, send address byte(s), begin read, receive data bytes, end.
*/
-static int lpc32xx_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
- int alen, u8 *data, int length)
+static int __i2c_read(struct lpc32xx_i2c_base *base, u8 dev, uint addr,
+ int alen, u8 *data, int length)
{
- struct lpc32xx_i2c_registers *i2c = lpc32xx_i2c[adap->hwadapnr];
int stat, wlen;
/* Soft-reset the controller */
- writel(LPC32XX_I2C_SOFT_RESET, &i2c->ctrl);
- while (readl(&i2c->ctrl) & LPC32XX_I2C_SOFT_RESET)
+ writel(LPC32XX_I2C_SOFT_RESET, &base->ctrl);
+ while (readl(&base->ctrl) & LPC32XX_I2C_SOFT_RESET)
;
/* do we need to write an address at all? */
if (alen) {
/* Address slave in write mode */
- writel((dev<<1) | LPC32XX_I2C_TX_START, &i2c->tx);
+ writel((dev<<1) | LPC32XX_I2C_TX_START, &base->tx);
/* write address bytes */
while (alen--) {
/* compute address byte + stop for the last one */
@@ -149,44 +128,44 @@ static int lpc32xx_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
if (!alen)
a |= LPC32XX_I2C_TX_STOP;
/* Send address byte */
- writel(a, &i2c->tx);
+ writel(a, &base->tx);
}
/* wait for end of transation */
- while (!((stat = readl(&i2c->stat)) & LPC32XX_I2C_STAT_TDI))
+ while (!((stat = readl(&base->stat)) & LPC32XX_I2C_STAT_TDI))
;
/* clear end-of-transaction flag */
- writel(1, &i2c->stat);
+ writel(1, &base->stat);
}
/* do we have to read data at all? */
if (length) {
/* Address slave in read mode */
- writel(1 | (dev<<1) | LPC32XX_I2C_TX_START, &i2c->tx);
+ writel(1 | (dev<<1) | LPC32XX_I2C_TX_START, &base->tx);
wlen = length;
/* get data */
while (length | wlen) {
/* read status for TFF and RFE */
- stat = readl(&i2c->stat);
+ stat = readl(&base->stat);
/* must we, can we write a trigger byte? */
if ((wlen > 0)
& (!(stat & LPC32XX_I2C_STAT_TFF))) {
wlen--;
/* write trigger byte + stop if last */
writel(wlen ? 0 :
- LPC32XX_I2C_TX_STOP, &i2c->tx);
+ LPC32XX_I2C_TX_STOP, &base->tx);
}
/* must we, can we read a data byte? */
if ((length > 0)
& (!(stat & LPC32XX_I2C_STAT_RFE))) {
length--;
/* read byte */
- *(data++) = readl(&i2c->rx);
+ *(data++) = readl(&base->rx);
}
}
/* wait for end of transation */
- while (!((stat = readl(&i2c->stat)) & LPC32XX_I2C_STAT_TDI))
+ while (!((stat = readl(&base->stat)) & LPC32XX_I2C_STAT_TDI))
;
/* clear end-of-transaction flag */
- writel(1, &i2c->stat);
+ writel(1, &base->stat);
}
/* success */
return 0;
@@ -196,38 +175,37 @@ static int lpc32xx_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
* I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c
* Begin write, send address byte(s), send data bytes, end.
*/
-static int lpc32xx_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
- int alen, u8 *data, int length)
+static int __i2c_write(struct lpc32xx_i2c_base *base, u8 dev, uint addr,
+ int alen, u8 *data, int length)
{
- struct lpc32xx_i2c_registers *i2c = lpc32xx_i2c[adap->hwadapnr];
int stat;
/* Soft-reset the controller */
- writel(LPC32XX_I2C_SOFT_RESET, &i2c->ctrl);
- while (readl(&i2c->ctrl) & LPC32XX_I2C_SOFT_RESET)
+ writel(LPC32XX_I2C_SOFT_RESET, &base->ctrl);
+ while (readl(&base->ctrl) & LPC32XX_I2C_SOFT_RESET)
;
/* do we need to write anything at all? */
if (alen | length)
/* Address slave in write mode */
- writel((dev<<1) | LPC32XX_I2C_TX_START, &i2c->tx);
+ writel((dev<<1) | LPC32XX_I2C_TX_START, &base->tx);
else
return 0;
/* write address bytes */
while (alen) {
/* wait for transmit fifo not full */
- stat = readl(&i2c->stat);
+ stat = readl(&base->stat);
if (!(stat & LPC32XX_I2C_STAT_TFF)) {
alen--;
int a = (addr >> (8 * alen)) & 0xff;
if (!(alen | length))
a |= LPC32XX_I2C_TX_STOP;
/* Send address byte */
- writel(a, &i2c->tx);
+ writel(a, &base->tx);
}
}
while (length) {
/* wait for transmit fifo not full */
- stat = readl(&i2c->stat);
+ stat = readl(&base->stat);
if (!(stat & LPC32XX_I2C_STAT_TFF)) {
/* compute data byte, add stop if length==0 */
length--;
@@ -235,34 +213,146 @@ static int lpc32xx_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
if (!length)
d |= LPC32XX_I2C_TX_STOP;
/* Send data byte */
- writel(d, &i2c->tx);
+ writel(d, &base->tx);
}
}
/* wait for end of transation */
- while (!((stat = readl(&i2c->stat)) & LPC32XX_I2C_STAT_TDI))
+ while (!((stat = readl(&base->stat)) & LPC32XX_I2C_STAT_TDI))
;
/* clear end-of-transaction flag */
- writel(1, &i2c->stat);
+ writel(1, &base->stat);
return 0;
}
-U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_0, _i2c_init, lpc32xx_i2c_probe,
+#ifndef CONFIG_DM_I2C
+static void lpc32xx_i2c_init(struct i2c_adapter *adap,
+ int requested_speed, int slaveadd)
+{
+ __i2c_init(lpc32xx_i2c[adap->hwadapnr], requested_speed, slaveadd,
+ adap->hwadapnr);
+}
+
+static int lpc32xx_i2c_probe_chip(struct i2c_adapter *adap, u8 dev)
+{
+ return __i2c_probe_chip(lpc32xx_i2c[adap->hwadapnr], dev);
+}
+
+static int lpc32xx_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
+ int alen, u8 *data, int length)
+{
+ return __i2c_read(lpc32xx_i2c[adap->hwadapnr], dev, addr,
+ alen, data, length);
+}
+
+static int lpc32xx_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
+ int alen, u8 *data, int length)
+{
+ return __i2c_write(lpc32xx_i2c[adap->hwadapnr], dev, addr,
+ alen, data, length);
+}
+
+static unsigned int lpc32xx_i2c_set_bus_speed(struct i2c_adapter *adap,
+ unsigned int speed)
+{
+ return __i2c_set_bus_speed(lpc32xx_i2c[adap->hwadapnr], speed,
+ adap->hwadapnr);
+}
+
+U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_0, lpc32xx_i2c_init, lpc32xx_i2c_probe_chip,
lpc32xx_i2c_read, lpc32xx_i2c_write,
lpc32xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_LPC32XX_SPEED,
CONFIG_SYS_I2C_LPC32XX_SLAVE,
0)
-U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_1, _i2c_init, lpc32xx_i2c_probe,
+U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_1, lpc32xx_i2c_init, lpc32xx_i2c_probe_chip,
lpc32xx_i2c_read, lpc32xx_i2c_write,
lpc32xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_LPC32XX_SPEED,
CONFIG_SYS_I2C_LPC32XX_SLAVE,
1)
-U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_2, _i2c_init, NULL,
+U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_2, lpc32xx_i2c_init, NULL,
lpc32xx_i2c_read, lpc32xx_i2c_write,
lpc32xx_i2c_set_bus_speed,
100000,
0,
2)
+#else /* CONFIG_DM_I2C */
+static int lpc32xx_i2c_probe(struct udevice *bus)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+ bus->seq = dev->index;
+
+ __i2c_init(dev->base, dev->speed, 0, dev->index);
+ return 0;
+}
+
+static int lpc32xx_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
+ u32 chip_flags)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+ return __i2c_probe_chip(dev->base, chip_addr);
+}
+
+static int lpc32xx_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+ int nmsgs)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+ struct i2c_msg *dmsg, *omsg, dummy;
+ uint i = 0, address = 0;
+
+ memset(&dummy, 0, sizeof(struct i2c_msg));
+
+ /* We expect either two messages (one with an offset and one with the
+ * actual data) or one message (just data)
+ */
+ if (nmsgs > 2 || nmsgs == 0) {
+ debug("%s: Only one or two messages are supported.", __func__);
+ return -1;
+ }
+
+ omsg = nmsgs == 1 ? &dummy : msg;
+ dmsg = nmsgs == 1 ? msg : msg + 1;
+
+ /* the address is expected to be a uint, not a array. */
+ address = omsg->buf[0];
+ for (i = 1; i < omsg->len; i++)
+ address = (address << 8) + omsg->buf[i];
+
+ if (dmsg->flags & I2C_M_RD)
+ return __i2c_read(dev->base, dmsg->addr, address,
+ omsg->len, dmsg->buf, dmsg->len);
+ else
+ return __i2c_write(dev->base, dmsg->addr, address,
+ omsg->len, dmsg->buf, dmsg->len);
+}
+
+static int lpc32xx_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+ return __i2c_set_bus_speed(dev->base, speed, dev->index);
+}
+
+static int lpc32xx_i2c_reset(struct udevice *bus)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+
+ __i2c_init(dev->base, dev->speed, 0, dev->index);
+ return 0;
+}
+
+static const struct dm_i2c_ops lpc32xx_i2c_ops = {
+ .xfer = lpc32xx_i2c_xfer,
+ .probe_chip = lpc32xx_i2c_probe_chip,
+ .deblock = lpc32xx_i2c_reset,
+ .set_bus_speed = lpc32xx_i2c_set_bus_speed,
+};
+
+U_BOOT_DRIVER(i2c_lpc32xx) = {
+ .id = UCLASS_I2C,
+ .name = "i2c_lpc32xx",
+ .probe = lpc32xx_i2c_probe,
+ .ops = &lpc32xx_i2c_ops,
+};
+#endif /* CONFIG_DM_I2C */
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 0006343..26996e9 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -64,36 +64,52 @@ struct omap_i2c {
static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
{
- unsigned int sampleclk, prescaler;
- int fsscll, fssclh;
+ unsigned long internal_clk = 0, fclk;
+ unsigned int prescaler;
- speed <<= 1;
- prescaler = 0;
/*
- * some divisors may cause a precission loss, but shouldn't
- * be a big thing, because i2c_clk is then allready very slow.
+ * This method is only called for Standard and Fast Mode speeds
+ *
+ * For some TI SoCs it is explicitly written in TRM (e,g, SPRUHZ6G,
+ * page 5685, Table 24-7)
+ * that the internal I2C clock (after prescaler) should be between
+ * 7-12 MHz (at least for Fast Mode (FS)).
+ *
+ * Such approach is used in v4.9 Linux kernel in:
+ * ./drivers/i2c/busses/i2c-omap.c (omap_i2c_init function).
*/
- while (prescaler <= 0xFF) {
- sampleclk = I2C_IP_CLK / (prescaler+1);
- fsscll = sampleclk / speed;
- fssclh = fsscll;
- fsscll -= I2C_FASTSPEED_SCLL_TRIM;
- fssclh -= I2C_FASTSPEED_SCLH_TRIM;
-
- if (((fsscll > 0) && (fssclh > 0)) &&
- ((fsscll <= (255-I2C_FASTSPEED_SCLL_TRIM)) &&
- (fssclh <= (255-I2C_FASTSPEED_SCLH_TRIM)))) {
- if (pscl)
- *pscl = fsscll;
- if (psch)
- *psch = fssclh;
-
- return prescaler;
- }
- prescaler++;
+ speed /= 1000; /* convert speed to kHz */
+
+ if (speed > 100)
+ internal_clk = 9600;
+ else
+ internal_clk = 4000;
+
+ fclk = I2C_IP_CLK / 1000;
+ prescaler = fclk / internal_clk;
+ prescaler = prescaler - 1;
+
+ if (speed > 100) {
+ unsigned long scl;
+
+ /* Fast mode */
+ scl = internal_clk / speed;
+ *pscl = scl - (scl / 3) - I2C_FASTSPEED_SCLL_TRIM;
+ *psch = (scl / 3) - I2C_FASTSPEED_SCLH_TRIM;
+ } else {
+ /* Standard mode */
+ *pscl = internal_clk / (speed * 2) - I2C_FASTSPEED_SCLL_TRIM;
+ *psch = internal_clk / (speed * 2) - I2C_FASTSPEED_SCLH_TRIM;
}
- return -1;
+
+ debug("%s: speed [kHz]: %d psc: 0x%x sscl: 0x%x ssch: 0x%x\n",
+ __func__, speed, prescaler, *pscl, *psch);
+
+ if (*pscl <= 0 || *psch <= 0 || prescaler <= 0)
+ return -EINVAL;
+
+ return prescaler;
}
/*
diff --git a/drivers/i2c/omap24xx_i2c.h b/drivers/i2c/omap24xx_i2c.h
index 3dae295..8a4ae98 100644
--- a/drivers/i2c/omap24xx_i2c.h
+++ b/drivers/i2c/omap24xx_i2c.h
@@ -121,17 +121,17 @@
* scll_trim = 7
* sclh_trim = 5
*
- * The linux 2.6.30 kernel uses
- * scll_trim = 6
- * sclh_trim = 6
+ * The linux 4.9 kernel uses
+ * scll_trim = 7
+ * sclh_trim = 5
*
* These are the trim values for standard and fast speed
*/
#ifndef I2C_FASTSPEED_SCLL_TRIM
-#define I2C_FASTSPEED_SCLL_TRIM 6
+#define I2C_FASTSPEED_SCLL_TRIM 7
#endif
#ifndef I2C_FASTSPEED_SCLH_TRIM
-#define I2C_FASTSPEED_SCLH_TRIM 6
+#define I2C_FASTSPEED_SCLH_TRIM 5
#endif
/* These are the trim values for high speed */
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 7ed5328..83dda09 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -56,9 +56,16 @@ DECLARE_GLOBAL_DATA_PTR;
#define SYSCTL_SRC (1 << 25)
#define SYSCTL_SRD (1 << 26)
+struct omap_hsmmc_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
struct omap_hsmmc_data {
struct hsmmc *base_addr;
+#ifndef CONFIG_DM_MMC
struct mmc_config cfg;
+#endif
#ifdef OMAP_HSMMC_USE_GPIO
#ifdef CONFIG_DM_MMC
struct gpio_desc cd_gpio; /* Change Detect GPIO */
@@ -78,7 +85,25 @@ static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
unsigned int siz);
-#if defined(OMAP_HSMMC_USE_GPIO) && !defined(CONFIG_DM_MMC)
+static inline struct omap_hsmmc_data *omap_hsmmc_get_data(struct mmc *mmc)
+{
+#ifdef CONFIG_DM_MMC
+ return dev_get_priv(mmc->dev);
+#else
+ return (struct omap_hsmmc_data *)mmc->priv;
+#endif
+}
+static inline struct mmc_config *omap_hsmmc_get_cfg(struct mmc *mmc)
+{
+#ifdef CONFIG_DM_MMC
+ struct omap_hsmmc_plat *plat = dev_get_platdata(mmc->dev);
+ return &plat->cfg;
+#else
+ return &((struct omap_hsmmc_data *)mmc->priv)->cfg;
+#endif
+}
+
+ #if defined(OMAP_HSMMC_USE_GPIO) && !defined(CONFIG_DM_MMC)
static int omap_mmc_setup_gpio_in(int gpio, const char *label)
{
int ret;
@@ -102,6 +127,7 @@ static int omap_mmc_setup_gpio_in(int gpio, const char *label)
static unsigned char mmc_board_init(struct mmc *mmc)
{
#if defined(CONFIG_OMAP34XX)
+ struct mmc_config *cfg = omap_hsmmc_get_cfg(mmc);
t2_t *t2_base = (t2_t *)T2_BASE;
struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
u32 pbias_lite;
@@ -142,7 +168,7 @@ static unsigned char mmc_board_init(struct mmc *mmc)
&t2_base->devconf1);
/* Change from default of 52MHz to 26MHz if necessary */
- if (!(mmc->cfg->host_caps & MMC_MODE_HS_52MHz))
+ if (!(cfg->host_caps & MMC_MODE_HS_52MHz))
writel(readl(&t2_base->ctl_prog_io1) & ~CTLPROGIO1SPEEDCTRL,
&t2_base->ctl_prog_io1);
@@ -157,7 +183,7 @@ static unsigned char mmc_board_init(struct mmc *mmc)
#if defined(CONFIG_OMAP54XX) || defined(CONFIG_OMAP44XX)
/* PBIAS config needed for MMC1 only */
- if (mmc->block_dev.devnum == 0)
+ if (mmc_get_blk_desc(mmc)->devnum == 0)
vmmc_pbias_config(LDO_VOLT_3V0);
#endif
@@ -194,12 +220,13 @@ void mmc_init_stream(struct hsmmc *mmc_base)
static int omap_hsmmc_init_setup(struct mmc *mmc)
{
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
struct hsmmc *mmc_base;
unsigned int reg_val;
unsigned int dsor;
ulong start;
- mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
+ mmc_base = priv->base_addr;
mmc_board_init(mmc);
writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET,
@@ -304,11 +331,12 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit)
static int omap_hsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
struct hsmmc *mmc_base;
unsigned int flags, mmc_stat;
ulong start;
- mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
+ mmc_base = priv->base_addr;
start = get_timer(0);
while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK)) != 0) {
if (get_timer(0) - start > MAX_RETRY_MS) {
@@ -533,11 +561,12 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
static int omap_hsmmc_set_ios(struct mmc *mmc)
{
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
struct hsmmc *mmc_base;
unsigned int dsor = 0;
ulong start;
- mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
+ mmc_base = priv->base_addr;
/* configue bus width */
switch (mmc->bus_width) {
case 8:
@@ -591,7 +620,7 @@ static int omap_hsmmc_set_ios(struct mmc *mmc)
#ifdef CONFIG_DM_MMC
static int omap_hsmmc_getcd(struct mmc *mmc)
{
- struct omap_hsmmc_data *priv = mmc->priv;
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
int value;
value = dm_gpio_get_value(&priv->cd_gpio);
@@ -606,7 +635,7 @@ static int omap_hsmmc_getcd(struct mmc *mmc)
static int omap_hsmmc_getwp(struct mmc *mmc)
{
- struct omap_hsmmc_data *priv = mmc->priv;
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
int value;
value = dm_gpio_get_value(&priv->wp_gpio);
@@ -618,11 +647,11 @@ static int omap_hsmmc_getwp(struct mmc *mmc)
#else
static int omap_hsmmc_getcd(struct mmc *mmc)
{
- struct omap_hsmmc_data *priv_data = mmc->priv;
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
int cd_gpio;
/* if no CD return as 1 */
- cd_gpio = priv_data->cd_gpio;
+ cd_gpio = priv->cd_gpio;
if (cd_gpio < 0)
return 1;
@@ -632,11 +661,11 @@ static int omap_hsmmc_getcd(struct mmc *mmc)
static int omap_hsmmc_getwp(struct mmc *mmc)
{
- struct omap_hsmmc_data *priv_data = mmc->priv;
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
int wp_gpio;
/* if no WP return as 0 */
- wp_gpio = priv_data->wp_gpio;
+ wp_gpio = priv->wp_gpio;
if (wp_gpio < 0)
return 0;
@@ -661,23 +690,23 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
int wp_gpio)
{
struct mmc *mmc;
- struct omap_hsmmc_data *priv_data;
+ struct omap_hsmmc_data *priv;
struct mmc_config *cfg;
uint host_caps_val;
- priv_data = malloc(sizeof(*priv_data));
- if (priv_data == NULL)
+ priv = malloc(sizeof(*priv));
+ if (priv == NULL)
return -1;
host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS;
switch (dev_index) {
case 0:
- priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
+ priv->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
break;
#ifdef OMAP_HSMMC2_BASE
case 1:
- priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE;
+ priv->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE;
#if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
defined(CONFIG_DRA7XX) || defined(CONFIG_AM33XX) || \
defined(CONFIG_AM43XX) || defined(CONFIG_SOC_KEYSTONE)) && \
@@ -689,7 +718,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
#endif
#ifdef OMAP_HSMMC3_BASE
case 2:
- priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE;
+ priv->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE;
#if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT)
/* Enable 8-bit interface for eMMC on DRA7XX */
host_caps_val |= MMC_MODE_8BIT;
@@ -697,16 +726,16 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
break;
#endif
default:
- priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
+ priv->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
return 1;
}
#ifdef OMAP_HSMMC_USE_GPIO
/* on error gpio values are set to -1, which is what we want */
- priv_data->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd");
- priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
+ priv->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd");
+ priv->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
#endif
- cfg = &priv_data->cfg;
+ cfg = &priv->cfg;
cfg->name = "OMAP SD/MMC";
cfg->ops = &omap_hsmmc_ops;
@@ -737,7 +766,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21))
cfg->b_max = 1;
#endif
- mmc = mmc_create(cfg, priv_data);
+ mmc = mmc_create(cfg, priv);
if (mmc == NULL)
return -1;
@@ -747,14 +776,14 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)
{
struct omap_hsmmc_data *priv = dev_get_priv(dev);
+ struct omap_hsmmc_plat *plat = dev_get_platdata(dev);
+ struct mmc_config *cfg = &plat->cfg;
const void *fdt = gd->fdt_blob;
int node = dev_of_offset(dev);
- struct mmc_config *cfg;
int val;
priv->base_addr = map_physmem(dev_get_addr(dev), sizeof(struct hsmmc *),
MAP_NOCACHE);
- cfg = &priv->cfg;
cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
val = fdtdec_get_int(fdt, node, "bus-width", -1);
@@ -786,20 +815,33 @@ static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)
return 0;
}
+#ifdef CONFIG_BLK
+
+static int omap_hsmmc_bind(struct udevice *dev)
+{
+ struct omap_hsmmc_plat *plat = dev_get_platdata(dev);
+
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+#endif
static int omap_hsmmc_probe(struct udevice *dev)
{
+ struct omap_hsmmc_plat *plat = dev_get_platdata(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct omap_hsmmc_data *priv = dev_get_priv(dev);
- struct mmc_config *cfg;
+ struct mmc_config *cfg = &plat->cfg;
struct mmc *mmc;
- cfg = &priv->cfg;
cfg->name = "OMAP SD/MMC";
cfg->ops = &omap_hsmmc_ops;
+#ifdef CONFIG_BLK
+ mmc = &plat->mmc;
+#else
mmc = mmc_create(cfg, priv);
if (mmc == NULL)
return -1;
+#endif
#ifdef OMAP_HSMMC_USE_GPIO
gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
@@ -824,7 +866,11 @@ U_BOOT_DRIVER(omap_hsmmc) = {
.id = UCLASS_MMC,
.of_match = omap_hsmmc_ids,
.ofdata_to_platdata = omap_hsmmc_ofdata_to_platdata,
+#ifdef CONFIG_BLK
+ .bind = omap_hsmmc_bind,
+#endif
.probe = omap_hsmmc_probe,
.priv_auto_alloc_size = sizeof(struct omap_hsmmc_data),
+ .platdata_auto_alloc_size = sizeof(struct omap_hsmmc_plat),
};
#endif
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
index 0551241..168bac6 100644
--- a/drivers/mtd/nand/nand.c
+++ b/drivers/mtd/nand/nand.c
@@ -131,8 +131,23 @@ static void create_mtd_concat(void)
}
#endif
+unsigned long nand_size(void)
+{
+ return total_nand_size;
+}
+
void nand_init(void)
{
+ static int initialized;
+
+ /*
+ * Avoid initializing NAND Flash multiple times,
+ * otherwise it will calculate a wrong total size.
+ */
+ if (initialized)
+ return;
+ initialized = 1;
+
#ifdef CONFIG_SYS_NAND_SELF_INIT
board_nand_init();
#else
@@ -142,8 +157,6 @@ void nand_init(void)
nand_init_chip(i);
#endif
- printf("%lu MiB\n", total_nand_size / 1024);
-
#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
/*
* Select the chip in the board/cpu specific driver
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 70e3661..8aa9279 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -124,12 +124,12 @@ config FEC_MXC
NXP i.MX processors.
config MVPP2
- bool "Marvell Armada 375 network interface support"
- depends on ARMADA_375
+ bool "Marvell Armada 375/7K/8K network interface support"
+ depends on ARMADA_375 || ARMADA_8K
select PHYLIB
help
This driver supports the network interface units in the
- Marvell ARMADA 375 SoC.
+ Marvell ARMADA 375, 7K and 8K SoCs.
config MACB
bool "Cadence MACB/GEM Ethernet Interface"
diff --git a/drivers/net/bcm-sf2-eth-gmac.c b/drivers/net/bcm-sf2-eth-gmac.c
index f2853cf..9ff72fa 100644
--- a/drivers/net/bcm-sf2-eth-gmac.c
+++ b/drivers/net/bcm-sf2-eth-gmac.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Broadcom Corporation.
+ * Copyright 2014-2017 Broadcom.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -28,6 +28,10 @@
} \
}
+#define RX_BUF_SIZE_ALIGNED ALIGN(RX_BUF_SIZE, ARCH_DMA_MINALIGN)
+#define TX_BUF_SIZE_ALIGNED ALIGN(TX_BUF_SIZE, ARCH_DMA_MINALIGN)
+#define DESCP_SIZE_ALIGNED ALIGN(sizeof(dma64dd_t), ARCH_DMA_MINALIGN)
+
static int gmac_disable_dma(struct eth_dma *dma, int dir);
static int gmac_enable_dma(struct eth_dma *dma, int dir);
@@ -114,7 +118,7 @@ static void dma_tx_dump(struct eth_dma *dma)
printf("TX Buffers:\n");
/* Initialize TX DMA descriptor table */
for (i = 0; i < TX_BUF_NUM; i++) {
- bufp = (uint8_t *)(dma->tx_buf + i * TX_BUF_SIZE);
+ bufp = (uint8_t *)(dma->tx_buf + i * TX_BUF_SIZE_ALIGNED);
printf("buf%d:0x%x; ", i, (uint32_t)bufp);
}
printf("\n");
@@ -145,7 +149,7 @@ static void dma_rx_dump(struct eth_dma *dma)
printf("RX Buffers:\n");
for (i = 0; i < RX_BUF_NUM; i++) {
- bufp = dma->rx_buf + i * RX_BUF_SIZE;
+ bufp = dma->rx_buf + i * RX_BUF_SIZE_ALIGNED;
printf("buf%d:0x%x; ", i, (uint32_t)bufp);
}
printf("\n");
@@ -163,15 +167,15 @@ static int dma_tx_init(struct eth_dma *dma)
/* clear descriptor memory */
memset((void *)(dma->tx_desc_aligned), 0,
- TX_BUF_NUM * sizeof(dma64dd_t));
- memset(dma->tx_buf, 0, TX_BUF_NUM * TX_BUF_SIZE);
+ TX_BUF_NUM * DESCP_SIZE_ALIGNED);
+ memset(dma->tx_buf, 0, TX_BUF_NUM * TX_BUF_SIZE_ALIGNED);
/* Initialize TX DMA descriptor table */
for (i = 0; i < TX_BUF_NUM; i++) {
descp = (dma64dd_t *)(dma->tx_desc_aligned) + i;
- bufp = dma->tx_buf + i * TX_BUF_SIZE;
+ bufp = dma->tx_buf + i * TX_BUF_SIZE_ALIGNED;
/* clear buffer memory */
- memset((void *)bufp, 0, TX_BUF_SIZE);
+ memset((void *)bufp, 0, TX_BUF_SIZE_ALIGNED);
ctrl = 0;
/* if last descr set endOfTable */
@@ -187,10 +191,11 @@ static int dma_tx_init(struct eth_dma *dma)
descp = dma->tx_desc_aligned;
bufp = dma->tx_buf;
flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp +
- sizeof(dma64dd_t) * TX_BUF_NUM));
- flush_dcache_range((unsigned long)(bufp),
- (unsigned long)(bufp + TX_BUF_SIZE * TX_BUF_NUM));
+ (unsigned long)descp +
+ DESCP_SIZE_ALIGNED * TX_BUF_NUM);
+ flush_dcache_range((unsigned long)bufp,
+ (unsigned long)bufp +
+ TX_BUF_SIZE_ALIGNED * TX_BUF_NUM);
/* initialize the DMA channel */
writel((uint32_t)(dma->tx_desc_aligned), GMAC0_DMA_TX_ADDR_LOW_ADDR);
@@ -215,20 +220,20 @@ static int dma_rx_init(struct eth_dma *dma)
/* clear descriptor memory */
memset((void *)(dma->rx_desc_aligned), 0,
- RX_BUF_NUM * sizeof(dma64dd_t));
+ RX_BUF_NUM * DESCP_SIZE_ALIGNED);
/* clear buffer memory */
- memset(dma->rx_buf, 0, RX_BUF_NUM * RX_BUF_SIZE);
+ memset(dma->rx_buf, 0, RX_BUF_NUM * RX_BUF_SIZE_ALIGNED);
/* Initialize RX DMA descriptor table */
for (i = 0; i < RX_BUF_NUM; i++) {
descp = (dma64dd_t *)(dma->rx_desc_aligned) + i;
- bufp = dma->rx_buf + i * RX_BUF_SIZE;
+ bufp = dma->rx_buf + i * RX_BUF_SIZE_ALIGNED;
ctrl = 0;
/* if last descr set endOfTable */
if (i == (RX_BUF_NUM - 1))
ctrl = D64_CTRL1_EOT;
descp->ctrl1 = ctrl;
- descp->ctrl2 = RX_BUF_SIZE;
+ descp->ctrl2 = RX_BUF_SIZE_ALIGNED;
descp->addrlow = (uint32_t)bufp;
descp->addrhigh = 0;
@@ -240,10 +245,11 @@ static int dma_rx_init(struct eth_dma *dma)
bufp = dma->rx_buf;
/* flush descriptor and buffer */
flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp +
- sizeof(dma64dd_t) * RX_BUF_NUM));
+ (unsigned long)descp +
+ DESCP_SIZE_ALIGNED * RX_BUF_NUM);
flush_dcache_range((unsigned long)(bufp),
- (unsigned long)(bufp + RX_BUF_SIZE * RX_BUF_NUM));
+ (unsigned long)bufp +
+ RX_BUF_SIZE_ALIGNED * RX_BUF_NUM);
/* initailize the DMA channel */
writel((uint32_t)descp, GMAC0_DMA_RX_ADDR_LOW_ADDR);
@@ -292,14 +298,12 @@ static int dma_deinit(struct eth_dma *dma)
free(dma->tx_buf);
dma->tx_buf = NULL;
- free(dma->tx_desc);
- dma->tx_desc = NULL;
+ free(dma->tx_desc_aligned);
dma->tx_desc_aligned = NULL;
free(dma->rx_buf);
dma->rx_buf = NULL;
- free(dma->rx_desc);
- dma->rx_desc = NULL;
+ free(dma->rx_desc_aligned);
dma->rx_desc_aligned = NULL;
return 0;
@@ -307,7 +311,7 @@ static int dma_deinit(struct eth_dma *dma)
int gmac_tx_packet(struct eth_dma *dma, void *packet, int length)
{
- uint8_t *bufp = dma->tx_buf + dma->cur_tx_index * TX_BUF_SIZE;
+ uint8_t *bufp = dma->tx_buf + dma->cur_tx_index * TX_BUF_SIZE_ALIGNED;
/* kick off the dma */
size_t len = length;
@@ -348,10 +352,11 @@ int gmac_tx_packet(struct eth_dma *dma, void *packet, int length)
descp->ctrl2 = ctrl;
/* flush descriptor and buffer */
- flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp + sizeof(dma64dd_t)));
+ flush_dcache_range((unsigned long)dma->tx_desc_aligned,
+ (unsigned long)dma->tx_desc_aligned +
+ DESCP_SIZE_ALIGNED * TX_BUF_NUM);
flush_dcache_range((unsigned long)bufp,
- (unsigned long)(bufp + TX_BUF_SIZE));
+ (unsigned long)bufp + TX_BUF_SIZE_ALIGNED);
/* now update the dma last descriptor */
writel(last_desc, GMAC0_DMA_TX_PTR_ADDR);
@@ -426,14 +431,15 @@ int gmac_check_rx_done(struct eth_dma *dma, uint8_t *buf)
;
/* get the packet pointer that corresponds to the rx descriptor */
- bufp = dma->rx_buf + index * RX_BUF_SIZE;
+ bufp = dma->rx_buf + index * RX_BUF_SIZE_ALIGNED;
descp = (dma64dd_t *)(dma->rx_desc_aligned) + index;
/* flush descriptor and buffer */
- flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp + sizeof(dma64dd_t)));
+ flush_dcache_range((unsigned long)dma->rx_desc_aligned,
+ (unsigned long)dma->rx_desc_aligned +
+ DESCP_SIZE_ALIGNED * RX_BUF_NUM);
flush_dcache_range((unsigned long)bufp,
- (unsigned long)(bufp + RX_BUF_SIZE));
+ (unsigned long)bufp + RX_BUF_SIZE_ALIGNED);
buflen = (descp->ctrl2 & D64_CTRL2_BC_MASK);
@@ -457,12 +463,13 @@ int gmac_check_rx_done(struct eth_dma *dma, uint8_t *buf)
memcpy(buf, datap, rcvlen);
/* update descriptor that is being added back on ring */
- descp->ctrl2 = RX_BUF_SIZE;
+ descp->ctrl2 = RX_BUF_SIZE_ALIGNED;
descp->addrlow = (uint32_t)bufp;
descp->addrhigh = 0;
/* flush descriptor */
- flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp + sizeof(dma64dd_t)));
+ flush_dcache_range((unsigned long)dma->rx_desc_aligned,
+ (unsigned long)dma->rx_desc_aligned +
+ DESCP_SIZE_ALIGNED * RX_BUF_NUM);
/* set the lastdscr for the rx ring */
writel(((uint32_t)descp) & D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR);
@@ -573,7 +580,7 @@ static int gmac_enable_dma(struct eth_dma *dma, int dir)
* set the lastdscr for the rx ring
*/
writel(((uint32_t)(dma->rx_desc_aligned) +
- (RX_BUF_NUM - 1) * RX_BUF_SIZE) &
+ (RX_BUF_NUM - 1) * RX_BUF_SIZE_ALIGNED) &
D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR);
}
@@ -893,54 +900,52 @@ int gmac_add(struct eth_device *dev)
void *tmp;
/*
- * Desc has to be 16-byte aligned ?
- * If it is 8-byte aligned by malloc, fail Tx
+ * Desc has to be 16-byte aligned. But for dcache flush it must be
+ * aligned to ARCH_DMA_MINALIGN.
*/
- tmp = malloc(sizeof(dma64dd_t) * TX_BUF_NUM + 8);
+ tmp = memalign(ARCH_DMA_MINALIGN, DESCP_SIZE_ALIGNED * TX_BUF_NUM);
if (tmp == NULL) {
printf("%s: Failed to allocate TX desc Buffer\n", __func__);
return -1;
}
- dma->tx_desc = (void *)tmp;
- dma->tx_desc_aligned = (void *)(((uint32_t)tmp) & (~0xf));
+ dma->tx_desc_aligned = (void *)tmp;
debug("TX Descriptor Buffer: %p; length: 0x%x\n",
- dma->tx_desc_aligned, sizeof(dma64dd_t) * TX_BUF_NUM);
+ dma->tx_desc_aligned, DESCP_SIZE_ALIGNED * TX_BUF_NUM);
- tmp = malloc(TX_BUF_SIZE * TX_BUF_NUM);
+ tmp = memalign(ARCH_DMA_MINALIGN, TX_BUF_SIZE_ALIGNED * TX_BUF_NUM);
if (tmp == NULL) {
printf("%s: Failed to allocate TX Data Buffer\n", __func__);
- free(dma->tx_desc);
+ free(dma->tx_desc_aligned);
return -1;
}
dma->tx_buf = (uint8_t *)tmp;
debug("TX Data Buffer: %p; length: 0x%x\n",
- dma->tx_buf, TX_BUF_SIZE * TX_BUF_NUM);
+ dma->tx_buf, TX_BUF_SIZE_ALIGNED * TX_BUF_NUM);
- /* Desc has to be 16-byte aligned ? */
- tmp = malloc(sizeof(dma64dd_t) * RX_BUF_NUM + 8);
+ /* Desc has to be 16-byte aligned */
+ tmp = memalign(ARCH_DMA_MINALIGN, DESCP_SIZE_ALIGNED * RX_BUF_NUM);
if (tmp == NULL) {
printf("%s: Failed to allocate RX Descriptor\n", __func__);
- free(dma->tx_desc);
+ free(dma->tx_desc_aligned);
free(dma->tx_buf);
return -1;
}
- dma->rx_desc = tmp;
- dma->rx_desc_aligned = (void *)(((uint32_t)tmp) & (~0xf));
+ dma->rx_desc_aligned = (void *)tmp;
debug("RX Descriptor Buffer: %p, length: 0x%x\n",
- dma->rx_desc_aligned, sizeof(dma64dd_t) * RX_BUF_NUM);
+ dma->rx_desc_aligned, DESCP_SIZE_ALIGNED * RX_BUF_NUM);
- tmp = malloc(RX_BUF_SIZE * RX_BUF_NUM);
+ tmp = memalign(ARCH_DMA_MINALIGN, RX_BUF_SIZE_ALIGNED * RX_BUF_NUM);
if (tmp == NULL) {
printf("%s: Failed to allocate RX Data Buffer\n", __func__);
- free(dma->tx_desc);
+ free(dma->tx_desc_aligned);
free(dma->tx_buf);
- free(dma->rx_desc);
+ free(dma->rx_desc_aligned);
return -1;
}
- dma->rx_buf = tmp;
+ dma->rx_buf = (uint8_t *)tmp;
debug("RX Data Buffer: %p; length: 0x%x\n",
- dma->rx_buf, RX_BUF_SIZE * RX_BUF_NUM);
+ dma->rx_buf, RX_BUF_SIZE_ALIGNED * RX_BUF_NUM);
g_dmactrlflags = 0;
diff --git a/drivers/net/bcm-sf2-eth.h b/drivers/net/bcm-sf2-eth.h
index 6104aff..c4e2e01 100644
--- a/drivers/net/bcm-sf2-eth.h
+++ b/drivers/net/bcm-sf2-eth.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Broadcom Corporation.
+ * Copyright 2014-2017 Broadcom.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -30,8 +30,6 @@ enum {
struct eth_dma {
void *tx_desc_aligned;
void *rx_desc_aligned;
- void *tx_desc;
- void *rx_desc;
uint8_t *tx_buf;
uint8_t *rx_buf;
diff --git a/drivers/net/ldpaa_eth/ls2080a.c b/drivers/net/ldpaa_eth/ls2080a.c
index 93ed4f1..673e428 100644
--- a/drivers/net/ldpaa_eth/ls2080a.c
+++ b/drivers/net/ldpaa_eth/ls2080a.c
@@ -79,3 +79,33 @@ phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtcl)
return PHY_INTERFACE_MODE_NONE;
}
+
+void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
+{
+ switch (lane_prtcl) {
+ case QSGMII_A:
+ wriop_init_dpmac(sd, 5, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 6, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 7, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 8, (int)lane_prtcl);
+ break;
+ case QSGMII_B:
+ wriop_init_dpmac(sd, 1, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 2, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 3, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 4, (int)lane_prtcl);
+ break;
+ case QSGMII_C:
+ wriop_init_dpmac(sd, 13, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 14, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 15, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 16, (int)lane_prtcl);
+ break;
+ case QSGMII_D:
+ wriop_init_dpmac(sd, 9, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 10, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 11, (int)lane_prtcl);
+ wriop_init_dpmac(sd, 12, (int)lane_prtcl);
+ break;
+ }
+}
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index 88e88b9..8ffe6c8 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -6,7 +6,7 @@
* Marcin Wojtas <mw@semihalf.com>
*
* U-Boot version:
- * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2016-2017 Stefan Roese <sr@denx.de>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -91,9 +91,11 @@ do { \
#define MVPP2_SNOOP_PKT_SIZE_MASK 0x1ff
#define MVPP2_SNOOP_BUF_HDR_MASK BIT(9)
#define MVPP2_RXQ_POOL_SHORT_OFFS 20
-#define MVPP2_RXQ_POOL_SHORT_MASK 0x700000
+#define MVPP21_RXQ_POOL_SHORT_MASK 0x700000
+#define MVPP22_RXQ_POOL_SHORT_MASK 0xf00000
#define MVPP2_RXQ_POOL_LONG_OFFS 24
-#define MVPP2_RXQ_POOL_LONG_MASK 0x7000000
+#define MVPP21_RXQ_POOL_LONG_MASK 0x7000000
+#define MVPP22_RXQ_POOL_LONG_MASK 0xf000000
#define MVPP2_RXQ_PACKET_OFFSET_OFFS 28
#define MVPP2_RXQ_PACKET_OFFSET_MASK 0x70000000
#define MVPP2_RXQ_DISABLE_MASK BIT(31)
@@ -141,6 +143,7 @@ do { \
/* Descriptor Manager Top Registers */
#define MVPP2_RXQ_NUM_REG 0x2040
#define MVPP2_RXQ_DESC_ADDR_REG 0x2044
+#define MVPP22_DESC_ADDR_OFFS 8
#define MVPP2_RXQ_DESC_SIZE_REG 0x2048
#define MVPP2_RXQ_DESC_SIZE_MASK 0x3ff0
#define MVPP2_RXQ_STATUS_UPDATE_REG(rxq) (0x3000 + 4 * (rxq))
@@ -182,6 +185,7 @@ do { \
#define MVPP2_TXQ_RSVD_CLR_REG 0x20b8
#define MVPP2_TXQ_RSVD_CLR_OFFSET 16
#define MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu) (0x2100 + 4 * (cpu))
+#define MVPP22_AGGR_TXQ_DESC_ADDR_OFFS 8
#define MVPP2_AGGR_TXQ_DESC_SIZE_REG(cpu) (0x2140 + 4 * (cpu))
#define MVPP2_AGGR_TXQ_DESC_SIZE_MASK 0x3ff0
#define MVPP2_AGGR_TXQ_STATUS_REG(cpu) (0x2180 + 4 * (cpu))
@@ -194,9 +198,51 @@ do { \
#define MVPP2_WIN_REMAP(w) (0x4040 + ((w) << 2))
#define MVPP2_BASE_ADDR_ENABLE 0x4060
+/* AXI Bridge Registers */
+#define MVPP22_AXI_BM_WR_ATTR_REG 0x4100
+#define MVPP22_AXI_BM_RD_ATTR_REG 0x4104
+#define MVPP22_AXI_AGGRQ_DESCR_RD_ATTR_REG 0x4110
+#define MVPP22_AXI_TXQ_DESCR_WR_ATTR_REG 0x4114
+#define MVPP22_AXI_TXQ_DESCR_RD_ATTR_REG 0x4118
+#define MVPP22_AXI_RXQ_DESCR_WR_ATTR_REG 0x411c
+#define MVPP22_AXI_RX_DATA_WR_ATTR_REG 0x4120
+#define MVPP22_AXI_TX_DATA_RD_ATTR_REG 0x4130
+#define MVPP22_AXI_RD_NORMAL_CODE_REG 0x4150
+#define MVPP22_AXI_RD_SNOOP_CODE_REG 0x4154
+#define MVPP22_AXI_WR_NORMAL_CODE_REG 0x4160
+#define MVPP22_AXI_WR_SNOOP_CODE_REG 0x4164
+
+/* Values for AXI Bridge registers */
+#define MVPP22_AXI_ATTR_CACHE_OFFS 0
+#define MVPP22_AXI_ATTR_DOMAIN_OFFS 12
+
+#define MVPP22_AXI_CODE_CACHE_OFFS 0
+#define MVPP22_AXI_CODE_DOMAIN_OFFS 4
+
+#define MVPP22_AXI_CODE_CACHE_NON_CACHE 0x3
+#define MVPP22_AXI_CODE_CACHE_WR_CACHE 0x7
+#define MVPP22_AXI_CODE_CACHE_RD_CACHE 0xb
+
+#define MVPP22_AXI_CODE_DOMAIN_OUTER_DOM 2
+#define MVPP22_AXI_CODE_DOMAIN_SYSTEM 3
+
/* Interrupt Cause and Mask registers */
#define MVPP2_ISR_RX_THRESHOLD_REG(rxq) (0x5200 + 4 * (rxq))
-#define MVPP2_ISR_RXQ_GROUP_REG(rxq) (0x5400 + 4 * (rxq))
+#define MVPP21_ISR_RXQ_GROUP_REG(rxq) (0x5400 + 4 * (rxq))
+
+#define MVPP22_ISR_RXQ_GROUP_INDEX_REG 0x5400
+#define MVPP22_ISR_RXQ_GROUP_INDEX_SUBGROUP_MASK 0xf
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_MASK 0x380
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET 7
+
+#define MVPP22_ISR_RXQ_GROUP_INDEX_SUBGROUP_MASK 0xf
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_MASK 0x380
+
+#define MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG 0x5404
+#define MVPP22_ISR_RXQ_SUB_GROUP_STARTQ_MASK 0x1f
+#define MVPP22_ISR_RXQ_SUB_GROUP_SIZE_MASK 0xf00
+#define MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET 8
+
#define MVPP2_ISR_ENABLE_REG(port) (0x5420 + 4 * (port))
#define MVPP2_ISR_ENABLE_INTERRUPT(mask) ((mask) & 0xffff)
#define MVPP2_ISR_DISABLE_INTERRUPT(mask) (((mask) << 16) & 0xffff0000)
@@ -251,14 +297,23 @@ do { \
#define MVPP2_BM_PHY_ALLOC_REG(pool) (0x6400 + ((pool) * 4))
#define MVPP2_BM_PHY_ALLOC_GRNTD_MASK BIT(0)
#define MVPP2_BM_VIRT_ALLOC_REG 0x6440
+#define MVPP2_BM_ADDR_HIGH_ALLOC 0x6444
+#define MVPP2_BM_ADDR_HIGH_PHYS_MASK 0xff
+#define MVPP2_BM_ADDR_HIGH_VIRT_MASK 0xff00
+#define MVPP2_BM_ADDR_HIGH_VIRT_SHIFT 8
#define MVPP2_BM_PHY_RLS_REG(pool) (0x6480 + ((pool) * 4))
#define MVPP2_BM_PHY_RLS_MC_BUFF_MASK BIT(0)
#define MVPP2_BM_PHY_RLS_PRIO_EN_MASK BIT(1)
#define MVPP2_BM_PHY_RLS_GRNTD_MASK BIT(2)
#define MVPP2_BM_VIRT_RLS_REG 0x64c0
-#define MVPP2_BM_MC_RLS_REG 0x64c4
+#define MVPP21_BM_MC_RLS_REG 0x64c4
#define MVPP2_BM_MC_ID_MASK 0xfff
#define MVPP2_BM_FORCE_RELEASE_MASK BIT(12)
+#define MVPP22_BM_ADDR_HIGH_RLS_REG 0x64c4
+#define MVPP22_BM_ADDR_HIGH_PHYS_RLS_MASK 0xff
+#define MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK 0xff00
+#define MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT 8
+#define MVPP22_BM_MC_RLS_REG 0x64d4
/* TX Scheduler registers */
#define MVPP2_TXP_SCHED_PORT_INDEX_REG 0x8000
@@ -294,16 +349,13 @@ do { \
#define MVPP2_SRC_ADDR_HIGH 0x28
#define MVPP2_PHY_AN_CFG0_REG 0x34
#define MVPP2_PHY_AN_STOP_SMI0_MASK BIT(7)
-#define MVPP2_MIB_COUNTERS_BASE(port) (0x1000 + ((port) >> 1) * \
- 0x400 + (port) * 0x400)
-#define MVPP2_MIB_LATE_COLLISION 0x7c
-#define MVPP2_ISR_SUM_MASK_REG 0x220c
#define MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG 0x305c
-#define MVPP2_EXT_GLOBAL_CTRL_DEFAULT 0x27
+#define MVPP2_EXT_GLOBAL_CTRL_DEFAULT 0x27
/* Per-port registers */
#define MVPP2_GMAC_CTRL_0_REG 0x0
#define MVPP2_GMAC_PORT_EN_MASK BIT(0)
+#define MVPP2_GMAC_PORT_TYPE_MASK BIT(1)
#define MVPP2_GMAC_MAX_RX_SIZE_OFFS 2
#define MVPP2_GMAC_MAX_RX_SIZE_MASK 0x7ffc
#define MVPP2_GMAC_MIB_CNTR_EN_MASK BIT(15)
@@ -315,23 +367,131 @@ do { \
#define MVPP2_GMAC_SA_LOW_OFFS 7
#define MVPP2_GMAC_CTRL_2_REG 0x8
#define MVPP2_GMAC_INBAND_AN_MASK BIT(0)
+#define MVPP2_GMAC_SGMII_MODE_MASK BIT(0)
#define MVPP2_GMAC_PCS_ENABLE_MASK BIT(3)
#define MVPP2_GMAC_PORT_RGMII_MASK BIT(4)
+#define MVPP2_GMAC_PORT_DIS_PADING_MASK BIT(5)
#define MVPP2_GMAC_PORT_RESET_MASK BIT(6)
+#define MVPP2_GMAC_CLK_125_BYPS_EN_MASK BIT(9)
#define MVPP2_GMAC_AUTONEG_CONFIG 0xc
#define MVPP2_GMAC_FORCE_LINK_DOWN BIT(0)
#define MVPP2_GMAC_FORCE_LINK_PASS BIT(1)
+#define MVPP2_GMAC_EN_PCS_AN BIT(2)
+#define MVPP2_GMAC_AN_BYPASS_EN BIT(3)
#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6)
#define MVPP2_GMAC_AN_SPEED_EN BIT(7)
#define MVPP2_GMAC_FC_ADV_EN BIT(9)
+#define MVPP2_GMAC_EN_FC_AN BIT(11)
#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
+#define MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG BIT(15)
#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
#define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6
#define MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK 0x1fc0
#define MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v) (((v) << 6) & \
MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
+#define MVPP2_GMAC_CTRL_4_REG 0x90
+#define MVPP2_GMAC_CTRL4_EXT_PIN_GMII_SEL_MASK BIT(0)
+#define MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK BIT(5)
+#define MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK BIT(6)
+#define MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK BIT(7)
+
+/*
+ * Per-port XGMAC registers. PPv2.2 only, only for GOP port 0,
+ * relative to port->base.
+ */
+
+/* Port Mac Control0 */
+#define MVPP22_XLG_CTRL0_REG 0x100
+#define MVPP22_XLG_PORT_EN BIT(0)
+#define MVPP22_XLG_MAC_RESETN BIT(1)
+#define MVPP22_XLG_RX_FC_EN BIT(7)
+#define MVPP22_XLG_MIBCNT_DIS BIT(13)
+/* Port Mac Control1 */
+#define MVPP22_XLG_CTRL1_REG 0x104
+#define MVPP22_XLG_MAX_RX_SIZE_OFFS 0
+#define MVPP22_XLG_MAX_RX_SIZE_MASK 0x1fff
+/* Port Interrupt Mask */
+#define MVPP22_XLG_INTERRUPT_MASK_REG 0x118
+#define MVPP22_XLG_INTERRUPT_LINK_CHANGE BIT(1)
+/* Port Mac Control3 */
+#define MVPP22_XLG_CTRL3_REG 0x11c
+#define MVPP22_XLG_CTRL3_MACMODESELECT_MASK (7 << 13)
+#define MVPP22_XLG_CTRL3_MACMODESELECT_GMAC (0 << 13)
+#define MVPP22_XLG_CTRL3_MACMODESELECT_10GMAC (1 << 13)
+/* Port Mac Control4 */
+#define MVPP22_XLG_CTRL4_REG 0x184
+#define MVPP22_XLG_FORWARD_802_3X_FC_EN BIT(5)
+#define MVPP22_XLG_FORWARD_PFC_EN BIT(6)
+#define MVPP22_XLG_MODE_DMA_1G BIT(12)
+#define MVPP22_XLG_EN_IDLE_CHECK_FOR_LINK BIT(14)
+
+/* XPCS registers */
+
+/* Global Configuration 0 */
+#define MVPP22_XPCS_GLOBAL_CFG_0_REG 0x0
+#define MVPP22_XPCS_PCSRESET BIT(0)
+#define MVPP22_XPCS_PCSMODE_OFFS 3
+#define MVPP22_XPCS_PCSMODE_MASK (0x3 << \
+ MVPP22_XPCS_PCSMODE_OFFS)
+#define MVPP22_XPCS_LANEACTIVE_OFFS 5
+#define MVPP22_XPCS_LANEACTIVE_MASK (0x3 << \
+ MVPP22_XPCS_LANEACTIVE_OFFS)
+
+/* MPCS registers */
+
+#define PCS40G_COMMON_CONTROL 0x14
+#define FORWARD_ERROR_CORRECTION_MASK BIT(1)
+
+#define PCS_CLOCK_RESET 0x14c
+#define TX_SD_CLK_RESET_MASK BIT(0)
+#define RX_SD_CLK_RESET_MASK BIT(1)
+#define MAC_CLK_RESET_MASK BIT(2)
+#define CLK_DIVISION_RATIO_OFFS 4
+#define CLK_DIVISION_RATIO_MASK (0x7 << CLK_DIVISION_RATIO_OFFS)
+#define CLK_DIV_PHASE_SET_MASK BIT(11)
+
+/* System Soft Reset 1 */
+#define GOP_SOFT_RESET_1_REG 0x108
+#define NETC_GOP_SOFT_RESET_OFFS 6
+#define NETC_GOP_SOFT_RESET_MASK (0x1 << \
+ NETC_GOP_SOFT_RESET_OFFS)
+
+/* Ports Control 0 */
+#define NETCOMP_PORTS_CONTROL_0_REG 0x110
+#define NETC_BUS_WIDTH_SELECT_OFFS 1
+#define NETC_BUS_WIDTH_SELECT_MASK (0x1 << \
+ NETC_BUS_WIDTH_SELECT_OFFS)
+#define NETC_GIG_RX_DATA_SAMPLE_OFFS 29
+#define NETC_GIG_RX_DATA_SAMPLE_MASK (0x1 << \
+ NETC_GIG_RX_DATA_SAMPLE_OFFS)
+#define NETC_CLK_DIV_PHASE_OFFS 31
+#define NETC_CLK_DIV_PHASE_MASK (0x1 << NETC_CLK_DIV_PHASE_OFFS)
+/* Ports Control 1 */
+#define NETCOMP_PORTS_CONTROL_1_REG 0x114
+#define NETC_PORTS_ACTIVE_OFFSET(p) (0 + p)
+#define NETC_PORTS_ACTIVE_MASK(p) (0x1 << \
+ NETC_PORTS_ACTIVE_OFFSET(p))
+#define NETC_PORT_GIG_RF_RESET_OFFS(p) (28 + p)
+#define NETC_PORT_GIG_RF_RESET_MASK(p) (0x1 << \
+ NETC_PORT_GIG_RF_RESET_OFFS(p))
+#define NETCOMP_CONTROL_0_REG 0x120
+#define NETC_GBE_PORT0_SGMII_MODE_OFFS 0
+#define NETC_GBE_PORT0_SGMII_MODE_MASK (0x1 << \
+ NETC_GBE_PORT0_SGMII_MODE_OFFS)
+#define NETC_GBE_PORT1_SGMII_MODE_OFFS 1
+#define NETC_GBE_PORT1_SGMII_MODE_MASK (0x1 << \
+ NETC_GBE_PORT1_SGMII_MODE_OFFS)
+#define NETC_GBE_PORT1_MII_MODE_OFFS 2
+#define NETC_GBE_PORT1_MII_MODE_MASK (0x1 << \
+ NETC_GBE_PORT1_MII_MODE_OFFS)
+
+#define MVPP22_SMI_MISC_CFG_REG (MVPP22_SMI + 0x04)
+#define MVPP22_SMI_POLLING_EN BIT(10)
+
+#define MVPP22_SMI_PHY_ADDR_REG(port) (MVPP22_SMI + 0x04 + \
+ (0x4 * (port)))
#define MVPP2_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff
@@ -340,7 +500,9 @@ do { \
(((index) < (q)->last_desc) ? ((index) + 1) : 0)
/* SMI: 0xc0054 -> offset 0x54 to lms_base */
-#define MVPP2_SMI 0x0054
+#define MVPP21_SMI 0x0054
+/* PP2.2: SMI: 0x12a200 -> offset 0x1200 to iface_base */
+#define MVPP22_SMI 0x1200
#define MVPP2_PHY_REG_MASK 0x1f
/* SMI register fields */
#define MVPP2_SMI_DATA_OFFS 0 /* Data */
@@ -355,6 +517,48 @@ do { \
#define MVPP2_PHY_ADDR_MASK 0x1f
#define MVPP2_PHY_REG_MASK 0x1f
+/* Additional PPv2.2 offsets */
+#define MVPP22_MPCS 0x007000
+#define MVPP22_XPCS 0x007400
+#define MVPP22_PORT_BASE 0x007e00
+#define MVPP22_PORT_OFFSET 0x001000
+#define MVPP22_RFU1 0x318000
+
+/* Maximum number of ports */
+#define MVPP22_GOP_MAC_NUM 4
+
+/* Sets the field located at the specified in data */
+#define MVPP2_RGMII_TX_FIFO_MIN_TH 0x41
+#define MVPP2_SGMII_TX_FIFO_MIN_TH 0x5
+#define MVPP2_SGMII2_5_TX_FIFO_MIN_TH 0xb
+
+/* Net Complex */
+enum mv_netc_topology {
+ MV_NETC_GE_MAC2_SGMII = BIT(0),
+ MV_NETC_GE_MAC3_SGMII = BIT(1),
+ MV_NETC_GE_MAC3_RGMII = BIT(2),
+};
+
+enum mv_netc_phase {
+ MV_NETC_FIRST_PHASE,
+ MV_NETC_SECOND_PHASE,
+};
+
+enum mv_netc_sgmii_xmi_mode {
+ MV_NETC_GBE_SGMII,
+ MV_NETC_GBE_XMII,
+};
+
+enum mv_netc_mii_mode {
+ MV_NETC_GBE_RGMII,
+ MV_NETC_GBE_MII,
+};
+
+enum mv_netc_lanes {
+ MV_NETC_LANE_23,
+ MV_NETC_LANE_45,
+};
+
/* Various constants */
/* Coalescing */
@@ -397,9 +601,6 @@ do { \
/* Maximum number of TXQs used by single port */
#define MVPP2_MAX_TXQ 8
-/* Maximum number of RXQs used by single port */
-#define MVPP2_MAX_RXQ 8
-
/* Default number of TXQs in use */
#define MVPP2_DEFAULT_TXQ 1
@@ -407,9 +608,6 @@ do { \
#define MVPP2_DEFAULT_RXQ 1
#define CONFIG_MV_ETH_RXQ 8 /* increment by 8 */
-/* Total number of RXQs available to all ports */
-#define MVPP2_RXQ_TOTAL_NUM (MVPP2_MAX_PORTS * MVPP2_MAX_RXQ)
-
/* Max number of Rx descriptors */
#define MVPP2_MAX_RXD 16
@@ -429,9 +627,23 @@ do { \
#define MVPP2_TX_DESC_ALIGN (MVPP2_DESC_ALIGNED_SIZE - 1)
/* RX FIFO constants */
-#define MVPP2_RX_FIFO_PORT_DATA_SIZE 0x2000
-#define MVPP2_RX_FIFO_PORT_ATTR_SIZE 0x80
-#define MVPP2_RX_FIFO_PORT_MIN_PKT 0x80
+#define MVPP21_RX_FIFO_PORT_DATA_SIZE 0x2000
+#define MVPP21_RX_FIFO_PORT_ATTR_SIZE 0x80
+#define MVPP22_RX_FIFO_10GB_PORT_DATA_SIZE 0x8000
+#define MVPP22_RX_FIFO_2_5GB_PORT_DATA_SIZE 0x2000
+#define MVPP22_RX_FIFO_1GB_PORT_DATA_SIZE 0x1000
+#define MVPP22_RX_FIFO_10GB_PORT_ATTR_SIZE 0x200
+#define MVPP22_RX_FIFO_2_5GB_PORT_ATTR_SIZE 0x80
+#define MVPP22_RX_FIFO_1GB_PORT_ATTR_SIZE 0x40
+#define MVPP2_RX_FIFO_PORT_MIN_PKT 0x80
+
+/* TX general registers */
+#define MVPP22_TX_FIFO_SIZE_REG(eth_tx_port) (0x8860 + ((eth_tx_port) << 2))
+#define MVPP22_TX_FIFO_SIZE_MASK 0xf
+
+/* TX FIFO constants */
+#define MVPP2_TX_FIFO_DATA_SIZE_10KB 0xa
+#define MVPP2_TX_FIFO_DATA_SIZE_3KB 0x3
/* RX buffer constants */
#define MVPP2_SKB_SHINFO_SIZE \
@@ -576,28 +788,28 @@ enum mvpp2_tag_type {
/* Sram result info bits assignment */
#define MVPP2_PRS_RI_MAC_ME_MASK 0x1
#define MVPP2_PRS_RI_DSA_MASK 0x2
-#define MVPP2_PRS_RI_VLAN_MASK 0xc
-#define MVPP2_PRS_RI_VLAN_NONE ~(BIT(2) | BIT(3))
+#define MVPP2_PRS_RI_VLAN_MASK (BIT(2) | BIT(3))
+#define MVPP2_PRS_RI_VLAN_NONE 0x0
#define MVPP2_PRS_RI_VLAN_SINGLE BIT(2)
#define MVPP2_PRS_RI_VLAN_DOUBLE BIT(3)
#define MVPP2_PRS_RI_VLAN_TRIPLE (BIT(2) | BIT(3))
#define MVPP2_PRS_RI_CPU_CODE_MASK 0x70
#define MVPP2_PRS_RI_CPU_CODE_RX_SPEC BIT(4)
-#define MVPP2_PRS_RI_L2_CAST_MASK 0x600
-#define MVPP2_PRS_RI_L2_UCAST ~(BIT(9) | BIT(10))
+#define MVPP2_PRS_RI_L2_CAST_MASK (BIT(9) | BIT(10))
+#define MVPP2_PRS_RI_L2_UCAST 0x0
#define MVPP2_PRS_RI_L2_MCAST BIT(9)
#define MVPP2_PRS_RI_L2_BCAST BIT(10)
#define MVPP2_PRS_RI_PPPOE_MASK 0x800
-#define MVPP2_PRS_RI_L3_PROTO_MASK 0x7000
-#define MVPP2_PRS_RI_L3_UN ~(BIT(12) | BIT(13) | BIT(14))
+#define MVPP2_PRS_RI_L3_PROTO_MASK (BIT(12) | BIT(13) | BIT(14))
+#define MVPP2_PRS_RI_L3_UN 0x0
#define MVPP2_PRS_RI_L3_IP4 BIT(12)
#define MVPP2_PRS_RI_L3_IP4_OPT BIT(13)
#define MVPP2_PRS_RI_L3_IP4_OTHER (BIT(12) | BIT(13))
#define MVPP2_PRS_RI_L3_IP6 BIT(14)
#define MVPP2_PRS_RI_L3_IP6_EXT (BIT(12) | BIT(14))
#define MVPP2_PRS_RI_L3_ARP (BIT(13) | BIT(14))
-#define MVPP2_PRS_RI_L3_ADDR_MASK 0x18000
-#define MVPP2_PRS_RI_L3_UCAST ~(BIT(15) | BIT(16))
+#define MVPP2_PRS_RI_L3_ADDR_MASK (BIT(15) | BIT(16))
+#define MVPP2_PRS_RI_L3_UCAST 0x0
#define MVPP2_PRS_RI_L3_MCAST BIT(15)
#define MVPP2_PRS_RI_L3_BCAST (BIT(15) | BIT(16))
#define MVPP2_PRS_RI_IP_FRAG_MASK 0x20000
@@ -693,6 +905,14 @@ struct mvpp2 {
/* Shared registers' base addresses */
void __iomem *base;
void __iomem *lms_base;
+ void __iomem *iface_base;
+ void __iomem *mdio_base;
+
+ void __iomem *mpcs_base;
+ void __iomem *xpcs_base;
+ void __iomem *rfu1_base;
+
+ u32 netc_config;
/* List of pointers to port structures */
struct mvpp2_port **port_list;
@@ -711,7 +931,15 @@ struct mvpp2 {
/* Tclk value */
u32 tclk;
+ /* HW version */
+ enum { MVPP21, MVPP22 } hw_version;
+
+ /* Maximum number of RXQs per port */
+ unsigned int max_port_rxqs;
+
struct mii_dev *bus;
+
+ int probe_done;
};
struct mvpp2_pcpu_stats {
@@ -724,6 +952,11 @@ struct mvpp2_pcpu_stats {
struct mvpp2_port {
u8 id;
+ /* Index of the port from the "group of ports" complex point
+ * of view
+ */
+ int gop_id;
+
int irq;
struct mvpp2 *priv;
@@ -757,6 +990,8 @@ struct mvpp2_port {
unsigned int duplex;
unsigned int speed;
+ unsigned int phy_speed; /* SGMII 1Gbps vs 2.5Gbps */
+
struct mvpp2_bm_pool *pool_long;
struct mvpp2_bm_pool *pool_short;
@@ -798,22 +1033,24 @@ struct mvpp2_port {
#define MVPP2_RXD_L3_IP6 BIT(30)
#define MVPP2_RXD_BUF_HDR BIT(31)
-struct mvpp2_tx_desc {
+/* HW TX descriptor for PPv2.1 */
+struct mvpp21_tx_desc {
u32 command; /* Options used by HW for packet transmitting.*/
u8 packet_offset; /* the offset from the buffer beginning */
u8 phys_txq; /* destination queue ID */
u16 data_size; /* data size of transmitted packet in bytes */
- u32 buf_phys_addr; /* physical addr of transmitted buffer */
+ u32 buf_dma_addr; /* physical addr of transmitted buffer */
u32 buf_cookie; /* cookie for access to TX buffer in tx path */
u32 reserved1[3]; /* hw_cmd (for future use, BM, PON, PNC) */
u32 reserved2; /* reserved (for future use) */
};
-struct mvpp2_rx_desc {
+/* HW RX descriptor for PPv2.1 */
+struct mvpp21_rx_desc {
u32 status; /* info about received packet */
u16 reserved1; /* parser_info (for future use, PnC) */
u16 data_size; /* size of received packet in bytes */
- u32 buf_phys_addr; /* physical address of the buffer */
+ u32 buf_dma_addr; /* physical address of the buffer */
u32 buf_cookie; /* cookie for access to RX buffer in rx path */
u16 reserved2; /* gem_port_id (for future use, PON) */
u16 reserved3; /* csum_l4 (for future use, PnC) */
@@ -824,6 +1061,45 @@ struct mvpp2_rx_desc {
u32 reserved8;
};
+/* HW TX descriptor for PPv2.2 */
+struct mvpp22_tx_desc {
+ u32 command;
+ u8 packet_offset;
+ u8 phys_txq;
+ u16 data_size;
+ u64 reserved1;
+ u64 buf_dma_addr_ptp;
+ u64 buf_cookie_misc;
+};
+
+/* HW RX descriptor for PPv2.2 */
+struct mvpp22_rx_desc {
+ u32 status;
+ u16 reserved1;
+ u16 data_size;
+ u32 reserved2;
+ u32 reserved3;
+ u64 buf_dma_addr_key_hash;
+ u64 buf_cookie_misc;
+};
+
+/* Opaque type used by the driver to manipulate the HW TX and RX
+ * descriptors
+ */
+struct mvpp2_tx_desc {
+ union {
+ struct mvpp21_tx_desc pp21;
+ struct mvpp22_tx_desc pp22;
+ };
+};
+
+struct mvpp2_rx_desc {
+ union {
+ struct mvpp21_rx_desc pp21;
+ struct mvpp22_rx_desc pp22;
+ };
+};
+
/* Per-CPU Tx queue control */
struct mvpp2_txq_pcpu {
int cpu;
@@ -868,7 +1144,7 @@ struct mvpp2_tx_queue {
struct mvpp2_tx_desc *descs;
/* DMA address of the Tx DMA descriptors array */
- dma_addr_t descs_phys;
+ dma_addr_t descs_dma;
/* Index of the last Tx DMA descriptor */
int last_desc;
@@ -891,7 +1167,7 @@ struct mvpp2_rx_queue {
struct mvpp2_rx_desc *descs;
/* DMA address of the RX DMA descriptors array */
- dma_addr_t descs_phys;
+ dma_addr_t descs_dma;
/* Index of the last RX DMA descriptor */
int last_desc;
@@ -963,33 +1239,14 @@ struct mvpp2_bm_pool {
int pkt_size;
/* BPPE virtual base address */
- u32 *virt_addr;
- /* BPPE physical base address */
- dma_addr_t phys_addr;
+ unsigned long *virt_addr;
+ /* BPPE DMA base address */
+ dma_addr_t dma_addr;
/* Ports using BM pool */
u32 port_map;
-
- /* Occupied buffers indicator */
- int in_use_thresh;
};
-struct mvpp2_buff_hdr {
- u32 next_buff_phys_addr;
- u32 next_buff_virt_addr;
- u16 byte_count;
- u16 info;
- u8 reserved1; /* bm_qset (for future use, BM) */
-};
-
-/* Buffer header info bits */
-#define MVPP2_B_HDR_INFO_MC_ID_MASK 0xfff
-#define MVPP2_B_HDR_INFO_MC_ID(info) ((info) & MVPP2_B_HDR_INFO_MC_ID_MASK)
-#define MVPP2_B_HDR_INFO_LAST_OFFS 12
-#define MVPP2_B_HDR_INFO_LAST_MASK BIT(12)
-#define MVPP2_B_HDR_INFO_IS_LAST(info) \
- ((info & MVPP2_B_HDR_INFO_LAST_MASK) >> MVPP2_B_HDR_INFO_LAST_OFFS)
-
/* Static declaractions */
/* Number of RXQs used by single port */
@@ -997,6 +1254,8 @@ static int rxq_number = MVPP2_DEFAULT_RXQ;
/* Number of TXQs used by single port */
static int txq_number = MVPP2_DEFAULT_TXQ;
+static int base_id;
+
#define MVPP2_DRIVER_NAME "mvpp2"
#define MVPP2_DRIVER_VERSION "1.0"
@@ -1007,8 +1266,8 @@ struct buffer_location {
struct mvpp2_tx_desc *aggr_tx_descs;
struct mvpp2_tx_desc *tx_descs;
struct mvpp2_rx_desc *rx_descs;
- u32 *bm_pool[MVPP2_BM_POOLS_NUM];
- u32 *rx_buffer[MVPP2_BM_LONG_BUF_NUM];
+ unsigned long *bm_pool[MVPP2_BM_POOLS_NUM];
+ unsigned long *rx_buffer[MVPP2_BM_LONG_BUF_NUM];
int first_rxq;
};
@@ -1036,6 +1295,96 @@ static u32 mvpp2_read(struct mvpp2 *priv, u32 offset)
return readl(priv->base + offset);
}
+static void mvpp2_txdesc_dma_addr_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ dma_addr_t dma_addr)
+{
+ if (port->priv->hw_version == MVPP21) {
+ tx_desc->pp21.buf_dma_addr = dma_addr;
+ } else {
+ u64 val = (u64)dma_addr;
+
+ tx_desc->pp22.buf_dma_addr_ptp &= ~GENMASK_ULL(40, 0);
+ tx_desc->pp22.buf_dma_addr_ptp |= val;
+ }
+}
+
+static void mvpp2_txdesc_size_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ size_t size)
+{
+ if (port->priv->hw_version == MVPP21)
+ tx_desc->pp21.data_size = size;
+ else
+ tx_desc->pp22.data_size = size;
+}
+
+static void mvpp2_txdesc_txq_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ unsigned int txq)
+{
+ if (port->priv->hw_version == MVPP21)
+ tx_desc->pp21.phys_txq = txq;
+ else
+ tx_desc->pp22.phys_txq = txq;
+}
+
+static void mvpp2_txdesc_cmd_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ unsigned int command)
+{
+ if (port->priv->hw_version == MVPP21)
+ tx_desc->pp21.command = command;
+ else
+ tx_desc->pp22.command = command;
+}
+
+static void mvpp2_txdesc_offset_set(struct mvpp2_port *port,
+ struct mvpp2_tx_desc *tx_desc,
+ unsigned int offset)
+{
+ if (port->priv->hw_version == MVPP21)
+ tx_desc->pp21.packet_offset = offset;
+ else
+ tx_desc->pp22.packet_offset = offset;
+}
+
+static dma_addr_t mvpp2_rxdesc_dma_addr_get(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ if (port->priv->hw_version == MVPP21)
+ return rx_desc->pp21.buf_dma_addr;
+ else
+ return rx_desc->pp22.buf_dma_addr_key_hash & GENMASK_ULL(40, 0);
+}
+
+static unsigned long mvpp2_rxdesc_cookie_get(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ if (port->priv->hw_version == MVPP21)
+ return rx_desc->pp21.buf_cookie;
+ else
+ return rx_desc->pp22.buf_cookie_misc & GENMASK_ULL(40, 0);
+}
+
+static size_t mvpp2_rxdesc_size_get(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ if (port->priv->hw_version == MVPP21)
+ return rx_desc->pp21.data_size;
+ else
+ return rx_desc->pp22.data_size;
+}
+
+static u32 mvpp2_rxdesc_status_get(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ if (port->priv->hw_version == MVPP21)
+ return rx_desc->pp21.status;
+ else
+ return rx_desc->pp22.status;
+}
+
static void mvpp2_txq_inc_get(struct mvpp2_txq_pcpu *txq_pcpu)
{
txq_pcpu->txq_get_index++;
@@ -2218,19 +2567,26 @@ static int mvpp2_bm_pool_create(struct udevice *dev,
{
u32 val;
+ /* Number of buffer pointers must be a multiple of 16, as per
+ * hardware constraints
+ */
+ if (!IS_ALIGNED(size, 16))
+ return -EINVAL;
+
bm_pool->virt_addr = buffer_loc.bm_pool[bm_pool->id];
- bm_pool->phys_addr = (dma_addr_t)buffer_loc.bm_pool[bm_pool->id];
+ bm_pool->dma_addr = (dma_addr_t)buffer_loc.bm_pool[bm_pool->id];
if (!bm_pool->virt_addr)
return -ENOMEM;
- if (!IS_ALIGNED((u32)bm_pool->virt_addr, MVPP2_BM_POOL_PTR_ALIGN)) {
+ if (!IS_ALIGNED((unsigned long)bm_pool->virt_addr,
+ MVPP2_BM_POOL_PTR_ALIGN)) {
dev_err(&pdev->dev, "BM pool %d is not %d bytes aligned\n",
bm_pool->id, MVPP2_BM_POOL_PTR_ALIGN);
return -ENOMEM;
}
mvpp2_write(priv, MVPP2_BM_POOL_BASE_REG(bm_pool->id),
- bm_pool->phys_addr);
+ lower_32_bits(bm_pool->dma_addr));
mvpp2_write(priv, MVPP2_BM_POOL_SIZE_REG(bm_pool->id), size);
val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id));
@@ -2337,17 +2693,20 @@ static int mvpp2_bm_init(struct udevice *dev, struct mvpp2 *priv)
static void mvpp2_rxq_long_pool_set(struct mvpp2_port *port,
int lrxq, int long_pool)
{
- u32 val;
+ u32 val, mask;
int prxq;
/* Get queue physical ID */
prxq = port->rxqs[lrxq]->id;
- val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
- val &= ~MVPP2_RXQ_POOL_LONG_MASK;
- val |= ((long_pool << MVPP2_RXQ_POOL_LONG_OFFS) &
- MVPP2_RXQ_POOL_LONG_MASK);
+ if (port->priv->hw_version == MVPP21)
+ mask = MVPP21_RXQ_POOL_LONG_MASK;
+ else
+ mask = MVPP22_RXQ_POOL_LONG_MASK;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+ val &= ~mask;
+ val |= (long_pool << MVPP2_RXQ_POOL_LONG_OFFS) & mask;
mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
}
@@ -2363,26 +2722,48 @@ static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool)
}
/* Get pool number from a BM cookie */
-static inline int mvpp2_bm_cookie_pool_get(u32 cookie)
+static inline int mvpp2_bm_cookie_pool_get(unsigned long cookie)
{
return (cookie >> MVPP2_BM_COOKIE_POOL_OFFS) & 0xFF;
}
/* Release buffer to BM */
static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
- u32 buf_phys_addr, u32 buf_virt_addr)
+ dma_addr_t buf_dma_addr,
+ unsigned long buf_phys_addr)
{
- mvpp2_write(port->priv, MVPP2_BM_VIRT_RLS_REG, buf_virt_addr);
- mvpp2_write(port->priv, MVPP2_BM_PHY_RLS_REG(pool), buf_phys_addr);
+ if (port->priv->hw_version == MVPP22) {
+ u32 val = 0;
+
+ if (sizeof(dma_addr_t) == 8)
+ val |= upper_32_bits(buf_dma_addr) &
+ MVPP22_BM_ADDR_HIGH_PHYS_RLS_MASK;
+
+ if (sizeof(phys_addr_t) == 8)
+ val |= (upper_32_bits(buf_phys_addr)
+ << MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT) &
+ MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK;
+
+ mvpp2_write(port->priv, MVPP22_BM_ADDR_HIGH_RLS_REG, val);
+ }
+
+ /* MVPP2_BM_VIRT_RLS_REG is not interpreted by HW, and simply
+ * returned in the "cookie" field of the RX
+ * descriptor. Instead of storing the virtual address, we
+ * store the physical address
+ */
+ mvpp2_write(port->priv, MVPP2_BM_VIRT_RLS_REG, buf_phys_addr);
+ mvpp2_write(port->priv, MVPP2_BM_PHY_RLS_REG(pool), buf_dma_addr);
}
/* Refill BM pool */
static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm,
- u32 phys_addr, u32 cookie)
+ dma_addr_t dma_addr,
+ phys_addr_t phys_addr)
{
int pool = mvpp2_bm_cookie_pool_get(bm);
- mvpp2_bm_pool_put(port, pool, phys_addr, cookie);
+ mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
}
/* Allocate buffers for the pool */
@@ -2390,7 +2771,6 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
struct mvpp2_bm_pool *bm_pool, int buf_num)
{
int i;
- u32 bm;
if (buf_num < 0 ||
(buf_num + bm_pool->buf_num > bm_pool->size)) {
@@ -2400,15 +2780,15 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
return 0;
}
- bm = mvpp2_bm_cookie_pool_set(0, bm_pool->id);
for (i = 0; i < buf_num; i++) {
- mvpp2_pool_refill(port, bm, (u32)buffer_loc.rx_buffer[i],
- (u32)buffer_loc.rx_buffer[i]);
+ mvpp2_bm_pool_put(port, bm_pool->id,
+ (dma_addr_t)buffer_loc.rx_buffer[i],
+ (unsigned long)buffer_loc.rx_buffer[i]);
+
}
/* Update BM driver with number of buffers added to pool */
bm_pool->buf_num += i;
- bm_pool->in_use_thresh = bm_pool->buf_num / 4;
return i;
}
@@ -2502,6 +2882,7 @@ static void mvpp2_port_mii_set(struct mvpp2_port *port)
val |= MVPP2_GMAC_INBAND_AN_MASK;
break;
case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
val |= MVPP2_GMAC_PORT_RGMII_MASK;
default:
val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
@@ -2593,22 +2974,749 @@ static inline void mvpp2_gmac_max_rx_size_set(struct mvpp2_port *port)
writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
}
-/* Set defaults to the MVPP2 port */
-static void mvpp2_defaults_set(struct mvpp2_port *port)
+/* PPv2.2 GoP/GMAC config */
+
+/* Set the MAC to reset or exit from reset */
+static int gop_gmac_reset(struct mvpp2_port *port, int reset)
{
- int tx_port_num, val, queue, ptxq, lrxq;
+ u32 val;
+
+ /* read - modify - write */
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ if (reset)
+ val |= MVPP2_GMAC_PORT_RESET_MASK;
+ else
+ val &= ~MVPP2_GMAC_PORT_RESET_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ return 0;
+}
+
+/*
+ * gop_gpcs_mode_cfg
+ *
+ * Configure port to working with Gig PCS or don't.
+ */
+static int gop_gpcs_mode_cfg(struct mvpp2_port *port, int en)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ if (en)
+ val |= MVPP2_GMAC_PCS_ENABLE_MASK;
+ else
+ val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
+ /* enable / disable PCS on this port */
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ return 0;
+}
+
+static int gop_bypass_clk_cfg(struct mvpp2_port *port, int en)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ if (en)
+ val |= MVPP2_GMAC_CLK_125_BYPS_EN_MASK;
+ else
+ val &= ~MVPP2_GMAC_CLK_125_BYPS_EN_MASK;
+ /* enable / disable PCS on this port */
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ return 0;
+}
+
+static void gop_gmac_sgmii2_5_cfg(struct mvpp2_port *port)
+{
+ u32 val, thresh;
+
+ /*
+ * Configure minimal level of the Tx FIFO before the lower part
+ * starts to read a packet
+ */
+ thresh = MVPP2_SGMII2_5_TX_FIFO_MIN_TH;
+ val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+ val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
+ writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+ /* Disable bypass of sync module */
+ val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
+ val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
+ /* configure DP clock select according to mode */
+ val |= MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
+ /* configure QSGMII bypass according to mode */
+ val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ val |= MVPP2_GMAC_PORT_DIS_PADING_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ /*
+ * Configure GIG MAC to 1000Base-X mode connected to a fiber
+ * transceiver
+ */
+ val |= MVPP2_GMAC_PORT_TYPE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+ /* configure AN 0x9268 */
+ val = MVPP2_GMAC_EN_PCS_AN |
+ MVPP2_GMAC_AN_BYPASS_EN |
+ MVPP2_GMAC_CONFIG_MII_SPEED |
+ MVPP2_GMAC_CONFIG_GMII_SPEED |
+ MVPP2_GMAC_FC_ADV_EN |
+ MVPP2_GMAC_CONFIG_FULL_DUPLEX |
+ MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
- /* Configure port to loopback if needed */
- if (port->flags & MVPP2_F_LOOPBACK)
- mvpp2_port_loopback_set(port);
+static void gop_gmac_sgmii_cfg(struct mvpp2_port *port)
+{
+ u32 val, thresh;
- /* Update TX FIFO MIN Threshold */
+ /*
+ * Configure minimal level of the Tx FIFO before the lower part
+ * starts to read a packet
+ */
+ thresh = MVPP2_SGMII_TX_FIFO_MIN_TH;
val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
- /* Min. TX threshold must be less than minimal packet length */
- val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64 - 4 - 2);
+ val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ /* Disable bypass of sync module */
+ val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
+ val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
+ /* configure DP clock select according to mode */
+ val &= ~MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
+ /* configure QSGMII bypass according to mode */
+ val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ val |= MVPP2_GMAC_PORT_DIS_PADING_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ /* configure GIG MAC to SGMII mode */
+ val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+ /* configure AN */
+ val = MVPP2_GMAC_EN_PCS_AN |
+ MVPP2_GMAC_AN_BYPASS_EN |
+ MVPP2_GMAC_AN_SPEED_EN |
+ MVPP2_GMAC_EN_FC_AN |
+ MVPP2_GMAC_AN_DUPLEX_EN |
+ MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+static void gop_gmac_rgmii_cfg(struct mvpp2_port *port)
+{
+ u32 val, thresh;
+
+ /*
+ * Configure minimal level of the Tx FIFO before the lower part
+ * starts to read a packet
+ */
+ thresh = MVPP2_RGMII_TX_FIFO_MIN_TH;
+ val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+ val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
+ writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+ /* Disable bypass of sync module */
+ val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
+ val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
+ /* configure DP clock select according to mode */
+ val &= ~MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
+ val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
+ val |= MVPP2_GMAC_CTRL4_EXT_PIN_GMII_SEL_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ val &= ~MVPP2_GMAC_PORT_DIS_PADING_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ /* configure GIG MAC to SGMII mode */
+ val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+ /* configure AN 0xb8e8 */
+ val = MVPP2_GMAC_AN_BYPASS_EN |
+ MVPP2_GMAC_AN_SPEED_EN |
+ MVPP2_GMAC_EN_FC_AN |
+ MVPP2_GMAC_AN_DUPLEX_EN |
+ MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+/* Set the internal mux's to the required MAC in the GOP */
+static int gop_gmac_mode_cfg(struct mvpp2_port *port)
+{
+ u32 val;
+
+ /* Set TX FIFO thresholds */
+ switch (port->phy_interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ if (port->phy_speed == 2500)
+ gop_gmac_sgmii2_5_cfg(port);
+ else
+ gop_gmac_sgmii_cfg(port);
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ gop_gmac_rgmii_cfg(port);
+ break;
+
+ default:
+ return -1;
+ }
+
+ /* Jumbo frame support - 0x1400*2= 0x2800 bytes */
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ val &= ~MVPP2_GMAC_MAX_RX_SIZE_MASK;
+ val |= 0x1400 << MVPP2_GMAC_MAX_RX_SIZE_OFFS;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+ /* PeriodicXonEn disable */
+ val = readl(port->base + MVPP2_GMAC_CTRL_1_REG);
+ val &= ~MVPP2_GMAC_PERIODIC_XON_EN_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_1_REG);
+
+ return 0;
+}
+
+static void gop_xlg_2_gig_mac_cfg(struct mvpp2_port *port)
+{
+ u32 val;
+
+ /* relevant only for MAC0 (XLG0 and GMAC0) */
+ if (port->gop_id > 0)
+ return;
+
+ /* configure 1Gig MAC mode */
+ val = readl(port->base + MVPP22_XLG_CTRL3_REG);
+ val &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
+ val |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC;
+ writel(val, port->base + MVPP22_XLG_CTRL3_REG);
+}
+
+static int gop_gpcs_reset(struct mvpp2_port *port, int reset)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ if (reset)
+ val &= ~MVPP2_GMAC_SGMII_MODE_MASK;
+ else
+ val |= MVPP2_GMAC_SGMII_MODE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ return 0;
+}
+
+/* Set the internal mux's to the required PCS in the PI */
+static int gop_xpcs_mode(struct mvpp2_port *port, int num_of_lanes)
+{
+ u32 val;
+ int lane;
+
+ switch (num_of_lanes) {
+ case 1:
+ lane = 0;
+ break;
+ case 2:
+ lane = 1;
+ break;
+ case 4:
+ lane = 2;
+ break;
+ default:
+ return -1;
+ }
+
+ /* configure XG MAC mode */
+ val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+ val &= ~MVPP22_XPCS_PCSMODE_OFFS;
+ val &= ~MVPP22_XPCS_LANEACTIVE_MASK;
+ val |= (2 * lane) << MVPP22_XPCS_LANEACTIVE_OFFS;
+ writel(val, port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+
+ return 0;
+}
+
+static int gop_mpcs_mode(struct mvpp2_port *port)
+{
+ u32 val;
+
+ /* configure PCS40G COMMON CONTROL */
+ val = readl(port->priv->mpcs_base + PCS40G_COMMON_CONTROL);
+ val &= ~FORWARD_ERROR_CORRECTION_MASK;
+ writel(val, port->priv->mpcs_base + PCS40G_COMMON_CONTROL);
+
+ /* configure PCS CLOCK RESET */
+ val = readl(port->priv->mpcs_base + PCS_CLOCK_RESET);
+ val &= ~CLK_DIVISION_RATIO_MASK;
+ val |= 1 << CLK_DIVISION_RATIO_OFFS;
+ writel(val, port->priv->mpcs_base + PCS_CLOCK_RESET);
+
+ val &= ~CLK_DIV_PHASE_SET_MASK;
+ val |= MAC_CLK_RESET_MASK;
+ val |= RX_SD_CLK_RESET_MASK;
+ val |= TX_SD_CLK_RESET_MASK;
+ writel(val, port->priv->mpcs_base + PCS_CLOCK_RESET);
+
+ return 0;
+}
+
+/* Set the internal mux's to the required MAC in the GOP */
+static int gop_xlg_mac_mode_cfg(struct mvpp2_port *port, int num_of_act_lanes)
+{
+ u32 val;
+
+ /* configure 10G MAC mode */
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ val |= MVPP22_XLG_RX_FC_EN;
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+
+ val = readl(port->base + MVPP22_XLG_CTRL3_REG);
+ val &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
+ val |= MVPP22_XLG_CTRL3_MACMODESELECT_10GMAC;
+ writel(val, port->base + MVPP22_XLG_CTRL3_REG);
+
+ /* read - modify - write */
+ val = readl(port->base + MVPP22_XLG_CTRL4_REG);
+ val &= ~MVPP22_XLG_MODE_DMA_1G;
+ val |= MVPP22_XLG_FORWARD_PFC_EN;
+ val |= MVPP22_XLG_FORWARD_802_3X_FC_EN;
+ val &= ~MVPP22_XLG_EN_IDLE_CHECK_FOR_LINK;
+ writel(val, port->base + MVPP22_XLG_CTRL4_REG);
+
+ /* Jumbo frame support: 0x1400 * 2 = 0x2800 bytes */
+ val = readl(port->base + MVPP22_XLG_CTRL1_REG);
+ val &= ~MVPP22_XLG_MAX_RX_SIZE_MASK;
+ val |= 0x1400 << MVPP22_XLG_MAX_RX_SIZE_OFFS;
+ writel(val, port->base + MVPP22_XLG_CTRL1_REG);
+
+ /* unmask link change interrupt */
+ val = readl(port->base + MVPP22_XLG_INTERRUPT_MASK_REG);
+ val |= MVPP22_XLG_INTERRUPT_LINK_CHANGE;
+ val |= 1; /* unmask summary bit */
+ writel(val, port->base + MVPP22_XLG_INTERRUPT_MASK_REG);
+
+ return 0;
+}
+
+/* Set PCS to reset or exit from reset */
+static int gop_xpcs_reset(struct mvpp2_port *port, int reset)
+{
+ u32 val;
+
+ /* read - modify - write */
+ val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+ if (reset)
+ val &= ~MVPP22_XPCS_PCSRESET;
+ else
+ val |= MVPP22_XPCS_PCSRESET;
+ writel(val, port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+
+ return 0;
+}
+
+/* Set the MAC to reset or exit from reset */
+static int gop_xlg_mac_reset(struct mvpp2_port *port, int reset)
+{
+ u32 val;
+
+ /* read - modify - write */
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ if (reset)
+ val &= ~MVPP22_XLG_MAC_RESETN;
+ else
+ val |= MVPP22_XLG_MAC_RESETN;
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+
+ return 0;
+}
+
+/*
+ * gop_port_init
+ *
+ * Init physical port. Configures the port mode and all it's elements
+ * accordingly.
+ * Does not verify that the selected mode/port number is valid at the
+ * core level.
+ */
+static int gop_port_init(struct mvpp2_port *port)
+{
+ int mac_num = port->gop_id;
+ int num_of_act_lanes;
+
+ if (mac_num >= MVPP22_GOP_MAC_NUM) {
+ netdev_err(NULL, "%s: illegal port number %d", __func__,
+ mac_num);
+ return -1;
+ }
+
+ switch (port->phy_interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ gop_gmac_reset(port, 1);
+
+ /* configure PCS */
+ gop_gpcs_mode_cfg(port, 0);
+ gop_bypass_clk_cfg(port, 1);
+
+ /* configure MAC */
+ gop_gmac_mode_cfg(port);
+ /* pcs unreset */
+ gop_gpcs_reset(port, 0);
+
+ /* mac unreset */
+ gop_gmac_reset(port, 0);
+ break;
+
+ case PHY_INTERFACE_MODE_SGMII:
+ /* configure PCS */
+ gop_gpcs_mode_cfg(port, 1);
+
+ /* configure MAC */
+ gop_gmac_mode_cfg(port);
+ /* select proper Mac mode */
+ gop_xlg_2_gig_mac_cfg(port);
+
+ /* pcs unreset */
+ gop_gpcs_reset(port, 0);
+ /* mac unreset */
+ gop_gmac_reset(port, 0);
+ break;
+
+ case PHY_INTERFACE_MODE_SFI:
+ num_of_act_lanes = 2;
+ mac_num = 0;
+ /* configure PCS */
+ gop_xpcs_mode(port, num_of_act_lanes);
+ gop_mpcs_mode(port);
+ /* configure MAC */
+ gop_xlg_mac_mode_cfg(port, num_of_act_lanes);
+
+ /* pcs unreset */
+ gop_xpcs_reset(port, 0);
+
+ /* mac unreset */
+ gop_xlg_mac_reset(port, 0);
+ break;
+
+ default:
+ netdev_err(NULL, "%s: Requested port mode (%d) not supported\n",
+ __func__, port->phy_interface);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void gop_xlg_mac_port_enable(struct mvpp2_port *port, int enable)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ if (enable) {
+ /* Enable port and MIB counters update */
+ val |= MVPP22_XLG_PORT_EN;
+ val &= ~MVPP22_XLG_MIBCNT_DIS;
+ } else {
+ /* Disable port */
+ val &= ~MVPP22_XLG_PORT_EN;
+ }
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+}
+
+static void gop_port_enable(struct mvpp2_port *port, int enable)
+{
+ switch (port->phy_interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_SGMII:
+ if (enable)
+ mvpp2_port_enable(port);
+ else
+ mvpp2_port_disable(port);
+ break;
+
+ case PHY_INTERFACE_MODE_SFI:
+ gop_xlg_mac_port_enable(port, enable);
+
+ break;
+ default:
+ netdev_err(NULL, "%s: Wrong port mode (%d)\n", __func__,
+ port->phy_interface);
+ return;
+ }
+}
+
+/* RFU1 functions */
+static inline u32 gop_rfu1_read(struct mvpp2 *priv, u32 offset)
+{
+ return readl(priv->rfu1_base + offset);
+}
+
+static inline void gop_rfu1_write(struct mvpp2 *priv, u32 offset, u32 data)
+{
+ writel(data, priv->rfu1_base + offset);
+}
+
+static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type)
+{
+ u32 val = 0;
+
+ if (gop_id == 2) {
+ if (phy_type == PHY_INTERFACE_MODE_SGMII)
+ val |= MV_NETC_GE_MAC2_SGMII;
+ }
+
+ if (gop_id == 3) {
+ if (phy_type == PHY_INTERFACE_MODE_SGMII)
+ val |= MV_NETC_GE_MAC3_SGMII;
+ else if (phy_type == PHY_INTERFACE_MODE_RGMII ||
+ phy_type == PHY_INTERFACE_MODE_RGMII_ID)
+ val |= MV_NETC_GE_MAC3_RGMII;
+ }
+
+ return val;
+}
+
+static void gop_netc_active_port(struct mvpp2 *priv, int gop_id, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_1_REG);
+ reg &= ~(NETC_PORTS_ACTIVE_MASK(gop_id));
+
+ val <<= NETC_PORTS_ACTIVE_OFFSET(gop_id);
+ val &= NETC_PORTS_ACTIVE_MASK(gop_id);
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_mii_mode(struct mvpp2 *priv, int gop_id, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_CONTROL_0_REG);
+ reg &= ~NETC_GBE_PORT1_MII_MODE_MASK;
+
+ val <<= NETC_GBE_PORT1_MII_MODE_OFFS;
+ val &= NETC_GBE_PORT1_MII_MODE_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_gop_reset(struct mvpp2 *priv, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, GOP_SOFT_RESET_1_REG);
+ reg &= ~NETC_GOP_SOFT_RESET_MASK;
+
+ val <<= NETC_GOP_SOFT_RESET_OFFS;
+ val &= NETC_GOP_SOFT_RESET_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, GOP_SOFT_RESET_1_REG, reg);
+}
+
+static void gop_netc_gop_clock_logic_set(struct mvpp2 *priv, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+ reg &= ~NETC_CLK_DIV_PHASE_MASK;
+
+ val <<= NETC_CLK_DIV_PHASE_OFFS;
+ val &= NETC_CLK_DIV_PHASE_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_port_rf_reset(struct mvpp2 *priv, int gop_id, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_1_REG);
+ reg &= ~(NETC_PORT_GIG_RF_RESET_MASK(gop_id));
+
+ val <<= NETC_PORT_GIG_RF_RESET_OFFS(gop_id);
+ val &= NETC_PORT_GIG_RF_RESET_MASK(gop_id);
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_gbe_sgmii_mode_select(struct mvpp2 *priv, int gop_id,
+ u32 val)
+{
+ u32 reg, mask, offset;
+
+ if (gop_id == 2) {
+ mask = NETC_GBE_PORT0_SGMII_MODE_MASK;
+ offset = NETC_GBE_PORT0_SGMII_MODE_OFFS;
+ } else {
+ mask = NETC_GBE_PORT1_SGMII_MODE_MASK;
+ offset = NETC_GBE_PORT1_SGMII_MODE_OFFS;
+ }
+ reg = gop_rfu1_read(priv, NETCOMP_CONTROL_0_REG);
+ reg &= ~mask;
+
+ val <<= offset;
+ val &= mask;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_bus_width_select(struct mvpp2 *priv, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+ reg &= ~NETC_BUS_WIDTH_SELECT_MASK;
+
+ val <<= NETC_BUS_WIDTH_SELECT_OFFS;
+ val &= NETC_BUS_WIDTH_SELECT_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_sample_stages_timing(struct mvpp2 *priv, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+ reg &= ~NETC_GIG_RX_DATA_SAMPLE_MASK;
+
+ val <<= NETC_GIG_RX_DATA_SAMPLE_OFFS;
+ val &= NETC_GIG_RX_DATA_SAMPLE_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_mac_to_xgmii(struct mvpp2 *priv, int gop_id,
+ enum mv_netc_phase phase)
+{
+ switch (phase) {
+ case MV_NETC_FIRST_PHASE:
+ /* Set Bus Width to HB mode = 1 */
+ gop_netc_bus_width_select(priv, 1);
+ /* Select RGMII mode */
+ gop_netc_gbe_sgmii_mode_select(priv, gop_id, MV_NETC_GBE_XMII);
+ break;
+
+ case MV_NETC_SECOND_PHASE:
+ /* De-assert the relevant port HB reset */
+ gop_netc_port_rf_reset(priv, gop_id, 1);
+ break;
+ }
+}
+
+static void gop_netc_mac_to_sgmii(struct mvpp2 *priv, int gop_id,
+ enum mv_netc_phase phase)
+{
+ switch (phase) {
+ case MV_NETC_FIRST_PHASE:
+ /* Set Bus Width to HB mode = 1 */
+ gop_netc_bus_width_select(priv, 1);
+ /* Select SGMII mode */
+ if (gop_id >= 1) {
+ gop_netc_gbe_sgmii_mode_select(priv, gop_id,
+ MV_NETC_GBE_SGMII);
+ }
+
+ /* Configure the sample stages */
+ gop_netc_sample_stages_timing(priv, 0);
+ /* Configure the ComPhy Selector */
+ /* gop_netc_com_phy_selector_config(netComplex); */
+ break;
+
+ case MV_NETC_SECOND_PHASE:
+ /* De-assert the relevant port HB reset */
+ gop_netc_port_rf_reset(priv, gop_id, 1);
+ break;
+ }
+}
+
+static int gop_netc_init(struct mvpp2 *priv, enum mv_netc_phase phase)
+{
+ u32 c = priv->netc_config;
+
+ if (c & MV_NETC_GE_MAC2_SGMII)
+ gop_netc_mac_to_sgmii(priv, 2, phase);
+ else
+ gop_netc_mac_to_xgmii(priv, 2, phase);
+
+ if (c & MV_NETC_GE_MAC3_SGMII) {
+ gop_netc_mac_to_sgmii(priv, 3, phase);
+ } else {
+ gop_netc_mac_to_xgmii(priv, 3, phase);
+ if (c & MV_NETC_GE_MAC3_RGMII)
+ gop_netc_mii_mode(priv, 3, MV_NETC_GBE_RGMII);
+ else
+ gop_netc_mii_mode(priv, 3, MV_NETC_GBE_MII);
+ }
+
+ /* Activate gop ports 0, 2, 3 */
+ gop_netc_active_port(priv, 0, 1);
+ gop_netc_active_port(priv, 2, 1);
+ gop_netc_active_port(priv, 3, 1);
+
+ if (phase == MV_NETC_SECOND_PHASE) {
+ /* Enable the GOP internal clock logic */
+ gop_netc_gop_clock_logic_set(priv, 1);
+ /* De-assert GOP unit reset */
+ gop_netc_gop_reset(priv, 1);
+ }
+
+ return 0;
+}
+
+/* Set defaults to the MVPP2 port */
+static void mvpp2_defaults_set(struct mvpp2_port *port)
+{
+ int tx_port_num, val, queue, ptxq, lrxq;
+
+ if (port->priv->hw_version == MVPP21) {
+ /* Configure port to loopback if needed */
+ if (port->flags & MVPP2_F_LOOPBACK)
+ mvpp2_port_loopback_set(port);
+
+ /* Update TX FIFO MIN Threshold */
+ val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+ /* Min. TX threshold must be less than minimal packet length */
+ val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64 - 4 - 2);
+ writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ }
+
/* Disable Legacy WRR, Disable EJP, Release from reset */
tx_port_num = mvpp2_egress_port(port);
mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG,
@@ -2791,11 +3899,15 @@ static void mvpp2_rxq_offset_set(struct mvpp2_port *port,
}
/* Obtain BM cookie information from descriptor */
-static u32 mvpp2_bm_cookie_build(struct mvpp2_rx_desc *rx_desc)
+static u32 mvpp2_bm_cookie_build(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
{
- int pool = (rx_desc->status & MVPP2_RXD_BM_POOL_ID_MASK) >>
- MVPP2_RXD_BM_POOL_ID_OFFS;
int cpu = smp_processor_id();
+ int pool;
+
+ pool = (mvpp2_rxdesc_status_get(port, rx_desc) &
+ MVPP2_RXD_BM_POOL_ID_MASK) >>
+ MVPP2_RXD_BM_POOL_ID_OFFS;
return ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS) |
((cpu & 0xFF) << MVPP2_BM_COOKIE_CPU_OFFS);
@@ -2944,9 +4056,11 @@ static int mvpp2_aggr_txq_init(struct udevice *dev,
int desc_num, int cpu,
struct mvpp2 *priv)
{
+ u32 txq_dma;
+
/* Allocate memory for TX descriptors */
aggr_txq->descs = buffer_loc.aggr_tx_descs;
- aggr_txq->descs_phys = (dma_addr_t)buffer_loc.aggr_tx_descs;
+ aggr_txq->descs_dma = (dma_addr_t)buffer_loc.aggr_tx_descs;
if (!aggr_txq->descs)
return -ENOMEM;
@@ -2960,10 +4074,16 @@ static int mvpp2_aggr_txq_init(struct udevice *dev,
aggr_txq->next_desc_to_proc = mvpp2_read(priv,
MVPP2_AGGR_TXQ_INDEX_REG(cpu));
- /* Set Tx descriptors queue starting address */
- /* indirect access */
- mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu),
- aggr_txq->descs_phys);
+ /* Set Tx descriptors queue starting address indirect
+ * access
+ */
+ if (priv->hw_version == MVPP21)
+ txq_dma = aggr_txq->descs_dma;
+ else
+ txq_dma = aggr_txq->descs_dma >>
+ MVPP22_AGGR_TXQ_DESC_ADDR_OFFS;
+
+ mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu), txq_dma);
mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_SIZE_REG(cpu), desc_num);
return 0;
@@ -2974,11 +4094,13 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
struct mvpp2_rx_queue *rxq)
{
+ u32 rxq_dma;
+
rxq->size = port->rx_ring_size;
/* Allocate memory for RX descriptors */
rxq->descs = buffer_loc.rx_descs;
- rxq->descs_phys = (dma_addr_t)buffer_loc.rx_descs;
+ rxq->descs_dma = (dma_addr_t)buffer_loc.rx_descs;
if (!rxq->descs)
return -ENOMEM;
@@ -2992,7 +4114,11 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
/* Set Rx descriptors queue starting address - indirect access */
mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
- mvpp2_write(port->priv, MVPP2_RXQ_DESC_ADDR_REG, rxq->descs_phys);
+ if (port->priv->hw_version == MVPP21)
+ rxq_dma = rxq->descs_dma;
+ else
+ rxq_dma = rxq->descs_dma >> MVPP22_DESC_ADDR_OFFS;
+ mvpp2_write(port->priv, MVPP2_RXQ_DESC_ADDR_REG, rxq_dma);
mvpp2_write(port->priv, MVPP2_RXQ_DESC_SIZE_REG, rxq->size);
mvpp2_write(port->priv, MVPP2_RXQ_INDEX_REG, 0);
@@ -3017,10 +4143,11 @@ static void mvpp2_rxq_drop_pkts(struct mvpp2_port *port,
for (i = 0; i < rx_received; i++) {
struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
- u32 bm = mvpp2_bm_cookie_build(rx_desc);
+ u32 bm = mvpp2_bm_cookie_build(port, rx_desc);
- mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
- rx_desc->buf_cookie);
+ mvpp2_pool_refill(port, bm,
+ mvpp2_rxdesc_dma_addr_get(port, rx_desc),
+ mvpp2_rxdesc_cookie_get(port, rx_desc));
}
mvpp2_rxq_status_update(port, rxq->id, rx_received, rx_received);
}
@@ -3034,7 +4161,7 @@ static void mvpp2_rxq_deinit(struct mvpp2_port *port,
rxq->descs = NULL;
rxq->last_desc = 0;
rxq->next_desc_to_proc = 0;
- rxq->descs_phys = 0;
+ rxq->descs_dma = 0;
/* Clear Rx descriptors queue starting address and size;
* free descriptor number
@@ -3057,7 +4184,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
/* Allocate memory for Tx descriptors */
txq->descs = buffer_loc.tx_descs;
- txq->descs_phys = (dma_addr_t)buffer_loc.tx_descs;
+ txq->descs_dma = (dma_addr_t)buffer_loc.tx_descs;
if (!txq->descs)
return -ENOMEM;
@@ -3069,7 +4196,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
/* Set Tx descriptors queue starting address - indirect access */
mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
- mvpp2_write(port->priv, MVPP2_TXQ_DESC_ADDR_REG, txq->descs_phys);
+ mvpp2_write(port->priv, MVPP2_TXQ_DESC_ADDR_REG, txq->descs_dma);
mvpp2_write(port->priv, MVPP2_TXQ_DESC_SIZE_REG, txq->size &
MVPP2_TXQ_DESC_SIZE_MASK);
mvpp2_write(port->priv, MVPP2_TXQ_INDEX_REG, 0);
@@ -3090,7 +4217,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG,
MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 |
- MVPP2_PREF_BUF_THRESH(desc_per_txq/2));
+ MVPP2_PREF_BUF_THRESH(desc_per_txq / 2));
/* WRR / EJP configuration - indirect access */
tx_port_num = mvpp2_egress_port(port);
@@ -3121,7 +4248,7 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
txq->descs = NULL;
txq->last_desc = 0;
txq->next_desc_to_proc = 0;
- txq->descs_phys = 0;
+ txq->descs_dma = 0;
/* Set minimum bandwidth for disabled TXQs */
mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0);
@@ -3314,20 +4441,21 @@ static void mvpp2_link_event(struct mvpp2_port *port)
static void mvpp2_rx_error(struct mvpp2_port *port,
struct mvpp2_rx_desc *rx_desc)
{
- u32 status = rx_desc->status;
+ u32 status = mvpp2_rxdesc_status_get(port, rx_desc);
+ size_t sz = mvpp2_rxdesc_size_get(port, rx_desc);
switch (status & MVPP2_RXD_ERR_CODE_MASK) {
case MVPP2_RXD_ERR_CRC:
- netdev_err(port->dev, "bad rx status %08x (crc error), size=%d\n",
- status, rx_desc->data_size);
+ netdev_err(port->dev, "bad rx status %08x (crc error), size=%zu\n",
+ status, sz);
break;
case MVPP2_RXD_ERR_OVERRUN:
- netdev_err(port->dev, "bad rx status %08x (overrun error), size=%d\n",
- status, rx_desc->data_size);
+ netdev_err(port->dev, "bad rx status %08x (overrun error), size=%zu\n",
+ status, sz);
break;
case MVPP2_RXD_ERR_RESOURCE:
- netdev_err(port->dev, "bad rx status %08x (resource error), size=%d\n",
- status, rx_desc->data_size);
+ netdev_err(port->dev, "bad rx status %08x (resource error), size=%zu\n",
+ status, sz);
break;
}
}
@@ -3335,9 +4463,9 @@ static void mvpp2_rx_error(struct mvpp2_port *port,
/* Reuse skb if possible, or allocate a new skb and add it to BM pool */
static int mvpp2_rx_refill(struct mvpp2_port *port,
struct mvpp2_bm_pool *bm_pool,
- u32 bm, u32 phys_addr)
+ u32 bm, dma_addr_t dma_addr)
{
- mvpp2_pool_refill(port, bm, phys_addr, phys_addr);
+ mvpp2_pool_refill(port, bm, dma_addr, (unsigned long)dma_addr);
return 0;
}
@@ -3347,7 +4475,10 @@ static void mvpp2_start_dev(struct mvpp2_port *port)
mvpp2_gmac_max_rx_size_set(port);
mvpp2_txp_max_tx_size_set(port);
- mvpp2_port_enable(port);
+ if (port->priv->hw_version == MVPP21)
+ mvpp2_port_enable(port);
+ else
+ gop_port_enable(port, 1);
}
/* Set hw internals when stopping port */
@@ -3357,7 +4488,11 @@ static void mvpp2_stop_dev(struct mvpp2_port *port)
mvpp2_ingress_disable(port);
mvpp2_egress_disable(port);
- mvpp2_port_disable(port);
+
+ if (port->priv->hw_version == MVPP21)
+ mvpp2_port_disable(port);
+ else
+ gop_port_enable(port, 0);
}
static int mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
@@ -3449,9 +4584,14 @@ static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port)
static void mvpp2_port_power_up(struct mvpp2_port *port)
{
- mvpp2_port_mii_set(port);
+ struct mvpp2 *priv = port->priv;
+
+ /* On PPv2.2 the GoP / interface configuration has already been done */
+ if (priv->hw_version == MVPP21)
+ mvpp2_port_mii_set(port);
mvpp2_port_periodic_xon_disable(port);
- mvpp2_port_fc_adv_enable(port);
+ if (priv->hw_version == MVPP21)
+ mvpp2_port_fc_adv_enable(port);
mvpp2_port_reset(port);
}
@@ -3462,12 +4602,16 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
struct mvpp2_txq_pcpu *txq_pcpu;
int queue, cpu, err;
- if (port->first_rxq + rxq_number > MVPP2_RXQ_TOTAL_NUM)
+ if (port->first_rxq + rxq_number >
+ MVPP2_MAX_PORTS * priv->max_port_rxqs)
return -EINVAL;
/* Disable port */
mvpp2_egress_disable(port);
- mvpp2_port_disable(port);
+ if (priv->hw_version == MVPP21)
+ mvpp2_port_disable(port);
+ else
+ gop_port_enable(port, 0);
port->txqs = devm_kcalloc(dev, txq_number, sizeof(*port->txqs),
GFP_KERNEL);
@@ -3523,7 +4667,19 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
}
/* Configure Rx queue group interrupt for this port */
- mvpp2_write(priv, MVPP2_ISR_RXQ_GROUP_REG(port->id), CONFIG_MV_ETH_RXQ);
+ if (priv->hw_version == MVPP21) {
+ mvpp2_write(priv, MVPP21_ISR_RXQ_GROUP_REG(port->id),
+ CONFIG_MV_ETH_RXQ);
+ } else {
+ u32 val;
+
+ val = (port->id << MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET);
+ mvpp2_write(priv, MVPP22_ISR_RXQ_GROUP_INDEX_REG, val);
+
+ val = (CONFIG_MV_ETH_RXQ <<
+ MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET);
+ mvpp2_write(priv, MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG, val);
+ }
/* Create Rx descriptor rings */
for (queue = 0; queue < rxq_number; queue++) {
@@ -3554,20 +4710,14 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
return 0;
}
-/* Ports initialization */
-static int mvpp2_port_probe(struct udevice *dev,
- struct mvpp2_port *port,
- int port_node,
- struct mvpp2 *priv,
- int *next_first_rxq)
+static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
{
+ int port_node = dev_of_offset(dev);
+ const char *phy_mode_str;
int phy_node;
u32 id;
u32 phyaddr;
- const char *phy_mode_str;
int phy_mode = -1;
- int priv_common_regs_num = 2;
- int err;
phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy");
if (phy_node < 0) {
@@ -3589,34 +4739,48 @@ static int mvpp2_port_probe(struct udevice *dev,
return -EINVAL;
}
+ /*
+ * ToDo:
+ * Not sure if this DT property "phy-speed" will get accepted, so
+ * this might change later
+ */
+ /* Get phy-speed for SGMII 2.5Gbps vs 1Gbps setup */
+ port->phy_speed = fdtdec_get_int(gd->fdt_blob, port_node,
+ "phy-speed", 1000);
+
phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0);
- port->priv = priv;
port->id = id;
- port->first_rxq = *next_first_rxq;
+ if (port->priv->hw_version == MVPP21)
+ port->first_rxq = port->id * rxq_number;
+ else
+ port->first_rxq = port->id * port->priv->max_port_rxqs;
port->phy_node = phy_node;
port->phy_interface = phy_mode;
port->phyaddr = phyaddr;
- port->base = (void __iomem *)dev_get_addr_index(dev->parent,
- priv_common_regs_num
- + id);
- if (IS_ERR(port->base))
- return PTR_ERR(port->base);
+ return 0;
+}
+
+/* Ports initialization */
+static int mvpp2_port_probe(struct udevice *dev,
+ struct mvpp2_port *port,
+ int port_node,
+ struct mvpp2 *priv)
+{
+ int err;
port->tx_ring_size = MVPP2_MAX_TXD;
port->rx_ring_size = MVPP2_MAX_RXD;
err = mvpp2_port_init(dev, port);
if (err < 0) {
- dev_err(&pdev->dev, "failed to init port %d\n", id);
+ dev_err(&pdev->dev, "failed to init port %d\n", port->id);
return err;
}
mvpp2_port_power_up(port);
- /* Increment the first Rx queue number to be used by the next port */
- *next_first_rxq += CONFIG_MV_ETH_RXQ;
- priv->port_list[id] = port;
+ priv->port_list[port->id] = port;
return 0;
}
@@ -3659,10 +4823,35 @@ static void mvpp2_rx_fifo_init(struct mvpp2 *priv)
int port;
for (port = 0; port < MVPP2_MAX_PORTS; port++) {
- mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(port),
- MVPP2_RX_FIFO_PORT_DATA_SIZE);
- mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
- MVPP2_RX_FIFO_PORT_ATTR_SIZE);
+ if (priv->hw_version == MVPP22) {
+ if (port == 0) {
+ mvpp2_write(priv,
+ MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+ MVPP22_RX_FIFO_10GB_PORT_DATA_SIZE);
+ mvpp2_write(priv,
+ MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+ MVPP22_RX_FIFO_10GB_PORT_ATTR_SIZE);
+ } else if (port == 1) {
+ mvpp2_write(priv,
+ MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+ MVPP22_RX_FIFO_2_5GB_PORT_DATA_SIZE);
+ mvpp2_write(priv,
+ MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+ MVPP22_RX_FIFO_2_5GB_PORT_ATTR_SIZE);
+ } else {
+ mvpp2_write(priv,
+ MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+ MVPP22_RX_FIFO_1GB_PORT_DATA_SIZE);
+ mvpp2_write(priv,
+ MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+ MVPP22_RX_FIFO_1GB_PORT_ATTR_SIZE);
+ }
+ } else {
+ mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+ MVPP21_RX_FIFO_PORT_DATA_SIZE);
+ mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+ MVPP21_RX_FIFO_PORT_ATTR_SIZE);
+ }
}
mvpp2_write(priv, MVPP2_RX_MIN_PKT_SIZE_REG,
@@ -3670,6 +4859,78 @@ static void mvpp2_rx_fifo_init(struct mvpp2 *priv)
mvpp2_write(priv, MVPP2_RX_FIFO_INIT_REG, 0x1);
}
+/* Initialize Tx FIFO's */
+static void mvpp2_tx_fifo_init(struct mvpp2 *priv)
+{
+ int port, val;
+
+ for (port = 0; port < MVPP2_MAX_PORTS; port++) {
+ /* Port 0 supports 10KB TX FIFO */
+ if (port == 0) {
+ val = MVPP2_TX_FIFO_DATA_SIZE_10KB &
+ MVPP22_TX_FIFO_SIZE_MASK;
+ } else {
+ val = MVPP2_TX_FIFO_DATA_SIZE_3KB &
+ MVPP22_TX_FIFO_SIZE_MASK;
+ }
+ mvpp2_write(priv, MVPP22_TX_FIFO_SIZE_REG(port), val);
+ }
+}
+
+static void mvpp2_axi_init(struct mvpp2 *priv)
+{
+ u32 val, rdval, wrval;
+
+ mvpp2_write(priv, MVPP22_BM_ADDR_HIGH_RLS_REG, 0x0);
+
+ /* AXI Bridge Configuration */
+
+ rdval = MVPP22_AXI_CODE_CACHE_RD_CACHE
+ << MVPP22_AXI_ATTR_CACHE_OFFS;
+ rdval |= MVPP22_AXI_CODE_DOMAIN_OUTER_DOM
+ << MVPP22_AXI_ATTR_DOMAIN_OFFS;
+
+ wrval = MVPP22_AXI_CODE_CACHE_WR_CACHE
+ << MVPP22_AXI_ATTR_CACHE_OFFS;
+ wrval |= MVPP22_AXI_CODE_DOMAIN_OUTER_DOM
+ << MVPP22_AXI_ATTR_DOMAIN_OFFS;
+
+ /* BM */
+ mvpp2_write(priv, MVPP22_AXI_BM_WR_ATTR_REG, wrval);
+ mvpp2_write(priv, MVPP22_AXI_BM_RD_ATTR_REG, rdval);
+
+ /* Descriptors */
+ mvpp2_write(priv, MVPP22_AXI_AGGRQ_DESCR_RD_ATTR_REG, rdval);
+ mvpp2_write(priv, MVPP22_AXI_TXQ_DESCR_WR_ATTR_REG, wrval);
+ mvpp2_write(priv, MVPP22_AXI_TXQ_DESCR_RD_ATTR_REG, rdval);
+ mvpp2_write(priv, MVPP22_AXI_RXQ_DESCR_WR_ATTR_REG, wrval);
+
+ /* Buffer Data */
+ mvpp2_write(priv, MVPP22_AXI_TX_DATA_RD_ATTR_REG, rdval);
+ mvpp2_write(priv, MVPP22_AXI_RX_DATA_WR_ATTR_REG, wrval);
+
+ val = MVPP22_AXI_CODE_CACHE_NON_CACHE
+ << MVPP22_AXI_CODE_CACHE_OFFS;
+ val |= MVPP22_AXI_CODE_DOMAIN_SYSTEM
+ << MVPP22_AXI_CODE_DOMAIN_OFFS;
+ mvpp2_write(priv, MVPP22_AXI_RD_NORMAL_CODE_REG, val);
+ mvpp2_write(priv, MVPP22_AXI_WR_NORMAL_CODE_REG, val);
+
+ val = MVPP22_AXI_CODE_CACHE_RD_CACHE
+ << MVPP22_AXI_CODE_CACHE_OFFS;
+ val |= MVPP22_AXI_CODE_DOMAIN_OUTER_DOM
+ << MVPP22_AXI_CODE_DOMAIN_OFFS;
+
+ mvpp2_write(priv, MVPP22_AXI_RD_SNOOP_CODE_REG, val);
+
+ val = MVPP22_AXI_CODE_CACHE_WR_CACHE
+ << MVPP22_AXI_CODE_CACHE_OFFS;
+ val |= MVPP22_AXI_CODE_DOMAIN_OUTER_DOM
+ << MVPP22_AXI_CODE_DOMAIN_OFFS;
+
+ mvpp2_write(priv, MVPP22_AXI_WR_SNOOP_CODE_REG, val);
+}
+
/* Initialize network controller common part HW */
static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
{
@@ -3678,7 +4939,8 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
u32 val;
/* Checks for hardware constraints (U-Boot uses only one rxq) */
- if ((rxq_number > MVPP2_MAX_RXQ) || (txq_number > MVPP2_MAX_TXQ)) {
+ if ((rxq_number > priv->max_port_rxqs) ||
+ (txq_number > MVPP2_MAX_TXQ)) {
dev_err(&pdev->dev, "invalid queue size parameter\n");
return -EINVAL;
}
@@ -3688,10 +4950,20 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
if (dram_target_info)
mvpp2_conf_mbus_windows(dram_target_info, priv);
- /* Disable HW PHY polling */
- val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
- val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
- writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+ if (priv->hw_version == MVPP22)
+ mvpp2_axi_init(priv);
+
+ if (priv->hw_version == MVPP21) {
+ /* Disable HW PHY polling */
+ val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+ val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
+ writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+ } else {
+ /* Enable HW PHY polling */
+ val = readl(priv->iface_base + MVPP22_SMI_MISC_CFG_REG);
+ val |= MVPP22_SMI_POLLING_EN;
+ writel(val, priv->iface_base + MVPP22_SMI_MISC_CFG_REG);
+ }
/* Allocate and initialize aggregated TXQs */
priv->aggr_txqs = devm_kcalloc(dev, num_present_cpus(),
@@ -3712,13 +4984,32 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
/* Rx Fifo Init */
mvpp2_rx_fifo_init(priv);
+ /* Tx Fifo Init */
+ if (priv->hw_version == MVPP22)
+ mvpp2_tx_fifo_init(priv);
+
/* Reset Rx queue group interrupt configuration */
- for (i = 0; i < MVPP2_MAX_PORTS; i++)
- mvpp2_write(priv, MVPP2_ISR_RXQ_GROUP_REG(i),
- CONFIG_MV_ETH_RXQ);
+ for (i = 0; i < MVPP2_MAX_PORTS; i++) {
+ if (priv->hw_version == MVPP21) {
+ mvpp2_write(priv, MVPP21_ISR_RXQ_GROUP_REG(i),
+ CONFIG_MV_ETH_RXQ);
+ continue;
+ } else {
+ u32 val;
+
+ val = (i << MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET);
+ mvpp2_write(priv, MVPP22_ISR_RXQ_GROUP_INDEX_REG, val);
+
+ val = (CONFIG_MV_ETH_RXQ <<
+ MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET);
+ mvpp2_write(priv,
+ MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG, val);
+ }
+ }
- writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
- priv->lms_base + MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG);
+ if (priv->hw_version == MVPP21)
+ writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
+ priv->lms_base + MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG);
/* Allow cache snoop when transmiting packets */
mvpp2_write(priv, MVPP2_TX_SNOOP_REG, 0x1);
@@ -3749,7 +5040,7 @@ static int smi_wait_ready(struct mvpp2 *priv)
/* wait till the SMI is not busy */
do {
/* read smi register */
- smi_reg = readl(priv->lms_base + MVPP2_SMI);
+ smi_reg = readl(priv->mdio_base);
if (timeout-- == 0) {
printf("Error: SMI busy timeout\n");
return -EFAULT;
@@ -3791,14 +5082,14 @@ static int mpp2_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
| MVPP2_SMI_OPCODE_READ;
/* write the smi register */
- writel(smi_reg, priv->lms_base + MVPP2_SMI);
+ writel(smi_reg, priv->mdio_base);
/* wait till read value is ready */
timeout = MVPP2_SMI_TIMEOUT;
do {
/* read smi register */
- smi_reg = readl(priv->lms_base + MVPP2_SMI);
+ smi_reg = readl(priv->mdio_base);
if (timeout-- == 0) {
printf("Err: SMI read ready timeout\n");
return -EFAULT;
@@ -3809,7 +5100,7 @@ static int mpp2_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
for (timeout = 0; timeout < MVPP2_SMI_TIMEOUT; timeout++)
;
- return readl(priv->lms_base + MVPP2_SMI) & MVPP2_SMI_DATA_MASK;
+ return readl(priv->mdio_base) & MVPP2_SMI_DATA_MASK;
}
/*
@@ -3846,7 +5137,7 @@ static int mpp2_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
smi_reg &= ~MVPP2_SMI_OPCODE_READ;
/* write the smi register */
- writel(smi_reg, priv->lms_base + MVPP2_SMI);
+ writel(smi_reg, priv->mdio_base);
return 0;
}
@@ -3856,7 +5147,7 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
struct mvpp2_port *port = dev_get_priv(dev);
struct mvpp2_rx_desc *rx_desc;
struct mvpp2_bm_pool *bm_pool;
- dma_addr_t phys_addr;
+ dma_addr_t dma_addr;
u32 bm, rx_status;
int pool, rx_bytes, err;
int rx_received;
@@ -3885,18 +5176,15 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
return 0;
rx_desc = mvpp2_rxq_next_desc_get(rxq);
- rx_status = rx_desc->status;
- rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
- phys_addr = rx_desc->buf_phys_addr;
+ rx_status = mvpp2_rxdesc_status_get(port, rx_desc);
+ rx_bytes = mvpp2_rxdesc_size_get(port, rx_desc);
+ rx_bytes -= MVPP2_MH_SIZE;
+ dma_addr = mvpp2_rxdesc_dma_addr_get(port, rx_desc);
- bm = mvpp2_bm_cookie_build(rx_desc);
+ bm = mvpp2_bm_cookie_build(port, rx_desc);
pool = mvpp2_bm_cookie_pool_get(bm);
bm_pool = &port->priv->bm_pools[pool];
- /* Check if buffer header is used */
- if (rx_status & MVPP2_RXD_BUF_HDR)
- return 0;
-
/* In case of an error, release the requested buffer pointer
* to the Buffer Manager. This request process is controlled
* by the hardware, and the information about the buffer is
@@ -3905,12 +5193,11 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
if (rx_status & MVPP2_RXD_ERR_SUMMARY) {
mvpp2_rx_error(port, rx_desc);
/* Return the buffer to the pool */
- mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
- rx_desc->buf_cookie);
+ mvpp2_pool_refill(port, bm, dma_addr, dma_addr);
return 0;
}
- err = mvpp2_rx_refill(port, bm_pool, bm, phys_addr);
+ err = mvpp2_rx_refill(port, bm_pool, bm, dma_addr);
if (err) {
netdev_err(port->dev, "failed to refill BM pools\n");
return 0;
@@ -3921,7 +5208,7 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
mvpp2_rxq_status_update(port, rxq->id, 1, 1);
/* give packet to stack - skip on first n bytes */
- data = (u8 *)phys_addr + 2 + 32;
+ data = (u8 *)dma_addr + 2 + 32;
if (rx_bytes <= 0)
return 0;
@@ -3963,16 +5250,20 @@ static int mvpp2_send(struct udevice *dev, void *packet, int length)
/* Get a descriptor for the first part of the packet */
tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
- tx_desc->phys_txq = txq->id;
- tx_desc->data_size = length;
- tx_desc->packet_offset = (u32)packet & MVPP2_TX_DESC_ALIGN;
- tx_desc->buf_phys_addr = (u32)packet & ~MVPP2_TX_DESC_ALIGN;
+ mvpp2_txdesc_txq_set(port, tx_desc, txq->id);
+ mvpp2_txdesc_size_set(port, tx_desc, length);
+ mvpp2_txdesc_offset_set(port, tx_desc,
+ (dma_addr_t)packet & MVPP2_TX_DESC_ALIGN);
+ mvpp2_txdesc_dma_addr_set(port, tx_desc,
+ (dma_addr_t)packet & ~MVPP2_TX_DESC_ALIGN);
/* First and Last descriptor */
- tx_desc->command = MVPP2_TXD_L4_CSUM_NOT | MVPP2_TXD_IP_CSUM_DISABLE
- | MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC;
+ mvpp2_txdesc_cmd_set(port, tx_desc,
+ MVPP2_TXD_L4_CSUM_NOT | MVPP2_TXD_IP_CSUM_DISABLE
+ | MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC);
/* Flush tx data */
- flush_dcache_range((u32)packet, (u32)packet + length);
+ flush_dcache_range((unsigned long)packet,
+ (unsigned long)packet + ALIGN(length, PKTALIGN));
/* Enable transmit */
mb();
@@ -4034,43 +5325,14 @@ static void mvpp2_stop(struct udevice *dev)
mvpp2_cleanup_txqs(port);
}
-static int mvpp2_probe(struct udevice *dev)
+static int mvpp22_smi_phy_addr_cfg(struct mvpp2_port *port)
{
- struct mvpp2_port *port = dev_get_priv(dev);
- struct mvpp2 *priv = dev_get_priv(dev->parent);
- int err;
-
- /* Initialize network controller */
- err = mvpp2_init(dev, priv);
- if (err < 0) {
- dev_err(&pdev->dev, "failed to initialize controller\n");
- return err;
- }
+ writel(port->phyaddr, port->priv->iface_base +
+ MVPP22_SMI_PHY_ADDR_REG(port->gop_id));
- return mvpp2_port_probe(dev, port, dev_of_offset(dev), priv,
- &buffer_loc.first_rxq);
+ return 0;
}
-static const struct eth_ops mvpp2_ops = {
- .start = mvpp2_start,
- .send = mvpp2_send,
- .recv = mvpp2_recv,
- .stop = mvpp2_stop,
-};
-
-static struct driver mvpp2_driver = {
- .name = "mvpp2",
- .id = UCLASS_ETH,
- .probe = mvpp2_probe,
- .ops = &mvpp2_ops,
- .priv_auto_alloc_size = sizeof(struct mvpp2_port),
- .platdata_auto_alloc_size = sizeof(struct eth_pdata),
-};
-
-/*
- * Use a MISC device to bind the n instances (child nodes) of the
- * network base controller in UCLASS_ETH.
- */
static int mvpp2_base_probe(struct udevice *dev)
{
struct mvpp2 *priv = dev_get_priv(dev);
@@ -4079,6 +5341,9 @@ static int mvpp2_base_probe(struct udevice *dev)
u32 size = 0;
int i;
+ /* Save hw-version */
+ priv->hw_version = dev_get_driver_data(dev);
+
/*
* U-Boot special buffer handling:
*
@@ -4089,35 +5354,66 @@ static int mvpp2_base_probe(struct udevice *dev)
/* Align buffer area for descs and rx_buffers to 1MiB */
bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
- mmu_set_region_dcache_behaviour((u32)bd_space, BD_SPACE, DCACHE_OFF);
+ mmu_set_region_dcache_behaviour((unsigned long)bd_space,
+ BD_SPACE, DCACHE_OFF);
buffer_loc.aggr_tx_descs = (struct mvpp2_tx_desc *)bd_space;
size += MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE;
- buffer_loc.tx_descs = (struct mvpp2_tx_desc *)((u32)bd_space + size);
+ buffer_loc.tx_descs =
+ (struct mvpp2_tx_desc *)((unsigned long)bd_space + size);
size += MVPP2_MAX_TXD * MVPP2_DESC_ALIGNED_SIZE;
- buffer_loc.rx_descs = (struct mvpp2_rx_desc *)((u32)bd_space + size);
+ buffer_loc.rx_descs =
+ (struct mvpp2_rx_desc *)((unsigned long)bd_space + size);
size += MVPP2_MAX_RXD * MVPP2_DESC_ALIGNED_SIZE;
for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
- buffer_loc.bm_pool[i] = (u32 *)((u32)bd_space + size);
- size += MVPP2_BM_POOL_SIZE_MAX * sizeof(u32);
+ buffer_loc.bm_pool[i] =
+ (unsigned long *)((unsigned long)bd_space + size);
+ if (priv->hw_version == MVPP21)
+ size += MVPP2_BM_POOL_SIZE_MAX * 2 * sizeof(u32);
+ else
+ size += MVPP2_BM_POOL_SIZE_MAX * 2 * sizeof(u64);
}
for (i = 0; i < MVPP2_BM_LONG_BUF_NUM; i++) {
- buffer_loc.rx_buffer[i] = (u32 *)((u32)bd_space + size);
+ buffer_loc.rx_buffer[i] =
+ (unsigned long *)((unsigned long)bd_space + size);
size += RX_BUFFER_SIZE;
}
+ /* Clear the complete area so that all descriptors are cleared */
+ memset(bd_space, 0, size);
+
/* Save base addresses for later use */
priv->base = (void *)dev_get_addr_index(dev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
- priv->lms_base = (void *)dev_get_addr_index(dev, 1);
- if (IS_ERR(priv->lms_base))
- return PTR_ERR(priv->lms_base);
+ if (priv->hw_version == MVPP21) {
+ priv->lms_base = (void *)dev_get_addr_index(dev, 1);
+ if (IS_ERR(priv->lms_base))
+ return PTR_ERR(priv->lms_base);
+
+ priv->mdio_base = priv->lms_base + MVPP21_SMI;
+ } else {
+ priv->iface_base = (void *)dev_get_addr_index(dev, 1);
+ if (IS_ERR(priv->iface_base))
+ return PTR_ERR(priv->iface_base);
+
+ priv->mdio_base = priv->iface_base + MVPP22_SMI;
+
+ /* Store common base addresses for all ports */
+ priv->mpcs_base = priv->iface_base + MVPP22_MPCS;
+ priv->xpcs_base = priv->iface_base + MVPP22_XPCS;
+ priv->rfu1_base = priv->iface_base + MVPP22_RFU1;
+ }
+
+ if (priv->hw_version == MVPP21)
+ priv->max_port_rxqs = 8;
+ else
+ priv->max_port_rxqs = 32;
/* Finally create and register the MDIO bus driver */
bus = mdio_alloc();
@@ -4135,6 +5431,96 @@ static int mvpp2_base_probe(struct udevice *dev)
return mdio_register(bus);
}
+static int mvpp2_probe(struct udevice *dev)
+{
+ struct mvpp2_port *port = dev_get_priv(dev);
+ struct mvpp2 *priv = dev_get_priv(dev->parent);
+ int err;
+
+ /* Only call the probe function for the parent once */
+ if (!priv->probe_done) {
+ err = mvpp2_base_probe(dev->parent);
+ priv->probe_done = 1;
+ }
+
+ port->priv = dev_get_priv(dev->parent);
+
+ err = phy_info_parse(dev, port);
+ if (err)
+ return err;
+
+ /*
+ * We need the port specific io base addresses at this stage, since
+ * gop_port_init() accesses these registers
+ */
+ if (priv->hw_version == MVPP21) {
+ int priv_common_regs_num = 2;
+
+ port->base = (void __iomem *)dev_get_addr_index(
+ dev->parent, priv_common_regs_num + port->id);
+ if (IS_ERR(port->base))
+ return PTR_ERR(port->base);
+ } else {
+ port->gop_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "gop-port-id", -1);
+ if (port->id == -1) {
+ dev_err(&pdev->dev, "missing gop-port-id value\n");
+ return -EINVAL;
+ }
+
+ port->base = priv->iface_base + MVPP22_PORT_BASE +
+ port->gop_id * MVPP22_PORT_OFFSET;
+
+ /* Set phy address of the port */
+ mvpp22_smi_phy_addr_cfg(port);
+
+ /* GoP Init */
+ gop_port_init(port);
+ }
+
+ /* Initialize network controller */
+ err = mvpp2_init(dev, priv);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to initialize controller\n");
+ return err;
+ }
+
+ err = mvpp2_port_probe(dev, port, dev_of_offset(dev), priv);
+ if (err)
+ return err;
+
+ if (priv->hw_version == MVPP22) {
+ priv->netc_config |= mvpp2_netc_cfg_create(port->gop_id,
+ port->phy_interface);
+
+ /* Netcomplex configurations for all ports */
+ gop_netc_init(priv, MV_NETC_FIRST_PHASE);
+ gop_netc_init(priv, MV_NETC_SECOND_PHASE);
+ }
+
+ return 0;
+}
+
+static const struct eth_ops mvpp2_ops = {
+ .start = mvpp2_start,
+ .send = mvpp2_send,
+ .recv = mvpp2_recv,
+ .stop = mvpp2_stop,
+};
+
+static struct driver mvpp2_driver = {
+ .name = "mvpp2",
+ .id = UCLASS_ETH,
+ .probe = mvpp2_probe,
+ .ops = &mvpp2_ops,
+ .priv_auto_alloc_size = sizeof(struct mvpp2_port),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+/*
+ * Use a MISC device to bind the n instances (child nodes) of the
+ * network base controller in UCLASS_ETH.
+ */
static int mvpp2_base_bind(struct udevice *parent)
{
const void *blob = gd->fdt_blob;
@@ -4145,6 +5531,7 @@ static int mvpp2_base_bind(struct udevice *parent)
char *name;
int subnode;
u32 id;
+ int base_id_add;
/* Lookup eth driver */
drv = lists_uclass_lookup(UCLASS_ETH);
@@ -4153,7 +5540,12 @@ static int mvpp2_base_bind(struct udevice *parent)
return -ENOENT;
}
+ base_id_add = base_id;
+
fdt_for_each_subnode(subnode, blob, node) {
+ /* Increment base_id for all subnodes, also the disabled ones */
+ base_id++;
+
/* Skip disabled ports */
if (!fdtdec_get_is_enabled(blob, subnode))
continue;
@@ -4163,6 +5555,7 @@ static int mvpp2_base_bind(struct udevice *parent)
return -ENOMEM;
id = fdtdec_get_int(blob, subnode, "port-id", -1);
+ id += base_id_add;
name = calloc(1, 16);
sprintf(name, "mvpp2-%d", id);
@@ -4176,7 +5569,14 @@ static int mvpp2_base_bind(struct udevice *parent)
}
static const struct udevice_id mvpp2_ids[] = {
- { .compatible = "marvell,armada-375-pp2" },
+ {
+ .compatible = "marvell,armada-375-pp2",
+ .data = MVPP21,
+ },
+ {
+ .compatible = "marvell,armada-7k-pp22",
+ .data = MVPP22,
+ },
{ }
};
@@ -4185,6 +5585,5 @@ U_BOOT_DRIVER(mvpp2_base) = {
.id = UCLASS_MISC,
.of_match = mvpp2_ids,
.bind = mvpp2_base_bind,
- .probe = mvpp2_base_probe,
.priv_auto_alloc_size = sizeof(struct mvpp2),
};
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 1d514e9..e562a8a 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -90,4 +90,14 @@ config PHY_VITESSE
config PHY_XILINX
bool "Xilinx Ethernet PHYs support"
+config PHY_FIXED
+ bool "Fixed-Link PHY"
+ depends on DM_ETH
+ help
+ Fixed PHY is used for having a 'fixed-link' to another MAC with a direct
+ connection (MII, RGMII, ...).
+ There is nothing like autoneogation and so
+ on, the link is always up with fixed speed and fixed duplex-setting.
+ More information: doc/device-tree-bindings/net/fixed-link.txt
+
endif #PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index d372971..88c00a5 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_PHY_TI) += ti.o
obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
obj-$(CONFIG_PHY_VITESSE) += vitesse.o
obj-$(CONFIG_PHY_MSCC) += mscc.o
+obj-$(CONFIG_PHY_FIXED) += fixed.o
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
new file mode 100644
index 0000000..df82356
--- /dev/null
+++ b/drivers/net/phy/fixed.c
@@ -0,0 +1,82 @@
+/*
+ * Fixed-Link phy
+ *
+ * Copyright 2017 Bernecker & Rainer Industrieelektronik GmbH
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <phy.h>
+#include <dm.h>
+#include <fdt_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int fixedphy_probe(struct phy_device *phydev)
+{
+ struct fixed_link *priv;
+ int ofnode = phydev->addr;
+ u32 val;
+
+ /* check for mandatory properties within fixed-link node */
+ val = fdt_getprop_u32_default_node(gd->fdt_blob,
+ ofnode, 0, "speed", 0);
+ if (val != SPEED_10 && val != SPEED_100 && val != SPEED_1000) {
+ printf("ERROR: no/invalid speed given in fixed-link node!");
+ return -EINVAL;
+ }
+
+ priv = malloc(sizeof(*priv));
+ if (!priv)
+ return -ENOMEM;
+ memset(priv, 0, sizeof(*priv));
+
+ phydev->priv = priv;
+ phydev->addr = 0;
+
+ priv->link_speed = val;
+ priv->duplex = fdtdec_get_bool(gd->fdt_blob, ofnode, "full-duplex");
+ priv->pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "pause");
+ priv->asym_pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "asym-pause");
+
+ /* fixed-link phy must not be reset by core phy code */
+ phydev->flags |= PHY_FLAG_BROKEN_RESET;
+
+ return 0;
+}
+
+int fixedphy_startup(struct phy_device *phydev)
+{
+ struct fixed_link *priv = phydev->priv;
+
+ phydev->asym_pause = priv->asym_pause;
+ phydev->pause = priv->pause;
+ phydev->duplex = priv->duplex;
+ phydev->speed = priv->link_speed;
+ phydev->link = 1;
+
+ return 0;
+}
+
+int fixedphy_shutdown(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static struct phy_driver fixedphy_driver = {
+ .uid = PHY_FIXED_ID,
+ .mask = 0xffffffff,
+ .name = "Fixed PHY",
+ .features = PHY_GBIT_FEATURES | SUPPORTED_MII,
+ .probe = fixedphy_probe,
+ .startup = fixedphy_startup,
+ .shutdown = fixedphy_shutdown,
+};
+
+int phy_fixed_init(void)
+{
+ phy_register(&fixedphy_driver);
+ return 0;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 8db6574..8bacd99 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -515,7 +515,9 @@ int phy_init(void)
#ifdef CONFIG_PHY_MSCC
phy_mscc_init();
#endif
-
+#ifdef CONFIG_PHY_FIXED
+ phy_fixed_init();
+#endif
return 0;
}
@@ -854,9 +856,24 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
struct eth_device *dev, phy_interface_t interface)
#endif
{
- struct phy_device *phydev;
+ struct phy_device *phydev = NULL;
+#ifdef CONFIG_PHY_FIXED
+ int sn;
+ const char *name;
+ sn = fdt_first_subnode(gd->fdt_blob, dev->of_offset);
+ while (sn > 0) {
+ name = fdt_get_name(gd->fdt_blob, sn, NULL);
+ if (name != NULL && strcmp(name, "fixed-link") == 0) {
+ phydev = phy_device_create(bus,
+ sn, PHY_FIXED_ID, interface);
+ break;
+ }
+ sn = fdt_next_subnode(gd->fdt_blob, sn);
+ }
+#endif
+ if (phydev == NULL)
+ phydev = phy_find_by_mask(bus, 1 << addr, interface);
- phydev = phy_find_by_mask(bus, 1 << addr, interface);
if (phydev)
phy_connect_dev(phydev, dev);
else
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 11cd0ea..99339db 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -327,6 +327,20 @@ static void emac_reset(struct emac_eth_dev *priv)
udelay(200);
}
+static int _sunxi_write_hwaddr(struct emac_eth_dev *priv, u8 *enetaddr)
+{
+ struct emac_regs *regs = priv->regs;
+ u32 enetaddr_lo, enetaddr_hi;
+
+ enetaddr_lo = enetaddr[2] | (enetaddr[1] << 8) | (enetaddr[0] << 16);
+ enetaddr_hi = enetaddr[5] | (enetaddr[4] << 8) | (enetaddr[3] << 16);
+
+ writel(enetaddr_hi, &regs->mac_a1);
+ writel(enetaddr_lo, &regs->mac_a0);
+
+ return 0;
+}
+
static int _sunxi_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr)
{
struct emac_regs *regs = priv->regs;
@@ -350,10 +364,7 @@ static int _sunxi_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr)
/* Set up EMAC */
emac_setup(priv);
- writel(enetaddr[0] << 16 | enetaddr[1] << 8 | enetaddr[2],
- &regs->mac_a1);
- writel(enetaddr[3] << 16 | enetaddr[4] << 8 | enetaddr[5],
- &regs->mac_a0);
+ _sunxi_write_hwaddr(priv, enetaddr);
mdelay(1);
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index a1408f5..40f59c0 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -551,9 +551,10 @@ int dm_pci_hose_probe_bus(struct udevice *bus)
* pci_match_one_device - Tell if a PCI device structure has a matching
* PCI device id structure
* @id: single PCI device id structure to match
- * @dev: the PCI device structure to match against
+ * @find: the PCI device id structure to match against
*
- * Returns the matching pci_device_id structure or %NULL if there is no match.
+ * Returns true if the finding pci_device_id structure matched or false if
+ * there is no match.
*/
static bool pci_match_one_id(const struct pci_device_id *id,
const struct pci_device_id *find)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c
index b6806cf..1c5a33a 100644
--- a/drivers/pci/pcie_layerscape.c
+++ b/drivers/pci/pcie_layerscape.c
@@ -167,6 +167,27 @@ static void ls_pcie_setup_atu(struct ls_pcie *pcie)
pci_get_regions(pcie->bus, &io, &mem, &pref);
idx = PCIE_ATU_REGION_INDEX1 + 1;
+ /* Fix the pcie memory map for LS2088A series SoCs */
+ svr = (svr >> SVR_VAR_PER_SHIFT) & 0xFFFFFE;
+ if (svr == SVR_LS2088A || svr == SVR_LS2084A ||
+ svr == SVR_LS2048A || svr == SVR_LS2044A) {
+ if (io)
+ io->phys_start = (io->phys_start &
+ (PCIE_PHYS_SIZE - 1)) +
+ LS2088A_PCIE1_PHYS_ADDR +
+ LS2088A_PCIE_PHYS_SIZE * pcie->idx;
+ if (mem)
+ mem->phys_start = (mem->phys_start &
+ (PCIE_PHYS_SIZE - 1)) +
+ LS2088A_PCIE1_PHYS_ADDR +
+ LS2088A_PCIE_PHYS_SIZE * pcie->idx;
+ if (pref)
+ pref->phys_start = (pref->phys_start &
+ (PCIE_PHYS_SIZE - 1)) +
+ LS2088A_PCIE1_PHYS_ADDR +
+ LS2088A_PCIE_PHYS_SIZE * pcie->idx;
+ }
+
if (io)
/* ATU : OUTBOUND : IO */
ls_pcie_atu_outbound_set(pcie, idx++,
@@ -409,6 +430,11 @@ static void ls_pcie_ep_setup_bars(void *bar_base)
ls_pcie_ep_setup_bar(bar_base, 4, PCIE_BAR4_SIZE);
}
+static void ls_pcie_ep_enable_cfg(struct ls_pcie *pcie)
+{
+ ctrl_writel(pcie, PCIE_CONFIG_READY, PCIE_PF_CONFIG);
+}
+
static void ls_pcie_setup_ep(struct ls_pcie *pcie)
{
u32 sriov;
@@ -432,6 +458,8 @@ static void ls_pcie_setup_ep(struct ls_pcie *pcie)
ls_pcie_ep_setup_bars(pcie->dbi + PCIE_NO_SRIOV_BAR_BASE);
ls_pcie_ep_setup_atu(pcie);
}
+
+ ls_pcie_ep_enable_cfg(pcie);
}
static int ls_pcie_probe(struct udevice *dev)
@@ -442,6 +470,7 @@ static int ls_pcie_probe(struct udevice *dev)
u8 header_type;
u16 link_sta;
bool ep_mode;
+ uint svr;
int ret;
pcie->bus = dev;
@@ -495,6 +524,19 @@ static int ls_pcie_probe(struct udevice *dev)
return ret;
}
+ /*
+ * Fix the pcie memory map address and PF control registers address
+ * for LS2088A series SoCs
+ */
+ svr = get_svr();
+ svr = (svr >> SVR_VAR_PER_SHIFT) & 0xFFFFFE;
+ if (svr == SVR_LS2088A || svr == SVR_LS2084A ||
+ svr == SVR_LS2048A || svr == SVR_LS2044A) {
+ pcie->cfg_res.start = LS2088A_PCIE1_PHYS_ADDR +
+ LS2088A_PCIE_PHYS_SIZE * pcie->idx;
+ pcie->ctrl = pcie->lut + 0x40000;
+ }
+
pcie->cfg0 = map_physmem(pcie->cfg_res.start,
fdt_resource_size(&pcie->cfg_res),
MAP_NOCACHE);
diff --git a/drivers/pci/pcie_layerscape.h b/drivers/pci/pcie_layerscape.h
index 1e635ef..e3324a5 100644
--- a/drivers/pci/pcie_layerscape.h
+++ b/drivers/pci/pcie_layerscape.h
@@ -26,6 +26,10 @@
#define CONFIG_SYS_PCI_EP_MEMORY_BASE CONFIG_SYS_LOAD_ADDR
#endif
+#define PCIE_PHYS_SIZE 0x200000000
+#define LS2088A_PCIE_PHYS_SIZE 0x800000000
+#define LS2088A_PCIE1_PHYS_ADDR 0x2000000000
+
/* iATU registers */
#define PCIE_ATU_VIEWPORT 0x900
#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
@@ -94,8 +98,10 @@
#define PCIE_LUT_ENTRY_COUNT 32
/* PF Controll registers */
+#define PCIE_PF_CONFIG 0x14
#define PCIE_PF_VF_CTRL 0x7F8
#define PCIE_PF_DBG 0x7FC
+#define PCIE_CONFIG_READY (1 << 0)
#define PCIE_SRDS_PRTCL(idx) (PCIE1 + (idx))
#define PCIE_SYS_BASE_ADDR 0x3400000
@@ -107,6 +113,10 @@
#define SVR_LS102XA 0
#define SVR_VAR_PER_SHIFT 8
#define SVR_LS102XA_MASK 0x700
+#define SVR_LS2088A 0x870900
+#define SVR_LS2084A 0x870910
+#define SVR_LS2048A 0x870920
+#define SVR_LS2044A 0x870930
/* LS1021a PCIE space */
#define LS1021_PCIE_SPACE_OFFSET 0x4000000000ULL
diff --git a/drivers/pci/pcie_layerscape_fixup.c b/drivers/pci/pcie_layerscape_fixup.c
index 19ede2f..d504bbd 100644
--- a/drivers/pci/pcie_layerscape_fixup.c
+++ b/drivers/pci/pcie_layerscape_fixup.c
@@ -15,7 +15,7 @@
#include <fdt_support.h>
#include "pcie_layerscape.h"
-#ifdef CONFIG_FSL_LSCH3
+#if defined(CONFIG_FSL_LSCH3) || defined(CONFIG_FSL_LSCH2)
/*
* Return next available LUT index.
*/
@@ -72,19 +72,26 @@ static void fdt_pcie_set_msi_map_entry(void *blob, struct ls_pcie *pcie,
u32 *prop;
u32 phandle;
int nodeoffset;
+ uint svr;
+ char *compat = NULL;
/* find pci controller node */
nodeoffset = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie",
pcie->dbi_res.start);
if (nodeoffset < 0) {
#ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts node */
- nodeoffset = fdt_node_offset_by_compat_reg(blob,
- CONFIG_FSL_PCIE_COMPAT, pcie->dbi_res.start);
+ svr = (get_svr() >> SVR_VAR_PER_SHIFT) & 0xFFFFFE;
+ if (svr == SVR_LS2088A || svr == SVR_LS2084A ||
+ svr == SVR_LS2048A || svr == SVR_LS2044A)
+ compat = "fsl,ls2088a-pcie";
+ else
+ compat = CONFIG_FSL_PCIE_COMPAT;
+ if (compat)
+ nodeoffset = fdt_node_offset_by_compat_reg(blob,
+ compat, pcie->dbi_res.start);
+#endif
if (nodeoffset < 0)
return;
-#else
- return;
-#endif
}
/* get phandle to MSI controller */
@@ -103,6 +110,58 @@ static void fdt_pcie_set_msi_map_entry(void *blob, struct ls_pcie *pcie,
fdt_appendprop_u32(blob, nodeoffset, "msi-map", 1);
}
+/*
+ * An iommu-map is a property to be added to the pci controller
+ * node. It is a table, where each entry consists of 4 fields
+ * e.g.:
+ *
+ * iommu-map = <[devid] [phandle-to-iommu-ctrl] [stream-id] [count]
+ * [devid] [phandle-to-iommu-ctrl] [stream-id] [count]>;
+ */
+static void fdt_pcie_set_iommu_map_entry(void *blob, struct ls_pcie *pcie,
+ u32 devid, u32 streamid)
+{
+ u32 *prop;
+ u32 iommu_map[4];
+ int nodeoffset;
+ int lenp;
+
+ /* find pci controller node */
+ nodeoffset = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie",
+ pcie->dbi_res.start);
+ if (nodeoffset < 0) {
+#ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts node */
+ nodeoffset = fdt_node_offset_by_compat_reg(blob,
+ CONFIG_FSL_PCIE_COMPAT, pcie->dbi_res.start);
+ if (nodeoffset < 0)
+ return;
+#else
+ return;
+#endif
+ }
+
+ /* get phandle to iommu controller */
+ prop = fdt_getprop_w(blob, nodeoffset, "iommu-map", &lenp);
+ if (prop == NULL) {
+ debug("\n%s: ERROR: missing iommu-map: PCIe%d\n",
+ __func__, pcie->idx);
+ return;
+ }
+
+ /* set iommu-map row */
+ iommu_map[0] = cpu_to_fdt32(devid);
+ iommu_map[1] = *++prop;
+ iommu_map[2] = cpu_to_fdt32(streamid);
+ iommu_map[3] = cpu_to_fdt32(1);
+
+ if (devid == 0) {
+ fdt_setprop_inplace(blob, nodeoffset, "iommu-map",
+ iommu_map, 16);
+ } else {
+ fdt_appendprop(blob, nodeoffset, "iommu-map", iommu_map, 16);
+ }
+}
+
static void fdt_fixup_pcie(void *blob)
{
struct udevice *dev, *bus;
@@ -139,6 +198,9 @@ static void fdt_fixup_pcie(void *blob)
/* update msi-map in device tree */
fdt_pcie_set_msi_map_entry(blob, pcie, bdf >> 8,
streamid);
+ /* update iommu-map in device tree */
+ fdt_pcie_set_iommu_map_entry(blob, pcie, bdf >> 8,
+ streamid);
}
}
#endif
@@ -146,19 +208,25 @@ static void fdt_fixup_pcie(void *blob)
static void ft_pcie_ls_setup(void *blob, struct ls_pcie *pcie)
{
int off;
+ uint svr;
+ char *compat = NULL;
off = fdt_node_offset_by_compat_reg(blob, "fsl,ls-pcie",
pcie->dbi_res.start);
if (off < 0) {
#ifdef CONFIG_FSL_PCIE_COMPAT /* Compatible with older version of dts node */
- off = fdt_node_offset_by_compat_reg(blob,
- CONFIG_FSL_PCIE_COMPAT,
- pcie->dbi_res.start);
+ svr = (get_svr() >> SVR_VAR_PER_SHIFT) & 0xFFFFFE;
+ if (svr == SVR_LS2088A || svr == SVR_LS2084A ||
+ svr == SVR_LS2048A || svr == SVR_LS2044A)
+ compat = "fsl,ls2088a-pcie";
+ else
+ compat = CONFIG_FSL_PCIE_COMPAT;
+ if (compat)
+ off = fdt_node_offset_by_compat_reg(blob,
+ compat, pcie->dbi_res.start);
+#endif
if (off < 0)
return;
-#else
- return;
-#endif
}
if (pcie->enabled)
@@ -175,7 +243,7 @@ void ft_pci_setup(void *blob, bd_t *bd)
list_for_each_entry(pcie, &ls_pcie_list, list)
ft_pcie_ls_setup(blob, pcie);
-#ifdef CONFIG_FSL_LSCH3
+#if defined(CONFIG_FSL_LSCH3) || defined(CONFIG_FSL_LSCH2)
fdt_fixup_pcie(blob);
#endif
}
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index f3e3072..9e2736c 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -212,6 +212,16 @@ config PINCTRL_STM32
definitions and pin control functions for each available multiplex
function.
+config PINCTRL_SINGLE
+ bool "Single register pin-control and pin-multiplex driver"
+ depends on DM
+ help
+ This enables pinctrl driver for systems using a single register for
+ pin configuration and multiplexing. TI's AM335X SoCs are examples of
+ such systems.
+ Depending on the platform make sure to also enable OF_TRANSLATE and
+ eventually SPL_OF_TRANSLATE to get correct address translations.
+
endif
source "drivers/pinctrl/meson/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index b04ca86..2ac9c19 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o
obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/
obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/
+obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
new file mode 100644
index 0000000..d2dcec0
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+#include <libfdt.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct single_pdata {
+ fdt_addr_t base; /* first configuration register */
+ int offset; /* index of last configuration register */
+ u32 mask; /* configuration-value mask bits */
+ int width; /* configuration register bit width */
+};
+
+struct single_fdt_pin_cfg {
+ fdt32_t reg; /* configuration register offset */
+ fdt32_t val; /* configuration register value */
+};
+
+/**
+ * single_configure_pins() - Configure pins based on FDT data
+ *
+ * @dev: Pointer to single pin configuration device which is the parent of
+ * the pins node holding the pin configuration data.
+ * @pins: Pointer to the first element of an array of register/value pairs
+ * of type 'struct single_fdt_pin_cfg'. Each such pair describes the
+ * the pin to be configured and the value to be used for configuration.
+ * This pointer points to a 'pinctrl-single,pins' property in the
+ * device-tree.
+ * @size: Size of the 'pins' array in bytes.
+ * The number of register/value pairs in the 'pins' array therefore
+ * equals to 'size / sizeof(struct single_fdt_pin_cfg)'.
+ */
+static int single_configure_pins(struct udevice *dev,
+ const struct single_fdt_pin_cfg *pins,
+ int size)
+{
+ struct single_pdata *pdata = dev->platdata;
+ int count = size / sizeof(struct single_fdt_pin_cfg);
+ int n, reg;
+ u32 val;
+
+ for (n = 0; n < count; n++) {
+ reg = fdt32_to_cpu(pins->reg);
+ if ((reg < 0) || (reg > pdata->offset)) {
+ dev_dbg(dev, " invalid register offset 0x%08x\n", reg);
+ pins++;
+ continue;
+ }
+ reg += pdata->base;
+ switch (pdata->width) {
+ case 32:
+ val = readl(reg) & ~pdata->mask;
+ val |= fdt32_to_cpu(pins->val) & pdata->mask;
+ writel(val, reg);
+ dev_dbg(dev, " reg/val 0x%08x/0x%08x\n",
+ reg, val);
+ break;
+ default:
+ dev_warn(dev, "unsupported register width %i\n",
+ pdata->width);
+ }
+ pins++;
+ }
+ return 0;
+}
+
+static int single_set_state(struct udevice *dev,
+ struct udevice *config)
+{
+ const void *fdt = gd->fdt_blob;
+ const struct single_fdt_pin_cfg *prop;
+ int len;
+
+ prop = fdt_getprop(fdt, config->of_offset, "pinctrl-single,pins", &len);
+ if (prop) {
+ dev_dbg(dev, "configuring pins for %s\n", config->name);
+ if (len % sizeof(struct single_fdt_pin_cfg)) {
+ dev_dbg(dev, " invalid pin configuration in fdt\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+ single_configure_pins(dev, prop, len);
+ len = 0;
+ }
+
+ return len;
+}
+
+static int single_ofdata_to_platdata(struct udevice *dev)
+{
+ fdt_addr_t addr;
+ u32 of_reg[2];
+ int res;
+ struct single_pdata *pdata = dev->platdata;
+
+ pdata->width = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "pinctrl-single,register-width", 0);
+
+ res = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+ "reg", of_reg, 2);
+ if (res)
+ return res;
+ pdata->offset = of_reg[1] - pdata->width / 8;
+
+ addr = dev_get_addr(dev);
+ if (addr == FDT_ADDR_T_NONE) {
+ dev_dbg(dev, "no valid base register address\n");
+ return -EINVAL;
+ }
+ pdata->base = addr;
+
+ pdata->mask = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "pinctrl-single,function-mask",
+ 0xffffffff);
+ return 0;
+}
+
+const struct pinctrl_ops single_pinctrl_ops = {
+ .set_state = single_set_state,
+};
+
+static const struct udevice_id single_pinctrl_match[] = {
+ { .compatible = "pinctrl-single" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(single_pinctrl) = {
+ .name = "single-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = single_pinctrl_match,
+ .ops = &single_pinctrl_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+ .platdata_auto_alloc_size = sizeof(struct single_pdata),
+ .ofdata_to_platdata = single_ofdata_to_platdata,
+};
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c42b0bc..fa77ee4 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -20,6 +20,14 @@ config SANDBOX_RESET
simply accepts requests to reset various HW modules without actually
doing anything beyond a little error checking.
+config STI_RESET
+ bool "Enable the STi reset"
+ depends on ARCH_STI
+ help
+ Support for reset controllers on STMicroelectronics STiH407 family SoCs.
+ Say Y if you want to control reset signals provided by system config
+ block.
+
config TEGRA_CAR_RESET
bool "Enable Tegra CAR-based reset driver"
depends on TEGRA_CAR
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 5c4305c..2b96396 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_DM_RESET) += reset-uclass.o
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
+obj-$(CONFIG_STI_RESET) += sti-reset.o
obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c
new file mode 100644
index 0000000..0c32a3d
--- /dev/null
+++ b/drivers/reset/sti-reset.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2017
+ * Patrice Chotard <patrice.chotard@st.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <wait_bit.h>
+#include <dm.h>
+#include <reset-uclass.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <dt-bindings/reset/stih407-resets.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct sti_reset {
+ const struct syscfg_reset_controller_data *data;
+};
+
+/**
+ * Reset channel description for a system configuration register based
+ * reset controller.
+ *
+ * @compatible: Compatible string of the syscon containing this
+ * channel's control and ack (status) bits.
+ * @reset_offset: Reset register offset in sysconf bank.
+ * @reset_bit: Bit number in reset register.
+ * @ack_offset: Ack reset register offset in syscon bank.
+ * @ack_bit: Bit number in Ack reset register.
+ */
+
+struct syscfg_reset_channel_data {
+ const char *compatible;
+ int reset_offset;
+ int reset_bit;
+ int ack_offset;
+ int ack_bit;
+};
+
+/**
+ * Description of a system configuration register based reset controller.
+ *
+ * @wait_for_ack: The controller will wait for reset assert and de-assert to
+ * be "ack'd" in a channel's ack field.
+ * @active_low: Are the resets in this controller active low, i.e. clearing
+ * the reset bit puts the hardware into reset.
+ * @nr_channels: The number of reset channels in this controller.
+ * @channels: An array of reset channel descriptions.
+ */
+struct syscfg_reset_controller_data {
+ bool wait_for_ack;
+ bool active_low;
+ int nr_channels;
+ const struct syscfg_reset_channel_data *channels;
+};
+
+/* STiH407 Peripheral powerdown definitions. */
+static const char stih407_core[] = "st,stih407-core-syscfg";
+static const char stih407_sbc_reg[] = "st,stih407-sbc-reg-syscfg";
+static const char stih407_lpm[] = "st,stih407-lpm-syscfg";
+
+#define _SYSCFG_RST_CH(_c, _rr, _rb, _ar, _ab) \
+ { .compatible = _c, \
+ .reset_offset = _rr, \
+ .reset_bit = _rb, \
+ .ack_offset = _ar, \
+ .ack_bit = _ab, }
+
+#define _SYSCFG_RST_CH_NO_ACK(_c, _rr, _rb) \
+ { .compatible = _c, \
+ .reset_offset = _rr, \
+ .reset_bit = _rb, }
+
+#define STIH407_SRST_CORE(_reg, _bit) \
+ _SYSCFG_RST_CH_NO_ACK(stih407_core, _reg, _bit)
+
+#define STIH407_SRST_SBC(_reg, _bit) \
+ _SYSCFG_RST_CH_NO_ACK(stih407_sbc_reg, _reg, _bit)
+
+#define STIH407_SRST_LPM(_reg, _bit) \
+ _SYSCFG_RST_CH_NO_ACK(stih407_lpm, _reg, _bit)
+
+#define STIH407_PDN_0(_bit) \
+ _SYSCFG_RST_CH(stih407_core, SYSCFG_5000, _bit, SYSSTAT_5500, _bit)
+#define STIH407_PDN_1(_bit) \
+ _SYSCFG_RST_CH(stih407_core, SYSCFG_5001, _bit, SYSSTAT_5501, _bit)
+#define STIH407_PDN_ETH(_bit, _stat) \
+ _SYSCFG_RST_CH(stih407_sbc_reg, SYSCFG_4032, _bit, SYSSTAT_4520, _stat)
+
+/* Powerdown requests control 0 */
+#define SYSCFG_5000 0x0
+#define SYSSTAT_5500 0x7d0
+/* Powerdown requests control 1 (High Speed Links) */
+#define SYSCFG_5001 0x4
+#define SYSSTAT_5501 0x7d4
+
+/* Ethernet powerdown/status/reset */
+#define SYSCFG_4032 0x80
+#define SYSSTAT_4520 0x820
+#define SYSCFG_4002 0x8
+
+static const struct syscfg_reset_channel_data stih407_powerdowns[] = {
+ [STIH407_EMISS_POWERDOWN] = STIH407_PDN_0(1),
+ [STIH407_NAND_POWERDOWN] = STIH407_PDN_0(0),
+ [STIH407_USB3_POWERDOWN] = STIH407_PDN_1(6),
+ [STIH407_USB2_PORT1_POWERDOWN] = STIH407_PDN_1(5),
+ [STIH407_USB2_PORT0_POWERDOWN] = STIH407_PDN_1(4),
+ [STIH407_PCIE1_POWERDOWN] = STIH407_PDN_1(3),
+ [STIH407_PCIE0_POWERDOWN] = STIH407_PDN_1(2),
+ [STIH407_SATA1_POWERDOWN] = STIH407_PDN_1(1),
+ [STIH407_SATA0_POWERDOWN] = STIH407_PDN_1(0),
+ [STIH407_ETH1_POWERDOWN] = STIH407_PDN_ETH(0, 2),
+};
+
+/* Reset Generator control 0/1 */
+#define SYSCFG_5128 0x200
+#define SYSCFG_5131 0x20c
+#define SYSCFG_5132 0x210
+
+#define LPM_SYSCFG_1 0x4 /* Softreset IRB & SBC UART */
+
+static const struct syscfg_reset_channel_data stih407_softresets[] = {
+ [STIH407_ETH1_SOFTRESET] = STIH407_SRST_SBC(SYSCFG_4002, 4),
+ [STIH407_MMC1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 3),
+ [STIH407_USB2_PORT0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 28),
+ [STIH407_USB2_PORT1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 29),
+ [STIH407_PICOPHY_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 30),
+ [STIH407_IRB_SOFTRESET] = STIH407_SRST_LPM(LPM_SYSCFG_1, 6),
+ [STIH407_PCIE0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 6),
+ [STIH407_PCIE1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 15),
+ [STIH407_SATA0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 7),
+ [STIH407_SATA1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 16),
+ [STIH407_MIPHY0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 4),
+ [STIH407_MIPHY1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 13),
+ [STIH407_MIPHY2_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 22),
+ [STIH407_SATA0_PWR_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 5),
+ [STIH407_SATA1_PWR_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 14),
+ [STIH407_DELTA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 3),
+ [STIH407_BLITTER_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 10),
+ [STIH407_HDTVOUT_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 11),
+ [STIH407_HDQVDP_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 12),
+ [STIH407_VDP_AUX_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 14),
+ [STIH407_COMPO_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 15),
+ [STIH407_HDMI_TX_PHY_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 21),
+ [STIH407_JPEG_DEC_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 23),
+ [STIH407_VP8_DEC_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 24),
+ [STIH407_GPU_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 30),
+ [STIH407_HVA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 0),
+ [STIH407_ERAM_HVA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 1),
+ [STIH407_LPM_SOFTRESET] = STIH407_SRST_SBC(SYSCFG_4002, 2),
+ [STIH407_KEYSCAN_SOFTRESET] = STIH407_SRST_LPM(LPM_SYSCFG_1, 8),
+ [STIH407_ST231_AUD_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 26),
+ [STIH407_ST231_DMU_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 27),
+ [STIH407_ST231_GP0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 28),
+ [STIH407_ST231_GP1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5128, 2),
+};
+
+/* PicoPHY reset/control */
+#define SYSCFG_5061 0x0f4
+
+static const struct syscfg_reset_channel_data stih407_picophyresets[] = {
+ [STIH407_PICOPHY0_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 5),
+ [STIH407_PICOPHY1_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 6),
+ [STIH407_PICOPHY2_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 7),
+};
+
+static const struct
+syscfg_reset_controller_data stih407_powerdown_controller = {
+ .wait_for_ack = true,
+ .nr_channels = ARRAY_SIZE(stih407_powerdowns),
+ .channels = stih407_powerdowns,
+};
+
+static const struct
+syscfg_reset_controller_data stih407_softreset_controller = {
+ .wait_for_ack = false,
+ .active_low = true,
+ .nr_channels = ARRAY_SIZE(stih407_softresets),
+ .channels = stih407_softresets,
+};
+
+static const struct
+syscfg_reset_controller_data stih407_picophyreset_controller = {
+ .wait_for_ack = false,
+ .nr_channels = ARRAY_SIZE(stih407_picophyresets),
+ .channels = stih407_picophyresets,
+};
+
+phys_addr_t sti_reset_get_regmap(const char *compatible)
+{
+ struct udevice *syscon;
+ struct regmap *regmap;
+ int node, ret;
+
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+ compatible);
+ if (node < 0) {
+ error("unable to find %s node\n", compatible);
+ return node;
+ }
+
+ ret = uclass_get_device_by_of_offset(UCLASS_SYSCON, node, &syscon);
+ if (ret) {
+ error("%s: uclass_get_device_by_of_offset failed: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ regmap = syscon_get_regmap(syscon);
+ if (!regmap) {
+ error("unable to get regmap for %s\n", syscon->name);
+ return -ENODEV;
+ }
+
+ return regmap->base;
+}
+
+static int sti_reset_program_hw(struct reset_ctl *reset_ctl, int assert)
+{
+ struct udevice *dev = reset_ctl->dev;
+ struct syscfg_reset_controller_data *reset_desc =
+ (struct syscfg_reset_controller_data *)(dev->driver_data);
+ struct syscfg_reset_channel_data ch;
+ phys_addr_t base;
+ u32 ctrl_val = reset_desc->active_low ? !assert : !!assert;
+ void __iomem *reg;
+
+ /* check if reset id is inside available range */
+ if (reset_ctl->id >= reset_desc->nr_channels)
+ return -EINVAL;
+
+ /* get reset sysconf register base address */
+ base = sti_reset_get_regmap(reset_desc->channels[reset_ctl->id].compatible);
+
+ ch = reset_desc->channels[reset_ctl->id];
+ reg = (void __iomem *)base + ch.reset_offset;
+
+ if (ctrl_val)
+ generic_set_bit(ch.reset_bit, reg);
+ else
+ generic_clear_bit(ch.reset_bit, reg);
+
+ if (!reset_desc->wait_for_ack)
+ return 0;
+
+ reg = (void __iomem *)base + ch.ack_offset;
+ if (wait_for_bit(__func__, reg, BIT(ch.ack_bit), ctrl_val,
+ 1000, false)) {
+ error("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n",
+ reset_ctl, reset_ctl->dev, reset_ctl->id);
+
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int sti_reset_request(struct reset_ctl *reset_ctl)
+{
+ return 0;
+}
+
+static int sti_reset_free(struct reset_ctl *reset_ctl)
+{
+ return 0;
+}
+
+static int sti_reset_assert(struct reset_ctl *reset_ctl)
+{
+ return sti_reset_program_hw(reset_ctl, true);
+}
+
+static int sti_reset_deassert(struct reset_ctl *reset_ctl)
+{
+ return sti_reset_program_hw(reset_ctl, false);
+}
+
+struct reset_ops sti_reset_ops = {
+ .request = sti_reset_request,
+ .free = sti_reset_free,
+ .rst_assert = sti_reset_assert,
+ .rst_deassert = sti_reset_deassert,
+};
+
+static int sti_reset_probe(struct udevice *dev)
+{
+ struct sti_reset *priv = dev_get_priv(dev);
+
+ priv->data = (void *)dev_get_driver_data(dev);
+
+ return 0;
+}
+
+static const struct udevice_id sti_reset_ids[] = {
+ {
+ .compatible = "st,stih407-picophyreset",
+ .data = (ulong)&stih407_picophyreset_controller,
+ },
+ {
+ .compatible = "st,stih407-powerdown",
+ .data = (ulong)&stih407_powerdown_controller,
+ },
+ {
+ .compatible = "st,stih407-softreset",
+ .data = (ulong)&stih407_softreset_controller,
+ },
+ { }
+};
+
+U_BOOT_DRIVER(sti_reset) = {
+ .name = "sti_reset",
+ .id = UCLASS_RESET,
+ .of_match = sti_reset_ids,
+ .probe = sti_reset_probe,
+ .priv_auto_alloc_size = sizeof(struct sti_reset),
+ .ops = &sti_reset_ops,
+};
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index b2a0583..e61c67b 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -1037,8 +1037,11 @@ static int fsl_qspi_probe(struct udevice *bus)
* setting the size of these devices to 0. This would ensure
* that the complete memory map is assigned to only one flash device.
*/
- qspi_write32(priv->flags, &priv->regs->sfa1ad, priv->amba_base[1]);
+ qspi_write32(priv->flags, &priv->regs->sfa1ad,
+ priv->amba_base[0] + amba_size_per_chip);
switch (priv->num_chipselect) {
+ case 1:
+ break;
case 2:
qspi_write32(priv->flags, &priv->regs->sfa2ad,
priv->amba_base[1]);
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig
index 3490ee0..2a64bc4 100644
--- a/drivers/tpm/Kconfig
+++ b/drivers/tpm/Kconfig
@@ -88,4 +88,19 @@ config TPM_FLUSH_RESOURCES
help
Enable support to flush specific resources (e.g. keys) from the TPM.
The functionality is available via the 'tpm' command as well.
+
+config TPM_LOAD_KEY_BY_SHA1
+ bool "Enable TPM key loading by SHA1 support"
+ depends on TPM
+ help
+ Enable support to load keys into the TPM by identifying
+ their parent via the public key's SHA1 hash.
+ The functionality is available via the 'tpm' command as well.
+
+config TPM_LIST_RESOURCES
+ bool "Enable TPM resource listing support"
+ depends on TPM
+ help
+ Enable support to list specific resources (e.g. keys) within the TPM.
+ The functionality is available via the 'tpm' command as well.
endmenu
diff --git a/dts/Makefile b/dts/Makefile
index c4ac153..3a93daf 100644
--- a/dts/Makefile
+++ b/dts/Makefile
@@ -12,10 +12,14 @@ ifeq ($(DEVICE_TREE),)
DEVICE_TREE := unset
endif
+ARCH_PATH := arch/$(ARCH)/dts
+dtb_depends := arch-dtbs
+
ifneq ($(EXT_DTB),)
DTB := $(EXT_DTB)
else
-DTB := arch/$(ARCH)/dts/$(DEVICE_TREE).dtb
+DTB := $(ARCH_PATH)/$(DEVICE_TREE).dtb
+dtb_depends += $(DTB:.dtb=.dts)
endif
$(obj)/dt.dtb: $(DTB) FORCE
@@ -23,7 +27,10 @@ $(obj)/dt.dtb: $(DTB) FORCE
targets += dt.dtb
-$(DTB): arch-dtbs
+$(DTB): $(dtb_depends)
+ifeq ($(EXT_DTB),)
+ $(Q)$(MAKE) $(build)=$(ARCH_PATH) $@
+endif
$(Q)test -e $@ || ( \
echo >&2; \
echo >&2 "Device Tree Source is not correctly specified."; \
@@ -33,7 +40,7 @@ $(DTB): arch-dtbs
/bin/false)
arch-dtbs:
- $(Q)$(MAKE) $(build)=arch/$(ARCH)/dts dtbs
+ $(Q)$(MAKE) $(build)=$(ARCH_PATH) dtbs
.SECONDARY: $(obj)/dt.dtb.S
diff --git a/include/configs/ls1012a_common.h b/include/configs/ls1012a_common.h
index af07672..1a0c7f8 100644
--- a/include/configs/ls1012a_common.h
+++ b/include/configs/ls1012a_common.h
@@ -11,6 +11,7 @@
#define CONFIG_GICV2
#include <asm/arch/config.h>
+#include <asm/arch/stream_id_lsch2.h>
#define CONFIG_SUPPORT_RAW_INITRD
diff --git a/include/configs/ls1043a_common.h b/include/configs/ls1043a_common.h
index 5a5f951..46d54a0 100644
--- a/include/configs/ls1043a_common.h
+++ b/include/configs/ls1043a_common.h
@@ -13,6 +13,7 @@
#define CONFIG_MP
#define CONFIG_GICV2
+#include <asm/arch/stream_id_lsch2.h>
#include <asm/arch/config.h>
/* Link Definitions */
@@ -187,12 +188,14 @@
#define MTDPARTS_DEFAULT "mtdparts=spi0.0:1m(uboot)," \
"5m(kernel),1m(dtb),9m(file_system)"
#else
-#define MTDPARTS_DEFAULT "mtdparts=60000000.nor:1m(nor_bank0_rcw)," \
- "1m(nor_bank0_uboot),1m(nor_bank0_uboot_env)," \
- "1m(nor_bank0_fman_uconde),40m(nor_bank0_fit)," \
- "1m(nor_bank4_rcw),1m(nor_bank4_uboot)," \
- "1m(nor_bank4_uboot_env),1m(nor_bank4_fman_ucode)," \
- "40m(nor_bank4_fit);7e800000.flash:" \
+#define MTDPARTS_DEFAULT "mtdparts=60000000.nor:" \
+ "2m@0x100000(nor_bank0_uboot),"\
+ "40m@0x1100000(nor_bank0_fit)," \
+ "7m(nor_bank0_user)," \
+ "2m@0x4100000(nor_bank4_uboot)," \
+ "40m@0x5100000(nor_bank4_fit),"\
+ "-(nor_bank4_user);" \
+ "7e800000.flash:" \
"1m(nand_uboot),1m(nand_uboot_env)," \
"20m(nand_fit);spi0.0:1m(uboot)," \
"5m(kernel),1m(dtb),9m(file_system)"
diff --git a/include/configs/ls1046a_common.h b/include/configs/ls1046a_common.h
index 1ed7517..cb79296 100644
--- a/include/configs/ls1046a_common.h
+++ b/include/configs/ls1046a_common.h
@@ -13,6 +13,7 @@
#define CONFIG_GICV2
#include <asm/arch/config.h>
+#include <asm/arch/stream_id_lsch2.h>
/* Link Definitions */
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_FSL_OCRAM_BASE + 0xfff0)
diff --git a/include/configs/ls1046aqds.h b/include/configs/ls1046aqds.h
index 4b3b21e..476387d 100644
--- a/include/configs/ls1046aqds.h
+++ b/include/configs/ls1046aqds.h
@@ -485,12 +485,14 @@ unsigned long get_board_ddr_clk(void);
#define MTDPARTS_DEFAULT "mtdparts=1550000.quadspi:2m(uboot)," \
"14m(free)"
#else
-#define MTDPARTS_DEFAULT "mtdparts=60000000.nor:1m(nor_bank0_rcw)," \
- "1m(nor_bank0_uboot),1m(nor_bank0_uboot_env)," \
- "1m(nor_bank0_fman_uconde),40m(nor_bank0_fit)," \
- "1m(nor_bank4_rcw),1m(nor_bank4_uboot)," \
- "1m(nor_bank4_uboot_env),1m(nor_bank4_fman_ucode)," \
- "40m(nor_bank4_fit);7e800000.flash:" \
+#define MTDPARTS_DEFAULT "mtdparts=60000000.nor:" \
+ "2m@0x100000(nor_bank0_uboot),"\
+ "40m@0x1100000(nor_bank0_fit)," \
+ "7m(nor_bank0_user)," \
+ "2m@0x4100000(nor_bank4_uboot)," \
+ "40m@0x5100000(nor_bank4_fit),"\
+ "-(nor_bank4_user);" \
+ "7e800000.flash:" \
"4m(nand_uboot),36m(nand_kernel)," \
"472m(nand_free);spi0.0:2m(uboot)," \
"14m(free)"
diff --git a/include/configs/ls2080a_common.h b/include/configs/ls2080a_common.h
index 5072e20..427f623 100644
--- a/include/configs/ls2080a_common.h
+++ b/include/configs/ls2080a_common.h
@@ -13,7 +13,7 @@
#define CONFIG_GICV3
#define CONFIG_FSL_TZPC_BP147
-#include <asm/arch/ls2080a_stream_id.h>
+#include <asm/arch/stream_id_lsch3.h>
#include <asm/arch/config.h>
/* Link Definitions */
diff --git a/include/configs/ls2080aqds.h b/include/configs/ls2080aqds.h
index 08d1586..beacb99 100644
--- a/include/configs/ls2080aqds.h
+++ b/include/configs/ls2080aqds.h
@@ -368,6 +368,7 @@ unsigned long get_board_ddr_clk(void);
"kernel_start=0x581100000\0" \
"kernel_load=0xa0000000\0" \
"kernel_size=0x2800000\0" \
+ "mcmemsize=0x40000000\0" \
"mcinitcmd=esbc_validate 0x580c80000;" \
"esbc_validate 0x580cc0000;" \
"fsl_mc start mc 0x580300000" \
@@ -384,6 +385,7 @@ unsigned long get_board_ddr_clk(void);
"kernel_start=0x581100000\0" \
"kernel_load=0xa0000000\0" \
"kernel_size=0x2800000\0" \
+ "mcmemsize=0x40000000\0" \
"mcinitcmd=fsl_mc start mc 0x580300000" \
" 0x580800000 \0"
#endif /* CONFIG_SECURE_BOOT */
diff --git a/include/configs/ls2080ardb.h b/include/configs/ls2080ardb.h
index 408140f..2155a89 100644
--- a/include/configs/ls2080ardb.h
+++ b/include/configs/ls2080ardb.h
@@ -339,6 +339,7 @@ unsigned long get_board_sys_clk(void);
"kernel_start=0x581100000\0" \
"kernel_load=0xa0000000\0" \
"kernel_size=0x2800000\0" \
+ "mcmemsize=0x40000000\0" \
"fdtfile=fsl-ls2080a-rdb.dtb\0" \
"mcinitcmd=esbc_validate 0x580c80000;" \
"esbc_validate 0x580cc0000;" \
@@ -362,6 +363,7 @@ unsigned long get_board_sys_clk(void);
"kernel_start=0x581100000\0" \
"kernel_load=0xa0000000\0" \
"kernel_size=0x2800000\0" \
+ "mcmemsize=0x40000000\0" \
"fdtfile=fsl-ls2080a-rdb.dtb\0" \
"mcinitcmd=fsl_mc start mc 0x580300000" \
" 0x580800000 \0" \
diff --git a/include/configs/mvebu_armada-8k.h b/include/configs/mvebu_armada-8k.h
index a8a9d15..8ee5f27 100644
--- a/include/configs/mvebu_armada-8k.h
+++ b/include/configs/mvebu_armada-8k.h
@@ -81,6 +81,14 @@
#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */
#define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */
+/*
+ * Ethernet Driver configuration
+ */
+#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */
+#define CONFIG_PHY_GIGE /* GbE speed/duplex detect */
+#define CONFIG_ARP_TIMEOUT 200
+#define CONFIG_NET_RETRY_COUNT 50
+
/* USB 2.0 */
#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3
diff --git a/include/fsl-mc/ldpaa_wriop.h b/include/fsl-mc/ldpaa_wriop.h
index 6dc159d..8ae0fc0 100644
--- a/include/fsl-mc/ldpaa_wriop.h
+++ b/include/fsl-mc/ldpaa_wriop.h
@@ -68,4 +68,5 @@ phy_interface_t wriop_get_enet_if(int);
void wriop_dpmac_disable(int);
void wriop_dpmac_enable(int);
phy_interface_t wriop_dpmac_enet_if(int, int);
+void wriop_init_dpmac_qsgmii(int, int);
#endif /* __LDPAA_WRIOP_H */
diff --git a/include/fsl_validate.h b/include/fsl_validate.h
index c350938..452c6df 100644
--- a/include/fsl_validate.h
+++ b/include/fsl_validate.h
@@ -40,8 +40,8 @@ struct fsl_secboot_img_hdr {
u8 num_srk;
u8 srk_sel;
u8 reserve;
- u8 ie_flag;
} len_kr;
+ u8 ie_flag;
u32 uid_flag;
@@ -69,6 +69,11 @@ struct fsl_secboot_img_hdr {
#define MAX_KEY_ENTRIES 8
#endif
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+#define IE_FLAG_MASK 0x1
+#define SCRATCH_IE_LOW_ADR 13
+#define SCRATCH_IE_HIGH_ADR 14
+#endif
#else /* CONFIG_ESBC_HDR_LS */
@@ -150,6 +155,10 @@ struct fsl_secboot_img_hdr {
#define MAX_KEY_ENTRIES 4
#endif
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+#define IE_FLAG_MASK 0xFFFFFFFF
+#endif
+
#endif /* CONFIG_ESBC_HDR_LS */
@@ -202,6 +211,17 @@ struct fsl_secboot_sg_table {
};
#endif
+/* ESBC global structure.
+ * Data to be used across verification of different images.
+ * Stores follwoing Data:
+ * IE Table
+ */
+struct fsl_secboot_glb {
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+ uintptr_t ie_addr;
+ struct ie_key_info ie_tbl;
+#endif
+};
/*
* ESBC private structure.
* Private structure used by ESBC to store following fields
@@ -213,7 +233,7 @@ struct fsl_secboot_sg_table {
*/
struct fsl_secboot_img_priv {
uint32_t hdr_location;
- u32 ie_addr;
+ uintptr_t ie_addr;
u32 key_len;
struct fsl_secboot_img_hdr hdr;
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 1b2e491..576b15d 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -2,6 +2,7 @@
#define _LINUX_BITOPS_H
#include <asm/types.h>
+#include <asm-generic/bitsperlong.h>
#include <linux/compiler.h>
#define BIT(nr) (1UL << (nr))
diff --git a/include/nand.h b/include/nand.h
index b6eb223..a865528 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -28,6 +28,7 @@
#endif
extern void nand_init(void);
+unsigned long nand_size(void);
#include <linux/compat.h>
#include <linux/mtd/mtd.h>
diff --git a/include/phy.h b/include/phy.h
index 5477496..4f2094b 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -15,6 +15,8 @@
#include <linux/ethtool.h>
#include <linux/mdio.h>
+#define PHY_FIXED_ID 0xa5a55a5a
+
#define PHY_MAX_ADDR 32
#define PHY_FLAG_BROKEN_RESET (1 << 0) /* soft reset not supported */
@@ -61,6 +63,9 @@ typedef enum {
PHY_INTERFACE_MODE_RGMII_TXID,
PHY_INTERFACE_MODE_RTBI,
PHY_INTERFACE_MODE_XGMII,
+ PHY_INTERFACE_MODE_XAUI,
+ PHY_INTERFACE_MODE_RXAUI,
+ PHY_INTERFACE_MODE_SFI,
PHY_INTERFACE_MODE_NONE, /* Must be last */
PHY_INTERFACE_MODE_COUNT,
@@ -80,6 +85,9 @@ static const char *phy_interface_strings[] = {
[PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
[PHY_INTERFACE_MODE_RTBI] = "rtbi",
[PHY_INTERFACE_MODE_XGMII] = "xgmii",
+ [PHY_INTERFACE_MODE_XAUI] = "xaui",
+ [PHY_INTERFACE_MODE_RXAUI] = "rxaui",
+ [PHY_INTERFACE_MODE_SFI] = "sfi",
[PHY_INTERFACE_MODE_NONE] = "",
};
@@ -267,6 +275,7 @@ int phy_ti_init(void);
int phy_vitesse_init(void);
int phy_xilinx_init(void);
int phy_mscc_init(void);
+int phy_fixed_init(void);
int board_phy_config(struct phy_device *phydev);
int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id);
diff --git a/include/tpm.h b/include/tpm.h
index 800f29c..f88388f 100644
--- a/include/tpm.h
+++ b/include/tpm.h
@@ -639,4 +639,16 @@ uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm);
*/
uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type);
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+/**
+ * Search for a key by usage AuthData and the hash of the parent's pub key.
+ *
+ * @param auth Usage auth of the key to search for
+ * @param pubkey_digest SHA1 hash of the pub key structure of the key
+ * @param[out] handle The handle of the key (Non-null iff found)
+ * @return 0 if key was found in TPM; != 0 if not.
+ */
+uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
+ pubkey_digest[20], uint32_t *handle);
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
#endif /* __TPM_H */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 81f47ef..1edfbf2 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -112,7 +112,7 @@ fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
return FDT_ADDR_T_NONE;
}
-#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_OF_LIBFDT)
+#if CONFIG_IS_ENABLED(OF_TRANSLATE)
if (translate)
addr = fdt_translate_address(blob, node, prop_addr);
else
diff --git a/lib/tpm.c b/lib/tpm.c
index fb12214..cd7f88f 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -996,4 +996,44 @@ uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
return 0;
}
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
+ pubkey_digest[20], uint32_t *handle)
+{
+ uint16_t key_count;
+ uint32_t key_handles[10];
+ uint8_t buf[288];
+ uint8_t *ptr;
+ uint32_t err;
+ uint8_t digest[20];
+ size_t buf_len;
+ unsigned int i;
+
+ /* fetch list of already loaded keys in the TPM */
+ err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+ if (err)
+ return -1;
+ key_count = get_unaligned_be16(buf);
+ ptr = buf + 2;
+ for (i = 0; i < key_count; ++i, ptr += 4)
+ key_handles[i] = get_unaligned_be32(ptr);
+
+ /* now search a(/ the) key which we can access with the given auth */
+ for (i = 0; i < key_count; ++i) {
+ buf_len = sizeof(buf);
+ err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+ if (err && err != TPM_AUTHFAIL)
+ return -1;
+ if (err)
+ continue;
+ sha1_csum(buf, buf_len, digest);
+ if (!memcmp(digest, pubkey_digest, 20)) {
+ *handle = key_handles[i];
+ return 0;
+ }
+ }
+ return 1;
+}
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
#endif /* CONFIG_TPM_AUTH_SESSIONS */
diff --git a/net/link_local.c b/net/link_local.c
index 27851b6..dfd240d 100644
--- a/net/link_local.c
+++ b/net/link_local.c
@@ -111,7 +111,7 @@ void link_local_start(void)
net_set_state(NETLOOP_FAIL);
return;
}
- net_netmask.s_addr = IN_CLASSB_NET;
+ net_netmask.s_addr = htonl(IN_CLASSB_NET);
seed = seed_mac();
if (ip.s_addr == 0)
diff --git a/tools/pblimage.c b/tools/pblimage.c
index 16d94c98..ffc3268 100644
--- a/tools/pblimage.c
+++ b/tools/pblimage.c
@@ -194,17 +194,20 @@ void pbl_load_uboot(int ifd, struct image_tool_params *params)
pbl_parser(params->imagename);
/* parse the pbi.cfg file. */
- pbl_parser(params->imagename2);
+ if (params->imagename2[0] != '\0')
+ pbl_parser(params->imagename2);
+
+ if (params->datafile) {
+ fp_uboot = fopen(params->datafile, "r");
+ if (fp_uboot == NULL) {
+ printf("Error: %s open failed\n", params->datafile);
+ exit(EXIT_FAILURE);
+ }
- fp_uboot = fopen(params->datafile, "r");
- if (fp_uboot == NULL) {
- printf("Error: %s open failed\n", params->datafile);
- exit(EXIT_FAILURE);
+ load_uboot(fp_uboot);
+ fclose(fp_uboot);
}
-
- load_uboot(fp_uboot);
add_end_cmd();
- fclose(fp_uboot);
lseek(ifd, 0, SEEK_SET);
size = pbl_size;
@@ -265,21 +268,24 @@ int pblimage_check_params(struct image_tool_params *params)
if (!params)
return EXIT_FAILURE;
- fp_uboot = fopen(params->datafile, "r");
- if (fp_uboot == NULL) {
- printf("Error: %s open failed\n", params->datafile);
- exit(EXIT_FAILURE);
- }
- fd = fileno(fp_uboot);
+ if (params->datafile) {
+ fp_uboot = fopen(params->datafile, "r");
+ if (fp_uboot == NULL) {
+ printf("Error: %s open failed\n", params->datafile);
+ exit(EXIT_FAILURE);
+ }
+ fd = fileno(fp_uboot);
- if (fstat(fd, &st) == -1) {
- printf("Error: Could not determine u-boot image size. %s\n",
- strerror(errno));
- exit(EXIT_FAILURE);
- }
+ if (fstat(fd, &st) == -1) {
+ printf("Error: Could not determine u-boot image size. %s\n",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
- /* For the variable size, we need to pad it to 64 byte boundary */
- uboot_size = roundup(st.st_size, 64);
+ /* For the variable size, pad it to 64 byte boundary */
+ uboot_size = roundup(st.st_size, 64);
+ fclose(fp_uboot);
+ }
if (params->arch == IH_ARCH_ARM) {
arch_flag = IH_ARCH_ARM;