diff options
author | Tom Rini <trini@konsulko.com> | 2016-03-22 12:14:27 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-03-22 12:14:27 -0400 |
commit | 55926ddd189546742a4496e6690c2b62958cd7cd (patch) | |
tree | 737b2eb33d373333dafdcaa6d8a55c14e13f7667 /drivers | |
parent | a119357c43a4d4bd0e488a701255bcfea8f8bf6c (diff) | |
parent | 6dedcedd6442295428ea7f02b0d30739499858a2 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-fsl-qoriq
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/crypto/fsl/desc.h | 80 | ||||
-rw-r--r-- | drivers/crypto/fsl/desc_constr.h | 27 | ||||
-rw-r--r-- | drivers/crypto/fsl/jr.c | 2 | ||||
-rw-r--r-- | drivers/ddr/fsl/ctrl_regs.c | 55 | ||||
-rw-r--r-- | drivers/ddr/fsl/fsl_ddr_gen4.c | 44 | ||||
-rw-r--r-- | drivers/ddr/fsl/options.c | 15 | ||||
-rw-r--r-- | drivers/net/fsl-mc/mc.c | 3 | ||||
-rw-r--r-- | drivers/net/ldpaa_eth/ldpaa_eth.c | 121 | ||||
-rw-r--r-- | drivers/pci/pcie_layerscape.c | 217 |
9 files changed, 446 insertions, 118 deletions
diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h index 18e2ec8d26..1ac3a09dff 100644 --- a/drivers/crypto/fsl/desc.h +++ b/drivers/crypto/fsl/desc.h @@ -436,6 +436,31 @@ #define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT) #define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT) #define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT) +#define OP_PCLID_DSA_SIGN (0x15 << OP_PCLID_SHIFT) +#define OP_PCLID_DSA_VERIFY (0x16 << OP_PCLID_SHIFT) + +/* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL */ +#define OP_PCLID_MP_PUB_KEY (0x14 << OP_PCLID_SHIFT) +#define OP_PCLID_MP_SIGN (0x15 << OP_PCLID_SHIFT) + +/* Assuming OP_TYPE = OP_TYPE_ENCAP_PROTOCOL */ +#define OP_PCLID_MP_PRIV_KEY (0x14 << OP_PCLID_SHIFT) + +/* PROTINFO fields for discrete log public key protocols */ +#define OP_PROTINFO_F2M_FP 0x00000001 +#define OP_PROTINFO_ECC_DL 0x00000002 +#define OP_PROTINFO_ENC_PRI 0x00000004 +#define OP_PROTINFO_TEST 0x00000008 +#define OP_PROTINFO_EXT_PRI 0x00000010 +#define OP_PROTINFO_ENC_Z 0x00000020 +#define OP_PROTINFO_EKT_Z 0x00000040 +#define OP_PROTINFO_MES_REP 0x00000400 +#define OP_PROTINFO_HASH_MD5 0x00000000 +#define OP_PROTINFO_HASH_SHA1 0x00000080 +#define OP_PROTINFO_HASH_SHA224 0x00000100 +#define OP_PROTINFO_HASH_SHA256 0x00000180 +#define OP_PROTINFO_HASH_SHA384 0x00000200 +#define OP_PROTINFO_HASH_SHA512 0x00000280 /* For non-protocol/alg-only op commands */ #define OP_ALG_TYPE_SHIFT 24 @@ -663,4 +688,59 @@ #define OP_ALG_RNG4_MAS (0x1f3 << OP_ALG_RNG4_SHIFT) #define OP_ALG_RNG4_SK (0x100 << OP_ALG_RNG4_SHIFT) + +/* Structures for Protocol Data Blocks */ +struct __packed pdb_ecdsa_verify { + uint32_t pdb_hdr; + dma_addr_t dma_q; /* Pointer to q (elliptic curve) */ + dma_addr_t dma_r; /* Pointer to r (elliptic curve) */ + dma_addr_t dma_g_xy; /* Pointer to Gx,y (elliptic curve) */ + dma_addr_t dma_pkey; /* Pointer to Wx,y (public key) */ + dma_addr_t dma_hash; /* Pointer to hash input */ + dma_addr_t dma_c; /* Pointer to C_signature */ + dma_addr_t dma_d; /* Pointer to D_signature */ + dma_addr_t dma_buf; /* Pointer to 64-byte temp buffer */ + dma_addr_t dma_ab; /* Pointer to a,b (elliptic curve ) */ + uint32_t img_size; /* Length of Message */ +}; + +struct __packed pdb_ecdsa_sign { + uint32_t pdb_hdr; + dma_addr_t dma_q; /* Pointer to q (elliptic curve) */ + dma_addr_t dma_r; /* Pointer to r (elliptic curve) */ + dma_addr_t dma_g_xy; /* Pointer to Gx,y (elliptic curve) */ + dma_addr_t dma_pri_key; /* Pointer to S (Private key) */ + dma_addr_t dma_hash; /* Pointer to hash input */ + dma_addr_t dma_c; /* Pointer to C_signature */ + dma_addr_t dma_d; /* Pointer to D_signature */ + dma_addr_t dma_ab; /* Pointer to a,b (elliptic curve ) */ + dma_addr_t dma_u; /* Pointer to Per Message Random */ + uint32_t img_size; /* Length of Message */ +}; + +#define PDB_ECDSA_SGF_SHIFT 23 +#define PDB_ECDSA_L_SHIFT 7 +#define PDB_ECDSA_N_SHIFT 0 + +struct __packed pdb_mp_pub_k { + uint32_t pdb_hdr; + #define PDB_MP_PUB_K_SGF_SHIFT 31 + dma_addr_t dma_pkey; /* Pointer to Wx,y (public key) */ +}; + +struct __packed pdb_mp_sign { + uint32_t pdb_hdr; + #define PDB_MP_SIGN_SGF_SHIFT 28 + dma_addr_t dma_addr_msg; /* Pointer to Message */ + dma_addr_t dma_addr_hash; /* Pointer to hash output */ + dma_addr_t dma_addr_c_sig; /* Pointer to C_signature */ + dma_addr_t dma_addr_d_sig; /* Pointer to D_signature */ + uint32_t img_size; /* Length of Message */ +}; + +#define PDB_MP_CSEL_SHIFT 17 +#define PDB_MP_CSEL_P256 0x3 << PDB_MP_CSEL_SHIFT /* P-256 */ +#define PDB_MP_CSEL_P384 0x4 << PDB_MP_CSEL_SHIFT /* P-384 */ +#define PDB_MP_CSEL_P521 0x5 << PDB_MP_CSEL_SHIFT /* P-521 */ + #endif /* DESC_H */ diff --git a/drivers/crypto/fsl/desc_constr.h b/drivers/crypto/fsl/desc_constr.h index 2559ccda8c..4ea93b03a2 100644 --- a/drivers/crypto/fsl/desc_constr.h +++ b/drivers/crypto/fsl/desc_constr.h @@ -53,6 +53,19 @@ union ptr_addr_t { }; #endif +static inline void pdb_add_ptr(dma_addr_t *offset, dma_addr_t ptr) +{ +#ifdef CONFIG_PHYS_64BIT + /* The Position of low and high part of 64 bit address + * will depend on the endianness of CAAM Block */ + union ptr_addr_t *ptr_addr = (union ptr_addr_t *)offset; + ptr_addr->m_halfs.high = (u32)(ptr >> 32); + ptr_addr->m_halfs.low = (u32)ptr; +#else + *offset = ptr; +#endif +} + static inline int desc_len(u32 *desc) { return *desc & HDR_DESCLEN_MASK; @@ -68,6 +81,11 @@ static inline u32 *desc_end(u32 *desc) return desc + desc_len(desc); } +static inline void *desc_pdb(u32 *desc) +{ + return desc + 1; +} + static inline void init_desc(u32 *desc, u32 options) { *desc = (options | HDR_ONE) + 1; @@ -78,6 +96,15 @@ static inline void init_job_desc(u32 *desc, u32 options) init_desc(desc, CMD_DESC_HDR | options); } +static inline void init_job_desc_pdb(u32 *desc, u32 options, size_t pdb_bytes) +{ + u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ; + + init_job_desc(desc, + (((pdb_len + 1) << HDR_START_IDX_SHIFT) + pdb_len) | + options); +} + static inline void append_ptr(u32 *desc, dma_addr_t ptr) { dma_addr_t *offset = (dma_addr_t *)desc_end(desc); diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c index b766470ce2..93c24712d1 100644 --- a/drivers/crypto/fsl/jr.c +++ b/drivers/crypto/fsl/jr.c @@ -360,7 +360,7 @@ int run_descriptor_jr(uint32_t *desc) } } - if (!op.status) { + if (op.status) { debug("Error %x\n", op.status); ret = op.status; } diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 0bfcd3413c..9073917914 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -895,11 +895,15 @@ static void set_ddr_sdram_cfg_2(const unsigned int ctrl_num, slow = get_ddr_freq(ctrl_num) < 1249000000; #endif - if (popts->registered_dimm_en) { + if (popts->registered_dimm_en) rcw_en = 1; - ap_en = popts->ap_en; - } else { + + /* DDR4 can have address parity for UDIMM and discrete */ + if ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) && + (!popts->registered_dimm_en)) { ap_en = 0; + } else { + ap_en = popts->ap_en; } x4_en = popts->x4_en ? 1 : 0; @@ -1135,6 +1139,7 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr, unsigned short esdmode5; /* Extended SDRAM mode 5 */ int rtt_park = 0; bool four_cs = false; + const unsigned int mclk_ps = get_memory_clk_period_ps(0); #if CONFIG_CHIP_SELECTS_PER_CTRL == 4 if ((ddr->cs[0].config & SDRAM_CS_CONFIG_EN) && @@ -1150,6 +1155,19 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr, esdmode5 = 0x00000400; /* Data mask enabled */ } + /* set command/address parity latency */ + if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { + if (mclk_ps >= 935) { + /* for DDR4-1600/1866/2133 */ + esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; + } else if (mclk_ps >= 833) { + /* for DDR4-2400 */ + esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; + } else { + printf("parity: mclk_ps = %d not supported\n", mclk_ps); + } + } + ddr->ddr_sdram_mode_9 = (0 | ((esdmode4 & 0xffff) << 16) | ((esdmode5 & 0xffff) << 0) @@ -1170,6 +1188,20 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr, } else { esdmode5 = 0x00000400; } + + if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { + if (mclk_ps >= 935) { + /* for DDR4-1600/1866/2133 */ + esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; + } else if (mclk_ps >= 833) { + /* for DDR4-2400 */ + esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; + } else { + printf("parity: mclk_ps = %d not supported\n", + mclk_ps); + } + } + switch (i) { case 1: ddr->ddr_sdram_mode_11 = (0 @@ -1925,12 +1957,25 @@ static void set_timing_cfg_7(const unsigned int ctrl_num, const common_timing_params_t *common_dimm) { unsigned int txpr, tcksre, tcksrx; - unsigned int cke_rst, cksre, cksrx, par_lat, cs_to_cmd; + unsigned int cke_rst, cksre, cksrx, par_lat = 0, cs_to_cmd; + const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); txpr = max(5U, picos_to_mclk(ctrl_num, common_dimm->trfc1_ps + 10000)); tcksre = max(5U, picos_to_mclk(ctrl_num, 10000)); tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000)); - par_lat = 0; + + if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { + if (mclk_ps >= 935) { + /* parity latency 4 clocks in case of 1600/1866/2133 */ + par_lat = 4; + } else if (mclk_ps >= 833) { + /* parity latency 5 clocks for DDR4-2400 */ + par_lat = 5; + } else { + printf("parity: mclk_ps = %d not supported\n", mclk_ps); + } + } + cs_to_cmd = 0; if (txpr <= 200) diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 6f76980d31..608810d4e2 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -12,7 +12,8 @@ #include <fsl_ddr.h> #include <fsl_errata.h> -#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008511) | \ + defined(CONFIG_SYS_FSL_ERRATUM_A009803) static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits) { int timeout = 1000; @@ -24,9 +25,9 @@ static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits) timeout--; } if (timeout <= 0) - puts("Error: A007865 wait for clear timeout.\n"); + puts("Error: wait for clear timeout.\n"); } -#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */ +#endif #if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL @@ -201,7 +202,18 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2); } + +#ifdef CONFIG_SYS_FSL_ERRATUM_A009803 + /* part 1 of 2 */ + if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { /* for RDIMM */ + ddr_out32(&ddr->ddr_sdram_rcw_2, + regs->ddr_sdram_rcw_2 & ~0x0f000000); + } + + ddr_out32(&ddr->err_disable, regs->err_disable | DDR_ERR_DISABLE_APED); +#else ddr_out32(&ddr->err_disable, regs->err_disable); +#endif ddr_out32(&ddr->err_int_en, regs->err_int_en); for (i = 0; i < 32; i++) { if (regs->debug[i]) { @@ -297,7 +309,8 @@ step2: mb(); isb(); -#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008511) || \ + defined(CONFIG_SYS_FSL_ERRATUM_A009803) /* Part 2 of 2 */ /* This erraum only applies to verion 5.2.0 */ if (fsl_ddr_get_version(ctrl_num) == 0x50200) { @@ -313,6 +326,7 @@ step2: ctrl_num, ddr_in32(&ddr->debug[1])); } +#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 /* The vref setting sequence is different for range 2 */ if (regs->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2) vref_seq = vref_seq2; @@ -359,9 +373,29 @@ step2: } /* Restore D_INIT */ ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); - } #endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009803 + /* if it's RDIMM */ + if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN)) + continue; + set_wait_for_bits_clear(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL(i) | + 0x070000ed, + MD_CNTL_MD_EN); + udelay(1); + } + } + + ddr_out32(&ddr->err_disable, + regs->err_disable & ~DDR_ERR_DISABLE_APED); +#endif + } +#endif + total_gb_size_per_controller = 0; for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { if (!(regs->cs[i].config & 0x80000000)) diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 791d644101..d0075ff1fd 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -1002,8 +1002,19 @@ unsigned int populate_memctl_options(const common_timing_params_t *common_dimm, popts->twot_en = 0; popts->threet_en = 0; - /* for RDIMM, address parity enable */ - popts->ap_en = 1; + /* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */ + if (popts->registered_dimm_en) + popts->ap_en = 1; /* 0 = disable, 1 = enable */ + else + popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */ + + if (hwconfig_sub_f("fsl_ddr", "parity", buf)) { + if (hwconfig_subarg_cmp_f("fsl_ddr", "parity", "on", buf)) { + if (popts->registered_dimm_en || + (CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4)) + popts->ap_en = 1; + } + } /* * BSTTOPRE precharge interval diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index 53c4966c33..f83bd0c7f0 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -1147,7 +1147,8 @@ int fsl_mc_ldpaa_exit(bd_t *bd) { int err = 0; - if (bd && get_mc_boot_status() == -1) + /* MC is not loaded intentionally, So return success. */ + if (bd && get_mc_boot_status() != 0) return 0; if (bd && !get_mc_boot_status() && get_dpl_apply_status() == -1) { diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 7f96883d34..bc7f8bb023 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -14,15 +14,32 @@ #include <linux/compat.h> #include <fsl-mc/fsl_dpmac.h> +#include <fsl-mc/ldpaa_wriop.h> #include "ldpaa_eth.h" -#undef CONFIG_PHYLIB +#ifdef CONFIG_PHYLIB static int init_phy(struct eth_device *dev) { - /*TODO for external PHY */ + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; + struct phy_device *phydev = NULL; + struct mii_dev *bus; - return 0; + bus = wriop_get_mdio(priv->dpmac_id); + if (bus == NULL) + return 0; + + phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id), + dev, wriop_get_enet_if(priv->dpmac_id)); + if (!phydev) { + printf("Failed to connect\n"); + return -1; + } + + priv->phydev = phydev; + + return phy_config(phydev); } +#endif #ifdef DEBUG static void ldpaa_eth_get_dpni_counter(void) @@ -380,7 +397,9 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) #ifdef DEBUG struct dpni_link_state link_state; #endif - int err; + int err = 0; + struct mii_dev *bus; + phy_interface_t enet_if; if (net_dev->state == ETH_STATE_ACTIVE) return 0; @@ -394,11 +413,48 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) printf("ERROR (DPL is deployed. No device available)\n"); return -ENODEV; } + /* DPMAC initialization */ err = ldpaa_dpmac_setup(priv); if (err < 0) goto err_dpmac_setup; +#ifdef CONFIG_PHYLIB + if (priv->phydev) + err = phy_startup(priv->phydev); + if (err) { + printf("%s: Could not initialize\n", + priv->phydev->dev->name); + goto err_dpamc_bind; + } +#else + priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device)); + memset(priv->phydev, 0, sizeof(struct phy_device)); + + priv->phydev->speed = SPEED_1000; + priv->phydev->link = 1; + priv->phydev->duplex = DUPLEX_FULL; +#endif + + bus = wriop_get_mdio(priv->dpmac_id); + enet_if = wriop_get_enet_if(priv->dpmac_id); + if ((bus == NULL) && + (enet_if == PHY_INTERFACE_MODE_XGMII)) { + priv->phydev = (struct phy_device *) + malloc(sizeof(struct phy_device)); + memset(priv->phydev, 0, sizeof(struct phy_device)); + + priv->phydev->speed = SPEED_10000; + priv->phydev->link = 1; + priv->phydev->duplex = DUPLEX_FULL; + } + + if (!priv->phydev->link) { + printf("%s: No link.\n", priv->phydev->dev->name); + err = -1; + goto err_dpamc_bind; + } + /* DPMAC binding DPNI */ err = ldpaa_dpmac_bind(priv); if (err) @@ -425,28 +481,24 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; } -#ifdef CONFIG_PHYLIB - /* TODO Check this path */ - err = phy_startup(priv->phydev); - if (err) { - printf("%s: Could not initialize\n", priv->phydev->dev->name); - return err; - } -#else - priv->phydev->speed = SPEED_1000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; -#endif - err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); if (err < 0) { printf("dpni_enable() failed\n"); return err; } - dpmac_link_state.rate = SPEED_1000; - dpmac_link_state.options = DPMAC_LINK_OPT_AUTONEG; - dpmac_link_state.up = 1; + dpmac_link_state.rate = priv->phydev->speed; + + if (priv->phydev->autoneg == AUTONEG_DISABLE) + dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG; + else + dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG; + + if (priv->phydev->duplex == DUPLEX_HALF) + dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX; + + dpmac_link_state.up = priv->phydev->link; + err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle, &dpmac_link_state); if (err < 0) { @@ -484,10 +536,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; } - if (!priv->phydev->link) - printf("%s: No link.\n", priv->phydev->dev->name); - - return priv->phydev->link ? 0 : -1; + return priv->phydev->link; err_qdid: err_rx_flow: @@ -495,9 +544,10 @@ err_rx_flow: err_dpni_bind: ldpaa_dpbp_free(); err_dpbp_setup: -err_dpamc_bind: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_setup: +err_dpamc_bind: + dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); err_dpmac_setup: return err; } @@ -506,6 +556,9 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; int err = 0; +#ifdef CONFIG_PHYLIB + struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id); +#endif if ((net_dev->state == ETH_STATE_PASSIVE) || (net_dev->state == ETH_STATE_INIT)) @@ -531,7 +584,10 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) printf("dpni_disable() failed\n"); #ifdef CONFIG_PHYLIB - phy_shutdown(priv->phydev); + if (priv->phydev && bus != NULL) + phy_shutdown(priv->phydev); + else + free(priv->phydev); #endif ldpaa_dpbp_free(); @@ -914,15 +970,12 @@ static int ldpaa_eth_netdev_init(struct eth_device *net_dev, net_dev->halt = ldpaa_eth_stop; net_dev->send = ldpaa_eth_tx; net_dev->recv = ldpaa_eth_pull_dequeue_rx; -/* - TODO: PHY MDIO information - priv->bus = info->bus; - priv->phyaddr = info->phy_addr; - priv->enet_if = info->enet_if; -*/ - if (init_phy(net_dev)) - return 0; +#ifdef CONFIG_PHYLIB + err = init_phy(net_dev); + if (err < 0) + return err; +#endif err = eth_register(net_dev); if (err < 0) { diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 99f9c83fa4..0ba960e248 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -93,6 +93,7 @@ struct ls_pcie { void __iomem *dbi; void __iomem *va_cfg0; void __iomem *va_cfg1; + int next_lut_index; struct pci_controller hose; }; @@ -482,6 +483,147 @@ static void ls_pcie_setup_ep(struct ls_pcie *pcie, struct ls_pcie_info *info) } } +#ifdef CONFIG_FSL_LSCH3 +/* + * Return next available LUT index. + */ +static int ls_pcie_next_lut_index(struct ls_pcie *pcie) +{ + if (pcie->next_lut_index < PCIE_LUT_ENTRY_COUNT) + return pcie->next_lut_index++; + else + return -1; /* LUT is full */ +} + +/* + * Program a single LUT entry + */ +static void ls_pcie_lut_set_mapping(struct ls_pcie *pcie, int index, u32 devid, + u32 streamid) +{ + void __iomem *lut; + + lut = pcie->dbi + PCIE_LUT_BASE; + + /* leave mask as all zeroes, want to match all bits */ + writel((devid << 16), lut + PCIE_LUT_UDR(index)); + writel(streamid | PCIE_LUT_ENABLE, lut + PCIE_LUT_LDR(index)); +} + +/* returns the next available streamid */ +static u32 ls_pcie_next_streamid(void) +{ + static int next_stream_id = FSL_PEX_STREAM_ID_START; + + if (next_stream_id > FSL_PEX_STREAM_ID_END) + return 0xffffffff; + + return next_stream_id++; +} + +/* + * An msi-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.: + * + * msi-map = <[devid] [phandle-to-msi-ctrl] [stream-id] [count] + * [devid] [phandle-to-msi-ctrl] [stream-id] [count]>; + */ +static void fdt_pcie_set_msi_map_entry(void *blob, struct ls_pcie *pcie, + u32 devid, u32 streamid) +{ + char pcie_path[19]; + u32 *prop; + u32 phandle; + int nodeoffset; + + /* find pci controller node */ + snprintf(pcie_path, sizeof(pcie_path), "/soc/pcie@%llx", + (u64)pcie->dbi); + nodeoffset = fdt_path_offset(blob, pcie_path); + if (nodeoffset < 0) { + printf("\n%s: ERROR: unable to update PCIe node: %s\n", + __func__, pcie_path); + return; + } + + /* get phandle to MSI controller */ + prop = (u32 *)fdt_getprop(blob, nodeoffset, "msi-parent", 0); + if (prop == NULL) { + printf("\n%s: ERROR: missing msi-parent: %s\n", __func__, + pcie_path); + return; + } + phandle = be32_to_cpu(*prop); + + /* set one msi-map row */ + fdt_appendprop_u32(blob, nodeoffset, "msi-map", devid); + fdt_appendprop_u32(blob, nodeoffset, "msi-map", phandle); + fdt_appendprop_u32(blob, nodeoffset, "msi-map", streamid); + fdt_appendprop_u32(blob, nodeoffset, "msi-map", 1); +} + +static void fdt_fixup_pcie(void *blob) +{ + unsigned int found_multi = 0; + unsigned char header_type; + int index; + u32 streamid; + pci_dev_t dev; + int bus; + unsigned short id; + struct pci_controller *hose; + struct ls_pcie *pcie; + int i; + + for (i = 0, hose = pci_get_hose_head(); hose; hose = hose->next, i++) { + pcie = hose->priv_data; + for (bus = hose->first_busno; bus <= hose->last_busno; bus++) { + + for (dev = PCI_BDF(bus, 0, 0); + dev < PCI_BDF(bus, PCI_MAX_PCI_DEVICES - 1, + PCI_MAX_PCI_FUNCTIONS - 1); + dev += PCI_BDF(0, 0, 1)) { + + if (PCI_FUNC(dev) && !found_multi) + continue; + + pci_read_config_word(dev, PCI_VENDOR_ID, &id); + + pci_read_config_byte(dev, PCI_HEADER_TYPE, + &header_type); + + if ((id == 0xFFFF) || (id == 0x0000)) + continue; + + if (!PCI_FUNC(dev)) + found_multi = header_type & 0x80; + + streamid = ls_pcie_next_streamid(); + if (streamid == 0xffffffff) { + printf("ERROR: no stream ids free\n"); + continue; + } + + index = ls_pcie_next_lut_index(pcie); + if (index < 0) { + printf("ERROR: no LUT indexes free\n"); + continue; + } + + /* map PCI b.d.f to streamID in LUT */ + ls_pcie_lut_set_mapping(pcie, index, dev >> 8, + streamid); + + /* update msi-map in device tree */ + fdt_pcie_set_msi_map_entry(blob, pcie, dev >> 8, + streamid); + } + } + } +} +#endif + int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) { struct ls_pcie *pcie; @@ -513,6 +655,7 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) pcie->va_cfg1 = map_physmem(info->cfg1_phys, info->cfg1_size, MAP_NOCACHE); + pcie->next_lut_index = 0; /* outbound memory */ pci_set_region(&hose->regions[0], @@ -657,6 +800,10 @@ void ft_pci_setup(void *blob, bd_t *bd) #ifdef CONFIG_PCIE4 ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE4_ADDR, PCIE4); #endif + + #ifdef CONFIG_FSL_LSCH3 + fdt_fixup_pcie(blob); + #endif } #else @@ -664,73 +811,3 @@ void ft_pci_setup(void *blob, bd_t *bd) { } #endif - -#if defined(CONFIG_LS2080A) || defined(CONFIG_LS2085A) - -void pcie_set_available_streamids(void *blob, const char *pcie_path, - u32 *stream_ids, int count) -{ - int nodeoffset; - int i; - - nodeoffset = fdt_path_offset(blob, pcie_path); - if (nodeoffset < 0) { - printf("\n%s: ERROR: unable to update PCIe node\n", __func__); - return; - } - - /* for each stream ID, append to mmu-masters */ - for (i = 0; i < count; i++) { - fdt_appendprop_u32(blob, nodeoffset, "available-stream-ids", - stream_ids[i]); - } -} - -#define MAX_STREAM_IDS 4 -void fdt_fixup_smmu_pcie(void *blob) -{ - int count; - u32 stream_ids[MAX_STREAM_IDS]; - u32 ctlr_streamid = 0x300; - - #ifdef CONFIG_PCIE1 - /* PEX1 stream ID fixup */ - count = FSL_PEX1_STREAM_ID_END - FSL_PEX1_STREAM_ID_START + 1; - alloc_stream_ids(FSL_PEX1_STREAM_ID_START, count, stream_ids, - MAX_STREAM_IDS); - pcie_set_available_streamids(blob, "/pcie@3400000", stream_ids, count); - append_mmu_masters(blob, "/iommu@5000000", "/pcie@3400000", - &ctlr_streamid, 1); - #endif - - #ifdef CONFIG_PCIE2 - /* PEX2 stream ID fixup */ - count = FSL_PEX2_STREAM_ID_END - FSL_PEX2_STREAM_ID_START + 1; - alloc_stream_ids(FSL_PEX2_STREAM_ID_START, count, stream_ids, - MAX_STREAM_IDS); - pcie_set_available_streamids(blob, "/pcie@3500000", stream_ids, count); - append_mmu_masters(blob, "/iommu@5000000", "/pcie@3500000", - &ctlr_streamid, 1); - #endif - - #ifdef CONFIG_PCIE3 - /* PEX3 stream ID fixup */ - count = FSL_PEX3_STREAM_ID_END - FSL_PEX3_STREAM_ID_START + 1; - alloc_stream_ids(FSL_PEX3_STREAM_ID_START, count, stream_ids, - MAX_STREAM_IDS); - pcie_set_available_streamids(blob, "/pcie@3600000", stream_ids, count); - append_mmu_masters(blob, "/iommu@5000000", "/pcie@3600000", - &ctlr_streamid, 1); - #endif - - #ifdef CONFIG_PCIE4 - /* PEX4 stream ID fixup */ - count = FSL_PEX4_STREAM_ID_END - FSL_PEX4_STREAM_ID_START + 1; - alloc_stream_ids(FSL_PEX4_STREAM_ID_START, count, stream_ids, - MAX_STREAM_IDS); - pcie_set_available_streamids(blob, "/pcie@3700000", stream_ids, count); - append_mmu_masters(blob, "/iommu@5000000", "/pcie@3700000", - &ctlr_streamid, 1); - #endif -} -#endif |