Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot
Patch queue for efi - 2018-06-14
A few minor fixes for the release:
- Compile fixes
- HI20 relocations for RISC-V
- Fix bootefi without load path
- Fix Runtime Services with certain compilers
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5c23b2c..18c7fb2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -735,6 +735,12 @@
slave) interrupt controllers. Include this to have U-Boot set up
the interrupt correctly.
+config PINCTRL_ICH6
+ bool
+ help
+ Intel ICH6 compatible chipset pinctrl driver. It needs to work
+ together with the ICH6 compatible gpio driver.
+
config I8254_TIMER
bool
default y
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index d5a17d0..af9e26c 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -18,7 +18,8 @@
ifndef CONFIG_$(SPL_)X86_64
AFLAGS_REMOVE_call32.o := -mregparm=3 \
$(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32)
-AFLAGS_call32.o := -fpic -fshort-wchar
+AFLAGS_call32.o := -fpic -fshort-wchar \
+ $(if $(CONFIG_EFI_STUB_64BIT),-m64)
extra-y += call32.o
endif
diff --git a/arch/x86/cpu/baytrail/Kconfig b/arch/x86/cpu/baytrail/Kconfig
index ac58b03..022a9f2 100644
--- a/arch/x86/cpu/baytrail/Kconfig
+++ b/arch/x86/cpu/baytrail/Kconfig
@@ -12,6 +12,7 @@
imply AHCI_PCI
imply ICH_SPI
imply INTEL_ICH6_GPIO
+ imply PINCTRL_ICH6
imply MMC
imply MMC_PCI
imply MMC_SDHCI
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 29baf08..56e9813 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -80,7 +80,7 @@
perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
/*
- * Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
+ * Set guaranteed vid [22:16] from IACORE_VIDS to bits [7:0] of
* the PERF_CTL
*/
msr = msr_read(MSR_IACORE_VIDS);
diff --git a/arch/x86/cpu/intel_common/mrc.c b/arch/x86/cpu/intel_common/mrc.c
index a5697a6..b35102a 100644
--- a/arch/x86/cpu/intel_common/mrc.c
+++ b/arch/x86/cpu/intel_common/mrc.c
@@ -242,11 +242,6 @@
version >> 24 , (version >> 16) & 0xff,
(version >> 8) & 0xff, version & 0xff);
-#if CONFIG_USBDEBUG
- /* mrc.bin reconfigures USB, so reinit it to have debug */
- early_usbdebug_init();
-#endif
-
return 0;
}
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c
index 305cd3d..3adc155 100644
--- a/arch/x86/cpu/irq.c
+++ b/arch/x86/cpu/irq.c
@@ -16,16 +16,75 @@
DECLARE_GLOBAL_DATA_PTR;
+/**
+ * pirq_reg_to_linkno() - Convert a PIRQ routing register offset to link number
+ *
+ * @priv: IRQ router driver's priv data
+ * @reg: PIRQ routing register offset from the base address
+ * @return: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc)
+ */
+static inline int pirq_reg_to_linkno(struct irq_router *priv, int reg)
+{
+ int linkno = 0;
+
+ if (priv->has_regmap) {
+ struct pirq_regmap *map = priv->regmap;
+ int i;
+
+ for (i = 0; i < priv->link_num; i++) {
+ if (reg - priv->link_base == map->offset) {
+ linkno = map->link;
+ break;
+ }
+ map++;
+ }
+ } else {
+ linkno = reg - priv->link_base;
+ }
+
+ return linkno;
+}
+
+/**
+ * pirq_linkno_to_reg() - Convert a PIRQ link number to routing register offset
+ *
+ * @priv: IRQ router driver's priv data
+ * @linkno: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc)
+ * @return: PIRQ routing register offset from the base address
+ */
+static inline int pirq_linkno_to_reg(struct irq_router *priv, int linkno)
+{
+ int reg = 0;
+
+ if (priv->has_regmap) {
+ struct pirq_regmap *map = priv->regmap;
+ int i;
+
+ for (i = 0; i < priv->link_num; i++) {
+ if (linkno == map->link) {
+ reg = map->offset + priv->link_base;
+ break;
+ }
+ map++;
+ }
+ } else {
+ reg = linkno + priv->link_base;
+ }
+
+ return reg;
+}
+
bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq)
{
struct irq_router *priv = dev_get_priv(dev);
u8 pirq;
- int base = priv->link_base;
if (priv->config == PIRQ_VIA_PCI)
- dm_pci_read_config8(dev->parent, LINK_N2V(link, base), &pirq);
+ dm_pci_read_config8(dev->parent,
+ pirq_linkno_to_reg(priv, link), &pirq);
else
- pirq = readb((uintptr_t)priv->ibase + LINK_N2V(link, base));
+ pirq = readb((uintptr_t)priv->ibase +
+ pirq_linkno_to_reg(priv, link));
pirq &= 0xf;
@@ -40,22 +99,23 @@
{
struct irq_router *priv = dev_get_priv(dev);
- return LINK_V2N(link, priv->link_base);
+ return pirq_reg_to_linkno(priv, link);
}
void pirq_assign_irq(struct udevice *dev, int link, u8 irq)
{
struct irq_router *priv = dev_get_priv(dev);
- int base = priv->link_base;
/* IRQ# 0/1/2/8/13 are reserved */
if (irq < 3 || irq == 8 || irq == 13)
return;
if (priv->config == PIRQ_VIA_PCI)
- dm_pci_write_config8(dev->parent, LINK_N2V(link, base), irq);
+ dm_pci_write_config8(dev->parent,
+ pirq_linkno_to_reg(priv, link), irq);
else
- writeb(irq, (uintptr_t)priv->ibase + LINK_N2V(link, base));
+ writeb(irq, (uintptr_t)priv->ibase +
+ pirq_linkno_to_reg(priv, link));
}
static struct irq_info *check_dup_entry(struct irq_info *slot_base,
@@ -78,7 +138,7 @@
{
slot->bus = bus;
slot->devfn = (device << 3) | 0;
- slot->irq[pin - 1].link = LINK_N2V(pirq, priv->link_base);
+ slot->irq[pin - 1].link = pirq_linkno_to_reg(priv, pirq);
slot->irq[pin - 1].bitmap = priv->irq_mask;
}
@@ -89,6 +149,7 @@
int node;
int len, count;
const u32 *cell;
+ struct pirq_regmap *map;
struct irq_routing_table *rt;
struct irq_info *slot, *slot_base;
int irq_entries = 0;
@@ -112,10 +173,43 @@
return -EINVAL;
}
- ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1);
- if (ret == -1)
- return ret;
- priv->link_base = ret;
+ cell = fdt_getprop(blob, node, "intel,pirq-link", &len);
+ if (!cell || len != 8)
+ return -EINVAL;
+ priv->link_base = fdt_addr_to_cpu(cell[0]);
+ priv->link_num = fdt_addr_to_cpu(cell[1]);
+ if (priv->link_num > CONFIG_MAX_PIRQ_LINKS) {
+ debug("Limiting supported PIRQ link number from %d to %d\n",
+ priv->link_num, CONFIG_MAX_PIRQ_LINKS);
+ priv->link_num = CONFIG_MAX_PIRQ_LINKS;
+ }
+
+ cell = fdt_getprop(blob, node, "intel,pirq-regmap", &len);
+ if (cell) {
+ if (len % sizeof(struct pirq_regmap))
+ return -EINVAL;
+
+ count = len / sizeof(struct pirq_regmap);
+ if (count < priv->link_num) {
+ printf("Number of pirq-regmap entires is wrong\n");
+ return -EINVAL;
+ }
+
+ count = priv->link_num;
+ priv->regmap = calloc(count, sizeof(struct pirq_regmap));
+ if (!priv->regmap)
+ return -ENOMEM;
+
+ priv->has_regmap = true;
+ map = priv->regmap;
+ for (i = 0; i < count; i++) {
+ map->link = fdt_addr_to_cpu(cell[0]);
+ map->offset = fdt_addr_to_cpu(cell[1]);
+
+ cell += sizeof(struct pirq_regmap) / sizeof(u32);
+ map++;
+ }
+ }
priv->irq_mask = fdtdec_get_int(blob, node,
"intel,pirq-mask", PIRQ_BITMAP);
@@ -199,7 +293,7 @@
* routing information in the device tree.
*/
if (slot->irq[pr.pin - 1].link !=
- LINK_N2V(pr.pirq, priv->link_base))
+ pirq_linkno_to_reg(priv, pr.pirq))
debug("WARNING: Inconsistent PIRQ routing information\n");
continue;
}
@@ -237,7 +331,7 @@
}
}
-int irq_router_common_init(struct udevice *dev)
+int irq_router_probe(struct udevice *dev)
{
int ret;
@@ -256,11 +350,6 @@
return 0;
}
-int irq_router_probe(struct udevice *dev)
-{
- return irq_router_common_init(dev);
-}
-
ulong write_pirq_routing_table(ulong addr)
{
if (!gd->arch.pirq_routing_table)
diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig
index 82d5489..5f0e608 100644
--- a/arch/x86/cpu/ivybridge/Kconfig
+++ b/arch/x86/cpu/ivybridge/Kconfig
@@ -13,11 +13,13 @@
imply AHCI_PCI
imply ICH_SPI
imply INTEL_ICH6_GPIO
+ imply PINCTRL_ICH6
imply SCSI
imply SCSI_AHCI
imply SPI_FLASH
imply USB
imply USB_EHCI_HCD
+ imply USB_XHCI_HCD
imply VIDEO_VESA
if NORTHBRIDGE_INTEL_IVYBRIDGE
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile
index 27cfb26..716134e 100644
--- a/arch/x86/cpu/ivybridge/Makefile
+++ b/arch/x86/cpu/ivybridge/Makefile
@@ -8,7 +8,6 @@
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += cpu.o
obj-y += early_me.o
obj-y += lpc.o
-obj-y += model_206ax.o
obj-y += northbridge.o
ifndef CONFIG_SPL_BUILD
obj-y += sata.o
@@ -18,4 +17,5 @@
obj-y += sdram_nop.o
endif
endif
+obj-y += model_206ax.o
obj-y += bd82x6x.o
diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c
index c5441aa..33e5c62 100644
--- a/arch/x86/cpu/ivybridge/model_206ax.c
+++ b/arch/x86/cpu/ivybridge/model_206ax.c
@@ -393,10 +393,6 @@
msr_write(IA32_MC0_STATUS + (i * 4), msr);
}
-#if CONFIG_USBDEBUG
-static unsigned ehci_debug_addr;
-#endif
-
static int model_206ax_init(struct udevice *dev)
{
int ret;
@@ -404,17 +400,6 @@
/* Clear out pending MCEs */
configure_mca();
-#if CONFIG_USBDEBUG
- /* Is this caution really needed? */
- if (!ehci_debug_addr)
- ehci_debug_addr = get_ehci_debug();
- set_ehci_debug(0);
-#endif
-
-#if CONFIG_USBDEBUG
- set_ehci_debug(ehci_debug_addr);
-#endif
-
/* Enable the local cpu apics */
enable_lapic_tpr();
diff --git a/arch/x86/cpu/quark/Makefile b/arch/x86/cpu/quark/Makefile
index 476e37c..7039f8b 100644
--- a/arch/x86/cpu/quark/Makefile
+++ b/arch/x86/cpu/quark/Makefile
@@ -2,6 +2,6 @@
#
# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
-obj-y += car.o dram.o irq.o msg_port.o quark.o
+obj-y += car.o dram.o msg_port.o quark.o
obj-y += mrc.o mrc_util.o hte.o smc.o
obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o
diff --git a/arch/x86/cpu/quark/irq.c b/arch/x86/cpu/quark/irq.c
deleted file mode 100644
index 6928c33..0000000
--- a/arch/x86/cpu/quark/irq.c
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
- * Copyright (C) 2015 Google, Inc
- */
-
-#include <common.h>
-#include <dm.h>
-#include <asm/irq.h>
-#include <asm/arch/device.h>
-#include <asm/arch/quark.h>
-
-int quark_irq_router_probe(struct udevice *dev)
-{
- struct quark_rcba *rcba;
- u32 base;
-
- qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base);
- base &= ~MEM_BAR_EN;
- rcba = (struct quark_rcba *)base;
-
- /*
- * Route Quark PCI device interrupt pin to PIRQ
- *
- * Route device#23's INTA/B/C/D to PIRQA/B/C/D
- * Route device#20,21's INTA/B/C/D to PIRQE/F/G/H
- */
- writew(PIRQC, &rcba->rmu_ir);
- writew(PIRQA | (PIRQB << 4) | (PIRQC << 8) | (PIRQD << 12),
- &rcba->d23_ir);
- writew(PIRQD, &rcba->core_ir);
- writew(PIRQE | (PIRQF << 4) | (PIRQG << 8) | (PIRQH << 12),
- &rcba->d20d21_ir);
-
- return irq_router_common_init(dev);
-}
-
-static const struct udevice_id quark_irq_router_ids[] = {
- { .compatible = "intel,quark-irq-router" },
- { }
-};
-
-U_BOOT_DRIVER(quark_irq_router_drv) = {
- .name = "quark_intel_irq",
- .id = UCLASS_IRQ,
- .of_match = quark_irq_router_ids,
- .probe = quark_irq_router_probe,
-};
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c
index 46141c4..4fd6864 100644
--- a/arch/x86/cpu/quark/quark.c
+++ b/arch/x86/cpu/quark/quark.c
@@ -7,6 +7,7 @@
#include <mmc.h>
#include <asm/io.h>
#include <asm/ioapic.h>
+#include <asm/irq.h>
#include <asm/mrccache.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
@@ -313,12 +314,37 @@
writel((0xf << 16) | 0xf, bar + USBD_EP_INT_STS);
}
+static void quark_irq_init(void)
+{
+ struct quark_rcba *rcba;
+ u32 base;
+
+ qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base);
+ base &= ~MEM_BAR_EN;
+ rcba = (struct quark_rcba *)base;
+
+ /*
+ * Route Quark PCI device interrupt pin to PIRQ
+ *
+ * Route device#23's INTA/B/C/D to PIRQA/B/C/D
+ * Route device#20,21's INTA/B/C/D to PIRQE/F/G/H
+ */
+ writew(PIRQC, &rcba->rmu_ir);
+ writew(PIRQA | (PIRQB << 4) | (PIRQC << 8) | (PIRQD << 12),
+ &rcba->d23_ir);
+ writew(PIRQD, &rcba->core_ir);
+ writew(PIRQE | (PIRQF << 4) | (PIRQG << 8) | (PIRQH << 12),
+ &rcba->d20d21_ir);
+}
+
int arch_early_init_r(void)
{
quark_pcie_init();
quark_usb_init();
+ quark_irq_init();
+
return 0;
}
diff --git a/arch/x86/cpu/queensbay/Makefile b/arch/x86/cpu/queensbay/Makefile
index b535b2a..ac29613 100644
--- a/arch/x86/cpu/queensbay/Makefile
+++ b/arch/x86/cpu/queensbay/Makefile
@@ -2,5 +2,5 @@
#
# Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
-obj-y += fsp_configs.o irq.o
+obj-y += fsp_configs.o
obj-y += tnc.o
diff --git a/arch/x86/cpu/queensbay/irq.c b/arch/x86/cpu/queensbay/irq.c
deleted file mode 100644
index 208cd61..0000000
--- a/arch/x86/cpu/queensbay/irq.c
+++ /dev/null
@@ -1,64 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
- * Copyright (C) 2015 Google, Inc
- */
-
-#include <common.h>
-#include <dm.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/arch/device.h>
-#include <asm/arch/tnc.h>
-
-int queensbay_irq_router_probe(struct udevice *dev)
-{
- struct tnc_rcba *rcba;
- u32 base;
-
- dm_pci_read_config32(dev->parent, LPC_RCBA, &base);
- base &= ~MEM_BAR_EN;
- rcba = (struct tnc_rcba *)base;
-
- /* Make sure all internal PCI devices are using INTA */
- writel(INTA, &rcba->d02ip);
- writel(INTA, &rcba->d03ip);
- writel(INTA, &rcba->d27ip);
- writel(INTA, &rcba->d31ip);
- writel(INTA, &rcba->d23ip);
- writel(INTA, &rcba->d24ip);
- writel(INTA, &rcba->d25ip);
- writel(INTA, &rcba->d26ip);
-
- /*
- * Route TunnelCreek PCI device interrupt pin to PIRQ
- *
- * Since PCIe downstream ports received INTx are routed to PIRQ
- * A/B/C/D directly and not configurable, we have to route PCIe
- * root ports' INTx to PIRQ A/B/C/D as well. For other devices
- * on TunneCreek, route them to PIRQ E/F/G/H.
- */
- writew(PIRQE, &rcba->d02ir);
- writew(PIRQF, &rcba->d03ir);
- writew(PIRQG, &rcba->d27ir);
- writew(PIRQH, &rcba->d31ir);
- writew(PIRQA, &rcba->d23ir);
- writew(PIRQB, &rcba->d24ir);
- writew(PIRQC, &rcba->d25ir);
- writew(PIRQD, &rcba->d26ir);
-
- return irq_router_common_init(dev);
-}
-
-static const struct udevice_id queensbay_irq_router_ids[] = {
- { .compatible = "intel,queensbay-irq-router" },
- { }
-};
-
-U_BOOT_DRIVER(queensbay_irq_router_drv) = {
- .name = "queensbay_intel_irq",
- .id = UCLASS_IRQ,
- .of_match = queensbay_irq_router_ids,
- .probe = queensbay_irq_router_probe,
-};
diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c
index 439c14d..76556fc 100644
--- a/arch/x86/cpu/queensbay/tnc.c
+++ b/arch/x86/cpu/queensbay/tnc.c
@@ -98,6 +98,43 @@
return x86_cpu_init_f();
}
+static void tnc_irq_init(void)
+{
+ struct tnc_rcba *rcba;
+ u32 base;
+
+ pci_read_config32(TNC_LPC, LPC_RCBA, &base);
+ base &= ~MEM_BAR_EN;
+ rcba = (struct tnc_rcba *)base;
+
+ /* Make sure all internal PCI devices are using INTA */
+ writel(INTA, &rcba->d02ip);
+ writel(INTA, &rcba->d03ip);
+ writel(INTA, &rcba->d27ip);
+ writel(INTA, &rcba->d31ip);
+ writel(INTA, &rcba->d23ip);
+ writel(INTA, &rcba->d24ip);
+ writel(INTA, &rcba->d25ip);
+ writel(INTA, &rcba->d26ip);
+
+ /*
+ * Route TunnelCreek PCI device interrupt pin to PIRQ
+ *
+ * Since PCIe downstream ports received INTx are routed to PIRQ
+ * A/B/C/D directly and not configurable, we have to route PCIe
+ * root ports' INTx to PIRQ A/B/C/D as well. For other devices
+ * on TunneCreek, route them to PIRQ E/F/G/H.
+ */
+ writew(PIRQE, &rcba->d02ir);
+ writew(PIRQF, &rcba->d03ir);
+ writew(PIRQG, &rcba->d27ir);
+ writew(PIRQH, &rcba->d31ir);
+ writew(PIRQA, &rcba->d23ir);
+ writew(PIRQB, &rcba->d24ir);
+ writew(PIRQC, &rcba->d25ir);
+ writew(PIRQD, &rcba->d26ir);
+}
+
int arch_early_init_r(void)
{
int ret = 0;
@@ -106,5 +143,7 @@
ret = disable_igd();
#endif
+ tnc_irq_init();
+
return ret;
}
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts
index fab919a..26b9f85 100644
--- a/arch/x86/dts/chromebook_link.dts
+++ b/arch/x86/dts/chromebook_link.dts
@@ -26,14 +26,12 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
- u-boot,dm-pre-reloc;
cpu@0 {
device_type = "cpu";
compatible = "intel,core-gen3";
reg = <0>;
intel,apic-id = <0>;
- u-boot,dm-pre-reloc;
};
cpu@1 {
@@ -41,7 +39,6 @@
compatible = "intel,core-gen3";
reg = <1>;
intel,apic-id = <1>;
- u-boot,dm-pre-reloc;
};
cpu@2 {
@@ -49,7 +46,6 @@
compatible = "intel,core-gen3";
reg = <2>;
intel,apic-id = <2>;
- u-boot,dm-pre-reloc;
};
cpu@3 {
@@ -57,7 +53,6 @@
compatible = "intel,core-gen3";
reg = <3>;
intel,apic-id = <3>;
- u-boot,dm-pre-reloc;
};
};
diff --git a/arch/x86/dts/cougarcanyon2.dts b/arch/x86/dts/cougarcanyon2.dts
index ea836ee..c1cda73 100644
--- a/arch/x86/dts/cougarcanyon2.dts
+++ b/arch/x86/dts/cougarcanyon2.dts
@@ -5,6 +5,8 @@
/dts-v1/;
+#include <dt-bindings/interrupt-router/intel-irq.h>
+
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
/include/ "keyboard.dtsi"
@@ -27,6 +29,39 @@
stdout-path = "/serial";
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "intel,core-gen3";
+ reg = <0>;
+ intel,apic-id = <0>;
+ };
+
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "intel,core-gen3";
+ reg = <1>;
+ intel,apic-id = <1>;
+ };
+
+ cpu@2 {
+ device_type = "cpu";
+ compatible = "intel,core-gen3";
+ reg = <2>;
+ intel,apic-id = <2>;
+ };
+
+ cpu@3 {
+ device_type = "cpu";
+ compatible = "intel,core-gen3";
+ reg = <3>;
+ intel,apic-id = <3>;
+ };
+ };
+
microcode {
update@0 {
#include "microcode/m12306a2_00000008.dtsi"
@@ -66,10 +101,56 @@
#address-cells = <1>;
#size-cells = <1>;
+ irq-router {
+ compatible = "intel,irq-router";
+ intel,pirq-config = "pci";
+ intel,actl-8bit;
+ intel,actl-addr = <0x44>;
+ intel,pirq-link = <0x60 8>;
+ intel,pirq-regmap = <
+ PIRQA 0
+ PIRQB 1
+ PIRQC 2
+ PIRQD 3
+ PIRQE 8
+ PIRQF 9
+ PIRQG 10
+ PIRQH 11
+ >;
+ intel,pirq-mask = <0xcee0>;
+ intel,pirq-routing = <
+ /* Panther Point PCI devices */
+ PCI_BDF(0, 2, 0) INTA PIRQA
+ PCI_BDF(0, 20, 0) INTA PIRQA
+ PCI_BDF(0, 22, 0) INTA PIRQA
+ PCI_BDF(0, 22, 1) INTB PIRQB
+ PCI_BDF(0, 22, 2) INTC PIRQC
+ PCI_BDF(0, 22, 3) INTD PIRQD
+ PCI_BDF(0, 25, 0) INTA PIRQA
+ PCI_BDF(0, 26, 0) INTA PIRQA
+ PCI_BDF(0, 27, 0) INTB PIRQA
+ PCI_BDF(0, 28, 0) INTA PIRQA
+ PCI_BDF(0, 28, 1) INTB PIRQB
+ PCI_BDF(0, 28, 2) INTC PIRQC
+ PCI_BDF(0, 28, 3) INTD PIRQD
+ PCI_BDF(0, 28, 4) INTA PIRQA
+ PCI_BDF(0, 28, 5) INTB PIRQB
+ PCI_BDF(0, 28, 6) INTC PIRQC
+ PCI_BDF(0, 28, 7) INTD PIRQD
+ PCI_BDF(0, 29, 0) INTA PIRQA
+ PCI_BDF(0, 31, 2) INTB PIRQB
+ PCI_BDF(0, 31, 3) INTC PIRQC
+ PCI_BDF(0, 31, 5) INTB PIRQB
+ PCI_BDF(0, 31, 6) INTC PIRQC
+ >;
+ };
+
spi0: spi {
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,ich9-spi";
+ intel,spi-lock-down;
+
spi-flash@0 {
reg = <0>;
compatible = "winbond,w25q64bv", "spi-flash";
diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts
index 4fe076a..d8faa9d 100644
--- a/arch/x86/dts/crownbay.dts
+++ b/arch/x86/dts/crownbay.dts
@@ -151,7 +151,7 @@
#size-cells = <1>;
irq-router {
- compatible = "intel,queensbay-irq-router";
+ compatible = "intel,irq-router";
intel,pirq-config = "pci";
intel,actl-addr = <0x58>;
intel,pirq-link = <0x60 8>;
diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts
index d86fdc0..3454abd 100644
--- a/arch/x86/dts/galileo.dts
+++ b/arch/x86/dts/galileo.dts
@@ -97,7 +97,7 @@
#size-cells = <1>;
irq-router {
- compatible = "intel,quark-irq-router";
+ compatible = "intel,irq-router";
intel,pirq-config = "pci";
intel,actl-addr = <0x58>;
intel,pirq-link = <0x60 8>;
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 169b281..e5c9160 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -22,6 +22,11 @@
PIRQ_VIA_IBASE
};
+struct pirq_regmap {
+ int link;
+ int offset;
+};
+
/**
* Intel interrupt router control block
*
@@ -29,6 +34,8 @@
*
* @config: PIRQ_VIA_PCI or PIRQ_VIA_IBASE
* @link_base: link value base number
+ * @link_num: number of PIRQ links supported
+ * @has_regmap: has mapping table between PIRQ link and routing register offset
* @irq_mask: IRQ mask reprenting the 16 IRQs in 8259, bit N is 1 means
* IRQ N is available to be routed
* @lb_bdf: irq router's PCI bus/device/function number encoding
@@ -39,6 +46,9 @@
struct irq_router {
int config;
u32 link_base;
+ int link_num;
+ bool has_regmap;
+ struct pirq_regmap *regmap;
u16 irq_mask;
u32 bdf;
u32 ibase;
@@ -52,17 +62,6 @@
int pirq;
};
-/* PIRQ link number and value conversion */
-#define LINK_V2N(link, base) (link - base)
-#define LINK_N2V(link, base) (link + base)
-
#define PIRQ_BITMAP 0xdef8
-/**
- * irq_router_common_init() - Perform common x86 interrupt init
- *
- * This creates the PIRQ routing table and routes the IRQs
- */
-int irq_router_common_init(struct udevice *dev);
-
#endif /* _ARCH_IRQ_H_ */
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 5a64f6e..0e054da 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -24,7 +24,7 @@
obj-y += northbridge-uclass.o
obj-$(CONFIG_I8259_PIC) += i8259.o
obj-$(CONFIG_I8254_TIMER) += i8254.o
-obj-y += pinctrl_ich6.o
+obj-$(CONFIG_PINCTRL_ICH6) += pinctrl_ich6.o
obj-y += pirq_routing.o
obj-y += relocate.o
obj-y += physmem.o
@@ -58,10 +58,10 @@
# When building for 64-bit we must remove the i386-specific flags
CFLAGS_REMOVE_reloc_x86_64_efi.o += -mregparm=3 -march=i386 -m32
-CFLAGS_reloc_x86_64_efi.o += -fpic -fshort-wchar
+CFLAGS_reloc_x86_64_efi.o += -fpic -fshort-wchar -m64
AFLAGS_REMOVE_crt0_x86_64_efi.o += -mregparm=3 -march=i386 -m32
-AFLAGS_crt0_x86_64_efi.o += -fpic -fshort-wchar
+AFLAGS_crt0_x86_64_efi.o += -fpic -fshort-wchar -m64
extra-$(CONFIG_EFI_STUB_32BIT) += crt0_ia32_efi.o reloc_ia32_efi.o
extra-$(CONFIG_EFI_STUB_64BIT) += crt0_x86_64_efi.o reloc_x86_64_efi.o
diff --git a/cmd/Kconfig b/cmd/Kconfig
index e283cb9..1eb55e5 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1219,6 +1219,7 @@
config CMD_LINK_LOCAL
bool "linklocal"
+ select LIB_RAND
help
Acquire a network IP address using the link-local protocol
diff --git a/configs/cougarcanyon2_defconfig b/configs/cougarcanyon2_defconfig
index 6c79b77..eeee252 100644
--- a/configs/cougarcanyon2_defconfig
+++ b/configs/cougarcanyon2_defconfig
@@ -3,13 +3,18 @@
CONFIG_VENDOR_INTEL=y
CONFIG_DEFAULT_DEVICE_TREE="cougarcanyon2"
CONFIG_TARGET_COUGARCANYON2=y
+# CONFIG_HAVE_INTEL_ME is not set
# CONFIG_ENABLE_MRC_CACHE is not set
+CONFIG_SMP=y
+CONFIG_GENERATE_PIRQ_TABLE=y
+CONFIG_GENERATE_MP_TABLE=y
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_PART=y
@@ -31,6 +36,7 @@
CONFIG_EFI_PARTITION=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
+CONFIG_CPU=y
CONFIG_SYS_NS16550=y
CONFIG_SPI=y
CONFIG_USB_STORAGE=y
diff --git a/configs/efi-x86_defconfig b/configs/efi-x86_defconfig
index 815b51e..a2f072b 100644
--- a/configs/efi-x86_defconfig
+++ b/configs/efi-x86_defconfig
@@ -13,12 +13,8 @@
CONFIG_LAST_STAGE_INIT=y
CONFIG_HUSH_PARSER=y
# CONFIG_CMD_BOOTM is not set
-CONFIG_CMD_GPIO=y
CONFIG_CMD_PART=y
-CONFIG_CMD_SF=y
# CONFIG_CMD_SF_TEST is not set
-CONFIG_CMD_SPI=y
-CONFIG_CMD_USB=y
# CONFIG_CMD_NET is not set
CONFIG_CMD_TIME=y
CONFIG_CMD_EXT2=y
@@ -30,10 +26,10 @@
CONFIG_ISO_PARTITION=y
CONFIG_EFI_PARTITION=y
CONFIG_OF_EMBED=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
# CONFIG_DM_ETH is not set
CONFIG_DEBUG_EFI_CONSOLE=y
-CONFIG_SPI=y
-CONFIG_ICH_SPI=y
# CONFIG_REGEX is not set
CONFIG_EFI=y
# CONFIG_EFI_LOADER is not set
diff --git a/doc/README.x86 b/doc/README.x86
index 04f0220..78664c3 100644
--- a/doc/README.x86
+++ b/doc/README.x86
@@ -256,7 +256,9 @@
and SPI-1 flash is used to store U-Boot. For convenience, the complete 8MB SPI-0
flash image is included in the FSP package (named Rom00_8M_MB_PPT.bin). Program
this image to the SPI-0 flash according to the board manual just once and we are
-all set. For programming U-Boot we just need to program SPI-1 flash.
+all set. For programming U-Boot we just need to program SPI-1 flash. Since the
+default u-boot.rom image for this board is set to 2MB, it should be programmed
+to the last 2MB of the 8MB chip, address range [600000, 7FFFFF].
---
diff --git a/doc/device-tree-bindings/misc/intel,irq-router.txt b/doc/device-tree-bindings/misc/intel,irq-router.txt
index 04ad346..09e97b4 100644
--- a/doc/device-tree-bindings/misc/intel,irq-router.txt
+++ b/doc/device-tree-bindings/misc/intel,irq-router.txt
@@ -22,6 +22,12 @@
- intel,pirq-link : Specifies the PIRQ link information with two cells. The
first cell is the register offset that controls the first PIRQ link routing.
The second cell is the total number of PIRQ links the router supports.
+- intel,pirq-regmap : Specifies PIRQ routing register offset of all PIRQ links,
+ encoded as 2 cells a group for each link. The first cell is the PIRQ link
+ number (0 for PIRQA, 1 for PIRQB, etc). The second cell is the PIRQ routing
+ register offset from the interrupt router's base address. If this property
+ is omitted, it indicates a consecutive register offset from the first PIRQ
+ link, as specified by the first cell of intel,pirq-link.
- intel,pirq-mask : Specifies the IRQ mask representing the 16 IRQs in the
8259 PIC. Bit N is 1 means IRQ N is available to be routed.
- intel,pirq-routing : Specifies all PCI devices' IRQ routing information,
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f2cc75f..e88f056 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -362,6 +362,16 @@
This driver implements support for the Fast Ethernet Controller
on MPC8XX
+config SNI_AVE
+ bool "Socionext AVE Ethernet support"
+ depends on DM_ETH && ARCH_UNIPHIER
+ select PHYLIB
+ select SYSCON
+ select REGMAP
+ help
+ This driver implements support for the Socionext AVE Ethernet
+ controller, as found on the Socionext UniPhier family.
+
config ETHER_ON_FEC1
bool "FEC1"
depends on MPC8XX_FEC
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 584bfdf..058dd00 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -70,3 +70,4 @@
obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
obj-$(CONFIG_FSL_PFE) += pfe_eth/
+obj-$(CONFIG_SNI_AVE) += sni_ave.o
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index e2395db..9919d39 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -910,8 +910,22 @@
return ret;
}
+static int cpsw_reap_completed_packets(struct cpsw_priv *priv)
+{
+ int timeout = CPDMA_TIMEOUT;
+
+ /* reap completed packets */
+ while (timeout-- &&
+ (cpdma_process(priv, &priv->tx_chan, NULL, NULL) >= 0))
+ ;
+
+ return timeout;
+}
+
static void _cpsw_halt(struct cpsw_priv *priv)
{
+ cpsw_reap_completed_packets(priv);
+
writel(0, priv->dma_regs + CPDMA_TXCONTROL);
writel(0, priv->dma_regs + CPDMA_RXCONTROL);
@@ -925,18 +939,12 @@
static int _cpsw_send(struct cpsw_priv *priv, void *packet, int length)
{
- void *buffer;
- int len;
- int timeout = CPDMA_TIMEOUT;
+ int timeout;
flush_dcache_range((unsigned long)packet,
(unsigned long)packet + ALIGN(length, PKTALIGN));
- /* first reap completed packets */
- while (timeout-- &&
- (cpdma_process(priv, &priv->tx_chan, &buffer, &len) >= 0))
- ;
-
+ timeout = cpsw_reap_completed_packets(priv);
if (timeout == -1) {
printf("cpdma_process timeout\n");
return -ETIMEDOUT;
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index cf12521..10a8709 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -280,6 +280,15 @@
writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode);
+ /*
+ * When a MII PHY is used, we must set the PS bit for the DMA
+ * reset to succeed.
+ */
+ if (priv->phydev->interface == PHY_INTERFACE_MODE_MII)
+ writel(readl(&mac_p->conf) | MII_PORTSELECT, &mac_p->conf);
+ else
+ writel(readl(&mac_p->conf) & ~MII_PORTSELECT, &mac_p->conf);
+
start = get_timer(0);
while (readl(&dma_p->busmode) & DMAMAC_SRST) {
if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) {
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index 4e1aff6..e6585ef 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -15,6 +15,7 @@
#include <net.h>
#include <malloc.h>
#include <miiphy.h>
+#include <wait_bit.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <asm/types.h>
@@ -40,10 +41,24 @@
#define MVGBE_SMI_REG (((struct mvgbe_registers *)MVGBE0_BASE)->smi)
#if defined(CONFIG_PHYLIB) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+static int smi_wait_ready(struct mvgbe_device *dmvgbe)
+{
+ int ret;
+
+ ret = wait_for_bit_le32(&MVGBE_SMI_REG, MVGBE_PHY_SMI_BUSY_MASK, false,
+ MVGBE_PHY_SMI_TIMEOUT_MS, false);
+ if (ret) {
+ printf("Error: SMI busy timeout\n");
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* smi_reg_read - miiphy_read callback function.
*
- * Returns 16bit phy register value, or 0xffff on error
+ * Returns 16bit phy register value, or -EFAULT on error
*/
static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
int reg_ofs)
@@ -74,16 +89,9 @@
return -EFAULT;
}
- timeout = MVGBE_PHY_SMI_TIMEOUT;
/* wait till the SMI is not busy */
- do {
- /* read smi register */
- smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
- if (timeout-- == 0) {
- printf("Err..(%s) SMI busy timeout\n", __func__);
- return -EFAULT;
- }
- } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
+ if (smi_wait_ready(dmvgbe) < 0)
+ return -EFAULT;
/* fill the phy address and regiser offset and read opcode */
smi_reg = (phy_adr << MVGBE_PHY_SMI_DEV_ADDR_OFFS)
@@ -119,10 +127,9 @@
}
/*
- * smi_reg_write - imiiphy_write callback function.
+ * smi_reg_write - miiphy_write callback function.
*
- * Returns 0 if write succeed, -EINVAL on bad parameters
- * -ETIME on timeout
+ * Returns 0 if write succeed, -EFAULT on error
*/
static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
int reg_ofs, u16 data)
@@ -131,7 +138,6 @@
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
struct mvgbe_registers *regs = dmvgbe->regs;
u32 smi_reg;
- u32 timeout;
/* Phyadr write request*/
if (phy_adr == MV_PHY_ADR_REQUEST &&
@@ -147,19 +153,12 @@
}
if (reg_ofs > PHYREG_MASK) {
printf("Err..(%s) Invalid register offset\n", __func__);
- return -EINVAL;
+ return -EFAULT;
}
/* wait till the SMI is not busy */
- timeout = MVGBE_PHY_SMI_TIMEOUT;
- do {
- /* read smi register */
- smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
- if (timeout-- == 0) {
- printf("Err..(%s) SMI busy timeout\n", __func__);
- return -ETIME;
- }
- } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
+ if (smi_wait_ready(dmvgbe) < 0)
+ return -EFAULT;
/* fill the phy addr and reg offset and write opcode and data */
smi_reg = (data << MVGBE_PHY_SMI_DATA_OFFS);
diff --git a/drivers/net/mvgbe.h b/drivers/net/mvgbe.h
index c20d1d7..1dc9bbe 100644
--- a/drivers/net/mvgbe.h
+++ b/drivers/net/mvgbe.h
@@ -216,6 +216,7 @@
/* SMI register fields */
#define MVGBE_PHY_SMI_TIMEOUT 10000
+#define MVGBE_PHY_SMI_TIMEOUT_MS 1000
#define MVGBE_PHY_SMI_DATA_OFFS 0 /* Data */
#define MVGBE_PHY_SMI_DATA_MASK (0xffff << MVGBE_PHY_SMI_DATA_OFFS)
#define MVGBE_PHY_SMI_DEV_ADDR_OFFS 16 /* PHY device address */
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 7036b51..45e5eda 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -1025,6 +1025,8 @@
if (rxq->descs == NULL)
return -ENOMEM;
+ WARN_ON(rxq->descs != PTR_ALIGN(rxq->descs, ARCH_DMA_MINALIGN));
+
rxq->last_desc = rxq->size - 1;
/* Set Rx descriptors queue starting address */
@@ -1061,6 +1063,8 @@
if (txq->descs == NULL)
return -ENOMEM;
+ WARN_ON(txq->descs != PTR_ALIGN(txq->descs, ARCH_DMA_MINALIGN));
+
txq->last_desc = txq->size - 1;
/* Set maximum bandwidth for enabled TXQs */
@@ -1694,18 +1698,20 @@
* be active. Make this area DMA safe by disabling the D-cache
*/
if (!buffer_loc.tx_descs) {
+ u32 size;
+
/* Align buffer area for descs and rx_buffers to 1MiB */
bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
mmu_set_region_dcache_behaviour((phys_addr_t)bd_space, BD_SPACE,
DCACHE_OFF);
buffer_loc.tx_descs = (struct mvneta_tx_desc *)bd_space;
+ size = roundup(MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc),
+ ARCH_DMA_MINALIGN);
buffer_loc.rx_descs = (struct mvneta_rx_desc *)
- ((phys_addr_t)bd_space +
- MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc));
- buffer_loc.rx_buffers = (phys_addr_t)
- (bd_space +
- MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc) +
- MVNETA_MAX_RXD * sizeof(struct mvneta_rx_desc));
+ ((phys_addr_t)bd_space + size);
+ size += roundup(MVNETA_MAX_RXD * sizeof(struct mvneta_rx_desc),
+ ARCH_DMA_MINALIGN);
+ buffer_loc.rx_buffers = (phys_addr_t)(bd_space + size);
}
pp->base = (void __iomem *)pdata->iobase;
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index 9b60d1a..a04a118 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -284,6 +284,38 @@
return 0;
}
+int cs4223_phy_init(struct phy_device *phydev)
+{
+ int reg_value;
+
+ reg_value = phy_read(phydev, 0x00, CS4223_EEPROM_STATUS);
+ if (!(reg_value & CS4223_EEPROM_FIRMWARE_LOADDONE)) {
+ printf("%s CS4223 Firmware not present in EERPOM\n", __func__);
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+int cs4223_config(struct phy_device *phydev)
+{
+ return cs4223_phy_init(phydev);
+}
+
+int cs4223_probe(struct phy_device *phydev)
+{
+ phydev->flags = PHY_FLAG_BROKEN_RESET;
+ return 0;
+}
+
+int cs4223_startup(struct phy_device *phydev)
+{
+ phydev->link = 1;
+ phydev->speed = SPEED_10000;
+ phydev->duplex = DUPLEX_FULL;
+ return 0;
+}
+
struct phy_driver cs4340_driver = {
.name = "Cortina CS4315/CS4340",
.uid = PHY_UID_CS4340,
@@ -298,9 +330,23 @@
.shutdown = &gen10g_shutdown,
};
+struct phy_driver cs4223_driver = {
+ .name = "Cortina CS4223",
+ .uid = PHY_UID_CS4223,
+ .mask = 0x0ffff00f,
+ .features = PHY_10G_FEATURES,
+ .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
+ MDIO_DEVS_AN),
+ .config = &cs4223_config,
+ .probe = &cs4223_probe,
+ .startup = &cs4223_startup,
+ .shutdown = &gen10g_shutdown,
+};
+
int phy_cortina_init(void)
{
phy_register(&cs4340_driver);
+ phy_register(&cs4223_driver);
return 0;
}
@@ -319,7 +365,7 @@
return -EIO;
*phy_id |= (phy_reg & 0xffff);
- if (*phy_id == PHY_UID_CS4340)
+ if ((*phy_id == PHY_UID_CS4340) || (*phy_id == PHY_UID_CS4223))
return 0;
/*
diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c
index 17040bd..ea54a15 100644
--- a/drivers/net/phy/mv88e61xx.c
+++ b/drivers/net/phy/mv88e61xx.c
@@ -705,6 +705,31 @@
return res;
}
+static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
+{
+ int val;
+
+ val = mv88e61xx_port_read(phydev, port, PORT_REG_PHYS_CTRL);
+ if (val < 0)
+ return val;
+
+ val &= ~(PORT_REG_PHYS_CTRL_SPD_MASK |
+ PORT_REG_PHYS_CTRL_FC_VALUE);
+ val |= PORT_REG_PHYS_CTRL_PCS_AN_EN |
+ PORT_REG_PHYS_CTRL_PCS_AN_RST |
+ PORT_REG_PHYS_CTRL_FC_FORCE |
+ PORT_REG_PHYS_CTRL_DUPLEX_VALUE |
+ PORT_REG_PHYS_CTRL_DUPLEX_FORCE |
+ PORT_REG_PHYS_CTRL_SPD1000;
+
+ if (port == CONFIG_MV88E61XX_CPU_PORT)
+ val |= PORT_REG_PHYS_CTRL_LINK_VALUE |
+ PORT_REG_PHYS_CTRL_LINK_FORCE;
+
+ return mv88e61xx_port_write(phydev, port, PORT_REG_PHYS_CTRL,
+ val);
+}
+
static int mv88e61xx_set_cpu_port(struct phy_device *phydev)
{
int val;
@@ -748,6 +773,11 @@
if (val < 0)
return val;
}
+ } else {
+ val = mv88e61xx_fixed_port_setup(phydev,
+ CONFIG_MV88E61XX_CPU_PORT);
+ if (val < 0)
+ return val;
}
return 0;
@@ -810,27 +840,6 @@
return 0;
}
-static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
-{
- int val;
-
- val = mv88e61xx_port_read(phydev, port, PORT_REG_PHYS_CTRL);
- if (val < 0)
- return val;
-
- val &= ~(PORT_REG_PHYS_CTRL_SPD_MASK |
- PORT_REG_PHYS_CTRL_FC_VALUE);
- val |= PORT_REG_PHYS_CTRL_PCS_AN_EN |
- PORT_REG_PHYS_CTRL_PCS_AN_RST |
- PORT_REG_PHYS_CTRL_FC_FORCE |
- PORT_REG_PHYS_CTRL_DUPLEX_VALUE |
- PORT_REG_PHYS_CTRL_DUPLEX_FORCE |
- PORT_REG_PHYS_CTRL_SPD1000;
-
- return mv88e61xx_port_write(phydev, port, PORT_REG_PHYS_CTRL,
- val);
-}
-
static int mv88e61xx_phy_config_port(struct phy_device *phydev, u8 phy)
{
int val;
diff --git a/drivers/net/sni_ave.c b/drivers/net/sni_ave.c
new file mode 100644
index 0000000..ba51ea5
--- /dev/null
+++ b/drivers/net/sni_ave.c
@@ -0,0 +1,995 @@
+// SPDX-License-Identifier: GPL-2.0+
+/**
+ * sni_ave.c - Socionext UniPhier AVE ethernet driver
+ * Copyright 2016-2018 Socionext inc.
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <fdt_support.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <miiphy.h>
+#include <net.h>
+#include <regmap.h>
+#include <reset.h>
+#include <syscon.h>
+
+#define AVE_GRST_DELAY_MSEC 40
+#define AVE_MIN_XMITSIZE 60
+#define AVE_SEND_TIMEOUT_COUNT 1000
+#define AVE_MDIO_TIMEOUT_USEC 10000
+#define AVE_HALT_TIMEOUT_USEC 10000
+
+/* General Register Group */
+#define AVE_IDR 0x000 /* ID */
+#define AVE_VR 0x004 /* Version */
+#define AVE_GRR 0x008 /* Global Reset */
+#define AVE_CFGR 0x00c /* Configuration */
+
+/* Interrupt Register Group */
+#define AVE_GIMR 0x100 /* Global Interrupt Mask */
+#define AVE_GISR 0x104 /* Global Interrupt Status */
+
+/* MAC Register Group */
+#define AVE_TXCR 0x200 /* TX Setup */
+#define AVE_RXCR 0x204 /* RX Setup */
+#define AVE_RXMAC1R 0x208 /* MAC address (lower) */
+#define AVE_RXMAC2R 0x20c /* MAC address (upper) */
+#define AVE_MDIOCTR 0x214 /* MDIO Control */
+#define AVE_MDIOAR 0x218 /* MDIO Address */
+#define AVE_MDIOWDR 0x21c /* MDIO Data */
+#define AVE_MDIOSR 0x220 /* MDIO Status */
+#define AVE_MDIORDR 0x224 /* MDIO Rd Data */
+
+/* Descriptor Control Register Group */
+#define AVE_DESCC 0x300 /* Descriptor Control */
+#define AVE_TXDC 0x304 /* TX Descriptor Configuration */
+#define AVE_RXDC 0x308 /* RX Descriptor Ring0 Configuration */
+#define AVE_IIRQC 0x34c /* Interval IRQ Control */
+
+/* 64bit descriptor memory */
+#define AVE_DESC_SIZE_64 12 /* Descriptor Size */
+#define AVE_TXDM_64 0x1000 /* Tx Descriptor Memory */
+#define AVE_RXDM_64 0x1c00 /* Rx Descriptor Memory */
+
+/* 32bit descriptor memory */
+#define AVE_DESC_SIZE_32 8 /* Descriptor Size */
+#define AVE_TXDM_32 0x1000 /* Tx Descriptor Memory */
+#define AVE_RXDM_32 0x1800 /* Rx Descriptor Memory */
+
+/* RMII Bridge Register Group */
+#define AVE_RSTCTRL 0x8028 /* Reset control */
+#define AVE_RSTCTRL_RMIIRST BIT(16)
+#define AVE_LINKSEL 0x8034 /* Link speed setting */
+#define AVE_LINKSEL_100M BIT(0)
+
+/* AVE_GRR */
+#define AVE_GRR_PHYRST BIT(4) /* Reset external PHY */
+#define AVE_GRR_GRST BIT(0) /* Reset all MAC */
+
+/* AVE_CFGR */
+#define AVE_CFGR_MII BIT(27) /* Func mode (1:MII/RMII, 0:RGMII) */
+
+/* AVE_GISR (common with GIMR) */
+#define AVE_GIMR_CLR 0
+#define AVE_GISR_CLR GENMASK(31, 0)
+
+/* AVE_TXCR */
+#define AVE_TXCR_FLOCTR BIT(18) /* Flow control */
+#define AVE_TXCR_TXSPD_1G BIT(17)
+#define AVE_TXCR_TXSPD_100 BIT(16)
+
+/* AVE_RXCR */
+#define AVE_RXCR_RXEN BIT(30) /* Rx enable */
+#define AVE_RXCR_FDUPEN BIT(22) /* Interface mode */
+#define AVE_RXCR_FLOCTR BIT(21) /* Flow control */
+
+/* AVE_MDIOCTR */
+#define AVE_MDIOCTR_RREQ BIT(3) /* Read request */
+#define AVE_MDIOCTR_WREQ BIT(2) /* Write request */
+
+/* AVE_MDIOSR */
+#define AVE_MDIOSR_STS BIT(0) /* access status */
+
+/* AVE_DESCC */
+#define AVE_DESCC_RXDSTPSTS BIT(20)
+#define AVE_DESCC_RD0 BIT(8) /* Enable Rx descriptor Ring0 */
+#define AVE_DESCC_RXDSTP BIT(4) /* Pause Rx descriptor */
+#define AVE_DESCC_TD BIT(0) /* Enable Tx descriptor */
+
+/* AVE_TXDC/RXDC */
+#define AVE_DESC_SIZE(priv, num) \
+ ((num) * ((priv)->data->is_desc_64bit ? AVE_DESC_SIZE_64 : \
+ AVE_DESC_SIZE_32))
+
+/* Command status for descriptor */
+#define AVE_STS_OWN BIT(31) /* Descriptor ownership */
+#define AVE_STS_OK BIT(27) /* Normal transmit */
+#define AVE_STS_1ST BIT(26) /* Head of buffer chain */
+#define AVE_STS_LAST BIT(25) /* Tail of buffer chain */
+#define AVE_STS_PKTLEN_TX_MASK GENMASK(15, 0)
+#define AVE_STS_PKTLEN_RX_MASK GENMASK(10, 0)
+
+#define AVE_DESC_OFS_CMDSTS 0
+#define AVE_DESC_OFS_ADDRL 4
+#define AVE_DESC_OFS_ADDRU 8
+
+/* Parameter for ethernet frame */
+#define AVE_RXCR_MTU 1518
+
+/* SG */
+#define SG_ETPINMODE 0x540
+#define SG_ETPINMODE_EXTPHY BIT(1) /* for LD11 */
+#define SG_ETPINMODE_RMII(ins) BIT(ins)
+
+#define AVE_MAX_CLKS 4
+#define AVE_MAX_RSTS 2
+
+enum desc_id {
+ AVE_DESCID_TX,
+ AVE_DESCID_RX,
+};
+
+struct ave_private {
+ phys_addr_t iobase;
+ unsigned int nclks;
+ struct clk clk[AVE_MAX_CLKS];
+ unsigned int nrsts;
+ struct reset_ctl rst[AVE_MAX_RSTS];
+ struct regmap *regmap;
+ unsigned int regmap_arg;
+
+ struct mii_dev *bus;
+ struct phy_device *phydev;
+ int phy_mode;
+ int max_speed;
+
+ int rx_pos;
+ int rx_siz;
+ int rx_off;
+ int tx_num;
+
+ u8 tx_adj_packetbuf[PKTSIZE_ALIGN + PKTALIGN];
+ void *tx_adj_buf;
+
+ const struct ave_soc_data *data;
+};
+
+struct ave_soc_data {
+ bool is_desc_64bit;
+ const char *clock_names[AVE_MAX_CLKS];
+ const char *reset_names[AVE_MAX_RSTS];
+ int (*get_pinmode)(struct ave_private *priv);
+};
+
+static u32 ave_desc_read(struct ave_private *priv, enum desc_id id, int entry,
+ int offset)
+{
+ int desc_size;
+ u32 addr;
+
+ if (priv->data->is_desc_64bit) {
+ desc_size = AVE_DESC_SIZE_64;
+ addr = (id == AVE_DESCID_TX) ? AVE_TXDM_64 : AVE_RXDM_64;
+ } else {
+ desc_size = AVE_DESC_SIZE_32;
+ addr = (id == AVE_DESCID_TX) ? AVE_TXDM_32 : AVE_RXDM_32;
+ }
+
+ addr += entry * desc_size + offset;
+
+ return readl(priv->iobase + addr);
+}
+
+static u32 ave_desc_read_cmdsts(struct ave_private *priv, enum desc_id id,
+ int entry)
+{
+ return ave_desc_read(priv, id, entry, AVE_DESC_OFS_CMDSTS);
+}
+
+static void ave_desc_write(struct ave_private *priv, enum desc_id id,
+ int entry, int offset, u32 val)
+{
+ int desc_size;
+ u32 addr;
+
+ if (priv->data->is_desc_64bit) {
+ desc_size = AVE_DESC_SIZE_64;
+ addr = (id == AVE_DESCID_TX) ? AVE_TXDM_64 : AVE_RXDM_64;
+ } else {
+ desc_size = AVE_DESC_SIZE_32;
+ addr = (id == AVE_DESCID_TX) ? AVE_TXDM_32 : AVE_RXDM_32;
+ }
+
+ addr += entry * desc_size + offset;
+ writel(val, priv->iobase + addr);
+}
+
+static void ave_desc_write_cmdsts(struct ave_private *priv, enum desc_id id,
+ int entry, u32 val)
+{
+ ave_desc_write(priv, id, entry, AVE_DESC_OFS_CMDSTS, val);
+}
+
+static void ave_desc_write_addr(struct ave_private *priv, enum desc_id id,
+ int entry, uintptr_t paddr)
+{
+ ave_desc_write(priv, id, entry,
+ AVE_DESC_OFS_ADDRL, lower_32_bits(paddr));
+ if (priv->data->is_desc_64bit)
+ ave_desc_write(priv, id, entry,
+ AVE_DESC_OFS_ADDRU, upper_32_bits(paddr));
+}
+
+static void ave_cache_invalidate(uintptr_t vaddr, int len)
+{
+ invalidate_dcache_range(rounddown(vaddr, ARCH_DMA_MINALIGN),
+ roundup(vaddr + len, ARCH_DMA_MINALIGN));
+}
+
+static void ave_cache_flush(uintptr_t vaddr, int len)
+{
+ flush_dcache_range(rounddown(vaddr, ARCH_DMA_MINALIGN),
+ roundup(vaddr + len, ARCH_DMA_MINALIGN));
+}
+
+static int ave_mdiobus_read(struct mii_dev *bus,
+ int phyid, int devad, int regnum)
+{
+ struct ave_private *priv = bus->priv;
+ u32 mdioctl, mdiosr;
+ int ret;
+
+ /* write address */
+ writel((phyid << 8) | regnum, priv->iobase + AVE_MDIOAR);
+
+ /* read request */
+ mdioctl = readl(priv->iobase + AVE_MDIOCTR);
+ writel(mdioctl | AVE_MDIOCTR_RREQ, priv->iobase + AVE_MDIOCTR);
+
+ ret = readl_poll_timeout(priv->iobase + AVE_MDIOSR, mdiosr,
+ !(mdiosr & AVE_MDIOSR_STS),
+ AVE_MDIO_TIMEOUT_USEC);
+ if (ret) {
+ pr_err("%s: failed to read from mdio (phy:%d reg:%x)\n",
+ priv->phydev->dev->name, phyid, regnum);
+ return ret;
+ }
+
+ return readl(priv->iobase + AVE_MDIORDR) & GENMASK(15, 0);
+}
+
+static int ave_mdiobus_write(struct mii_dev *bus,
+ int phyid, int devad, int regnum, u16 val)
+{
+ struct ave_private *priv = bus->priv;
+ u32 mdioctl, mdiosr;
+ int ret;
+
+ /* write address */
+ writel((phyid << 8) | regnum, priv->iobase + AVE_MDIOAR);
+
+ /* write data */
+ writel(val, priv->iobase + AVE_MDIOWDR);
+
+ /* write request */
+ mdioctl = readl(priv->iobase + AVE_MDIOCTR);
+ writel((mdioctl | AVE_MDIOCTR_WREQ) & ~AVE_MDIOCTR_RREQ,
+ priv->iobase + AVE_MDIOCTR);
+
+ ret = readl_poll_timeout(priv->iobase + AVE_MDIOSR, mdiosr,
+ !(mdiosr & AVE_MDIOSR_STS),
+ AVE_MDIO_TIMEOUT_USEC);
+ if (ret)
+ pr_err("%s: failed to write to mdio (phy:%d reg:%x)\n",
+ priv->phydev->dev->name, phyid, regnum);
+
+ return ret;
+}
+
+static int ave_adjust_link(struct ave_private *priv)
+{
+ struct phy_device *phydev = priv->phydev;
+ struct eth_pdata *pdata = dev_get_platdata(phydev->dev);
+ u32 val, txcr, rxcr, rxcr_org;
+ u16 rmt_adv = 0, lcl_adv = 0;
+ u8 cap;
+
+ /* set RGMII speed */
+ val = readl(priv->iobase + AVE_TXCR);
+ val &= ~(AVE_TXCR_TXSPD_100 | AVE_TXCR_TXSPD_1G);
+
+ if (phy_interface_is_rgmii(phydev) && phydev->speed == SPEED_1000)
+ val |= AVE_TXCR_TXSPD_1G;
+ else if (phydev->speed == SPEED_100)
+ val |= AVE_TXCR_TXSPD_100;
+
+ writel(val, priv->iobase + AVE_TXCR);
+
+ /* set RMII speed (100M/10M only) */
+ if (!phy_interface_is_rgmii(phydev)) {
+ val = readl(priv->iobase + AVE_LINKSEL);
+ if (phydev->speed == SPEED_10)
+ val &= ~AVE_LINKSEL_100M;
+ else
+ val |= AVE_LINKSEL_100M;
+ writel(val, priv->iobase + AVE_LINKSEL);
+ }
+
+ /* check current RXCR/TXCR */
+ rxcr = readl(priv->iobase + AVE_RXCR);
+ txcr = readl(priv->iobase + AVE_TXCR);
+ rxcr_org = rxcr;
+
+ if (phydev->duplex) {
+ rxcr |= AVE_RXCR_FDUPEN;
+
+ if (phydev->pause)
+ rmt_adv |= LPA_PAUSE_CAP;
+ if (phydev->asym_pause)
+ rmt_adv |= LPA_PAUSE_ASYM;
+ if (phydev->advertising & ADVERTISED_Pause)
+ lcl_adv |= ADVERTISE_PAUSE_CAP;
+ if (phydev->advertising & ADVERTISED_Asym_Pause)
+ lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+ cap = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+ if (cap & FLOW_CTRL_TX)
+ txcr |= AVE_TXCR_FLOCTR;
+ else
+ txcr &= ~AVE_TXCR_FLOCTR;
+ if (cap & FLOW_CTRL_RX)
+ rxcr |= AVE_RXCR_FLOCTR;
+ else
+ rxcr &= ~AVE_RXCR_FLOCTR;
+ } else {
+ rxcr &= ~AVE_RXCR_FDUPEN;
+ rxcr &= ~AVE_RXCR_FLOCTR;
+ txcr &= ~AVE_TXCR_FLOCTR;
+ }
+
+ if (rxcr_org != rxcr) {
+ /* disable Rx mac */
+ writel(rxcr & ~AVE_RXCR_RXEN, priv->iobase + AVE_RXCR);
+ /* change and enable TX/Rx mac */
+ writel(txcr, priv->iobase + AVE_TXCR);
+ writel(rxcr, priv->iobase + AVE_RXCR);
+ }
+
+ pr_notice("%s: phy:%s speed:%d mac:%pM\n",
+ phydev->dev->name, phydev->drv->name, phydev->speed,
+ pdata->enetaddr);
+
+ return phydev->link;
+}
+
+static int ave_mdiobus_init(struct ave_private *priv, const char *name)
+{
+ struct mii_dev *bus = mdio_alloc();
+
+ if (!bus)
+ return -ENOMEM;
+
+ bus->read = ave_mdiobus_read;
+ bus->write = ave_mdiobus_write;
+ snprintf(bus->name, sizeof(bus->name), "%s", name);
+ bus->priv = priv;
+
+ return mdio_register(bus);
+}
+
+static int ave_phy_init(struct ave_private *priv, void *dev)
+{
+ struct phy_device *phydev;
+ int mask = GENMASK(31, 0), ret;
+
+ phydev = phy_find_by_mask(priv->bus, mask, priv->phy_mode);
+ if (!phydev)
+ return -ENODEV;
+
+ phy_connect_dev(phydev, dev);
+
+ phydev->supported &= PHY_GBIT_FEATURES;
+ if (priv->max_speed) {
+ ret = phy_set_supported(phydev, priv->max_speed);
+ if (ret)
+ return ret;
+ }
+ phydev->advertising = phydev->supported;
+
+ priv->phydev = phydev;
+ phy_config(phydev);
+
+ return 0;
+}
+
+static void ave_stop(struct udevice *dev)
+{
+ struct ave_private *priv = dev_get_priv(dev);
+ u32 val;
+ int ret;
+
+ val = readl(priv->iobase + AVE_GRR);
+ if (val)
+ return;
+
+ val = readl(priv->iobase + AVE_RXCR);
+ val &= ~AVE_RXCR_RXEN;
+ writel(val, priv->iobase + AVE_RXCR);
+
+ writel(0, priv->iobase + AVE_DESCC);
+ ret = readl_poll_timeout(priv->iobase + AVE_DESCC, val, !val,
+ AVE_HALT_TIMEOUT_USEC);
+ if (ret)
+ pr_warn("%s: halt timeout\n", priv->phydev->dev->name);
+
+ writel(AVE_GRR_GRST, priv->iobase + AVE_GRR);
+
+ phy_shutdown(priv->phydev);
+}
+
+static void ave_reset(struct ave_private *priv)
+{
+ u32 val;
+
+ /* reset RMII register */
+ val = readl(priv->iobase + AVE_RSTCTRL);
+ val &= ~AVE_RSTCTRL_RMIIRST;
+ writel(val, priv->iobase + AVE_RSTCTRL);
+
+ /* assert reset */
+ writel(AVE_GRR_GRST | AVE_GRR_PHYRST, priv->iobase + AVE_GRR);
+ mdelay(AVE_GRST_DELAY_MSEC);
+
+ /* 1st, negate PHY reset only */
+ writel(AVE_GRR_GRST, priv->iobase + AVE_GRR);
+ mdelay(AVE_GRST_DELAY_MSEC);
+
+ /* negate reset */
+ writel(0, priv->iobase + AVE_GRR);
+ mdelay(AVE_GRST_DELAY_MSEC);
+
+ /* negate RMII register */
+ val = readl(priv->iobase + AVE_RSTCTRL);
+ val |= AVE_RSTCTRL_RMIIRST;
+ writel(val, priv->iobase + AVE_RSTCTRL);
+}
+
+static int ave_start(struct udevice *dev)
+{
+ struct ave_private *priv = dev_get_priv(dev);
+ uintptr_t paddr;
+ u32 val;
+ int i;
+
+ ave_reset(priv);
+
+ priv->rx_pos = 0;
+ priv->rx_off = 2; /* RX data has 2byte offsets */
+ priv->tx_num = 0;
+ priv->tx_adj_buf =
+ (void *)roundup((uintptr_t)&priv->tx_adj_packetbuf[0],
+ PKTALIGN);
+ priv->rx_siz = (PKTSIZE_ALIGN - priv->rx_off);
+
+ val = 0;
+ if (priv->phy_mode != PHY_INTERFACE_MODE_RGMII)
+ val |= AVE_CFGR_MII;
+ writel(val, priv->iobase + AVE_CFGR);
+
+ /* use one descriptor for Tx */
+ writel(AVE_DESC_SIZE(priv, 1) << 16, priv->iobase + AVE_TXDC);
+ ave_desc_write_cmdsts(priv, AVE_DESCID_TX, 0, 0);
+ ave_desc_write_addr(priv, AVE_DESCID_TX, 0, 0);
+
+ /* use PKTBUFSRX descriptors for Rx */
+ writel(AVE_DESC_SIZE(priv, PKTBUFSRX) << 16, priv->iobase + AVE_RXDC);
+ for (i = 0; i < PKTBUFSRX; i++) {
+ paddr = (uintptr_t)net_rx_packets[i];
+ ave_cache_flush(paddr, priv->rx_siz + priv->rx_off);
+ ave_desc_write_addr(priv, AVE_DESCID_RX, i, paddr);
+ ave_desc_write_cmdsts(priv, AVE_DESCID_RX, i, priv->rx_siz);
+ }
+
+ writel(AVE_GISR_CLR, priv->iobase + AVE_GISR);
+ writel(AVE_GIMR_CLR, priv->iobase + AVE_GIMR);
+
+ writel(AVE_RXCR_RXEN | AVE_RXCR_FDUPEN | AVE_RXCR_FLOCTR | AVE_RXCR_MTU,
+ priv->iobase + AVE_RXCR);
+ writel(AVE_DESCC_RD0 | AVE_DESCC_TD, priv->iobase + AVE_DESCC);
+
+ phy_startup(priv->phydev);
+ ave_adjust_link(priv);
+
+ return 0;
+}
+
+static int ave_write_hwaddr(struct udevice *dev)
+{
+ struct ave_private *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ u8 *mac = pdata->enetaddr;
+
+ writel(mac[0] | mac[1] << 8 | mac[2] << 16 | mac[3] << 24,
+ priv->iobase + AVE_RXMAC1R);
+ writel(mac[4] | mac[5] << 8, priv->iobase + AVE_RXMAC2R);
+
+ return 0;
+}
+
+static int ave_send(struct udevice *dev, void *packet, int length)
+{
+ struct ave_private *priv = dev_get_priv(dev);
+ u32 val;
+ void *ptr = packet;
+ int count;
+
+ /* adjust alignment for descriptor */
+ if ((uintptr_t)ptr & 0x3) {
+ memcpy(priv->tx_adj_buf, (const void *)ptr, length);
+ ptr = priv->tx_adj_buf;
+ }
+
+ /* padding for minimum length */
+ if (length < AVE_MIN_XMITSIZE) {
+ memset(ptr + length, 0, AVE_MIN_XMITSIZE - length);
+ length = AVE_MIN_XMITSIZE;
+ }
+
+ /* check ownership and wait for previous xmit done */
+ count = AVE_SEND_TIMEOUT_COUNT;
+ do {
+ val = ave_desc_read_cmdsts(priv, AVE_DESCID_TX, 0);
+ } while ((val & AVE_STS_OWN) && --count);
+ if (!count)
+ return -ETIMEDOUT;
+
+ ave_cache_flush((uintptr_t)ptr, length);
+ ave_desc_write_addr(priv, AVE_DESCID_TX, 0, (uintptr_t)ptr);
+
+ val = AVE_STS_OWN | AVE_STS_1ST | AVE_STS_LAST |
+ (length & AVE_STS_PKTLEN_TX_MASK);
+ ave_desc_write_cmdsts(priv, AVE_DESCID_TX, 0, val);
+ priv->tx_num++;
+
+ count = AVE_SEND_TIMEOUT_COUNT;
+ do {
+ val = ave_desc_read_cmdsts(priv, AVE_DESCID_TX, 0);
+ } while ((val & AVE_STS_OWN) && --count);
+ if (!count)
+ return -ETIMEDOUT;
+
+ if (!(val & AVE_STS_OK))
+ pr_warn("%s: bad send packet status:%08x\n",
+ priv->phydev->dev->name, le32_to_cpu(val));
+
+ return 0;
+}
+
+static int ave_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct ave_private *priv = dev_get_priv(dev);
+ uchar *ptr;
+ int length = 0;
+ u32 cmdsts;
+
+ while (1) {
+ cmdsts = ave_desc_read_cmdsts(priv, AVE_DESCID_RX,
+ priv->rx_pos);
+ if (!(cmdsts & AVE_STS_OWN))
+ /* hardware ownership, no received packets */
+ return -EAGAIN;
+
+ ptr = net_rx_packets[priv->rx_pos] + priv->rx_off;
+ if (cmdsts & AVE_STS_OK)
+ break;
+
+ pr_warn("%s: bad packet[%d] status:%08x ptr:%p\n",
+ priv->phydev->dev->name, priv->rx_pos,
+ le32_to_cpu(cmdsts), ptr);
+ }
+
+ length = cmdsts & AVE_STS_PKTLEN_RX_MASK;
+
+ /* invalidate after DMA is done */
+ ave_cache_invalidate((uintptr_t)ptr, length);
+ *packetp = ptr;
+
+ return length;
+}
+
+static int ave_free_packet(struct udevice *dev, uchar *packet, int length)
+{
+ struct ave_private *priv = dev_get_priv(dev);
+
+ ave_cache_flush((uintptr_t)net_rx_packets[priv->rx_pos],
+ priv->rx_siz + priv->rx_off);
+
+ ave_desc_write_cmdsts(priv, AVE_DESCID_RX,
+ priv->rx_pos, priv->rx_siz);
+
+ if (++priv->rx_pos >= PKTBUFSRX)
+ priv->rx_pos = 0;
+
+ return 0;
+}
+
+static int ave_pro4_get_pinmode(struct ave_private *priv)
+{
+ u32 reg, mask, val = 0;
+
+ if (priv->regmap_arg > 0)
+ return -EINVAL;
+
+ mask = SG_ETPINMODE_RMII(0);
+
+ switch (priv->phy_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ val = SG_ETPINMODE_RMII(0);
+ break;
+ case PHY_INTERFACE_MODE_MII:
+ case PHY_INTERFACE_MODE_RGMII:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_read(priv->regmap, SG_ETPINMODE, ®);
+ reg &= ~mask;
+ reg |= val;
+ regmap_write(priv->regmap, SG_ETPINMODE, reg);
+
+ return 0;
+}
+
+static int ave_ld11_get_pinmode(struct ave_private *priv)
+{
+ u32 reg, mask, val = 0;
+
+ if (priv->regmap_arg > 0)
+ return -EINVAL;
+
+ mask = SG_ETPINMODE_EXTPHY | SG_ETPINMODE_RMII(0);
+
+ switch (priv->phy_mode) {
+ case PHY_INTERFACE_MODE_INTERNAL:
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ val = SG_ETPINMODE_EXTPHY | SG_ETPINMODE_RMII(0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_read(priv->regmap, SG_ETPINMODE, ®);
+ reg &= ~mask;
+ reg |= val;
+ regmap_write(priv->regmap, SG_ETPINMODE, reg);
+
+ return 0;
+}
+
+static int ave_ld20_get_pinmode(struct ave_private *priv)
+{
+ u32 reg, mask, val = 0;
+
+ if (priv->regmap_arg > 0)
+ return -EINVAL;
+
+ mask = SG_ETPINMODE_RMII(0);
+
+ switch (priv->phy_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ val = SG_ETPINMODE_RMII(0);
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_read(priv->regmap, SG_ETPINMODE, ®);
+ reg &= ~mask;
+ reg |= val;
+ regmap_write(priv->regmap, SG_ETPINMODE, reg);
+
+ return 0;
+}
+
+static int ave_pxs3_get_pinmode(struct ave_private *priv)
+{
+ u32 reg, mask, val = 0;
+
+ if (priv->regmap_arg > 1)
+ return -EINVAL;
+
+ mask = SG_ETPINMODE_RMII(priv->regmap_arg);
+
+ switch (priv->phy_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ val = SG_ETPINMODE_RMII(priv->regmap_arg);
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_read(priv->regmap, SG_ETPINMODE, ®);
+ reg &= ~mask;
+ reg |= val;
+ regmap_write(priv->regmap, SG_ETPINMODE, reg);
+
+ return 0;
+}
+
+static int ave_ofdata_to_platdata(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct ave_private *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args args;
+ const char *phy_mode;
+ const u32 *valp;
+ int ret, nc, nr;
+ const char *name;
+
+ priv->data = (const struct ave_soc_data *)dev_get_driver_data(dev);
+ if (!priv->data)
+ return -EINVAL;
+
+ pdata->iobase = devfdt_get_addr(dev);
+ pdata->phy_interface = -1;
+ phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
+ NULL);
+ if (phy_mode)
+ pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+ if (pdata->phy_interface == -1) {
+ dev_err(dev, "Invalid PHY interface '%s'\n", phy_mode);
+ return -EINVAL;
+ }
+
+ pdata->max_speed = 0;
+ valp = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed",
+ NULL);
+ if (valp)
+ pdata->max_speed = fdt32_to_cpu(*valp);
+
+ for (nc = 0; nc < AVE_MAX_CLKS; nc++) {
+ name = priv->data->clock_names[nc];
+ if (!name)
+ break;
+ ret = clk_get_by_name(dev, name, &priv->clk[nc]);
+ if (ret) {
+ dev_err(dev, "Failed to get clocks property: %d\n",
+ ret);
+ goto out_clk_free;
+ }
+ priv->nclks++;
+ }
+
+ for (nr = 0; nr < AVE_MAX_RSTS; nr++) {
+ name = priv->data->reset_names[nr];
+ if (!name)
+ break;
+ ret = reset_get_by_name(dev, name, &priv->rst[nr]);
+ if (ret) {
+ dev_err(dev, "Failed to get resets property: %d\n",
+ ret);
+ goto out_reset_free;
+ }
+ priv->nrsts++;
+ }
+
+ ret = dev_read_phandle_with_args(dev, "socionext,syscon-phy-mode",
+ NULL, 1, 0, &args);
+ if (ret) {
+ dev_err(dev, "Failed to get syscon-phy-mode property: %d\n",
+ ret);
+ goto out_reset_free;
+ }
+
+ priv->regmap = syscon_node_to_regmap(args.node);
+ if (IS_ERR(priv->regmap)) {
+ ret = PTR_ERR(priv->regmap);
+ dev_err(dev, "can't get syscon: %d\n", ret);
+ goto out_reset_free;
+ }
+
+ if (args.args_count != 1) {
+ ret = -EINVAL;
+ dev_err(dev, "Invalid argument of syscon-phy-mode\n");
+ goto out_reset_free;
+ }
+
+ priv->regmap_arg = args.args[0];
+
+ return 0;
+
+out_reset_free:
+ while (--nr >= 0)
+ reset_free(&priv->rst[nr]);
+out_clk_free:
+ while (--nc >= 0)
+ clk_free(&priv->clk[nc]);
+
+ return ret;
+}
+
+static int ave_probe(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct ave_private *priv = dev_get_priv(dev);
+ int ret, nc, nr;
+
+ priv->data = (const struct ave_soc_data *)dev_get_driver_data(dev);
+ if (!priv->data)
+ return -EINVAL;
+
+ priv->iobase = pdata->iobase;
+ priv->phy_mode = pdata->phy_interface;
+ priv->max_speed = pdata->max_speed;
+
+ ret = priv->data->get_pinmode(priv);
+ if (ret) {
+ dev_err(dev, "Invalid phy-mode\n");
+ return -EINVAL;
+ }
+
+ for (nc = 0; nc < priv->nclks; nc++) {
+ ret = clk_enable(&priv->clk[nc]);
+ if (ret) {
+ dev_err(dev, "Failed to enable clk: %d\n", ret);
+ goto out_clk_release;
+ }
+ }
+
+ for (nr = 0; nr < priv->nrsts; nr++) {
+ ret = reset_deassert(&priv->rst[nr]);
+ if (ret) {
+ dev_err(dev, "Failed to deassert reset: %d\n", ret);
+ goto out_reset_release;
+ }
+ }
+
+ ave_reset(priv);
+
+ ret = ave_mdiobus_init(priv, dev->name);
+ if (ret) {
+ dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
+ goto out_reset_release;
+ }
+
+ priv->bus = miiphy_get_dev_by_name(dev->name);
+
+ ret = ave_phy_init(priv, dev);
+ if (ret) {
+ dev_err(dev, "Failed to initialize phy: %d\n", ret);
+ goto out_mdiobus_release;
+ }
+
+ return 0;
+
+out_mdiobus_release:
+ mdio_unregister(priv->bus);
+ mdio_free(priv->bus);
+out_reset_release:
+ reset_release_all(priv->rst, nr);
+out_clk_release:
+ clk_release_all(priv->clk, nc);
+
+ return ret;
+}
+
+static int ave_remove(struct udevice *dev)
+{
+ struct ave_private *priv = dev_get_priv(dev);
+
+ free(priv->phydev);
+ mdio_unregister(priv->bus);
+ mdio_free(priv->bus);
+ reset_release_all(priv->rst, priv->nrsts);
+ clk_release_all(priv->clk, priv->nclks);
+
+ return 0;
+}
+
+static const struct eth_ops ave_ops = {
+ .start = ave_start,
+ .stop = ave_stop,
+ .send = ave_send,
+ .recv = ave_recv,
+ .free_pkt = ave_free_packet,
+ .write_hwaddr = ave_write_hwaddr,
+};
+
+static const struct ave_soc_data ave_pro4_data = {
+ .is_desc_64bit = false,
+ .clock_names = {
+ "gio", "ether", "ether-gb", "ether-phy",
+ },
+ .reset_names = {
+ "gio", "ether",
+ },
+ .get_pinmode = ave_pro4_get_pinmode,
+};
+
+static const struct ave_soc_data ave_pxs2_data = {
+ .is_desc_64bit = false,
+ .clock_names = {
+ "ether",
+ },
+ .reset_names = {
+ "ether",
+ },
+ .get_pinmode = ave_pro4_get_pinmode,
+};
+
+static const struct ave_soc_data ave_ld11_data = {
+ .is_desc_64bit = false,
+ .clock_names = {
+ "ether",
+ },
+ .reset_names = {
+ "ether",
+ },
+ .get_pinmode = ave_ld11_get_pinmode,
+};
+
+static const struct ave_soc_data ave_ld20_data = {
+ .is_desc_64bit = true,
+ .clock_names = {
+ "ether",
+ },
+ .reset_names = {
+ "ether",
+ },
+ .get_pinmode = ave_ld20_get_pinmode,
+};
+
+static const struct ave_soc_data ave_pxs3_data = {
+ .is_desc_64bit = false,
+ .clock_names = {
+ "ether",
+ },
+ .reset_names = {
+ "ether",
+ },
+ .get_pinmode = ave_pxs3_get_pinmode,
+};
+
+static const struct udevice_id ave_ids[] = {
+ {
+ .compatible = "socionext,uniphier-pro4-ave4",
+ .data = (ulong)&ave_pro4_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs2-ave4",
+ .data = (ulong)&ave_pxs2_data,
+ },
+ {
+ .compatible = "socionext,uniphier-ld11-ave4",
+ .data = (ulong)&ave_ld11_data,
+ },
+ {
+ .compatible = "socionext,uniphier-ld20-ave4",
+ .data = (ulong)&ave_ld20_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs3-ave4",
+ .data = (ulong)&ave_pxs3_data,
+ },
+ { /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(ave) = {
+ .name = "ave",
+ .id = UCLASS_ETH,
+ .of_match = ave_ids,
+ .probe = ave_probe,
+ .remove = ave_remove,
+ .ofdata_to_platdata = ave_ofdata_to_platdata,
+ .ops = &ave_ops,
+ .priv_auto_alloc_size = sizeof(struct ave_private),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index d20b808..8dbd3c5 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -334,8 +334,8 @@
enetaddr_lo = enetaddr[2] | (enetaddr[1] << 8) | (enetaddr[0] << 16);
enetaddr_hi = enetaddr[5] | (enetaddr[4] << 8) | (enetaddr[3] << 16);
- writel(enetaddr_hi, ®s->mac_a1);
- writel(enetaddr_lo, ®s->mac_a0);
+ writel(enetaddr_hi, ®s->mac_a0);
+ writel(enetaddr_lo, ®s->mac_a1);
return 0;
}
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 3784042..03a46da 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -796,8 +796,9 @@
parent = ofnode_get_parent(phandle_args.node);
if (ofnode_valid(parent)) {
- int reg = ofnode_read_u32_default(parent, "reg", 0);
- priv->phyregs_sgmii = (struct tsec_mii_mng *)(reg + 0x520);
+ int reg = ofnode_get_addr_index(parent, 0);
+
+ priv->phyregs_sgmii = (struct tsec_mii_mng *)reg;
} else {
debug("No parent node for PHY?\n");
return -ENOENT;
diff --git a/drivers/net/vsc9953.c b/drivers/net/vsc9953.c
index 5d196cf..f17839c 100644
--- a/drivers/net/vsc9953.c
+++ b/drivers/net/vsc9953.c
@@ -2468,6 +2468,139 @@
debug("VSC9953: failed to set default aggregation code mode\n");
}
+static void vcap_entry2cache_init(u32 target, u32 entry_words)
+{
+ int i;
+
+ for (i = 0; i < entry_words; i++) {
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CACHE_ENTRY_DAT(target, i)), 0x00);
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CACHE_MASK_DAT(target, i)), 0xFF);
+ }
+
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CACHE_TG_DAT(target)), 0x00);
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CFG_MV_CFG(target)),
+ VSC9953_VCAP_CFG_MV_CFG_SIZE(entry_words));
+}
+
+static void vcap_action2cache_init(u32 target, u32 action_words,
+ u32 counter_words)
+{
+ int i;
+
+ for (i = 0; i < action_words; i++)
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CACHE_ACTION_DAT(target, i)), 0x00);
+
+ for (i = 0; i < counter_words; i++)
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CACHE_CNT_DAT(target, i)), 0x00);
+}
+
+static int vcap_cmd(u32 target, u16 ix, int cmd, int sel, int entry_count)
+{
+ u32 tgt = target;
+ u32 value = (VSC9953_VCAP_UPDATE_CTRL_UPDATE_CMD(cmd) |
+ VSC9953_VCAP_UPDATE_CTRL_UPDATE_ADDR(ix) |
+ VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT);
+
+ if ((sel & TCAM_SEL_ENTRY) && ix >= entry_count)
+ return CMD_RET_FAILURE;
+
+ if (!(sel & TCAM_SEL_ENTRY))
+ value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS;
+
+ if (!(sel & TCAM_SEL_ACTION))
+ value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS;
+
+ if (!(sel & TCAM_SEL_COUNTER))
+ value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_CNT_DIS;
+
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CFG_UPDATE_CTRL(tgt)), value);
+
+ do {
+ value = in_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CFG_UPDATE_CTRL(tgt)));
+
+ } while (value & VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT);
+
+ return CMD_RET_SUCCESS;
+}
+
+static void vsc9953_vcap_init(void)
+{
+ u32 tgt = VSC9953_ES0;
+ int cmd_ret;
+
+ /* write entries */
+ vcap_entry2cache_init(tgt, ENTRY_WORDS_ES0);
+ cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
+ ENTRY_WORDS_ES0);
+ if (cmd_ret != CMD_RET_SUCCESS)
+ debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n",
+ __LINE__);
+
+ /* write actions and counters */
+ vcap_action2cache_init(tgt, BITS_TO_DWORD(ES0_ACT_WIDTH),
+ BITS_TO_DWORD(ES0_CNT_WIDTH));
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CFG_MV_CFG(tgt)),
+ VSC9953_VCAP_CFG_MV_CFG_SIZE(ES0_ACT_COUNT));
+ cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
+ TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_ES0);
+ if (cmd_ret != CMD_RET_SUCCESS)
+ debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
+ __LINE__);
+
+ tgt = VSC9953_IS1;
+
+ /* write entries */
+ vcap_entry2cache_init(tgt, ENTRY_WORDS_IS1);
+ cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
+ ENTRY_WORDS_IS1);
+ if (cmd_ret != CMD_RET_SUCCESS)
+ debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n",
+ __LINE__);
+
+ /* write actions and counters */
+ vcap_action2cache_init(tgt, BITS_TO_DWORD(IS1_ACT_WIDTH),
+ BITS_TO_DWORD(IS1_CNT_WIDTH));
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CFG_MV_CFG(tgt)),
+ VSC9953_VCAP_CFG_MV_CFG_SIZE(IS1_ACT_COUNT));
+ cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
+ TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS1);
+ if (cmd_ret != CMD_RET_SUCCESS)
+ debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
+ __LINE__);
+
+ tgt = VSC9953_IS2;
+
+ /* write entries */
+ vcap_entry2cache_init(tgt, ENTRY_WORDS_IS2);
+ cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
+ ENTRY_WORDS_IS2);
+ if (cmd_ret != CMD_RET_SUCCESS)
+ debug("VSC9953:%d invalid selection: TCAM_SEL_ENTRY\n",
+ __LINE__);
+
+ /* write actions and counters */
+ vcap_action2cache_init(tgt, BITS_TO_DWORD(IS2_ACT_WIDTH),
+ BITS_TO_DWORD(IS2_CNT_WIDTH));
+ out_le32((unsigned int *)(VSC9953_OFFSET +
+ VSC9953_VCAP_CFG_MV_CFG(tgt)),
+ VSC9953_VCAP_CFG_MV_CFG_SIZE(IS2_ACT_COUNT));
+ cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
+ TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS2);
+ if (cmd_ret != CMD_RET_SUCCESS)
+ debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
+ __LINE__);
+}
+
void vsc9953_init(bd_t *bis)
{
u32 i;
@@ -2604,6 +2737,7 @@
}
}
+ vsc9953_vcap_init();
vsc9953_default_configuration();
#ifdef CONFIG_CMD_ETHSW
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index a218c92..a817f2e 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -185,7 +185,7 @@
bool int_pcs;
};
-static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
+static int phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
u32 op, u16 *data)
{
u32 mgtcr;
@@ -216,10 +216,10 @@
return 0;
}
-static u32 phyread(struct zynq_gem_priv *priv, u32 phy_addr,
+static int phyread(struct zynq_gem_priv *priv, u32 phy_addr,
u32 regnum, u16 *val)
{
- u32 ret;
+ int ret;
ret = phy_setup_op(priv, phy_addr, regnum,
ZYNQ_GEM_PHYMNTNC_OP_R_MASK, val);
@@ -231,7 +231,7 @@
return ret;
}
-static u32 phywrite(struct zynq_gem_priv *priv, u32 phy_addr,
+static int phywrite(struct zynq_gem_priv *priv, u32 phy_addr,
u32 regnum, u16 data)
{
debug("%s: phy_addr %d, regnum 0x%x, data 0x%x\n", __func__, phy_addr,
@@ -244,7 +244,7 @@
static int phy_detection(struct udevice *dev)
{
int i;
- u16 phyreg;
+ u16 phyreg = 0;
struct zynq_gem_priv *priv = dev->priv;
if (priv->phyaddr != -1) {
@@ -633,10 +633,16 @@
/* Align rxbuffers to ARCH_DMA_MINALIGN */
priv->rxbuffers = memalign(ARCH_DMA_MINALIGN, RX_BUF * PKTSIZE_ALIGN);
+ if (!priv->rxbuffers)
+ return -ENOMEM;
+
memset(priv->rxbuffers, 0, RX_BUF * PKTSIZE_ALIGN);
/* Align bd_space to MMU_SECTION_SHIFT */
bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
+ if (!bd_space)
+ return -ENOMEM;
+
mmu_set_region_dcache_behaviour((phys_addr_t)bd_space,
BD_SPACE, DCACHE_OFF);
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 1cd1e40..46e9c71 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -810,8 +810,8 @@
return ret;
}
-static int decode_regions(struct pci_controller *hose, ofnode parent_node,
- ofnode node)
+static void decode_regions(struct pci_controller *hose, ofnode parent_node,
+ ofnode node)
{
int pci_addr_cells, addr_cells, size_cells;
int cells_per_record;
@@ -820,8 +820,11 @@
int i;
prop = ofnode_get_property(node, "ranges", &len);
- if (!prop)
- return -EINVAL;
+ if (!prop) {
+ debug("%s: Cannot decode regions\n", __func__);
+ return;
+ }
+
pci_addr_cells = ofnode_read_simple_addr_cells(node);
addr_cells = ofnode_read_simple_addr_cells(parent_node);
size_cells = ofnode_read_simple_size_cells(node);
@@ -883,7 +886,7 @@
bd_t *bd = gd->bd;
if (!bd)
- return 0;
+ return;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
if (bd->bi_dram[i].size) {
@@ -908,13 +911,12 @@
base, size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
#endif
- return 0;
+ return;
}
static int pci_uclass_pre_probe(struct udevice *bus)
{
struct pci_controller *hose;
- int ret;
debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name,
bus->parent->name);
@@ -923,12 +925,7 @@
/* For bridges, use the top-level PCI controller */
if (!device_is_on_pci_bus(bus)) {
hose->ctlr = bus;
- ret = decode_regions(hose, dev_ofnode(bus->parent),
- dev_ofnode(bus));
- if (ret) {
- debug("%s: Cannot decode regions\n", __func__);
- return ret;
- }
+ decode_regions(hose, dev_ofnode(bus->parent), dev_ofnode(bus));
} else {
struct pci_controller *parent_hose;
@@ -1185,6 +1182,11 @@
struct pci_region *res;
int i;
+ if (hose->region_count == 0) {
+ *pa = bus_addr;
+ return 0;
+ }
+
for (i = 0; i < hose->region_count; i++) {
res = &hose->regions[i];
@@ -1248,6 +1250,11 @@
ctlr = pci_get_controller(dev);
hose = dev_get_uclass_priv(ctlr);
+ if (hose->region_count == 0) {
+ *ba = phys_addr;
+ return 0;
+ }
+
for (i = 0; i < hose->region_count; i++) {
res = &hose->regions[i];
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c
index c7fefd2..cf86999 100644
--- a/drivers/timer/tsc_timer.c
+++ b/drivers/timer/tsc_timer.c
@@ -21,6 +21,17 @@
DECLARE_GLOBAL_DATA_PTR;
+static unsigned long cpu_mhz_from_cpuid(void)
+{
+ if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
+ return 0;
+
+ if (cpuid_eax(0) < 0x16)
+ return 0;
+
+ return cpuid_eax(0x16);
+}
+
/*
* According to Intel 64 and IA-32 System Programming Guide,
* if MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be
@@ -343,13 +354,21 @@
if (!gd->arch.clock_rate) {
unsigned long fast_calibrate;
- fast_calibrate = cpu_mhz_from_msr();
- if (!fast_calibrate) {
- fast_calibrate = quick_pit_calibrate();
- if (!fast_calibrate)
- panic("TSC frequency is ZERO");
- }
+ fast_calibrate = cpu_mhz_from_cpuid();
+ if (fast_calibrate)
+ goto done;
+ fast_calibrate = cpu_mhz_from_msr();
+ if (fast_calibrate)
+ goto done;
+
+ fast_calibrate = quick_pit_calibrate();
+ if (fast_calibrate)
+ goto done;
+
+ panic("TSC frequency is ZERO");
+
+done:
gd->arch.clock_rate = fast_calibrate * 1000000;
}
}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index e8fd6bf..b995aef 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -23,9 +23,8 @@
hcor = (struct xhci_hcor *)((uintptr_t) hccr +
HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
- debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
- (u32)hccr, (u32)hcor,
- (u32)HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
+ debug("XHCI-PCI init hccr %p and hcor %p hc_length %d\n",
+ hccr, hcor, (u32)HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
*ret_hccr = hccr;
*ret_hcor = hcor;
diff --git a/include/cortina.h b/include/cortina.h
index 4cb0985..ba7fafe 100644
--- a/include/cortina.h
+++ b/include/cortina.h
@@ -64,6 +64,10 @@
#define VILLA_LINE_SDS_COMMON_STX0_TX_OUTPUT_CTRLA 0x427
#define VILLA_LINE_SDS_COMMON_STX0_TX_OUTPUT_CTRLB 0x428
+/* Cortina CS4223 */
+#define CS4223_EEPROM_STATUS 0x5001
+#define CS4223_EEPROM_FIRMWARE_LOADDONE 0x1
+
#define mseq_edc_bist_done (0x1<<0)
#define mseq_edc_bist_fail (0x1<<8)
diff --git a/include/phy.h b/include/phy.h
index 52bf997..7c3fc5c 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -65,6 +65,7 @@
PHY_INTERFACE_MODE_XAUI,
PHY_INTERFACE_MODE_RXAUI,
PHY_INTERFACE_MODE_SFI,
+ PHY_INTERFACE_MODE_INTERNAL,
PHY_INTERFACE_MODE_NONE, /* Must be last */
PHY_INTERFACE_MODE_COUNT,
@@ -87,6 +88,7 @@
[PHY_INTERFACE_MODE_XAUI] = "xaui",
[PHY_INTERFACE_MODE_RXAUI] = "rxaui",
[PHY_INTERFACE_MODE_SFI] = "sfi",
+ [PHY_INTERFACE_MODE_INTERNAL] = "internal",
[PHY_INTERFACE_MODE_NONE] = "",
};
@@ -314,6 +316,7 @@
/* PHY UIDs for various PHYs that are referenced in external code */
#define PHY_UID_CS4340 0x13e51002
+#define PHY_UID_CS4223 0x03e57003
#define PHY_UID_TN2020 0x00a19410
#endif
diff --git a/include/vsc9953.h b/include/vsc9953.h
index bb7f8ec..fe072da 100644
--- a/include/vsc9953.h
+++ b/include/vsc9953.h
@@ -186,6 +186,76 @@
#define MIIMIND_OPR_PEND 0x00000004
+#define VSC9953_BITMASK(offset) ((BIT(offset)) - 1)
+#define VSC9953_ENC_BITFIELD(target, offset, width) \
+ (((target) & VSC9953_BITMASK(width)) << (offset))
+
+#define VSC9953_IO_ADDR(target, offset) ((target) + (offset << 2))
+
+#define VSC9953_IO_REG(target, offset) (VSC9953_IO_ADDR(target, offset))
+#define VSC9953_VCAP_CACHE_ENTRY_DAT(target, ri) \
+ VSC9953_IO_REG(target, (0x2 + (ri)))
+
+#define VSC9953_VCAP_CACHE_MASK_DAT(target, ri) \
+ VSC9953_IO_REG(target, (0x42 + (ri)))
+
+#define VSC9953_VCAP_CACHE_TG_DAT(target) VSC9953_IO_REG(target, 0xe2)
+#define VSC9953_VCAP_CFG_MV_CFG(target) VSC9953_IO_REG(target, 0x1)
+#define VSC9953_VCAP_CFG_MV_CFG_SIZE(target) \
+ VSC9953_ENC_BITFIELD(target, 0, 16)
+
+#define VSC9953_VCAP_CFG_UPDATE_CTRL(target) VSC9953_IO_REG(target, 0x0)
+#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_CMD(target) \
+ VSC9953_ENC_BITFIELD(target, 22, 3)
+
+#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ADDR(target) \
+ VSC9953_ENC_BITFIELD(target, 3, 16)
+
+#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT BIT(2)
+#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS BIT(21)
+#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS BIT(20)
+#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_CNT_DIS BIT(19)
+#define VSC9953_VCAP_CACHE_ACTION_DAT(target, ri) \
+ VSC9953_IO_REG(target, (0x82 + (ri)))
+
+#define VSC9953_VCAP_CACHE_CNT_DAT(target, ri) \
+ VSC9953_IO_REG(target, (0xc2 + (ri)))
+
+#define VSC9953_PORT_OFFSET 1
+#define VSC9953_IS1_CNT 256
+#define VSC9953_IS2_CNT 1024
+#define VSC9953_ES0_CNT 1024
+
+#define BITS_TO_DWORD(in) (1 + (((in) - 1) / 32))
+#define ENTRY_WORDS_ES0 BITS_TO_DWORD(29)
+#define ENTRY_WORDS_IS1 BITS_TO_DWORD(376)
+#define ENTRY_WORDS_IS2 BITS_TO_DWORD(376)
+#define ES0_ACT_WIDTH BITS_TO_DWORD(91)
+#define ES0_CNT_WIDTH BITS_TO_DWORD(1)
+#define IS1_ACT_WIDTH BITS_TO_DWORD(320)
+#define IS1_CNT_WIDTH BITS_TO_DWORD(4)
+#define IS2_ACT_WIDTH BITS_TO_DWORD(103 - 2 * VSC9953_PORT_OFFSET)
+#define IS2_CNT_WIDTH BITS_TO_DWORD(4 * 32)
+#define ES0_ACT_COUNT (VSC9953_ES0_CNT + VSC9953_MAX_PORTS)
+#define IS1_ACT_COUNT (VSC9953_IS1_CNT + 1)
+#define IS2_ACT_COUNT (VSC9953_IS2_CNT + VSC9953_MAX_PORTS + 2)
+
+/* TCAM entries */
+enum tcam_sel {
+ TCAM_SEL_ENTRY = BIT(0),
+ TCAM_SEL_ACTION = BIT(1),
+ TCAM_SEL_COUNTER = BIT(2),
+ TCAM_SEL_ALL = VSC9953_BITMASK(3),
+};
+
+enum tcam_cmd {
+ TCAM_CMD_WRITE = 0,
+ TCAM_CMD_READ = 1,
+ TCAM_CMD_MOVE_UP = 2,
+ TCAM_CMD_MOVE_DOWN = 3,
+ TCAM_CMD_INITIALIZE = 4,
+};
+
struct vsc9953_mdio_info {
struct vsc9953_mii_mng *regs;
char *name;
diff --git a/lib/efi/Makefile b/lib/efi/Makefile
index 18d081a..f1a3929 100644
--- a/lib/efi/Makefile
+++ b/lib/efi/Makefile
@@ -7,9 +7,11 @@
CFLAGS_REMOVE_efi_stub.o := -mregparm=3 \
$(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32)
-CFLAGS_efi_stub.o := -fpic -fshort-wchar -DEFI_STUB
+CFLAGS_efi_stub.o := -fpic -fshort-wchar -DEFI_STUB \
+ $(if $(CONFIG_EFI_STUB_64BIT),-m64)
CFLAGS_REMOVE_efi.o := -mregparm=3 \
$(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32)
-CFLAGS_efi.o := -fpic -fshort-wchar -DEFI_STUB
+CFLAGS_efi.o := -fpic -fshort-wchar -DEFI_STUB \
+ $(if $(CONFIG_EFI_STUB_64BIT),-m64)
extra-$(CONFIG_EFI_STUB) += efi_stub.o efi.o
diff --git a/lib/efi/efi_stub.c b/lib/efi/efi_stub.c
index 3138739..09023a2 100644
--- a/lib/efi/efi_stub.c
+++ b/lib/efi/efi_stub.c
@@ -281,7 +281,8 @@
ret = efi_init(priv, "Payload", image, sys_table);
if (ret) {
- printhex2(ret); puts(" efi_init() failed\n");
+ printhex2(ret);
+ puts(" efi_init() failed\n");
return ret;
}
global_priv = priv;
@@ -294,7 +295,8 @@
size = 0;
ret = boot->get_memory_map(&size, NULL, &key, &desc_size, &version);
if (ret != EFI_BUFFER_TOO_SMALL) {
- printhex2(BITS_PER_LONG);
+ printhex2(EFI_BITS_PER_LONG);
+ putc(' ');
printhex2(ret);
puts(" No memory map\n");
return ret;
@@ -303,7 +305,7 @@
desc = efi_malloc(priv, size, &ret);
if (!desc) {
printhex2(ret);
- puts(" No memory for memory descriptor: ");
+ puts(" No memory for memory descriptor\n");
return ret;
}
ret = setup_info_table(priv, size + 128);
diff --git a/net/arp.c b/net/arp.c
index 990b771..b8a7168 100644
--- a/net/arp.c
+++ b/net/arp.c
@@ -182,7 +182,8 @@
(net_read_ip(&arp->ar_spa).s_addr & net_netmask.s_addr))
udelay(5000);
#endif
- net_send_packet((uchar *)et, eth_hdr_size + ARP_HDR_SIZE);
+ memcpy(net_tx_packet, et, eth_hdr_size + ARP_HDR_SIZE);
+ net_send_packet(net_tx_packet, eth_hdr_size + ARP_HDR_SIZE);
return;
case ARPOP_REPLY: /* arp reply */
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index d20a1cf..e4b4922 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -395,7 +395,7 @@
* This is accomplished by attempting to probe each device and calling
* their write_hwaddr() operation.
*/
- uclass_first_device(UCLASS_ETH, &dev);
+ uclass_first_device_check(UCLASS_ETH, &dev);
if (!dev) {
printf("No ethernet found.\n");
bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
@@ -424,7 +424,7 @@
eth_write_hwaddr(dev);
- uclass_next_device(&dev);
+ uclass_next_device_check(&dev);
num_devices++;
} while (dev);
diff --git a/net/net.c b/net/net.c
index a4932f4..b4563a4 100644
--- a/net/net.c
+++ b/net/net.c
@@ -393,6 +393,7 @@
int net_loop(enum proto_t protocol)
{
int ret = -EINVAL;
+ enum net_loop_state prev_net_state = net_state;
net_restarted = 0;
net_dev_exists = 0;
@@ -430,6 +431,7 @@
case 1:
/* network not configured */
eth_halt();
+ net_set_state(prev_net_state);
return -ENODEV;
case 2:
@@ -655,6 +657,7 @@
net_set_udp_handler(NULL);
net_set_icmp_handler(NULL);
#endif
+ net_set_state(prev_net_state);
return ret;
}
diff --git a/net/nfs.c b/net/nfs.c
index 83ed0a7..9a16765 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -822,6 +822,8 @@
case STATE_READ_REQ:
rlen = nfs_read_reply(pkt, len);
+ if (rlen == -NFS_RPC_DROP)
+ break;
net_set_timeout_handler(nfs_timeout, nfs_timeout_handler);
if (rlen > 0) {
nfs_offset += rlen;
diff --git a/net/ping.c b/net/ping.c
index 5464f2f..3e5461a 100644
--- a/net/ping.c
+++ b/net/ping.c
@@ -107,7 +107,8 @@
icmph->type = ICMP_ECHO_REPLY;
icmph->checksum = 0;
icmph->checksum = compute_ip_checksum(icmph, len - IP_HDR_SIZE);
- net_send_packet((uchar *)et, eth_hdr_size + len);
+ memcpy(net_tx_packet, et, eth_hdr_size + len);
+ net_send_packet(net_tx_packet, eth_hdr_size + len);
return;
/* default:
return;*/
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 461f1c7..f8c3fff 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -405,6 +405,7 @@
$(obj)/dsdt.c: $(src)/dsdt.asl
$(call cmd,acpi_c_asl)
+ $(Q)sed -i -e "s,dsdt_aml_code,AmlCode," $@
# Bzip2
# ---------------------------------------------------------------------------
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index e99ba6b..1a54337 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -4581,7 +4581,6 @@
CONFIG_USART_BASE
CONFIG_USART_ID
CONFIG_USBBOOTCOMMAND
-CONFIG_USBDEBUG
CONFIG_USBD_CONFIGURATION_STR
CONFIG_USBD_CTRL_INTERFACE_STR
CONFIG_USBD_DATA_INTERFACE_STR