diff options
author | Tom Rini <trini@konsulko.com> | 2020-01-25 12:20:51 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-01-25 12:20:51 -0500 |
commit | 40521a6c90d4adfb7f3041033c8cbbeff087a5ca (patch) | |
tree | d7053cb605bd7235ec3c32a36b7671324ba90f15 /drivers | |
parent | d31dd3b596190bdecbd109e404f16bd208fe32ba (diff) | |
parent | 6666408535523377428846bad5a9362d589e396c (diff) |
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-fsl-qoriq
Updates and fixes for ls1028a, lx2160a, ls1012a, ls1021a, ls2080a,
ls1088a platforms:
- lx2-rev2 pcie support, enetc related updates, layerscape-pcie fixes
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/fsl_enetc.c | 156 | ||||
-rw-r--r-- | drivers/net/fsl_enetc.h | 3 | ||||
-rw-r--r-- | drivers/pci/Makefile | 5 | ||||
-rw-r--r-- | drivers/pci/pcie_layerscape.c | 13 | ||||
-rw-r--r-- | drivers/pci/pcie_layerscape_fixup.c | 23 | ||||
-rw-r--r-- | drivers/pci/pcie_layerscape_fixup_common.c | 124 | ||||
-rw-r--r-- | drivers/pci/pcie_layerscape_fixup_common.h | 22 | ||||
-rw-r--r-- | drivers/pci/pcie_layerscape_gen4_fixup.c | 24 |
8 files changed, 303 insertions, 67 deletions
diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index 02c1ee70d9..f0d15febcc 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -14,6 +14,69 @@ #include "fsl_enetc.h" +#define ENETC_DRIVER_NAME "enetc_eth" + +/* + * sets the MAC address in IERB registers, this setting is persistent and + * carried over to Linux. + */ +static void enetc_set_ierb_primary_mac(struct udevice *dev, int devfn, + const u8 *enetaddr) +{ +#ifdef CONFIG_ARCH_LS1028A +/* + * LS1028A is the only part with IERB at this time and there are plans to change + * its structure, keep this LS1028A specific for now + */ +#define IERB_BASE 0x1f0800000ULL +#define IERB_PFMAC(pf, vf, n) (IERB_BASE + 0x8000 + (pf) * 0x100 + (vf) * 8 \ + + (n) * 4) + +static int ierb_fn_to_pf[] = {0, 1, 2, -1, -1, -1, 3}; + + u16 lower = *(const u16 *)(enetaddr + 4); + u32 upper = *(const u32 *)enetaddr; + + if (ierb_fn_to_pf[devfn] < 0) + return; + + out_le32(IERB_PFMAC(ierb_fn_to_pf[devfn], 0, 0), upper); + out_le32(IERB_PFMAC(ierb_fn_to_pf[devfn], 0, 1), (u32)lower); +#endif +} + +/* sets up primary MAC addresses in DT/IERB */ +void fdt_fixup_enetc_mac(void *blob) +{ + struct pci_child_platdata *ppdata; + struct eth_pdata *pdata; + struct udevice *dev; + struct uclass *uc; + char path[256]; + int offset; + int devfn; + + uclass_get(UCLASS_ETH, &uc); + uclass_foreach_dev(dev, uc) { + if (!dev->driver || !dev->driver->name || + strcmp(dev->driver->name, ENETC_DRIVER_NAME)) + continue; + + pdata = dev_get_platdata(dev); + ppdata = dev_get_parent_platdata(dev); + devfn = PCI_FUNC(ppdata->devfn); + + enetc_set_ierb_primary_mac(dev, devfn, pdata->enetaddr); + + snprintf(path, 256, "/soc/pcie@1f0000000/ethernet@%x,%x", + PCI_DEV(ppdata->devfn), PCI_FUNC(ppdata->devfn)); + offset = fdt_path_offset(blob, path); + if (offset < 0) + continue; + fdt_setprop(blob, offset, "mac-address", pdata->enetaddr, 6); + } +} + /* * Bind the device: * - set a more explicit name on the interface @@ -122,16 +185,34 @@ static int enetc_init_rgmii(struct udevice *dev) return 0; } -/* set up MAC and serdes for SXGMII */ -static int enetc_init_sxgmii(struct udevice *dev) +/* set up MAC configuration for the given interface type */ +static void enetc_setup_mac_iface(struct udevice *dev) { struct enetc_priv *priv = dev_get_priv(dev); u32 if_mode; - /* set ifmode to (US)XGMII */ - if_mode = enetc_read_port(priv, ENETC_PM_IF_MODE); - if_mode &= ~ENETC_PM_IF_IFMODE_MASK; - enetc_write_port(priv, ENETC_PM_IF_MODE, if_mode); + switch (priv->if_type) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + enetc_init_rgmii(dev); + break; + case PHY_INTERFACE_MODE_XGMII: + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_XFI: + /* set ifmode to (US)XGMII */ + if_mode = enetc_read_port(priv, ENETC_PM_IF_MODE); + if_mode &= ~ENETC_PM_IF_IFMODE_MASK; + enetc_write_port(priv, ENETC_PM_IF_MODE, if_mode); + break; + }; +} + +/* set up serdes for SXGMII */ +static int enetc_init_sxgmii(struct udevice *dev) +{ + struct enetc_priv *priv = dev_get_priv(dev); if (!enetc_has_imdio(dev)) return 0; @@ -267,14 +348,57 @@ static int enetc_remove(struct udevice *dev) return 0; } -/* ENETC Port MAC address registers, accepts big-endian format */ -static void enetc_set_primary_mac_addr(struct enetc_priv *priv, const u8 *addr) +/* + * LS1028A is the only part with IERB at this time and there are plans to + * change its structure, keep this LS1028A specific for now. + */ +#define LS1028A_IERB_BASE 0x1f0800000ULL +#define LS1028A_IERB_PSIPMAR0(pf, vf) (LS1028A_IERB_BASE + 0x8000 \ + + (pf) * 0x100 + (vf) * 8) +#define LS1028A_IERB_PSIPMAR1(pf, vf) (LS1028A_IERB_PSIPMAR0(pf, vf) + 4) + +static int enetc_ls1028a_write_hwaddr(struct udevice *dev) { + struct pci_child_platdata *ppdata = dev_get_parent_platdata(dev); + const int devfn_to_pf[] = {0, 1, 2, -1, -1, -1, 3}; + struct eth_pdata *plat = dev_get_platdata(dev); + int devfn = PCI_FUNC(ppdata->devfn); + u8 *addr = plat->enetaddr; + u32 lower, upper; + int pf; + + if (devfn >= ARRAY_SIZE(devfn_to_pf)) + return 0; + + pf = devfn_to_pf[devfn]; + if (pf < 0) + return 0; + + lower = *(const u16 *)(addr + 4); + upper = *(const u32 *)addr; + + out_le32(LS1028A_IERB_PSIPMAR0(pf, 0), upper); + out_le32(LS1028A_IERB_PSIPMAR1(pf, 0), lower); + + return 0; +} + +static int enetc_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct enetc_priv *priv = dev_get_priv(dev); + u8 *addr = plat->enetaddr; + + if (IS_ENABLED(CONFIG_ARCH_LS1028A)) + return enetc_ls1028a_write_hwaddr(dev); + u16 lower = *(const u16 *)(addr + 4); u32 upper = *(const u32 *)addr; enetc_write_port(priv, ENETC_PSIPMAR0, upper); enetc_write_port(priv, ENETC_PSIPMAR1, lower); + + return 0; } /* Configure port parameters (# of rings, frame size, enable port) */ @@ -405,7 +529,6 @@ static void enetc_setup_rx_bdr(struct udevice *dev) */ static int enetc_start(struct udevice *dev) { - struct eth_pdata *plat = dev_get_platdata(dev); struct enetc_priv *priv = dev_get_priv(dev); /* reset and enable the PCI device */ @@ -413,23 +536,13 @@ static int enetc_start(struct udevice *dev) dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - if (!is_valid_ethaddr(plat->enetaddr)) { - enetc_dbg(dev, "invalid MAC address, generate random ...\n"); - net_random_ethaddr(plat->enetaddr); - } - enetc_set_primary_mac_addr(priv, plat->enetaddr); - enetc_enable_si_port(priv); /* setup Tx/Rx buffer descriptors */ enetc_setup_tx_bdr(dev); enetc_setup_rx_bdr(dev); - if (priv->if_type == PHY_INTERFACE_MODE_RGMII || - priv->if_type == PHY_INTERFACE_MODE_RGMII_ID || - priv->if_type == PHY_INTERFACE_MODE_RGMII_RXID || - priv->if_type == PHY_INTERFACE_MODE_RGMII_TXID) - enetc_init_rgmii(dev); + enetc_setup_mac_iface(dev); if (priv->phy) phy_startup(priv->phy); @@ -548,10 +661,11 @@ static const struct eth_ops enetc_ops = { .send = enetc_send, .recv = enetc_recv, .stop = enetc_stop, + .write_hwaddr = enetc_write_hwaddr, }; U_BOOT_DRIVER(eth_enetc) = { - .name = "enetc_eth", + .name = ENETC_DRIVER_NAME, .id = UCLASS_ETH, .bind = enetc_bind, .probe = enetc_probe, diff --git a/drivers/net/fsl_enetc.h b/drivers/net/fsl_enetc.h index 9a36cdad80..48c3005cb3 100644 --- a/drivers/net/fsl_enetc.h +++ b/drivers/net/fsl_enetc.h @@ -227,4 +227,7 @@ int enetc_mdio_read_priv(struct enetc_mdio_priv *priv, int addr, int devad, int enetc_mdio_write_priv(struct enetc_mdio_priv *priv, int addr, int devad, int reg, u16 val); +/* sets up primary MAC addresses in DT/IERB */ +void fdt_fixup_enetc_mac(void *blob); + #endif /* _ENETC_H */ diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 8a33eb0266..c051ecc9f3 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -34,9 +34,10 @@ obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o obj-$(CONFIG_PCIE_DW_MVEBU) += pcie_dw_mvebu.o obj-$(CONFIG_PCIE_FSL) += pcie_fsl.o pcie_fsl_fixup.o obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o -obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape_fixup.o +obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape_fixup.o pcie_layerscape_fixup_common.o obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie_layerscape_gen4.o \ - pcie_layerscape_gen4_fixup.o pcie_layerscape.o + pcie_layerscape_gen4_fixup.o \ + pcie_layerscape_fixup_common.o obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o obj-$(CONFIG_PCI_PHYTIUM) += pcie_phytium.o obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 47394bdba7..2ab67d1fc9 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -312,20 +312,9 @@ static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie) /* Disable all bars in RC mode */ static void ls_pcie_disable_bars(struct ls_pcie *pcie) { - u32 sriov; - - sriov = in_le32(pcie->dbi + PCIE_SRIOV); - - /* - * TODO: For PCIe controller with SRIOV, the method to disable bars - * is different and more complex, so will add later. - */ - if (PCI_EXT_CAP_ID(sriov) == PCI_EXT_CAP_ID_SRIOV) - return; - dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_BASE_ADDRESS_0); dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_BASE_ADDRESS_1); - dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_ROM_ADDRESS1); + dbi_writel(pcie, 0xfffffffe, PCIE_CS2_OFFSET + PCI_ROM_ADDRESS1); } static void ls_pcie_setup_ctrl(struct ls_pcie *pcie) diff --git a/drivers/pci/pcie_layerscape_fixup.c b/drivers/pci/pcie_layerscape_fixup.c index 27ef20d4c3..ec6acbb138 100644 --- a/drivers/pci/pcie_layerscape_fixup.c +++ b/drivers/pci/pcie_layerscape_fixup.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2017-2019 NXP + * Copyright 2017-2020 NXP * Copyright 2014-2015 Freescale Semiconductor, Inc. * Layerscape PCIe driver */ @@ -17,6 +17,7 @@ #include <asm/arch/clock.h> #endif #include "pcie_layerscape.h" +#include "pcie_layerscape_fixup_common.h" #if defined(CONFIG_FSL_LSCH3) || defined(CONFIG_FSL_LSCH2) /* @@ -30,17 +31,6 @@ static int ls_pcie_next_lut_index(struct ls_pcie *pcie) return -ENOSPC; /* LUT is full */ } -/* returns the next available streamid for pcie, -errno if failed */ -static int 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 -EINVAL; - - return next_stream_id++; -} - static void lut_writel(struct ls_pcie *pcie, unsigned int value, unsigned int offset) { @@ -191,10 +181,12 @@ static void fdt_fixup_pcie_ls(void *blob) bus = bus->parent; pcie = dev_get_priv(bus); - streamid = ls_pcie_next_streamid(); + streamid = pcie_next_streamid(pcie->stream_id_cur, pcie->idx); if (streamid < 0) { debug("ERROR: no stream ids free\n"); continue; + } else { + pcie->stream_id_cur++; } index = ls_pcie_next_lut_index(pcie); @@ -215,6 +207,7 @@ static void fdt_fixup_pcie_ls(void *blob) fdt_pcie_set_iommu_map_entry_ls(blob, pcie, bdf >> 8, streamid); } + pcie_board_fix_fdt(blob); } #endif @@ -271,7 +264,7 @@ static void ft_pcie_ls_setup(void *blob, struct ls_pcie *pcie) } /* Fixup Kernel DT for PCIe */ -void ft_pci_setup(void *blob, bd_t *bd) +void ft_pci_setup_ls(void *blob, bd_t *bd) { struct ls_pcie *pcie; @@ -284,7 +277,7 @@ void ft_pci_setup(void *blob, bd_t *bd) } #else /* !CONFIG_OF_BOARD_SETUP */ -void ft_pci_setup(void *blob, bd_t *bd) +void ft_pci_setup_ls(void *blob, bd_t *bd) { } #endif diff --git a/drivers/pci/pcie_layerscape_fixup_common.c b/drivers/pci/pcie_layerscape_fixup_common.c new file mode 100644 index 0000000000..b010a6300c --- /dev/null +++ b/drivers/pci/pcie_layerscape_fixup_common.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019-2020 NXP + * + * PCIe DT fixup for NXP Layerscape SoCs + * Author: Wasim Khan <wasim.khan@nxp.com> + * + */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/soc.h> +#include "pcie_layerscape_fixup_common.h" + +void ft_pci_setup(void *blob, bd_t *bd) +{ +#if defined(CONFIG_PCIE_LAYERSCAPE_GEN4) + uint svr; + + svr = SVR_SOC_VER(get_svr()); + + if (svr == SVR_LX2160A && IS_SVR_REV(get_svr(), 1, 0)) + ft_pci_setup_ls_gen4(blob, bd); + else +#endif /* CONFIG_PCIE_LAYERSCAPE_GEN4 */ + ft_pci_setup_ls(blob, bd); +} + +#if defined(CONFIG_FSL_LAYERSCAPE) +int lx2_board_fix_fdt(void *fdt) +{ + char *reg_name, *old_str, *new_str; + const char *reg_names; + int names_len, old_str_len, new_str_len, remaining_str_len; + struct str_map { + char *old_str; + char *new_str; + } reg_names_map[] = { + { "csr_axi_slave", "regs" }, + { "config_axi_slave", "config" } + }; + int off = -1, i; + + off = fdt_node_offset_by_compatible(fdt, -1, "fsl,lx2160a-pcie"); + while (off != -FDT_ERR_NOTFOUND) { + fdt_setprop(fdt, off, "compatible", "fsl,ls2088a-pcie", + strlen("fsl,ls2088a-pcie") + 1); + + reg_names = fdt_getprop(fdt, off, "reg-names", &names_len); + if (!reg_names) + continue; + reg_name = (char *)reg_names; + remaining_str_len = names_len - (reg_name - reg_names); + i = 0; + while ((i < ARRAY_SIZE(reg_names_map)) && remaining_str_len) { + old_str = reg_names_map[i].old_str; + new_str = reg_names_map[i].new_str; + old_str_len = strlen(old_str); + new_str_len = strlen(new_str); + if (memcmp(reg_name, old_str, old_str_len) == 0) { + /* first only leave required bytes for new_str + * and copy rest of the string after it + */ + memcpy(reg_name + new_str_len, + reg_name + old_str_len, + remaining_str_len - old_str_len); + + /* Now copy new_str */ + memcpy(reg_name, new_str, new_str_len); + names_len -= old_str_len; + names_len += new_str_len; + i++; + } + + reg_name = memchr(reg_name, '\0', remaining_str_len); + if (!reg_name) + break; + reg_name += 1; + + remaining_str_len = names_len - (reg_name - reg_names); + } + fdt_setprop(fdt, off, "reg-names", reg_names, names_len); + fdt_delprop(fdt, off, "apio-wins"); + fdt_delprop(fdt, off, "ppio-wins"); + off = fdt_node_offset_by_compatible(fdt, off, + "fsl,lx2160a-pcie"); + } + return 0; +} + +int pcie_board_fix_fdt(void *fdt) +{ + uint svr; + + svr = SVR_SOC_VER(get_svr()); + + if (svr == SVR_LX2160A && IS_SVR_REV(get_svr(), 2, 0)) + return lx2_board_fix_fdt(fdt); + + return 0; +} + +#ifdef CONFIG_ARCH_LX2160A +/* returns the next available streamid for pcie, -errno if failed */ +int pcie_next_streamid(int currentid, int idx) +{ + if (currentid > FSL_PEX_STREAM_ID_END) + return -EINVAL; + + return currentid | ((idx + 1) << 11); +} +#else +/* returns the next available streamid for pcie, -errno if failed */ +int pcie_next_streamid(int currentid, int idx) +{ + static int next_stream_id = FSL_PEX_STREAM_ID_START; + + if (next_stream_id > FSL_PEX_STREAM_ID_END) + return -EINVAL; + + return next_stream_id++; +} +#endif +#endif /* CONFIG_FSL_LAYERSCAPE */ diff --git a/drivers/pci/pcie_layerscape_fixup_common.h b/drivers/pci/pcie_layerscape_fixup_common.h new file mode 100644 index 0000000000..e1970a5790 --- /dev/null +++ b/drivers/pci/pcie_layerscape_fixup_common.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019-2020 NXP + * + * PCIe DT fixup for NXP Layerscape SoCs + * Author: Wasim Khan <wasim.khan@nxp.com> + * + */ +#ifndef _PCIE_LAYERSCAPE_FIXUP_COMMON_H_ +#define _PCIE_LAYERSCAPE_FIXUP_COMMON_H_ + +#include <common.h> + +void ft_pci_setup_ls(void *blob, bd_t *bd); + +#ifdef CONFIG_PCIE_LAYERSCAPE_GEN4 +void ft_pci_setup_ls_gen4(void *blob, bd_t *bd); +#endif /* CONFIG_PCIE_LAYERSCAPE_GEN4 */ +int pcie_next_streamid(int currentid, int id); +int pcie_board_fix_fdt(void *fdt); + +#endif //_PCIE_LAYERSCAPE_FIXUP_COMMON_H_ diff --git a/drivers/pci/pcie_layerscape_gen4_fixup.c b/drivers/pci/pcie_layerscape_gen4_fixup.c index da9817159f..bfe197e7d8 100644 --- a/drivers/pci/pcie_layerscape_gen4_fixup.c +++ b/drivers/pci/pcie_layerscape_gen4_fixup.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ OR X11 /* - * Copyright 2018-2019 NXP + * Copyright 2018-2020 NXP * * PCIe Gen4 driver for NXP Layerscape SoCs * Author: Hou Zhiqiang <Minder.Hou@gmail.com> @@ -19,6 +19,7 @@ #include <asm/arch/clock.h> #endif #include "pcie_layerscape_gen4.h" +#include "pcie_layerscape_fixup_common.h" #if defined(CONFIG_FSL_LSCH3) || defined(CONFIG_FSL_LSCH2) /* @@ -32,19 +33,6 @@ static int ls_pcie_g4_next_lut_index(struct ls_pcie_g4 *pcie) return -ENOSPC; /* LUT is full */ } -/* returns the next available streamid for pcie, -errno if failed */ -static int ls_pcie_g4_next_streamid(struct ls_pcie_g4 *pcie) -{ - int stream_id = pcie->stream_id_cur; - - if (stream_id > FSL_PEX_STREAM_ID_END) - return -EINVAL; - - pcie->stream_id_cur++; - - return stream_id | ((pcie->idx + 1) << 11); -} - /* * Program a single LUT entry */ @@ -161,10 +149,12 @@ static void fdt_fixup_pcie_ls_gen4(void *blob) bus = bus->parent; pcie = dev_get_priv(bus); - streamid = ls_pcie_g4_next_streamid(pcie); + streamid = pcie_next_streamid(pcie->stream_id_cur, pcie->idx); if (streamid < 0) { debug("ERROR: no stream ids free\n"); continue; + } else { + pcie->stream_id_cur++; } index = ls_pcie_g4_next_lut_index(pcie); @@ -234,7 +224,7 @@ static void ft_pcie_layerscape_gen4_setup(void *blob, struct ls_pcie_g4 *pcie) } /* Fixup Kernel DT for PCIe */ -void ft_pci_setup(void *blob, bd_t *bd) +void ft_pci_setup_ls_gen4(void *blob, bd_t *bd) { struct ls_pcie_g4 *pcie; @@ -247,7 +237,7 @@ void ft_pci_setup(void *blob, bd_t *bd) } #else /* !CONFIG_OF_BOARD_SETUP */ -void ft_pci_setup(void *blob, bd_t *bd) +void ft_pci_setup_ls_gen4(void *blob, bd_t *bd) { } #endif |