Merge Official Source

Closes: #332

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2021-03-26 18:37:54 +08:00
commit 0ee01d71cd
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
78 changed files with 3822 additions and 283 deletions

View File

@ -27,6 +27,10 @@ define Build/append-kernel
dd if=$(IMAGE_KERNEL) >> $@
endef
define Build/append-image
dd if=$(BIN_DIR)/$(DEVICE_IMG_PREFIX)-$(1) >> $@
endef
compat_version=$(if $(DEVICE_COMPAT_VERSION),$(DEVICE_COMPAT_VERSION),1.0)
json_quote=$(subst ','\'',$(subst ",\",$(1)))
#")')

View File

@ -419,7 +419,7 @@ DEFAULT_DEVICE_VARS := \
CMDLINE UBOOTENV_IN_UBI KERNEL_IN_UBI BLOCKSIZE PAGESIZE SUBPAGESIZE \
VID_HDR_OFFSET UBINIZE_OPTS UBINIZE_PARTS MKUBIFS_OPTS DEVICE_DTS \
DEVICE_DTS_CONFIG DEVICE_DTS_DIR DEVICE_DTS_OVERLAY DEVICE_FDT_NUM \
SOC BOARD_NAME UIMAGE_MAGIC UIMAGE_NAME \
DEVICE_IMG_PREFIX SOC BOARD_NAME UIMAGE_MAGIC UIMAGE_NAME \
SUPPORTED_DEVICES IMAGE_METADATA KERNEL_ENTRY KERNEL_LOADADDR \
UBOOT_PATH IMAGE_SIZE \
DEVICE_COMPAT_VERSION DEVICE_COMPAT_MESSAGE \
@ -478,6 +478,7 @@ define Device/Build/initramfs
$$(if $$(CONFIG_JSON_OVERVIEW_IMAGE_INFO), $(BUILD_DIR)/json_info_files/$$(KERNEL_INITRAMFS_IMAGE).json,))
$(KDIR)/$$(KERNEL_INITRAMFS_NAME):: image_prepare
$(1)-images: $(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE)
$(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE): $(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE)
cp $$^ $$@
@ -570,6 +571,7 @@ define Device/Build/image
$(BUILD_DIR)/json_info_files/$(call DEVICE_IMG_NAME,$(1),$(2)).json, \
$(BIN_DIR)/$(call DEVICE_IMG_NAME,$(1),$(2))$$(GZ_SUFFIX))
$(eval $(call Device/Export,$(KDIR)/tmp/$(call DEVICE_IMG_NAME,$(1),$(2)),$(1)))
$(3)-images: $(BIN_DIR)/$(call DEVICE_IMG_NAME,$(1),$(2))$$(GZ_SUFFIX)
ROOTFS/$(1)/$(3) := \
$(KDIR)/root.$(1)$$(strip \
@ -628,7 +630,7 @@ endef
define Device/Build/artifact
$$(_TARGET): $(BIN_DIR)/$(DEVICE_IMG_PREFIX)-$(1)
$(eval $(call Device/Export,$(KDIR)/tmp/$(DEVICE_IMG_PREFIX)-$(1)))
$(KDIR)/tmp/$(DEVICE_IMG_PREFIX)-$(1): $$(KDIR_KERNEL_IMAGE)
$(KDIR)/tmp/$(DEVICE_IMG_PREFIX)-$(1): $$(KDIR_KERNEL_IMAGE) $(2)-images
@rm -f $$@
$$(call concat_cmd,$(ARTIFACT/$(1)))
@ -651,7 +653,7 @@ define Device/Build
$$(call Device/Build/image,$$(fs),$$(image),$(1)))))
$$(eval $$(foreach artifact,$$(ARTIFACTS), \
$$(call Device/Build/artifact,$$(artifact))))
$$(call Device/Build/artifact,$$(artifact),$(1))))
endef

View File

@ -7,10 +7,10 @@ ifdef CONFIG_TESTING_KERNEL
endif
LINUX_VERSION-5.4 = .106
LINUX_VERSION-5.10 = .23
LINUX_VERSION-5.10 = .26
LINUX_KERNEL_HASH-5.4.106 = cc873b2c39c1823d4bc4f6cde527943c8cfd28ae94cb517804b0f9679359c8db
LINUX_KERNEL_HASH-5.10.23 = f6e21c03ec6ff85b26d77c59fdab81e64707792a57593643307df192749edb6a
LINUX_KERNEL_HASH-5.10.26 = fc532833f1ac167f363f1b9de85db39d2d635ab516f66dc381bdd70804601482
remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1))))
sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1)))))))

View File

@ -136,6 +136,10 @@ $(eval $(call SetupHostCommand,bzip2,Please install 'bzip2', \
$(eval $(call SetupHostCommand,wget,Please install GNU 'wget', \
wget --version | grep GNU))
$(eval $(call SetupHostCommand,install,Please install GNU 'install', \
install --version | grep GNU, \
ginstall --version | grep GNU))
$(eval $(call SetupHostCommand,perl,Please install Perl 5.x, \
perl --version | grep "perl.*v5"))

View File

@ -21,6 +21,7 @@ PKG_MIRROR_HASH:=0eda0e774a87e58e611d6436350e1cf2be3de50fddde334909a07a15b0c9862
PKG_MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>
PKG_BUILD_PARALLEL:=1
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk

View File

@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=elfutils
PKG_VERSION:=0.180
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=https://sourceware.org/$(PKG_NAME)/ftp/$(PKG_VERSION)
@ -21,7 +21,7 @@ PKG_CPE_ID:=cpe:/a:elfutils_project:elfutils
PKG_FIXUP:=autoreconf
PKG_INSTALL:=1
PKG_USE_MIPS16:=0
PKG_USE_MIPS16:=1
PKG_BUILD_DEPENDS:=!USE_GLIBC:argp-standalone
include $(INCLUDE_DIR)/package.mk

View File

@ -14,7 +14,7 @@ PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=https://github.com/jow-/ucode.git
PKG_SOURCE_DATE:=2021-03-19
PKG_SOURCE_VERSION:=4a5b9010ccc56fdf288fe758023af445feb93fad
PKG_MIRROR_HASH:=145a2ce69e14cae9b448de85b94c7a817ba3aea04b1611399186ad36fb88958e
PKG_MIRROR_HASH:=2d15fe2f51ebdeae532a2e8130689400cf2364876e737cfbb1bf9c045719acf1
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=ISC

View File

@ -75,12 +75,12 @@ IS_PACKAGE_BUILD := $(if $(filter package/%,$(BUILD_SUBDIR)),1)
OPTIMIZE_FOR_CPU=$(subst i386,i486,$(ARCH))
ifneq (,$(findstring $(ARCH) , aarch64 aarch64_be powerpc ))
FPIC:=-fPIC
FPIC:=-DPIC -fPIC
else
FPIC:=-fpic
FPIC:=-DPIC -fpic
endif
HOST_FPIC:=-fPIC
HOST_FPIC:=-DPIC -fPIC
ARCH_SUFFIX:=$(call qstrip,$(CONFIG_CPU_TYPE))
GCC_ARCH:=

View File

@ -38,10 +38,9 @@ if output:
"make",
"--no-print-directory",
"-C",
"target/linux/{}".format(output["target"].split("/")[0]),
"target/linux/",
"val.DEFAULT_PACKAGES",
"val.ARCH_PACKAGES",
"DUMP=1",
],
stdout=PIPE,
stderr=PIPE,
@ -50,7 +49,8 @@ if output:
universal_newlines=True,
).stdout.splitlines()
output["default_packages"] = default_packages.split()
output["default_packages"] = sorted(default_packages.split())
output_path.write_text(json.dumps(output, sort_keys=True, separators=(",", ":")))
else:
print("JSON info file script could not find any JSON files for target")

View File

@ -13,7 +13,7 @@ produce a noisy warning.
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -260,6 +260,7 @@ static void xhci_pci_quirks(struct devic
@@ -261,6 +261,7 @@ static void xhci_pci_quirks(struct devic
pdev->device == 0x0015) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci->quirks |= XHCI_ZERO_64B_REGS;
@ -43,7 +43,7 @@ produce a noisy warning.
hcd->msi_enabled = 1;
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1886,6 +1886,7 @@ struct xhci_hcd {
@@ -1887,6 +1887,7 @@ struct xhci_hcd {
struct xhci_hub usb2_rhub;
struct xhci_hub usb3_rhub;
/* support xHCI 1.0 spec USB2 hardware LPM */

View File

@ -141,7 +141,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
{
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -713,6 +713,7 @@ static inline void devm_acpi_dev_remove_
@@ -715,6 +715,7 @@ static inline void devm_acpi_dev_remove_
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
@ -149,7 +149,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
@@ -720,6 +721,13 @@ void gpiod_unexport(struct gpio_desc *de
@@ -722,6 +723,13 @@ void gpiod_unexport(struct gpio_desc *de
#else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */

View File

@ -0,0 +1,51 @@
From f1f811410af297c848e9ec17eaa280d190fdce10 Mon Sep 17 00:00:00 2001
From: Mauri Sandberg <sandberg@mailfence.com>
Date: Tue, 23 Feb 2021 18:09:31 +0200
Subject: [PATCH] mtd: cfi_cmdset_0002: AMD chip 0x2201 - write words
Buffer writes do not work with AMD chip 0x2201. The chip in question
is a AMD/Spansion/Cypress Semiconductor S29GL256N and datasheet [1]
talks about writing buffers being possible. While waiting for a neater
solution resort to writing word-sized chunks only.
Without the patch kernel logs will be flooded with entries like below:
jffs2_scan_eraseblock(): End of filesystem marker found at 0x0
jffs2_build_filesystem(): unlocking the mtd device...
done.
jffs2_build_filesystem(): erasing all blocks after the end marker...
MTD do_write_buffer_wait(): software timeout, address:0x01ec000a.
jffs2: Write clean marker to block at 0x01920000 failed: -5
MTD do_write_buffer_wait(): software timeout, address:0x01e2000a.
jffs2: Write clean marker to block at 0x01880000 failed: -5
MTD do_write_buffer_wait(): software timeout, address:0x01e0000a.
jffs2: Write clean marker to block at 0x01860000 failed: -5
MTD do_write_buffer_wait(): software timeout, address:0x01dc000a.
jffs2: Write clean marker to block at 0x01820000 failed: -5
MTD do_write_buffer_wait(): software timeout, address:0x01da000a.
jffs2: Write clean marker to block at 0x01800000 failed: -5
...
Tested on a Buffalo wzr-hp-g300nh running kernel 5.10.16.
[1] https://www.cypress.com/file/219941/download
or https://datasheetspdf.com/pdf-file/565708/SPANSION/S29GL256N/1
Signed-off-by: Mauri Sandberg <sandberg@mailfence.com>
---
drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -272,6 +272,10 @@ static void fixup_use_write_buffers(stru
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
+
+ if ((cfi->mfr == CFI_MFR_AMD) && (cfi->id == 0x2201))
+ return;
+
if (cfi->cfiq->BufWriteTimeoutTyp) {
pr_debug("Using buffer write method\n");
mtd->_write = cfi_amdstd_write_buffers;

View File

@ -4,7 +4,7 @@ Date: Mon, 28 Jan 2013 20:06:30 +0100
Subject: [PATCH 12/12] MIPS: BCM63XX: EHCI controller does not support
overcurrent
This patch sets the ignore_oc flag for the BCM63XX EHCI controller as it
This patch sets the spurious_oc flag for the BCM63XX EHCI controller as it
does not support proper overcurrent reporting.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
@ -18,7 +18,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
static struct usb_ehci_pdata bcm63xx_ehci_pdata = {
.big_endian_desc = 1,
.big_endian_mmio = 1,
+ .ignore_oc = 1,
+ .spurious_oc = 1,
.power_on = bcm63xx_ehci_power_on,
.power_off = bcm63xx_ehci_power_off,
.power_suspend = bcm63xx_ehci_power_off,

View File

@ -116,7 +116,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
}
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1886,7 +1886,8 @@ int gpiochip_add_pingroup_range(struct g
@@ -1897,7 +1897,8 @@ int gpiochip_add_pingroup_range(struct g
list_add_tail(&pin_range->node, &gdev->pin_ranges);
@ -126,7 +126,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
}
EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
@@ -1943,7 +1944,7 @@ int gpiochip_add_pin_range(struct gpio_c
@@ -1954,7 +1955,7 @@ int gpiochip_add_pin_range(struct gpio_c
list_add_tail(&pin_range->node, &gdev->pin_ranges);

View File

@ -4,7 +4,7 @@ Date: Mon, 28 Jan 2013 20:06:30 +0100
Subject: [PATCH 12/12] MIPS: BCM63XX: EHCI controller does not support
overcurrent
This patch sets the ignore_oc flag for the BCM63XX EHCI controller as it
This patch sets the spurious_oc flag for the BCM63XX EHCI controller as it
does not support proper overcurrent reporting.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
@ -18,7 +18,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
static struct usb_ehci_pdata bcm63xx_ehci_pdata = {
.big_endian_desc = 1,
.big_endian_mmio = 1,
+ .ignore_oc = 1,
+ .spurious_oc = 1,
.power_on = bcm63xx_ehci_power_on,
.power_off = bcm63xx_ehci_power_off,
.power_suspend = bcm63xx_ehci_power_off,

View File

@ -16,6 +16,17 @@ CONFIG_BCM63XX_POWER=y
CONFIG_BCM7038_L1_IRQ=y
CONFIG_BCM7038_WDT=y
CONFIG_BCM7120_L2_IRQ=y
CONFIG_BCMA=y
CONFIG_BCMA_BLOCKIO=y
# CONFIG_BCMA_DEBUG is not set
# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
# CONFIG_BCMA_DRIVER_MIPS is not set
CONFIG_BCMA_DRIVER_PCI=y
# CONFIG_BCMA_DRIVER_PCI_HOSTMODE is not set
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
# CONFIG_BCMA_HOST_SOC is not set
CONFIG_BLK_MQ_PCI=y
CONFIG_BLK_PM=y
CONFIG_BMIPS_GENERIC=y
CONFIG_BOARD_SCACHE=y
@ -139,6 +150,7 @@ CONFIG_MDIO_BUS=y
CONFIG_MDIO_BUS_MUX=y
CONFIG_MDIO_BUS_MUX_BCM6368=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEMFD_CREATE=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
@ -194,6 +206,13 @@ CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_NET=y
CONFIG_PADATA=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_BCM6318=y
CONFIG_PCIE_BCM6328=y
CONFIG_PCIE_PME=y
CONFIG_PCI_BCM6348=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DRIVERS_LEGACY=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
@ -244,6 +263,15 @@ CONFIG_SPI_BCM63XX_HSSPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SRCU=y
CONFIG_SSB=y
CONFIG_SSB_B43_PCI_BRIDGE=y
CONFIG_SSB_BLOCKIO=y
# CONFIG_SSB_DRIVER_MIPS is not set
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_PCIHOST=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_SPROM=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_SWPHY=y
CONFIG_SYNC_R4K=y

View File

@ -31,6 +31,28 @@
debounce-interval = <60>;
};
};
bcm43217-sprom {
compatible = "brcm,bcm43217-sprom";
pci-bus = <1>;
pci-dev = <0>;
mtd-mac-address = <&cfe 0x6a0>;
mtd-mac-address-increment = <1>;
brcm,sprom-fixups = <6 0x1c00>,
<65 0x1255>,
<97 0xfe55>,
<98 0x171d>,
<99 0xfa42>,
<113 0xfeb7>,
<114 0x18cd>,
<115 0xfa4f>,
<162 0x6444>,
<170 0x6444>,
<172 0x6444>;
};
};
&ehci {
@ -164,6 +186,10 @@
status = "okay";
};
&pcie {
status = "okay";
};
&pinctrl {
pinctrl_leds: leds {
function = "led";

View File

@ -304,7 +304,7 @@
compatible = "brcm,bcm6318-ehci", "generic-ehci";
reg = <0x10005000 0x100>;
big-endian;
ignore-oc;
spurious-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6318_IRQ_EHCI>;
@ -347,6 +347,41 @@
status = "disabled";
};
pcie: pcie@10010000 {
compatible = "brcm,bcm6318-pcie";
reg = <0x10010000 0x10000>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
bus-range = <0x00 0x01>;
ranges = <0x2000000 0 0x10200000 0x10200000 0 0x100000>;
linux,pci-probe-only = <1>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6318_IRQ_PCIE_RC>;
clocks = <&periph_clk BCM6318_CLK_PCIE>,
<&periph_clk BCM6318_CLK_PCIE25>,
<&ubus_clk BCM6318_UCLK_PCIE>;
clock-names = "pcie",
"pcie25",
"pcie-ubus";
resets = <&periph_rst BCM6318_RST_PCIE>,
<&periph_rst BCM6318_RST_PCIE_EXT>,
<&periph_rst BCM6318_RST_PCIE_CORE>,
<&periph_rst BCM6318_RST_PCIE_HARD>;
reset-names = "pcie",
"pcie-ext",
"pcie-core",
"pcie-hard";
power-domains = <&periph_pwr BCM6318_POWER_DOMAIN_PCIE>;
status = "disabled";
};
switch0: switch@10080000 {
#address-cells = <1>;
#size-cells = <0>;

View File

@ -371,6 +371,12 @@
status = "disabled";
};
serdes_cntl: syscon@10001804 {
compatible = "syscon";
reg = <0x10001804 0x4>;
native-endian;
};
periph_pwr: power-controller@1000184c {
compatible = "brcm,bcm63268-power-controller";
reg = <0x1000184c 0x4>;
@ -390,7 +396,7 @@
compatible = "brcm,bcm63268-ehci", "generic-ehci";
reg = <0x10002500 0x100>;
big-endian;
ignore-oc;
spurious-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_EHCI>;
@ -468,6 +474,39 @@
status = "disabled";
};
pcie: pcie@106e0000 {
compatible = "brcm,bcm6328-pcie";
reg = <0x106e0000 0x10000>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
bus-range = <0x00 0x01>;
ranges = <0x2000000 0 0x11000000 0x11000000 0 0xf00000>;
linux,pci-probe-only = <1>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_PCIE_RC>;
clocks = <&periph_clk BCM63268_CLK_PCIE>;
clock-names = "pcie";
resets = <&periph_rst BCM63268_RST_PCIE>,
<&periph_rst BCM63268_RST_PCIE_EXT>,
<&periph_rst BCM63268_RST_PCIE_CORE>,
<&periph_rst BCM63268_RST_PCIE_HARD>;
reset-names = "pcie",
"pcie-ext",
"pcie-core",
"pcie-hard";
power-domains = <&periph_pwr BCM63268_POWER_DOMAIN_PCIE>;
brcm,serdes = <&serdes_cntl>;
status = "disabled";
};
switch0: switch@10700000 {
#address-cells = <1>;
#size-cells = <0>;

View File

@ -24,6 +24,41 @@
debounce-interval = <60>;
};
};
bcm43225-sprom {
compatible = "brcm,bcm43225-sprom";
pci-bus = <1>;
pci-dev = <0>;
mtd-mac-address = <&cfe 0x6a0>;
mtd-mac-address-increment = <1>;
brcm,sprom-fixups = <2 0x05bb>,
<65 0x1204>,
<78 0x0303>,
<79 0x0202>,
<80 0xff02>,
<87 0x0315>,
<88 0x0315>,
<96 0x2048>,
<97 0xff11>,
<98 0x1567>,
<99 0xfb24>,
<100 0x3e3c>,
<101 0x4038>,
<102 0xfe7f>,
<103 0x1279>,
<112 0x2048>,
<113 0xff03>,
<114 0x154c>,
<115 0xfb27>,
<116 0x3e3c>,
<117 0x4038>,
<118 0xfe87>,
<119 0x1233>,
<203 0x2226>;
};
};
&ehci {
@ -111,6 +146,10 @@
status = "okay";
};
&pcie {
status = "okay";
};
&pinctrl {
pinctrl_leds: leds {
function = "led";

View File

@ -317,6 +317,12 @@
status = "disabled";
};
serdes_cntl: syscon@10001800 {
compatible = "syscon";
reg = <0x10001800 0x4>;
native-endian;
};
periph_pwr: power-controller@10001848 {
compatible = "brcm,bcm6328-power-controller";
reg = <0x10001848 0x4>;
@ -328,7 +334,7 @@
compatible = "brcm,bcm6328-ehci", "generic-ehci";
reg = <0x10002500 0x100>;
big-endian;
ignore-oc;
spurious-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6328_IRQ_EHCI>;
@ -462,5 +468,38 @@
reg = <1>;
};
};
pcie: pcie@10e40000 {
compatible = "brcm,bcm6328-pcie";
reg = <0x10e40000 0x10000>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
bus-range = <0x00 0x01>;
ranges = <0x2000000 0 0x10f00000 0x10f00000 0 0x100000>;
linux,pci-probe-only = <1>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6328_IRQ_PCIE_RC>;
clocks = <&periph_clk BCM6328_CLK_PCIE>;
clock-names = "pcie";
resets = <&periph_rst BCM6328_RST_PCIE>,
<&periph_rst BCM6328_RST_PCIE_EXT>,
<&periph_rst BCM6328_RST_PCIE_CORE>,
<&periph_rst BCM6328_RST_PCIE_HARD>;
reset-names = "pcie",
"pcie-ext",
"pcie-core",
"pcie-hard";
power-domains = <&periph_pwr BCM6328_POWER_DOMAIN_PCIE>;
brcm,serdes = <&serdes_cntl>;
status = "disabled";
};
};
};

View File

@ -119,6 +119,21 @@
gpios = <&pinctrl 28 GPIO_ACTIVE_LOW>;
};
};
ath9k-fixup {
compatible = "brcm,ath9k-fixup";
reg = <0x30000000 0x8000000>;
pci-dev = <1>;
mtd-mac-address = <&cfe 0x6a0>;
mtd-mac-address-increment = <1>;
ath,eeprom = <&cal_data 0x1e000>;
ath,endian-check;
ath,led-pin = <2>;
ath,led-active-high;
};
};
&ehci {
@ -129,6 +144,10 @@
status = "okay";
};
&pci {
status = "okay";
};
&pflash {
status = "okay";

View File

@ -280,11 +280,36 @@
status = "disabled";
};
pci: pci@fffe1000 {
compatible = "brcm,bcm6348-pci";
reg = <0xfffe1000 0x200>,
<0x08000000 0x10000>;
reg-names = "pci",
"pci-io";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
bus-range = <0x00 0x01>;
ranges = <0x2000000 0 0x30000000 0x30000000 0 0x8000000>;
linux,pci-probe-only = <1>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6358_IRQ_MPI>;
resets = <&periph_rst BCM6358_RST_MPI>;
reset-names = "pci";
brcm,remap;
status = "disabled";
};
ehci: usb@fffe1300 {
compatible = "brcm,bcm6358-ehci", "generic-ehci";
reg = <0xfffe1300 0x100>;
big-endian;
ignore-oc;
spurious-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6358_IRQ_EHCI>;

View File

@ -209,6 +209,10 @@
status = "okay";
};
&pcie {
status = "okay";
};
&pinctrl {
pinctrl_leds: leds {
function = "led";

View File

@ -406,6 +406,12 @@
status = "disabled";
};
serdes_cntl: syscon@10001804 {
compatible = "syscon";
reg = <0x10001804 0x4>;
native-endian;
};
periph_pwr: power-controller@10001848 {
compatible = "brcm,bcm6362-power-controller";
reg = <0x10001848 0x4>;
@ -425,7 +431,7 @@
compatible = "brcm,bcm6362-ehci", "generic-ehci";
reg = <0x10002500 0x100>;
big-endian;
ignore-oc;
spurious-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_EHCI>;
@ -559,5 +565,36 @@
reg = <1>;
};
};
pcie: pcie@10e40000 {
compatible = "brcm,bcm6328-pcie";
reg = <0x10e40000 0x10000>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
bus-range = <0x00 0x01>;
ranges = <0x2000000 0 0x10f00000 0x10f00000 0 0x100000>;
linux,pci-probe-only = <1>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_PCIE_RC>;
clocks = <&periph_clk BCM6362_CLK_PCIE>;
clock-names = "pcie";
resets = <&periph_rst BCM6362_RST_PCIE>,
<&periph_rst BCM6362_RST_PCIE_EXT>,
<&periph_rst BCM6362_RST_PCIE_CORE>;
reset-names = "pcie",
"pcie-ext",
"pcie-core";
power-domains = <&periph_pwr BCM6362_POWER_DOMAIN_PCIE>;
brcm,serdes = <&serdes_cntl>;
status = "disabled";
};
};
};

View File

@ -53,6 +53,23 @@
gpios = <&pinctrl 31 GPIO_ACTIVE_HIGH>;
};
};
bcm43222-sprom {
compatible = "brcm,bcm43222-sprom";
pci-bus = <0>;
pci-dev = <1>;
mtd-mac-address = <&cfe 0x6a0>;
mtd-mac-address-increment = <1>;
brcm,sprom-fixups = <97 0xfeb3>,
<98 0x1618>,
<99 0xfab0>,
<113 0xfed1>,
<114 0x1609>,
<115 0xfad9>;
};
};
&ehci {
@ -69,6 +86,10 @@
status = "okay";
};
&pci {
status = "okay";
};
&pflash {
status = "okay";
@ -98,7 +119,7 @@
&pinctrl {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pci &pinctrl_ephy0_led &pinctrl_ephy1_led
pinctrl-0 = <&pinctrl_ephy0_led &pinctrl_ephy1_led
&pinctrl_ephy2_led &pinctrl_ephy3_led>;
};

View File

@ -414,11 +414,39 @@
status = "disabled";
};
pci: pci@10001000 {
compatible = "brcm,bcm6348-pci";
reg = <0x10001000 0x200>,
<0x08000000 0x10000>;
reg-names = "pci",
"pci-io";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
bus-range = <0x00 0x01>;
ranges = <0x2000000 0 0x30000000 0x30000000 0 0x8000000>;
linux,pci-probe-only = <1>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6368_IRQ_MPI>;
resets = <&periph_rst BCM6368_RST_MPI>;
reset-names = "pci";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pci>;
brcm,remap;
status = "disabled";
};
ehci: usb@10001500 {
compatible = "brcm,bcm6368-ehci", "generic-ehci";
reg = <0x10001500 0x100>;
big-endian;
ignore-oc;
spurious-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6368_IRQ_EHCI>;

View File

@ -0,0 +1,240 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* ATH9K Fixup Driver
*
* Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
* Copyright (C) 2014 Jonas Gorski <jonas.gorski@gmail.com>
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
* Copyright (C) 2008 Florian Fainelli <f.fainelli@gmail.com>
*/
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/ath9k_platform.h>
#define ATH9K_MAX_FIXUPS 2
#define ATH9K_DEF_LED_PIN -1
#define ATH9K_DEF_PCI_DEV 255
struct ath9k_fixup {
struct device *dev;
struct resource *mem_res;
u32 pci_dev;
u8 mac[ETH_ALEN];
struct ath9k_platform_data pdata;
};
static int ath9k_num_fixups;
static struct ath9k_fixup *ath9k_fixups[ATH9K_MAX_FIXUPS];
static void ath9k_pci_fixup(struct pci_dev *dev)
{
void __iomem *mem;
struct ath9k_fixup *priv = NULL;
struct ath9k_platform_data *pdata = NULL;
struct pci_dev *bridge = pci_upstream_bridge(dev);
u16 *cal_data = NULL;
u16 cmd;
u32 bar0;
u32 val;
unsigned i;
for (i = 0; i < ath9k_num_fixups; i++) {
if (ath9k_fixups[i]->pci_dev != PCI_SLOT(dev->devfn))
continue;
priv = ath9k_fixups[i];
cal_data = priv->pdata.eeprom_data;
pdata = &priv->pdata;
break;
}
if (cal_data == NULL)
return;
if (*cal_data != 0xa55a) {
pr_err("pci %s: invalid calibration data\n", pci_name(dev));
return;
}
pr_info("pci %s: fixup device configuration\n", pci_name(dev));
val = priv->mem_res->start;
mem = ioremap(priv->mem_res->start, resource_size(priv->mem_res));
if (!mem) {
pr_err("pci %s: ioremap error\n", pci_name(dev));
return;
}
if (bridge)
pci_enable_device(bridge);
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, val);
pci_read_config_word(dev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
pci_write_config_word(dev, PCI_COMMAND, cmd);
/* set offset to first reg address */
cal_data += 3;
while(*cal_data != 0xffff) {
u32 reg;
reg = *cal_data++;
val = *cal_data++;
val |= (*cal_data++) << 16;
writel(val, mem + reg);
udelay(100);
}
pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
dev->vendor = val & 0xffff;
dev->device = (val >> 16) & 0xffff;
pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
dev->revision = val & 0xff;
dev->class = val >> 8; /* upper 3 bytes */
pci_read_config_word(dev, PCI_COMMAND, &cmd);
cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
pci_write_config_word(dev, PCI_COMMAND, cmd);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
if (bridge)
pci_disable_device(bridge);
iounmap(mem);
dev->dev.platform_data = pdata;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
static int ath9k_mtd_eeprom(struct ath9k_fixup *priv)
{
struct device *dev = priv->dev;
struct device_node *node = dev->of_node;
struct device_node *mtd_np = NULL;
struct mtd_info *the_mtd;
phandle phandle;
size_t eeprom_readlen;
const char *part;
const __be32 *list;
int ret, i;
list = of_get_property(node, "ath,eeprom", &i);
if (!list || (i != (2 * sizeof(*list))))
return -ENODEV;
phandle = be32_to_cpup(list++);
if (phandle)
mtd_np = of_find_node_by_phandle(phandle);
if (!mtd_np)
return -ENODEV;
part = of_get_property(mtd_np, "label", NULL);
if (!part)
part = mtd_np->name;
the_mtd = get_mtd_device_nm(part);
if (IS_ERR(the_mtd))
return -ENODEV;
ret = mtd_read(the_mtd, be32_to_cpup(list),
ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16),
&eeprom_readlen, (void *) priv->pdata.eeprom_data);
put_mtd_device(the_mtd);
if (ret)
return ret;
return 0;
}
static int ath9k_fixup_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct ath9k_fixup *priv;
struct resource *res;
const void *mac;
int ret;
if (ath9k_num_fixups >= ATH9K_MAX_FIXUPS)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = dev;
priv->mem_res = res;
ret = of_property_read_u32(node, "pci-dev", &priv->pci_dev);
if (ret)
priv->pci_dev = ATH9K_DEF_PCI_DEV;
ret = ath9k_mtd_eeprom(priv);
if (ret)
return ret;
priv->pdata.endian_check = of_property_read_bool(node,
"ath,endian-check");
ret = of_property_read_s32(node, "ath,led-pin", &priv->pdata.led_pin);
if (ret)
priv->pdata.led_pin = ATH9K_DEF_LED_PIN;
priv->pdata.led_active_high = of_property_read_bool(node,
"ath,led-active-high");
mac = of_get_mac_address(node);
if (!IS_ERR_OR_NULL(mac)) {
memcpy(priv->mac, mac, ETH_ALEN);
dev_info(dev, "mtd mac %pM\n", priv->mac);
} else {
random_ether_addr(priv->mac);
dev_info(dev, "random mac %pM\n", priv->mac);
}
priv->pdata.macaddr = priv->mac;
ath9k_fixups[ath9k_num_fixups] = priv;
ath9k_num_fixups++;
return 0;
}
static const struct of_device_id ath9k_fixup_of_match[] = {
{ .compatible = "brcm,ath9k-fixup" },
{ /* sentinel */ }
};
static struct platform_driver ath9k_fixup_driver = {
.probe = ath9k_fixup_probe,
.driver = {
.name = "ath9k-fixup",
.of_match_table = ath9k_fixup_of_match,
},
};
int __init ath9k_fixup_init(void)
{
int ret = platform_driver_register(&ath9k_fixup_driver);
if (ret)
pr_err("ath9k_fixup: Error registering platform driver!\n");
return ret;
}
late_initcall(ath9k_fixup_init);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
*/
#include <linux/pci.h>
int bmips_pci_irq = -1;
int pcibios_plat_dev_init(struct pci_dev *pci_dev)
{
return PCIBIOS_SUCCESSFUL;
}
int pcibios_map_irq(const struct pci_dev *pci_dev, u8 slot, u8 pin)
{
return bmips_pci_irq;
}

View File

@ -0,0 +1,825 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* BCM6348 PCI Controller Driver
*
* Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
* Copyright (C) 2015 Jonas Gorski <jonas.gorski@gmail.com>
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
*/
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/reset.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
#include "../pci.h"
#define CARDBUS_DUMMY_ID 0x6348
#define CARDBUS_PCI_IDSEL 0x8
#define FAKE_CB_BRIDGE_SLOT 0x1e
#define BCMPCI_REG_TIMERS 0x40
#define REG_TIMER_TRDY_SHIFT 0
#define REG_TIMER_TRDY_MASK (0xff << REG_TIMER_TRDY_SHIFT)
#define REG_TIMER_RETRY_SHIFT 8
#define REG_TIMER_RETRY_MASK (0xff << REG_TIMER_RETRY_SHIFT)
#define MPI_SP0_RANGE_REG 0x100
#define MPI_SP0_REMAP_REG 0x104
#define MPI_SP0_REMAP_ENABLE_MASK (1 << 0)
#define MPI_SP1_RANGE_REG 0x10C
#define MPI_SP1_REMAP_REG 0x110
#define MPI_SP1_REMAP_ENABLE_MASK (1 << 0)
#define MPI_L2PCFG_REG 0x11c
#define MPI_L2PCFG_CFG_TYPE_SHIFT 0
#define MPI_L2PCFG_CFG_TYPE_MASK (0x3 << MPI_L2PCFG_CFG_TYPE_SHIFT)
#define MPI_L2PCFG_REG_SHIFT 2
#define MPI_L2PCFG_REG_MASK (0x3f << MPI_L2PCFG_REG_SHIFT)
#define MPI_L2PCFG_FUNC_SHIFT 8
#define MPI_L2PCFG_FUNC_MASK (0x7 << MPI_L2PCFG_FUNC_SHIFT)
#define MPI_L2PCFG_DEVNUM_SHIFT 11
#define MPI_L2PCFG_DEVNUM_MASK (0x1f << MPI_L2PCFG_DEVNUM_SHIFT)
#define MPI_L2PCFG_CFG_USEREG_MASK (1 << 30)
#define MPI_L2PCFG_CFG_SEL_MASK (1 << 31)
#define MPI_L2PMEMRANGE1_REG 0x120
#define MPI_L2PMEMBASE1_REG 0x124
#define MPI_L2PMEMREMAP1_REG 0x128
#define MPI_L2PMEMRANGE2_REG 0x12C
#define MPI_L2PMEMBASE2_REG 0x130
#define MPI_L2PMEMREMAP2_REG 0x134
#define MPI_L2PIORANGE_REG 0x138
#define MPI_L2PIOBASE_REG 0x13C
#define MPI_L2PIOREMAP_REG 0x140
#define MPI_L2P_BASE_MASK (0xffff8000)
#define MPI_L2PREMAP_ENABLED_MASK (1 << 0)
#define MPI_L2PREMAP_IS_CARDBUS_MASK (1 << 2)
#define MPI_PCIMODESEL_REG 0x144
#define MPI_PCIMODESEL_BAR1_NOSWAP_MASK (1 << 0)
#define MPI_PCIMODESEL_BAR2_NOSWAP_MASK (1 << 1)
#define MPI_PCIMODESEL_EXT_ARB_MASK (1 << 2)
#define MPI_PCIMODESEL_PREFETCH_SHIFT 4
#define MPI_PCIMODESEL_PREFETCH_MASK (0xf << MPI_PCIMODESEL_PREFETCH_SHIFT)
#define MPI_LOCBUSCTL_REG 0x14c
#define MPI_LOCBUSCTL_EN_PCI_GPIO_MASK (1 << 0)
#define MPI_LOCBUSCTL_U2P_NOSWAP_MASK (1 << 1)
#define MPI_LOCINT_REG 0x150
#define MPI_LOCINT_MASK(x) (1 << (x + 16))
#define MPI_LOCINT_STAT(x) (1 << (x))
#define MPI_LOCINT_DIR_FAILED 6
#define MPI_LOCINT_EXT_PCI_INT 7
#define MPI_LOCINT_SERR 8
#define MPI_LOCINT_CSERR 9
#define MPI_PCICFGCTL_REG 0x178
#define MPI_PCICFGCTL_CFGADDR_SHIFT 2
#define MPI_PCICFGCTL_CFGADDR_MASK (0x1f << MPI_PCICFGCTL_CFGADDR_SHIFT)
#define MPI_PCICFGCTL_WRITEEN_MASK (1 << 7)
#define MPI_PCICFGDATA_REG 0x17c
#define PCMCIA_OFFSET 0x54
#define PCMCIA_C1_REG 0x0
#define PCMCIA_C1_CD1_MASK (1 << 0)
#define PCMCIA_C1_CD2_MASK (1 << 1)
#define PCMCIA_C1_VS1_MASK (1 << 2)
#define PCMCIA_C1_VS2_MASK (1 << 3)
#define PCMCIA_C1_VS1OE_MASK (1 << 6)
#define PCMCIA_C1_VS2OE_MASK (1 << 7)
#define PCMCIA_C1_CBIDSEL_SHIFT (8)
#define PCMCIA_C1_CBIDSEL_MASK (0x1f << PCMCIA_C1_CBIDSEL_SHIFT)
#define PCMCIA_C1_EN_PCMCIA_GPIO_MASK (1 << 13)
#define PCMCIA_C1_EN_PCMCIA_MASK (1 << 14)
#define PCMCIA_C1_EN_CARDBUS_MASK (1 << 15)
#define PCMCIA_C1_RESET_MASK (1 << 18)
#ifdef CONFIG_CARDBUS
struct bcm6348_cb {
u16 pci_command;
u8 cb_latency;
u8 subordinate_busn;
u8 cardbus_busn;
u8 pci_busn;
int bus_assigned;
u16 bridge_control;
u32 mem_base0;
u32 mem_limit0;
u32 mem_base1;
u32 mem_limit1;
u32 io_base0;
u32 io_limit0;
u32 io_base1;
u32 io_limit1;
};
#endif /* CONFIG_CARDBUS */
struct bcm6348_pci {
void __iomem *pci;
void __iomem *pcmcia;
void __iomem *io;
int irq;
struct reset_control *reset;
bool remap;
#ifdef CONFIG_CARDBUS
struct bcm6348_cb cb;
int cb_bus;
#endif /* CONFIG_CARDBUS */
};
static struct bcm6348_pci bcm6348_pci;
extern int bmips_pci_irq;
static u32 bcm6348_int_cfg_readl(u32 reg)
{
struct bcm6348_pci *priv = &bcm6348_pci;
u32 tmp;
tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK;
tmp |= MPI_PCICFGCTL_WRITEEN_MASK;
__raw_writel(tmp, priv->pci + MPI_PCICFGCTL_REG);
iob();
return __raw_readl(priv->pci + MPI_PCICFGDATA_REG);
}
static void bcm6348_int_cfg_writel(u32 val, u32 reg)
{
struct bcm6348_pci *priv = &bcm6348_pci;
u32 tmp;
tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK;
tmp |= MPI_PCICFGCTL_WRITEEN_MASK;
__raw_writel(tmp, priv->pci + MPI_PCICFGCTL_REG);
__raw_writel(val, priv->pci + MPI_PCICFGDATA_REG);
}
/*
* swizzle 32bits data to return only the needed part
*/
static int postprocess_read(u32 data, int where, unsigned int size)
{
u32 ret = 0;
switch (size) {
case 1:
ret = (data >> ((where & 3) << 3)) & 0xff;
break;
case 2:
ret = (data >> ((where & 3) << 3)) & 0xffff;
break;
case 4:
ret = data;
break;
}
return ret;
}
static int preprocess_write(u32 orig_data, u32 val, int where,
unsigned int size)
{
u32 ret = 0;
switch (size) {
case 1:
ret = (orig_data & ~(0xff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
break;
case 2:
ret = (orig_data & ~(0xffff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
break;
case 4:
ret = val;
break;
}
return ret;
}
static int bcm6348_setup_cfg_access(int type, unsigned int busn,
unsigned int devfn, int where)
{
struct bcm6348_pci *priv = &bcm6348_pci;
unsigned int slot, func, reg;
u32 val;
slot = PCI_SLOT(devfn);
func = PCI_FUNC(devfn);
reg = where >> 2;
/* sanity check */
if (slot > (MPI_L2PCFG_DEVNUM_MASK >> MPI_L2PCFG_DEVNUM_SHIFT))
return 1;
if (func > (MPI_L2PCFG_FUNC_MASK >> MPI_L2PCFG_FUNC_SHIFT))
return 1;
if (reg > (MPI_L2PCFG_REG_MASK >> MPI_L2PCFG_REG_SHIFT))
return 1;
/* ok, setup config access */
val = (reg << MPI_L2PCFG_REG_SHIFT);
val |= (func << MPI_L2PCFG_FUNC_SHIFT);
val |= (slot << MPI_L2PCFG_DEVNUM_SHIFT);
val |= MPI_L2PCFG_CFG_USEREG_MASK;
val |= MPI_L2PCFG_CFG_SEL_MASK;
/* type 0 cycle for local bus, type 1 cycle for anything else */
if (type != 0) {
/* FIXME: how to specify bus ??? */
val |= (1 << MPI_L2PCFG_CFG_TYPE_SHIFT);
}
__raw_writel(val, priv->pci + MPI_L2PCFG_REG);
return 0;
}
static int bcm6348_do_cfg_read(int type, unsigned int busn,
unsigned int devfn, int where, int size,
u32 *val)
{
struct bcm6348_pci *priv = &bcm6348_pci;
u32 data;
/* two phase cycle, first we write address, then read data at
* another location, caller already has a spinlock so no need
* to add one here */
if (bcm6348_setup_cfg_access(type, busn, devfn, where))
return PCIBIOS_DEVICE_NOT_FOUND;
iob();
data = le32_to_cpu(__raw_readl(priv->io));
/* restore IO space normal behaviour */
__raw_writel(0, priv->pci + MPI_L2PCFG_REG);
*val = postprocess_read(data, where, size);
return PCIBIOS_SUCCESSFUL;
}
static int bcm6348_do_cfg_write(int type, unsigned int busn,
unsigned int devfn, int where, int size,
u32 val)
{
struct bcm6348_pci *priv = &bcm6348_pci;
u32 data;
/* two phase cycle, first we write address, then write data to
* another location, caller already has a spinlock so no need
* to add one here */
if (bcm6348_setup_cfg_access(type, busn, devfn, where))
return PCIBIOS_DEVICE_NOT_FOUND;
iob();
data = le32_to_cpu(__raw_readl(priv->io));
data = preprocess_write(data, val, where, size);
__raw_writel(cpu_to_le32(data), priv->io);
wmb();
/* no way to know the access is done, we have to wait */
udelay(500);
/* restore IO space normal behaviour */
__raw_writel(0, priv->pci + MPI_L2PCFG_REG);
return PCIBIOS_SUCCESSFUL;
}
static int bcm6348_pci_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
int type;
type = bus->parent ? 1 : 0;
if (type == 0 && PCI_SLOT(devfn) == CARDBUS_PCI_IDSEL)
return PCIBIOS_DEVICE_NOT_FOUND;
return bcm6348_do_cfg_read(type, bus->number, devfn,
where, size, val);
}
static int bcm6348_pci_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
int type;
type = bus->parent ? 1 : 0;
if (type == 0 && PCI_SLOT(devfn) == CARDBUS_PCI_IDSEL)
return PCIBIOS_DEVICE_NOT_FOUND;
return bcm6348_do_cfg_write(type, bus->number, devfn,
where, size, val);
}
static struct pci_ops bcm6348_pci_ops = {
.read = bcm6348_pci_read,
.write = bcm6348_pci_write,
};
static struct resource bcm6348_pci_io_resource = {
.name = "BCM6348 PCI IO space",
.flags = IORESOURCE_IO,
};
static struct resource bcm6348_pci_mem_resource;
static struct resource bcm6348_pci_busn_resource;
static struct pci_controller bcm6348_pci_controller = {
.pci_ops = &bcm6348_pci_ops,
.io_resource = &bcm6348_pci_io_resource,
.mem_resource = &bcm6348_pci_mem_resource,
.busn_resource = &bcm6348_pci_busn_resource,
};
#ifdef CONFIG_CARDBUS
static int bcm6348_cb_bridge_read(int where, int size, u32 *val)
{
struct bcm6348_cb *cb = &bcm6348_pci.cb;
unsigned int reg;
u32 data;
data = 0;
reg = where >> 2;
switch (reg) {
case (PCI_VENDOR_ID >> 2):
case (PCI_CB_SUBSYSTEM_VENDOR_ID >> 2):
/* create dummy vendor/device id from our cpu id */
data = (CARDBUS_DUMMY_ID << 16) | PCI_VENDOR_ID_BROADCOM;
break;
case (PCI_COMMAND >> 2):
data = (PCI_STATUS_DEVSEL_SLOW << 16);
data |= cb->pci_command;
break;
case (PCI_CLASS_REVISION >> 2):
data = (PCI_CLASS_BRIDGE_CARDBUS << 16);
break;
case (PCI_CACHE_LINE_SIZE >> 2):
data = (PCI_HEADER_TYPE_CARDBUS << 16);
break;
case (PCI_INTERRUPT_LINE >> 2):
/* bridge control */
data = (cb->bridge_control << 16);
/* pin:intA line:0xff */
data |= (0x1 << 8) | 0xff;
break;
case (PCI_CB_PRIMARY_BUS >> 2):
data = (cb->cb_latency << 24);
data |= (cb->subordinate_busn << 16);
data |= (cb->cardbus_busn << 8);
data |= cb->pci_busn;
break;
case (PCI_CB_MEMORY_BASE_0 >> 2):
data = cb->mem_base0;
break;
case (PCI_CB_MEMORY_LIMIT_0 >> 2):
data = cb->mem_limit0;
break;
case (PCI_CB_MEMORY_BASE_1 >> 2):
data = cb->mem_base1;
break;
case (PCI_CB_MEMORY_LIMIT_1 >> 2):
data = cb->mem_limit1;
break;
case (PCI_CB_IO_BASE_0 >> 2):
/* | 1 for 32bits io support */
data = cb->io_base0 | 0x1;
break;
case (PCI_CB_IO_LIMIT_0 >> 2):
data = cb->io_limit0;
break;
case (PCI_CB_IO_BASE_1 >> 2):
/* | 1 for 32bits io support */
data = cb->io_base1 | 0x1;
break;
case (PCI_CB_IO_LIMIT_1 >> 2):
data = cb->io_limit1;
break;
}
*val = postprocess_read(data, where, size);
return PCIBIOS_SUCCESSFUL;
}
/*
* emulate configuration write access on a cardbus bridge
*/
static int bcm6348_cb_bridge_write(int where, int size, u32 val)
{
struct bcm6348_cb *cb = &bcm6348_pci.cb;
unsigned int reg;
u32 data, tmp;
int ret;
ret = bcm6348_cb_bridge_read((where & ~0x3), 4, &data);
if (ret != PCIBIOS_SUCCESSFUL)
return ret;
data = preprocess_write(data, val, where, size);
reg = where >> 2;
switch (reg) {
case (PCI_COMMAND >> 2):
cb->pci_command = (data & 0xffff);
break;
case (PCI_CB_PRIMARY_BUS >> 2):
cb->cb_latency = (data >> 24) & 0xff;
cb->subordinate_busn = (data >> 16) & 0xff;
cb->cardbus_busn = (data >> 8) & 0xff;
cb->pci_busn = data & 0xff;
if (cb->cardbus_busn)
cb->bus_assigned = 1;
break;
case (PCI_INTERRUPT_LINE >> 2):
tmp = (data >> 16) & 0xffff;
/* Disable memory prefetch support */
tmp &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
tmp &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
cb->bridge_control = tmp;
break;
case (PCI_CB_MEMORY_BASE_0 >> 2):
cb->mem_base0 = data;
break;
case (PCI_CB_MEMORY_LIMIT_0 >> 2):
cb->mem_limit0 = data;
break;
case (PCI_CB_MEMORY_BASE_1 >> 2):
cb->mem_base1 = data;
break;
case (PCI_CB_MEMORY_LIMIT_1 >> 2):
cb->mem_limit1 = data;
break;
case (PCI_CB_IO_BASE_0 >> 2):
cb->io_base0 = data;
break;
case (PCI_CB_IO_LIMIT_0 >> 2):
cb->io_limit0 = data;
break;
case (PCI_CB_IO_BASE_1 >> 2):
cb->io_base1 = data;
break;
case (PCI_CB_IO_LIMIT_1 >> 2):
cb->io_limit1 = data;
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int bcm6348_cb_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
struct bcm6348_pci *priv = &bcm6348_pci;
struct bcm6348_cb *cb = &priv->cb;
/* Snoop access to slot 0x1e on root bus, we fake a cardbus
* bridge at this location */
if (!bus->parent && PCI_SLOT(devfn) == FAKE_CB_BRIDGE_SLOT) {
priv->cb_bus = bus->number;
return bcm6348_cb_bridge_read(where, size, val);
}
/* A configuration cycle for the device behind the cardbus
* bridge is actually done as a type 0 cycle on the primary
* bus. This means that only one device can be on the cardbus
* bus */
if (cb->bus_assigned &&
bus->number == cb->cardbus_busn &&
PCI_SLOT(devfn) == 0)
return bcm6348_do_cfg_read(0, 0,
PCI_DEVFN(CARDBUS_PCI_IDSEL, 0),
where, size, val);
return PCIBIOS_DEVICE_NOT_FOUND;
}
static int bcm6348_cb_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
struct bcm6348_pci *priv = &bcm6348_pci;
struct bcm6348_cb *cb = &priv->cb;
if (!bus->parent && PCI_SLOT(devfn) == FAKE_CB_BRIDGE_SLOT) {
priv->cb_bus = bus->number;
return bcm6348_cb_bridge_write(where, size, val);
}
if (cb->bus_assigned &&
bus->number == cb->cardbus_busn &&
PCI_SLOT(devfn) == 0)
return bcm6348_do_cfg_write(0, 0,
PCI_DEVFN(CARDBUS_PCI_IDSEL, 0),
where, size, val);
return PCIBIOS_DEVICE_NOT_FOUND;
}
static struct pci_ops bcm6348_cb_ops = {
.read = bcm6348_cb_read,
.write = bcm6348_cb_write,
};
/*
* only one IO window, so it cannot be shared by PCI and cardbus, use
* fixup to choose and detect unhandled configuration
*/
static void bcm6348_pci_fixup(struct pci_dev *dev)
{
struct bcm6348_pci *priv = &bcm6348_pci;
struct bcm6348_cb *cb = &priv->cb;
static int io_window = -1;
int i, found, new_io_window;
u32 val;
/* look for any io resource */
found = 0;
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
found = 1;
break;
}
}
if (!found)
return;
/* skip our fake bus with only cardbus bridge on it */
if (dev->bus->number == priv->cb_bus)
return;
/* find on which bus the device is */
if (cb->bus_assigned &&
dev->bus->number == cb->cardbus_busn &&
PCI_SLOT(dev->devfn) == 0)
new_io_window = 1;
else
new_io_window = 0;
if (new_io_window == io_window)
return;
if (io_window != -1) {
pr_err("bcm63xx: both PCI and cardbus devices "
"need IO, which hardware cannot do\n");
return;
}
pr_info("bcm63xx: PCI IO window assigned to %s\n",
(new_io_window == 0) ? "PCI" : "cardbus");
val = __raw_readl(priv->pci + MPI_L2PIOREMAP_REG);
if (io_window)
val |= MPI_L2PREMAP_IS_CARDBUS_MASK;
else
val &= ~MPI_L2PREMAP_IS_CARDBUS_MASK;
__raw_writel(val, priv->pci + MPI_L2PIOREMAP_REG);
io_window = new_io_window;
}
DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm6348_pci_fixup);
static struct resource bcm6348_cb_io_resource = {
.name = "bcm6348 CB IO space",
.flags = IORESOURCE_IO,
};
static struct resource bcm6348_cb_mem_resource;
static struct pci_controller bcm6348_cb_controller = {
.pci_ops = &bcm6348_cb_ops,
.io_resource = &bcm6348_cb_io_resource,
.mem_resource = &bcm6348_cb_mem_resource,
};
#endif /* CONFIG_CARDBUS */
static void bcm6348_pci_setup(struct bcm6348_pci *priv)
{
u32 val;
/* Setup local bus to PCI access (PCI memory) */
val = bcm6348_pci_mem_resource.start & MPI_L2P_BASE_MASK;
__raw_writel(val, priv->pci + MPI_L2PMEMBASE1_REG);
__raw_writel(~(resource_size(&bcm6348_pci_mem_resource) - 1),
priv->pci + MPI_L2PMEMRANGE1_REG);
__raw_writel(val | MPI_L2PREMAP_ENABLED_MASK,
priv->pci + MPI_L2PMEMREMAP1_REG);
/* Set Cardbus IDSEL (type 0 cfg access on primary bus for
* this IDSEL will be done on Cardbus instead) */
val = __raw_readl(priv->pcmcia + PCMCIA_C1_REG);
val &= ~PCMCIA_C1_CBIDSEL_MASK;
val |= (CARDBUS_PCI_IDSEL << PCMCIA_C1_CBIDSEL_SHIFT);
__raw_writel(val, priv->pcmcia + PCMCIA_C1_REG);
#ifdef CONFIG_CARDBUS
/* setup local bus to PCI access (Cardbus memory) */
val = bcm6348_cb_mem_resource.start & MPI_L2P_BASE_MASK;
__raw_writel(val, priv->pci + MPI_L2PMEMBASE2_REG);
__raw_writel(~(resource_size(&bcm6348_cb_mem_resource) - 1),
priv->pci + MPI_L2PMEMRANGE2_REG);
val |= MPI_L2PREMAP_ENABLED_MASK | MPI_L2PREMAP_IS_CARDBUS_MASK;
__raw_writel(val, priv->pci + MPI_L2PMEMREMAP2_REG);
#else
/* disable second access windows */
__raw_writel(0, priv->pci + MPI_L2PMEMREMAP2_REG);
#endif
/* setup local bus to PCI access (IO memory), we have only 1
* IO window for both PCI and cardbus, but it cannot handle
* both at the same time, assume standard PCI for now, if
* cardbus card has IO zone, PCI fixup will change window to
* cardbus */
val = bcm6348_pci_io_resource.start & MPI_L2P_BASE_MASK;
__raw_writel(val, priv->pci + MPI_L2PIOBASE_REG);
__raw_writel(~(resource_size(&bcm6348_pci_io_resource) - 1),
priv->pci + MPI_L2PIORANGE_REG);
__raw_writel(val | MPI_L2PREMAP_ENABLED_MASK,
priv->pci + MPI_L2PIOREMAP_REG);
/* Enable PCI related GPIO pins */
__raw_writel(MPI_LOCBUSCTL_EN_PCI_GPIO_MASK,
priv->pci + MPI_LOCBUSCTL_REG);
/* Setup PCI to local bus access, used by PCI device to target
* local RAM while bus mastering */
bcm6348_int_cfg_writel(0, PCI_BASE_ADDRESS_3);
if (priv->remap)
val = MPI_SP0_REMAP_ENABLE_MASK;
else
val = 0;
__raw_writel(val, priv->pci + MPI_SP0_REMAP_REG);
bcm6348_int_cfg_writel(0, PCI_BASE_ADDRESS_4);
__raw_writel(0, priv->pci + MPI_SP1_REMAP_REG);
/* Setup sp0 range to local RAM size */
__raw_writel(~(memblock_phys_mem_size() - 1),
priv->pci + MPI_SP0_RANGE_REG);
__raw_writel(0, priv->pci + MPI_SP1_RANGE_REG);
/* Change host bridge retry counter to infinite number of
* retries, needed for some broadcom wifi cards with Silicon
* Backplane bus where access to srom seems very slow */
val = bcm6348_int_cfg_readl(BCMPCI_REG_TIMERS);
val &= ~REG_TIMER_RETRY_MASK;
bcm6348_int_cfg_writel(val, BCMPCI_REG_TIMERS);
/* EEnable memory decoder and bus mastering */
val = bcm6348_int_cfg_readl(PCI_COMMAND);
val |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
bcm6348_int_cfg_writel(val, PCI_COMMAND);
/* Enable read prefetching & disable byte swapping for bus
* mastering transfers */
val = __raw_readl(priv->pci + MPI_PCIMODESEL_REG);
val &= ~MPI_PCIMODESEL_BAR1_NOSWAP_MASK;
val &= ~MPI_PCIMODESEL_BAR2_NOSWAP_MASK;
val &= ~MPI_PCIMODESEL_PREFETCH_MASK;
val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT);
__raw_writel(val, priv->pci + MPI_PCIMODESEL_REG);
/* Enable pci interrupt */
val = __raw_readl(priv->pci + MPI_LOCINT_REG);
val |= MPI_LOCINT_MASK(MPI_LOCINT_EXT_PCI_INT);
__raw_writel(val, priv->pci + MPI_LOCINT_REG);
}
static int bcm6348_pci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct bcm6348_pci *priv = &bcm6348_pci;
struct resource *res;
of_pci_check_probe_only();
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pci");
priv->pci = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->pci))
return PTR_ERR(priv->pci);
priv->pcmcia = priv->pci + PCMCIA_OFFSET;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pci-io");
if (!res)
return -EINVAL;
#ifdef CONFIG_CARDBUS
bcm6348_pci_io_resource.start = res->start;
bcm6348_pci_io_resource.end = res->end - (resource_size(res) >> 1);
bcm6348_cb_io_resource.start = res->start + (resource_size(res) >> 1);
bcm6348_cb_io_resource.end = res->end;
#else
bcm6348_pci_io_resource.start = res->start;
bcm6348_pci_io_resource.end = res->end;
#endif
priv->irq = platform_get_irq(pdev, 0);
if (!priv->irq)
return -ENODEV;
bmips_pci_irq = priv->irq;
priv->reset = devm_reset_control_get(dev, "pci");
if (IS_ERR(priv->reset))
return PTR_ERR(priv->reset);
priv->remap = of_property_read_bool(np, "brcm,remap");
reset_control_reset(priv->reset);
pci_load_of_ranges(&bcm6348_pci_controller, np);
if (!bcm6348_pci_mem_resource.start)
return -EINVAL;
of_pci_parse_bus_range(np, &bcm6348_pci_busn_resource);
/*
* Configuration accesses are done through IO space, remap 4
* first bytes to access it from CPU.
*
* This means that no IO access from CPU should happen while
* we do a configuration cycle, but there's no way we can add
* a spinlock for each io access, so this is currently kind of
* broken on SMP.
*/
priv->io = ioremap(bcm6348_pci_io_resource.start, sizeof(u32));
if (!priv->io)
return -ENOMEM;
bcm6348_pci_setup(priv);
register_pci_controller(&bcm6348_pci_controller);
#ifdef CONFIG_CARDBUS
priv->cb_bus = -1;
register_pci_controller(&bcm6348_cb_controller);
#endif /* CONFIG_CARDBUS */
/* Mark memory space used for IO mapping as reserved */
request_mem_region(bcm6348_pci_io_resource.start,
resource_size(&bcm6348_pci_io_resource),
"BCM6348 PCI IO space");
return 0;
}
static const struct of_device_id bcm6348_pci_of_match[] = {
{ .compatible = "brcm,bcm6348-pci", },
{ /* sentinel */ }
};
static struct platform_driver bcm6348_pci_driver = {
.probe = bcm6348_pci_probe,
.driver = {
.name = "bcm6348-pci",
.of_match_table = bcm6348_pci_of_match,
},
};
int __init bcm6348_pci_init(void)
{
int ret = platform_driver_register(&bcm6348_pci_driver);
if (ret)
pr_err("pci-bcm6348: Error registering platform driver!\n");
return ret;
}
late_initcall_sync(bcm6348_pci_init);

View File

@ -0,0 +1,402 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* BCM6318 PCIe Controller Driver
*
* Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
* Copyright (C) 2015 Jonas Gorski <jonas.gorski@gmail.com>
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
*/
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/reset.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
#include "../pci.h"
#define PCIE_BUS_BRIDGE 0
#define PCIE_BUS_DEVICE 1
#define PCIE_SPECIFIC_REG 0x188
#define SPECIFIC_ENDIAN_MODE_BAR1_SHIFT 0
#define SPECIFIC_ENDIAN_MODE_BAR1_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
#define SPECIFIC_ENDIAN_MODE_BAR2_SHIFT 2
#define SPECIFIC_ENDIAN_MODE_BAR2_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
#define SPECIFIC_ENDIAN_MODE_BAR3_SHIFT 4
#define SPECIFIC_ENDIAN_MODE_BAR3_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
#define SPECIFIC_ENDIAN_MODE_WORD_ALIGN 0
#define SPECIFIC_ENDIAN_MODE_HALFWORD_ALIGN 1
#define SPECIFIC_ENDIAN_MODE_BYTE_ALIGN 2
#define PCIE_CONFIG2_REG 0x408
#define CONFIG2_BAR1_SIZE_EN 1
#define CONFIG2_BAR1_SIZE_MASK 0xf
#define PCIE_IDVAL3_REG 0x43c
#define IDVAL3_CLASS_CODE_MASK 0xffffff
#define IDVAL3_SUBCLASS_SHIFT 8
#define IDVAL3_CLASS_SHIFT 16
#define PCIE_DLSTATUS_REG 0x1048
#define DLSTATUS_PHYLINKUP (1 << 13)
#define PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG 0x400c
#define C2P_MEM_WIN_ENDIAN_MODE_MASK 0x3
#define C2P_MEM_WIN_ENDIAN_NO_SWAP 0
#define C2P_MEM_WIN_ENDIAN_HALF_WORD_SWAP 1
#define C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP 2
#define C2P_MEM_WIN_BASE_ADDR_SHIFT 20
#define C2P_MEM_WIN_BASE_ADDR_MASK (0xfff << C2P_MEM_WIN_BASE_ADDR_SHIFT)
#define PCIE_RC_BAR1_CONFIG_LO_REG 0x402c
#define RC_BAR_CFG_LO_SIZE_256MB 0xd
#define RC_BAR_CFG_LO_MATCH_ADDR_SHIFT 20
#define RC_BAR_CFG_LO_MATCH_ADDR_MASK (0xfff << RC_BAR_CFG_LO_MATCH_ADDR_SHIFT)
#define PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG 0x4070
#define C2P_BASELIMIT_LIMIT_SHIFT 20
#define C2P_BASELIMIT_LIMIT_MASK (0xfff << C2P_BASELIMIT_LIMIT_SHIFT)
#define C2P_BASELIMIT_BASE_SHIFT 4
#define C2P_BASELIMIT_BASE_MASK (0xfff << C2P_BASELIMIT_BASE_SHIFT)
#define PCIE_UBUS_BAR1_CFG_REMAP_REG 0x4088
#define BAR1_CFG_REMAP_OFFSET_SHIFT 20
#define BAR1_CFG_REMAP_OFFSET_MASK (0xfff << BAR1_CFG_REMAP_OFFSET_SHIFT)
#define BAR1_CFG_REMAP_ACCESS_EN 1
#define PCIE_HARD_DEBUG_REG 0x4204
#define HARD_DEBUG_SERDES_IDDQ (1 << 23)
#define PCIE_CPU_INT1_MASK_CLEAR_REG 0x830c
#define CPU_INT_PCIE_ERR_ATTN_CPU (1 << 0)
#define CPU_INT_PCIE_INTA (1 << 1)
#define CPU_INT_PCIE_INTB (1 << 2)
#define CPU_INT_PCIE_INTC (1 << 3)
#define CPU_INT_PCIE_INTD (1 << 4)
#define CPU_INT_PCIE_INTR (1 << 5)
#define CPU_INT_PCIE_NMI (1 << 6)
#define CPU_INT_PCIE_UBUS (1 << 7)
#define CPU_INT_IPI (1 << 8)
#define PCIE_EXT_CFG_INDEX_REG 0x8400
#define EXT_CFG_FUNC_NUM_SHIFT 12
#define EXT_CFG_FUNC_NUM_MASK (0x7 << EXT_CFG_FUNC_NUM_SHIFT)
#define EXT_CFG_DEV_NUM_SHIFT 15
#define EXT_CFG_DEV_NUM_MASK (0xf << EXT_CFG_DEV_NUM_SHIFT)
#define EXT_CFG_BUS_NUM_SHIFT 20
#define EXT_CFG_BUS_NUM_MASK (0xff << EXT_CFG_BUS_NUM_SHIFT)
#define PCIE_DEVICE_OFFSET 0x9000
struct bcm6318_pcie {
void __iomem *base;
int irq;
struct clk *clk;
struct clk *clk25;
struct clk *clk_ubus;
struct reset_control *reset;
struct reset_control *reset_ext;
struct reset_control *reset_core;
struct reset_control *reset_hard;
};
static struct bcm6318_pcie bcm6318_pcie;
extern int bmips_pci_irq;
/*
* swizzle 32bits data to return only the needed part
*/
static int postprocess_read(u32 data, int where, unsigned int size)
{
u32 ret = 0;
switch (size) {
case 1:
ret = (data >> ((where & 3) << 3)) & 0xff;
break;
case 2:
ret = (data >> ((where & 3) << 3)) & 0xffff;
break;
case 4:
ret = data;
break;
}
return ret;
}
static int preprocess_write(u32 orig_data, u32 val, int where,
unsigned int size)
{
u32 ret = 0;
switch (size) {
case 1:
ret = (orig_data & ~(0xff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
break;
case 2:
ret = (orig_data & ~(0xffff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
break;
case 4:
ret = val;
break;
}
return ret;
}
static int bcm6318_pcie_can_access(struct pci_bus *bus, int devfn)
{
struct bcm6318_pcie *priv = &bcm6318_pcie;
switch (bus->number) {
case PCIE_BUS_BRIDGE:
return PCI_SLOT(devfn) == 0;
case PCIE_BUS_DEVICE:
if (PCI_SLOT(devfn) == 0)
return __raw_readl(priv->base + PCIE_DLSTATUS_REG)
& DLSTATUS_PHYLINKUP;
/* else, fall through */
default:
return false;
}
}
static int bcm6318_pcie_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
struct bcm6318_pcie *priv = &bcm6318_pcie;
u32 data;
u32 reg = where & ~3;
if (!bcm6318_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus->number == PCIE_BUS_DEVICE)
reg += PCIE_DEVICE_OFFSET;
data = __raw_readl(priv->base + reg);
*val = postprocess_read(data, where, size);
return PCIBIOS_SUCCESSFUL;
}
static int bcm6318_pcie_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
struct bcm6318_pcie *priv = &bcm6318_pcie;
u32 data;
u32 reg = where & ~3;
if (!bcm6318_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus->number == PCIE_BUS_DEVICE)
reg += PCIE_DEVICE_OFFSET;
data = __raw_readl(priv->base + reg);
data = preprocess_write(data, val, where, size);
__raw_writel(data, priv->base + reg);
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops bcm6318_pcie_ops = {
.read = bcm6318_pcie_read,
.write = bcm6318_pcie_write,
};
static struct resource bcm6318_pcie_io_resource;
static struct resource bcm6318_pcie_mem_resource;
static struct resource bcm6318_pcie_busn_resource;
static struct pci_controller bcm6318_pcie_controller = {
.pci_ops = &bcm6318_pcie_ops,
.io_resource = &bcm6318_pcie_io_resource,
.mem_resource = &bcm6318_pcie_mem_resource,
.busn_resource = &bcm6318_pcie_busn_resource,
};
static void bcm6318_pcie_reset(struct bcm6318_pcie *priv)
{
u32 val;
reset_control_deassert(priv->reset_hard);
reset_control_assert(priv->reset);
reset_control_assert(priv->reset_core);
reset_control_assert(priv->reset_ext);
mdelay(10);
reset_control_deassert(priv->reset_ext);
mdelay(10);
reset_control_deassert(priv->reset);
mdelay(10);
val = __raw_readl(priv->base + PCIE_HARD_DEBUG_REG);
val &= ~HARD_DEBUG_SERDES_IDDQ;
__raw_writel(val, priv->base + PCIE_HARD_DEBUG_REG);
mdelay(10);
reset_control_deassert(priv->reset_core);
mdelay(200);
}
static void bcm6318_pcie_setup(struct bcm6318_pcie *priv)
{
u32 val;
__raw_writel(CPU_INT_PCIE_INTA | CPU_INT_PCIE_INTB |
CPU_INT_PCIE_INTC | CPU_INT_PCIE_INTD,
priv->base + PCIE_CPU_INT1_MASK_CLEAR_REG);
val = bcm6318_pcie_mem_resource.end & C2P_BASELIMIT_LIMIT_MASK;
val |= (bcm6318_pcie_mem_resource.start >> C2P_BASELIMIT_LIMIT_SHIFT)
<< C2P_BASELIMIT_BASE_SHIFT;
__raw_writel(val, priv->base + PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG);
/* setup class code as bridge */
val = __raw_readl(priv->base + PCIE_IDVAL3_REG);
val &= ~IDVAL3_CLASS_CODE_MASK;
val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
__raw_writel(val, priv->base + PCIE_IDVAL3_REG);
/* disable bar1 size */
val = __raw_readl(priv->base + PCIE_CONFIG2_REG);
val &= ~CONFIG2_BAR1_SIZE_MASK;
__raw_writel(val, priv->base + PCIE_CONFIG2_REG);
/* set bar0 to little endian */
val = __raw_readl(priv->base + PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG);
val |= bcm6318_pcie_mem_resource.start & C2P_MEM_WIN_BASE_ADDR_MASK;
val |= C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP;
__raw_writel(val, priv->base + PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG);
__raw_writel(SPECIFIC_ENDIAN_MODE_BYTE_ALIGN,
priv->base + PCIE_SPECIFIC_REG);
__raw_writel(RC_BAR_CFG_LO_SIZE_256MB,
priv->base + PCIE_RC_BAR1_CONFIG_LO_REG);
__raw_writel(BAR1_CFG_REMAP_ACCESS_EN,
priv->base + PCIE_UBUS_BAR1_CFG_REMAP_REG);
__raw_writel(PCIE_BUS_DEVICE << EXT_CFG_BUS_NUM_SHIFT,
priv->base + PCIE_EXT_CFG_INDEX_REG);
}
static int bcm6318_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct bcm6318_pcie *priv = &bcm6318_pcie;
struct resource *res;
int ret;
of_pci_check_probe_only();
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
priv->irq = platform_get_irq(pdev, 0);
if (!priv->irq)
return -ENODEV;
bmips_pci_irq = priv->irq;
priv->reset = devm_reset_control_get(dev, "pcie");
if (IS_ERR(priv->reset))
return PTR_ERR(priv->reset);
priv->reset_ext = devm_reset_control_get(dev, "pcie-ext");
if (IS_ERR(priv->reset_ext))
return PTR_ERR(priv->reset_ext);
priv->reset_core = devm_reset_control_get(dev, "pcie-core");
if (IS_ERR(priv->reset_core))
return PTR_ERR(priv->reset_core);
priv->reset_hard = devm_reset_control_get(dev, "pcie-hard");
if (IS_ERR(priv->reset_hard))
return PTR_ERR(priv->reset_hard);
priv->clk = devm_clk_get(dev, "pcie");
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
priv->clk25 = devm_clk_get(dev, "pcie25");
if (IS_ERR(priv->clk25))
return PTR_ERR(priv->clk25);
priv->clk_ubus = devm_clk_get(dev, "pcie-ubus");
if (IS_ERR(priv->clk_ubus))
return PTR_ERR(priv->clk_ubus);
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(dev, "could not enable clock\n");
return ret;
}
ret = clk_prepare_enable(priv->clk25);
if (ret) {
dev_err(dev, "could not enable clock\n");
return ret;
}
ret = clk_prepare_enable(priv->clk_ubus);
if (ret) {
dev_err(dev, "could not enable clock\n");
return ret;
}
pci_load_of_ranges(&bcm6318_pcie_controller, np);
if (!bcm6318_pcie_mem_resource.start)
return -EINVAL;
of_pci_parse_bus_range(np, &bcm6318_pcie_busn_resource);
bcm6318_pcie_reset(priv);
bcm6318_pcie_setup(priv);
register_pci_controller(&bcm6318_pcie_controller);
return 0;
}
static const struct of_device_id bcm6318_pcie_of_match[] = {
{ .compatible = "brcm,bcm6318-pcie", },
{ /* sentinel */ }
};
static struct platform_driver bcm6318_pcie_driver = {
.probe = bcm6318_pcie_probe,
.driver = {
.name = "bcm6318-pcie",
.of_match_table = bcm6318_pcie_of_match,
},
};
int __init bcm6318_pcie_init(void)
{
int ret = platform_driver_register(&bcm6318_pcie_driver);
if (ret)
pr_err("pci-bcm6318: Error registering platform driver!\n");
return ret;
}
late_initcall_sync(bcm6318_pcie_init);

View File

@ -0,0 +1,412 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* BCM6328 PCIe Controller Driver
*
* Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
* Copyright (C) 2015 Jonas Gorski <jonas.gorski@gmail.com>
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
*/
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/mm.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
#include "../pci.h"
#define SERDES_PCIE_EXD_EN BIT(15)
#define SERDES_PCIE_EN BIT(0)
#define PCIE_BUS_BRIDGE 0
#define PCIE_BUS_DEVICE 1
#define PCIE_CONFIG2_REG 0x408
#define CONFIG2_BAR1_SIZE_EN 1
#define CONFIG2_BAR1_SIZE_MASK 0xf
#define PCIE_IDVAL3_REG 0x43c
#define IDVAL3_CLASS_CODE_MASK 0xffffff
#define IDVAL3_SUBCLASS_SHIFT 8
#define IDVAL3_CLASS_SHIFT 16
#define PCIE_DLSTATUS_REG 0x1048
#define DLSTATUS_PHYLINKUP (1 << 13)
#define PCIE_BRIDGE_OPT1_REG 0x2820
#define OPT1_RD_BE_OPT_EN (1 << 7)
#define OPT1_RD_REPLY_BE_FIX_EN (1 << 9)
#define OPT1_PCIE_BRIDGE_HOLE_DET_EN (1 << 11)
#define OPT1_L1_INT_STATUS_MASK_POL (1 << 12)
#define PCIE_BRIDGE_OPT2_REG 0x2824
#define OPT2_UBUS_UR_DECODE_DIS (1 << 2)
#define OPT2_TX_CREDIT_CHK_EN (1 << 4)
#define OPT2_CFG_TYPE1_BD_SEL (1 << 7)
#define OPT2_CFG_TYPE1_BUS_NO_SHIFT 16
#define OPT2_CFG_TYPE1_BUS_NO_MASK (0xff << OPT2_CFG_TYPE1_BUS_NO_SHIFT)
#define PCIE_BRIDGE_BAR0_BASEMASK_REG 0x2828
#define BASEMASK_REMAP_EN (1 << 0)
#define BASEMASK_SWAP_EN (1 << 1)
#define BASEMASK_MASK_SHIFT 4
#define BASEMASK_MASK_MASK (0xfff << BASEMASK_MASK_SHIFT)
#define BASEMASK_BASE_SHIFT 20
#define BASEMASK_BASE_MASK (0xfff << BASEMASK_BASE_SHIFT)
#define PCIE_BRIDGE_BAR0_REBASE_ADDR_REG 0x282c
#define REBASE_ADDR_BASE_SHIFT 20
#define REBASE_ADDR_BASE_MASK (0xfff << REBASE_ADDR_BASE_SHIFT)
#define PCIE_BRIDGE_RC_INT_MASK_REG 0x2854
#define PCIE_RC_INT_A (1 << 0)
#define PCIE_RC_INT_B (1 << 1)
#define PCIE_RC_INT_C (1 << 2)
#define PCIE_RC_INT_D (1 << 3)
#define PCIE_DEVICE_OFFSET 0x8000
struct bcm6328_pcie {
void __iomem *base;
int irq;
struct regmap *serdes;
struct device **pm;
struct device_link **link_pm;
unsigned int num_pms;
struct clk *clk;
struct reset_control *reset;
struct reset_control *reset_ext;
struct reset_control *reset_core;
struct reset_control *reset_hard;
};
static struct bcm6328_pcie bcm6328_pcie;
extern int bmips_pci_irq;
/*
* swizzle 32bits data to return only the needed part
*/
static int postprocess_read(u32 data, int where, unsigned int size)
{
u32 ret = 0;
switch (size) {
case 1:
ret = (data >> ((where & 3) << 3)) & 0xff;
break;
case 2:
ret = (data >> ((where & 3) << 3)) & 0xffff;
break;
case 4:
ret = data;
break;
}
return ret;
}
static int preprocess_write(u32 orig_data, u32 val, int where,
unsigned int size)
{
u32 ret = 0;
switch (size) {
case 1:
ret = (orig_data & ~(0xff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
break;
case 2:
ret = (orig_data & ~(0xffff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
break;
case 4:
ret = val;
break;
}
return ret;
}
static int bcm6328_pcie_can_access(struct pci_bus *bus, int devfn)
{
struct bcm6328_pcie *priv = &bcm6328_pcie;
switch (bus->number) {
case PCIE_BUS_BRIDGE:
return PCI_SLOT(devfn) == 0;
case PCIE_BUS_DEVICE:
if (PCI_SLOT(devfn) == 0)
return __raw_readl(priv->base + PCIE_DLSTATUS_REG)
& DLSTATUS_PHYLINKUP;
/* else, fall through */
default:
return false;
}
}
static int bcm6328_pcie_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
struct bcm6328_pcie *priv = &bcm6328_pcie;
u32 data;
u32 reg = where & ~3;
if (!bcm6328_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus->number == PCIE_BUS_DEVICE)
reg += PCIE_DEVICE_OFFSET;
data = __raw_readl(priv->base + reg);
*val = postprocess_read(data, where, size);
return PCIBIOS_SUCCESSFUL;
}
static int bcm6328_pcie_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
struct bcm6328_pcie *priv = &bcm6328_pcie;
u32 data;
u32 reg = where & ~3;
if (!bcm6328_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus->number == PCIE_BUS_DEVICE)
reg += PCIE_DEVICE_OFFSET;
data = __raw_readl(priv->base + reg);
data = preprocess_write(data, val, where, size);
__raw_writel(data, priv->base + reg);
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops bcm6328_pcie_ops = {
.read = bcm6328_pcie_read,
.write = bcm6328_pcie_write,
};
static struct resource bcm6328_pcie_io_resource;
static struct resource bcm6328_pcie_mem_resource;
static struct resource bcm6328_pcie_busn_resource;
static struct pci_controller bcm6328_pcie_controller = {
.pci_ops = &bcm6328_pcie_ops,
.io_resource = &bcm6328_pcie_io_resource,
.mem_resource = &bcm6328_pcie_mem_resource,
.busn_resource = &bcm6328_pcie_busn_resource,
};
static void bcm6328_pcie_reset(struct bcm6328_pcie *priv)
{
regmap_write_bits(priv->serdes, 0,
SERDES_PCIE_EXD_EN | SERDES_PCIE_EN,
SERDES_PCIE_EXD_EN | SERDES_PCIE_EN);
reset_control_assert(priv->reset);
reset_control_assert(priv->reset_core);
reset_control_assert(priv->reset_ext);
if (priv->reset_hard) {
reset_control_assert(priv->reset_hard);
mdelay(10);
reset_control_deassert(priv->reset_hard);
}
mdelay(10);
reset_control_deassert(priv->reset_core);
reset_control_deassert(priv->reset);
mdelay(10);
reset_control_deassert(priv->reset_ext);
mdelay(200);
}
static void bcm6328_pcie_setup(struct bcm6328_pcie *priv)
{
u32 val;
val = __raw_readl(priv->base + PCIE_BRIDGE_OPT1_REG);
val |= OPT1_RD_BE_OPT_EN;
val |= OPT1_RD_REPLY_BE_FIX_EN;
val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN;
val |= OPT1_L1_INT_STATUS_MASK_POL;
__raw_writel(val, priv->base + PCIE_BRIDGE_OPT1_REG);
val = __raw_readl(priv->base + PCIE_BRIDGE_RC_INT_MASK_REG);
val |= PCIE_RC_INT_A;
val |= PCIE_RC_INT_B;
val |= PCIE_RC_INT_C;
val |= PCIE_RC_INT_D;
__raw_writel(val, priv->base + PCIE_BRIDGE_RC_INT_MASK_REG);
val = __raw_readl(priv->base + PCIE_BRIDGE_OPT2_REG);
/* enable credit checking and error checking */
val |= OPT2_TX_CREDIT_CHK_EN;
val |= OPT2_UBUS_UR_DECODE_DIS;
/* set device bus/func for the pcie device */
val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT);
val |= OPT2_CFG_TYPE1_BD_SEL;
__raw_writel(val, priv->base + PCIE_BRIDGE_OPT2_REG);
/* setup class code as bridge */
val = __raw_readl(priv->base + PCIE_IDVAL3_REG);
val &= ~IDVAL3_CLASS_CODE_MASK;
val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
__raw_writel(val, priv->base + PCIE_IDVAL3_REG);
/* disable bar1 size */
val = __raw_readl(priv->base + PCIE_CONFIG2_REG);
val &= ~CONFIG2_BAR1_SIZE_MASK;
__raw_writel(val, priv->base + PCIE_CONFIG2_REG);
/* set bar0 to little endian */
val = (bcm6328_pcie_mem_resource.start >> 20)
<< BASEMASK_BASE_SHIFT;
val |= (bcm6328_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT;
val |= BASEMASK_REMAP_EN;
__raw_writel(val, priv->base + PCIE_BRIDGE_BAR0_BASEMASK_REG);
val = (bcm6328_pcie_mem_resource.start >> 20)
<< REBASE_ADDR_BASE_SHIFT;
__raw_writel(val, priv->base + PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
}
static int bcm6328_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct bcm6328_pcie *priv = &bcm6328_pcie;
struct resource *res;
unsigned int i;
int ret;
pm_runtime_enable(dev);
pm_runtime_no_callbacks(dev);
priv->num_pms = of_count_phandle_with_args(np, "power-domains",
"#power-domain-cells");
if (priv->num_pms > 1) {
priv->pm = devm_kcalloc(dev, priv->num_pms,
sizeof(struct device *), GFP_KERNEL);
if (!priv->pm)
return -ENOMEM;
priv->link_pm = devm_kcalloc(dev, priv->num_pms,
sizeof(struct device_link *),
GFP_KERNEL);
if (!priv->link_pm)
return -ENOMEM;
for (i = 0; i < priv->num_pms; i++) {
priv->pm[i] = genpd_dev_pm_attach_by_id(dev, i);
if (IS_ERR(priv->pm[i])) {
dev_err(dev, "error getting pm %d\n", i);
return -EINVAL;
}
priv->link_pm[i] = device_link_add(dev, priv->pm[i],
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE);
}
}
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
pm_runtime_disable(dev);
dev_info(dev, "PM prober defer: ret=%d\n", ret);
return -EPROBE_DEFER;
}
of_pci_check_probe_only();
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
priv->irq = platform_get_irq(pdev, 0);
if (!priv->irq)
return -ENODEV;
bmips_pci_irq = priv->irq;
priv->serdes = syscon_regmap_lookup_by_phandle(np, "brcm,serdes");
if (IS_ERR(priv->serdes))
return PTR_ERR(priv->serdes);
priv->reset = devm_reset_control_get(dev, "pcie");
if (IS_ERR(priv->reset))
return PTR_ERR(priv->reset);
priv->reset_ext = devm_reset_control_get(dev, "pcie-ext");
if (IS_ERR(priv->reset_ext))
return PTR_ERR(priv->reset_ext);
priv->reset_core = devm_reset_control_get(dev, "pcie-core");
if (IS_ERR(priv->reset_core))
return PTR_ERR(priv->reset_core);
priv->reset_hard = devm_reset_control_get_optional(dev, "pcie-hard");
if (IS_ERR(priv->reset_hard))
return PTR_ERR(priv->reset_hard);
priv->clk = devm_clk_get(dev, "pcie");
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(dev, "could not enable clock\n");
return ret;
}
pci_load_of_ranges(&bcm6328_pcie_controller, np);
if (!bcm6328_pcie_mem_resource.start)
return -EINVAL;
of_pci_parse_bus_range(np, &bcm6328_pcie_busn_resource);
bcm6328_pcie_reset(priv);
bcm6328_pcie_setup(priv);
register_pci_controller(&bcm6328_pcie_controller);
return 0;
}
static const struct of_device_id bcm6328_pcie_of_match[] = {
{ .compatible = "brcm,bcm6328-pcie", },
{ /* sentinel */ }
};
static struct platform_driver bcm6328_pcie_driver = {
.probe = bcm6328_pcie_probe,
.driver = {
.name = "bcm6328-pcie",
.of_match_table = bcm6328_pcie_of_match,
},
};
int __init bcm6328_pcie_init(void)
{
int ret = platform_driver_register(&bcm6328_pcie_driver);
if (ret)
pr_err("pci-bcm6328: Error registering platform driver!\n");
return ret;
}
late_initcall_sync(bcm6328_pcie_init);

View File

@ -249,6 +249,8 @@ define Device/Default
DEVICE_LOADADDR :=
endef
ATH9K_PACKAGES := kmod-ath9k wpad-basic-wolfssl
B43_PACKAGES := kmod-b43 wpad-basic-wolfssl
USB1_PACKAGES := kmod-usb-ohci kmod-ledtrig-usbdev
USB2_PACKAGES := $(USB1_PACKAGES) kmod-usb2

View File

@ -33,7 +33,7 @@ define Device/comtrend_ar-5315u
CHIP_ID := 6318
CFE_BOARD_ID := 96318A-1441N1
FLASH_MB := 16
DEVICE_PACKAGES += $(USB2_PACKAGES)
DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES)
endef
TARGET_DEVICES += comtrend_ar-5315u
@ -44,7 +44,7 @@ define Device/comtrend_ar-5387un
CHIP_ID := 6328
CFE_BOARD_ID := 96328A-1441N1
FLASH_MB := 16
DEVICE_PACKAGES += $(USB2_PACKAGES)
DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES)
endef
TARGET_DEVICES += comtrend_ar-5387un
@ -56,7 +56,7 @@ define Device/comtrend_vr-3025u
CFE_BOARD_ID := 96368M-1541N
BLOCKSIZE := 0x20000
FLASH_MB := 32
DEVICE_PACKAGES += $(USB2_PACKAGES)
DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES)
endef
TARGET_DEVICES += comtrend_vr-3025u
@ -69,6 +69,6 @@ define Device/huawei_hg556a-b
CFE_BOARD_ID := HW556
CFE_EXTRAS += --rsa-signature "EchoLife_HG556a" --tag-version 8
BLOCKSIZE := 0x20000
DEVICE_PACKAGES += $(USB2_PACKAGES)
DEVICE_PACKAGES += $(USB2_PACKAGES) $(ATH9K_PACKAGES)
endef
TARGET_DEVICES += huawei_hg556a-b

View File

@ -74,7 +74,7 @@ define Device/netgear_dgnd3700-v2
CFE_RAM_JFFS2_PAD := 496k
BLOCKSIZE := 16k
PAGESIZE := 512
DEVICE_PACKAGES += $(USB2_PACKAGES)
DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES)
CFE_WFI_FLASH_TYPE := 2
CFE_WFI_VERSION := 0x5731
endef

View File

@ -1,104 +0,0 @@
From a3b0b6479700a5b0af2c631cb2ec0fb7a0d978f2 Mon Sep 17 00:00:00 2001
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Date: Sun, 1 Nov 2020 21:16:09 +0200
Subject: [PATCH] net: dsa: implement a central TX reallocation procedure
At the moment, taggers are left with the task of ensuring that the skb
headers are writable (which they aren't, if the frames were cloned for
TX timestamping, for flooding by the bridge, etc), and that there is
enough space in the skb data area for the DSA tag to be pushed.
Moreover, the life of tail taggers is even harder, because they need to
ensure that short frames have enough padding, a problem that normal
taggers don't have.
The principle of the DSA framework is that everything except for the
most intimate hardware specifics (like in this case, the actual packing
of the DSA tag bits) should be done inside the core, to avoid having
code paths that are very rarely tested.
So provide a TX reallocation procedure that should cover the known needs
of DSA today.
Note that this patch also gives the network stack a good hint about the
headroom/tailroom it's going to need. Up till now it wasn't doing that.
So the reallocation procedure should really be there only for the
exceptional cases, and for cloned packets which need to be unshared.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: Christian Eggers <ceggers@arri.de> # For tail taggers only
Tested-by: Kurt Kanzenbach <kurt@linutronix.de>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
net/dsa/slave.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -548,6 +548,30 @@ netdev_tx_t dsa_enqueue_skb(struct sk_bu
}
EXPORT_SYMBOL_GPL(dsa_enqueue_skb);
+static int dsa_realloc_skb(struct sk_buff *skb, struct net_device *dev)
+{
+ int needed_headroom = dev->needed_headroom;
+ int needed_tailroom = dev->needed_tailroom;
+
+ /* For tail taggers, we need to pad short frames ourselves, to ensure
+ * that the tail tag does not fail at its role of being at the end of
+ * the packet, once the master interface pads the frame. Account for
+ * that pad length here, and pad later.
+ */
+ if (unlikely(needed_tailroom && skb->len < ETH_ZLEN))
+ needed_tailroom += ETH_ZLEN - skb->len;
+ /* skb_headroom() returns unsigned int... */
+ needed_headroom = max_t(int, needed_headroom - skb_headroom(skb), 0);
+ needed_tailroom = max_t(int, needed_tailroom - skb_tailroom(skb), 0);
+
+ if (likely(!needed_headroom && !needed_tailroom && !skb_cloned(skb)))
+ /* No reallocation needed, yay! */
+ return 0;
+
+ return pskb_expand_head(skb, needed_headroom, needed_tailroom,
+ GFP_ATOMIC);
+}
+
static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dsa_slave_priv *p = netdev_priv(dev);
@@ -567,6 +591,17 @@ static netdev_tx_t dsa_slave_xmit(struct
*/
dsa_skb_tx_timestamp(p, skb);
+ if (dsa_realloc_skb(skb, dev)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ /* needed_tailroom should still be 'warm' in the cache line from
+ * dsa_realloc_skb(), which has also ensured that padding is safe.
+ */
+ if (dev->needed_tailroom)
+ eth_skb_pad(skb);
+
/* Transmit function may have to reallocate the original SKB,
* in which case it must have freed it. Only free it here on error.
*/
@@ -1825,6 +1860,16 @@ int dsa_slave_create(struct dsa_port *po
slave_dev->netdev_ops = &dsa_slave_netdev_ops;
if (ds->ops->port_max_mtu)
slave_dev->max_mtu = ds->ops->port_max_mtu(ds, port->index);
+ if (cpu_dp->tag_ops->tail_tag)
+ slave_dev->needed_tailroom = cpu_dp->tag_ops->overhead;
+ else
+ slave_dev->needed_headroom = cpu_dp->tag_ops->overhead;
+ /* Try to save one extra realloc later in the TX path (in the master)
+ * by also inheriting the master's needed headroom and tailroom.
+ * The 8021q driver also does this.
+ */
+ slave_dev->needed_headroom += master->needed_headroom;
+ slave_dev->needed_tailroom += master->needed_tailroom;
SET_NETDEV_DEVTYPE(slave_dev, &dsa_type);
netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one,

View File

@ -80,7 +80,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
#define BRCM_TAG_LEN 4
/* Tag is constructed and desconstructed using byte by byte access
@@ -197,6 +214,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops);
@@ -194,6 +211,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM);
#endif
@ -168,7 +168,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb,
struct net_device *dev)
@@ -229,6 +327,9 @@ static struct dsa_tag_driver *dsa_tag_dr
@@ -226,6 +324,9 @@ static struct dsa_tag_driver *dsa_tag_dr
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM)
&DSA_TAG_DRIVER_NAME(brcm_netdev_ops),
#endif

View File

@ -28,7 +28,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
This driver adds support for Broadcom managed switch chips. It supports
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -2010,15 +2010,17 @@ enum dsa_tag_protocol b53_get_tag_protoc
@@ -2028,15 +2028,17 @@ enum dsa_tag_protocol b53_get_tag_protoc
{
struct b53_device *dev = ds->priv;

View File

@ -1,12 +0,0 @@
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl
if (of_property_read_bool(dev->dev.of_node, "big-endian"))
ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+ if (of_property_read_bool(dev->dev.of_node, "ignore-oc"))
+ ehci->ignore_oc = 1;
+
if (of_property_read_bool(dev->dev.of_node,
"needs-reset-on-resume"))
priv->reset_on_resume = true;

View File

@ -13,7 +13,7 @@ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1140,6 +1140,36 @@ static void b53_force_port_config(struct
@@ -1155,6 +1155,36 @@ static void b53_force_port_config(struct
b53_write8(dev, B53_CTRL_PAGE, off, reg);
}
@ -50,7 +50,7 @@ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
static void b53_adjust_link(struct dsa_switch *ds, int port,
struct phy_device *phydev)
{
@@ -1166,6 +1196,9 @@ static void b53_adjust_link(struct dsa_s
@@ -1181,6 +1211,9 @@ static void b53_adjust_link(struct dsa_s
tx_pause, rx_pause);
b53_force_link(dev, port, phydev->link);
@ -60,7 +60,7 @@ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
if (is531x5(dev) && phy_interface_is_rgmii(phydev)) {
if (port == 8)
off = B53_RGMII_CTRL_IMP;
@@ -1358,6 +1391,9 @@ void b53_phylink_mac_link_up(struct dsa_
@@ -1373,6 +1406,9 @@ void b53_phylink_mac_link_up(struct dsa_
{
struct b53_device *dev = ds->priv;

View File

@ -0,0 +1,20 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -262,6 +262,7 @@ config BMIPS_GENERIC
select BCM7038_L1_IRQ
select BCM7120_L2_IRQ
select BRCMSTB_L2_IRQ
+ select HAVE_PCI
select IRQ_MIPS_CPU
select DMA_NONCOHERENT
select SYS_SUPPORTS_32BIT_KERNEL
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_PCI_XTALK_BRIDGE) += pci-xt
# These are still pretty much in the old state, watch, go blind.
#
obj-$(CONFIG_ATH79) += fixup-ath79.o
+obj-$(CONFIG_BMIPS_GENERIC) += fixup-bmips.o
obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o

View File

@ -0,0 +1,22 @@
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -3,6 +3,11 @@
menu "PCI controller drivers"
depends on PCI
+config PCIE_BCM6328
+ bool "BCM6328 PCIe controller"
+ depends on BMIPS_GENERIC || COMPILE_TEST
+ depends on OF
+
config PCI_MVEBU
bool "Marvell EBU PCIe controller"
depends on ARCH_MVEBU || ARCH_DOVE || COMPILE_TEST
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o
obj-$(CONFIG_PCIE_CADENCE) += cadence/
obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o
obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o

View File

@ -0,0 +1,22 @@
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -3,6 +3,11 @@
menu "PCI controller drivers"
depends on PCI
+config PCIE_BCM6318
+ bool "BCM6318 PCIe controller"
+ depends on BMIPS_GENERIC || COMPILE_TEST
+ depends on OF
+
config PCIE_BCM6328
bool "BCM6328 PCIe controller"
depends on BMIPS_GENERIC || COMPILE_TEST
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PCIE_BCM6318) += pcie-bcm6318.o
obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o
obj-$(CONFIG_PCIE_CADENCE) += cadence/
obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o

View File

@ -0,0 +1,22 @@
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -3,6 +3,11 @@
menu "PCI controller drivers"
depends on PCI
+config PCI_BCM6348
+ bool "BCM6348 PCI controller"
+ depends on BMIPS_GENERIC || COMPILE_TEST
+ depends on OF
+
config PCIE_BCM6318
bool "BCM6318 PCIe controller"
depends on BMIPS_GENERIC || COMPILE_TEST
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PCI_BCM6348) += pci-bcm6348.o
obj-$(CONFIG_PCIE_BCM6318) += pcie-bcm6318.o
obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o
obj-$(CONFIG_PCIE_CADENCE) += cadence/

View File

@ -0,0 +1,6 @@
--- a/arch/mips/bmips/Makefile
+++ b/arch/mips/bmips/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += setup.o irq.o dma.o
+obj-y += ath9k-fixup.o b43-sprom.o

View File

@ -25,7 +25,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2030,7 +2030,9 @@ static void dsa_slave_switchdev_event_wo
@@ -2075,7 +2075,9 @@ static void dsa_slave_switchdev_event_wo
err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid);
if (err) {
@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
break;
}
fdb_info->offloaded = true;
@@ -2045,9 +2047,11 @@ static void dsa_slave_switchdev_event_wo
@@ -2090,9 +2092,11 @@ static void dsa_slave_switchdev_event_wo
err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid);
if (err) {

View File

@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
struct sk_buff * (*xmit)(struct sk_buff *skb,
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2005,76 +2005,66 @@ static int dsa_slave_netdevice_event(str
@@ -2050,76 +2050,66 @@ static int dsa_slave_netdevice_event(str
return NOTIFY_DONE;
}
@ -167,7 +167,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
}
/* Called under rcu_read_lock() */
@@ -2082,7 +2072,9 @@ static int dsa_slave_switchdev_event(str
@@ -2127,7 +2117,9 @@ static int dsa_slave_switchdev_event(str
unsigned long event, void *ptr)
{
struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
@ -177,7 +177,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
int err;
if (event == SWITCHDEV_PORT_ATTR_SET) {
@@ -2095,20 +2087,32 @@ static int dsa_slave_switchdev_event(str
@@ -2140,20 +2132,32 @@ static int dsa_slave_switchdev_event(str
if (!dsa_slave_dev_check(dev))
return NOTIFY_DONE;
@ -213,7 +213,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
dev_hold(dev);
break;
default:
@@ -2118,10 +2122,6 @@ static int dsa_slave_switchdev_event(str
@@ -2163,10 +2167,6 @@ static int dsa_slave_switchdev_event(str
dsa_schedule_work(&switchdev_work->work);
return NOTIFY_OK;

View File

@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2077,31 +2077,29 @@ static int dsa_slave_switchdev_event(str
@@ -2122,31 +2122,29 @@ static int dsa_slave_switchdev_event(str
struct dsa_port *dp;
int err;
@ -68,7 +68,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
fdb_info = ptr;
if (!fdb_info->added_by_user) {
@@ -2114,13 +2112,12 @@ static int dsa_slave_switchdev_event(str
@@ -2159,13 +2157,12 @@ static int dsa_slave_switchdev_event(str
switchdev_work->vid = fdb_info->vid;
dev_hold(dev);

View File

@ -30,7 +30,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2090,6 +2090,9 @@ static int dsa_slave_switchdev_event(str
@@ -2135,6 +2135,9 @@ static int dsa_slave_switchdev_event(str
dp = dsa_slave_to_port(dev);

View File

@ -170,7 +170,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
*/
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2067,6 +2067,28 @@ static void dsa_slave_switchdev_event_wo
@@ -2112,6 +2112,28 @@ static void dsa_slave_switchdev_event_wo
dev_put(dp->slave);
}
@ -199,7 +199,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
/* Called under rcu_read_lock() */
static int dsa_slave_switchdev_event(struct notifier_block *unused,
unsigned long event, void *ptr)
@@ -2085,10 +2107,37 @@ static int dsa_slave_switchdev_event(str
@@ -2130,10 +2152,37 @@ static int dsa_slave_switchdev_event(str
return notifier_from_errno(err);
case SWITCHDEV_FDB_ADD_TO_DEVICE:
case SWITCHDEV_FDB_DEL_TO_DEVICE:
@ -240,7 +240,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del)
return NOTIFY_DONE;
@@ -2103,18 +2152,13 @@ static int dsa_slave_switchdev_event(str
@@ -2148,18 +2197,13 @@ static int dsa_slave_switchdev_event(str
switchdev_work->port = dp->index;
switchdev_work->event = event;

View File

@ -1,5 +1,11 @@
From 2d5ba37461013253d2ff0a3641b727fd32ea97a9 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Subject: USB: EHCI: add ignore_oc flag to disable overcurrent checking
Date: Tue, 23 Feb 2021 18:44:53 +0100
Subject: [PATCH 1/3] usb: ehci: add spurious flag to disable overcurrent
checking
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds an ignore_oc flag which can be set by EHCI controller
not supporting or wanting to disable overcurrent checking. The EHCI
@ -7,13 +13,16 @@ platform data in include/linux/usb/ehci_pdriver.h is also augmented to
take advantage of this new flag.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Link: https://lore.kernel.org/r/20210223174455.1378-2-noltari@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/ehci-hcd.c | 2 +-
drivers/usb/host/ehci-hub.c | 4 ++--
drivers/usb/host/ehci-platform.c | 1 +
drivers/usb/host/ehci.h | 1 +
include/linux/usb/ehci_pdriver.h | 1 +
5 files changed, 6 insertions(+), 3 deletions(-)
drivers/usb/host/ehci-hcd.c | 2 +-
drivers/usb/host/ehci-hub.c | 4 ++--
drivers/usb/host/ehci-platform.c | 2 ++
drivers/usb/host/ehci.h | 1 +
include/linux/usb/ehci_pdriver.h | 1 +
5 files changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@ -22,7 +31,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
temp >> 8, temp & 0xff,
- ignore_oc ? ", overcurrent ignored" : "");
+ (ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : "");
+ (ignore_oc || ehci->spurious_oc) ? ", overcurrent ignored" : "");
ehci_writel(ehci, INTR_MASK,
&ehci->regs->intr_enable); /* Turn On Interrupts */
@ -33,7 +42,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
* PORT_POWER; that's surprising, but maybe within-spec.
*/
- if (!ignore_oc)
+ if (!ignore_oc && !ehci->ignore_oc)
+ if (!ignore_oc && !ehci->spurious_oc)
mask = PORT_CSC | PORT_PEC | PORT_OCC;
else
mask = PORT_CSC | PORT_PEC;
@ -42,7 +51,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
status |= USB_PORT_STAT_C_ENABLE << 16;
- if ((temp & PORT_OCC) && !ignore_oc){
+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){
+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/*
@ -52,8 +61,8 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
hcd->has_tt = 1;
if (pdata->reset_on_resume)
priv->reset_on_resume = true;
+ if (pdata->ignore_oc)
+ ehci->ignore_oc = 1;
+ if (pdata->spurious_oc)
+ ehci->spurious_oc = 1;
#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
if (ehci->big_endian_mmio) {
@ -63,7 +72,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
unsigned need_oc_pp_cycle:1; /* MPC834X port power */
unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
+ unsigned ignore_oc:1;
+ unsigned spurious_oc:1;
/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)
@ -73,7 +82,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
unsigned no_io_watchdog:1;
unsigned reset_on_resume:1;
unsigned dma_mask_64:1;
+ unsigned ignore_oc:1;
+ unsigned spurious_oc:1;
/* Turn on all power and clocks */
int (*power_on)(struct platform_device *pdev);

View File

@ -0,0 +1,31 @@
From 4da57dbbffdfa7fe4e2b70b047fc5ff95ff25a3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Tue, 23 Feb 2021 18:44:55 +0100
Subject: [PATCH 3/3] usb: host: ehci-platform: add spurious_oc DT support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Over-current reporting isn't supported on some platforms such as bcm63xx.
These devices will incorrectly report over-current if this flag isn't properly
activated.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Link: https://lore.kernel.org/r/20210223174455.1378-4-noltari@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/ehci-platform.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl
if (of_property_read_bool(dev->dev.of_node, "big-endian"))
ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+ if (of_property_read_bool(dev->dev.of_node, "spurious-oc"))
+ ehci->spurious_oc = 1;
+
if (of_property_read_bool(dev->dev.of_node,
"needs-reset-on-resume"))
priv->reset_on_resume = true;

View File

@ -1,5 +1,11 @@
From 2d5ba37461013253d2ff0a3641b727fd32ea97a9 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Subject: USB: EHCI: add ignore_oc flag to disable overcurrent checking
Date: Tue, 23 Feb 2021 18:44:53 +0100
Subject: [PATCH 1/3] usb: ehci: add spurious flag to disable overcurrent
checking
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds an ignore_oc flag which can be set by EHCI controller
not supporting or wanting to disable overcurrent checking. The EHCI
@ -7,13 +13,16 @@ platform data in include/linux/usb/ehci_pdriver.h is also augmented to
take advantage of this new flag.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Link: https://lore.kernel.org/r/20210223174455.1378-2-noltari@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/ehci-hcd.c | 2 +-
drivers/usb/host/ehci-hub.c | 4 ++--
drivers/usb/host/ehci-platform.c | 1 +
drivers/usb/host/ehci.h | 1 +
include/linux/usb/ehci_pdriver.h | 1 +
5 files changed, 6 insertions(+), 3 deletions(-)
drivers/usb/host/ehci-hcd.c | 2 +-
drivers/usb/host/ehci-hub.c | 4 ++--
drivers/usb/host/ehci-platform.c | 2 ++
drivers/usb/host/ehci.h | 1 +
include/linux/usb/ehci_pdriver.h | 1 +
5 files changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@ -22,7 +31,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
temp >> 8, temp & 0xff,
- ignore_oc ? ", overcurrent ignored" : "");
+ (ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : "");
+ (ignore_oc || ehci->spurious_oc) ? ", overcurrent ignored" : "");
ehci_writel(ehci, INTR_MASK,
&ehci->regs->intr_enable); /* Turn On Interrupts */
@ -33,7 +42,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
* PORT_POWER; that's surprising, but maybe within-spec.
*/
- if (!ignore_oc)
+ if (!ignore_oc && !ehci->ignore_oc)
+ if (!ignore_oc && !ehci->spurious_oc)
mask = PORT_CSC | PORT_PEC | PORT_OCC;
else
mask = PORT_CSC | PORT_PEC;
@ -42,7 +51,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
status |= USB_PORT_STAT_C_ENABLE << 16;
- if ((temp & PORT_OCC) && !ignore_oc){
+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){
+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/*
@ -52,8 +61,8 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
hcd->has_tt = 1;
if (pdata->reset_on_resume)
priv->reset_on_resume = true;
+ if (pdata->ignore_oc)
+ ehci->ignore_oc = 1;
+ if (pdata->spurious_oc)
+ ehci->spurious_oc = 1;
#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
if (ehci->big_endian_mmio) {
@ -63,7 +72,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
unsigned need_oc_pp_cycle:1; /* MPC834X port power */
unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
+ unsigned ignore_oc:1;
+ unsigned spurious_oc:1;
/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)
@ -73,7 +82,7 @@ Signed-off-by: Florian Fainelli <florian@openwrt.org>
unsigned no_io_watchdog:1;
unsigned reset_on_resume:1;
unsigned dma_mask_64:1;
+ unsigned ignore_oc:1;
+ unsigned spurious_oc:1;
/* Turn on all power and clocks */
int (*power_on)(struct platform_device *pdev);

View File

@ -0,0 +1,31 @@
From 4da57dbbffdfa7fe4e2b70b047fc5ff95ff25a3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Tue, 23 Feb 2021 18:44:55 +0100
Subject: [PATCH 3/3] usb: host: ehci-platform: add spurious_oc DT support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Over-current reporting isn't supported on some platforms such as bcm63xx.
These devices will incorrectly report over-current if this flag isn't properly
activated.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Link: https://lore.kernel.org/r/20210223174455.1378-4-noltari@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/ehci-platform.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -278,6 +278,9 @@ static int ehci_platform_probe(struct pl
if (of_property_read_bool(dev->dev.of_node, "big-endian"))
ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+ if (of_property_read_bool(dev->dev.of_node, "spurious-oc"))
+ ehci->spurious_oc = 1;
+
if (of_property_read_bool(dev->dev.of_node,
"needs-reset-on-resume"))
priv->reset_on_resume = true;

View File

@ -17,7 +17,7 @@
#define je16_to_cpu(x) ((x).v16)
#define je32_to_cpu(x) ((x).v32)
#define NR_PARTS 1
#define NR_PARTS 2
static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd,
const struct mtd_partition **pparts,
@ -58,12 +58,16 @@ static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd,
if (!parts)
return -ENOMEM;
parts[0].name = "bootfs";
parts[0].offset = 0;
parts[0].size = rootfs_offset;
if (type == MTDSPLIT_PART_TYPE_UBI)
parts[0].name = UBI_PART_NAME;
parts[1].name = UBI_PART_NAME;
else
parts[0].name = ROOTFS_PART_NAME;
parts[0].offset = rootfs_offset;
parts[0].size = mtd->size - rootfs_offset;
parts[1].name = ROOTFS_PART_NAME;
parts[1].offset = rootfs_offset;
parts[1].size = mtd->size - rootfs_offset;
*pparts = parts;

View File

@ -104,7 +104,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
config MODULES_TREE_LOOKUP
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3161,9 +3161,11 @@ static int setup_load_info(struct load_i
@@ -3243,9 +3243,11 @@ static int setup_load_info(struct load_i
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
{
@ -117,7 +117,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (flags & MODULE_INIT_IGNORE_VERMAGIC)
modmagic = NULL;
@@ -3184,6 +3186,7 @@ static int check_modinfo(struct module *
@@ -3266,6 +3268,7 @@ static int check_modinfo(struct module *
mod->name);
add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);
}

View File

@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2996,6 +2996,8 @@ static const struct seq_operations locks
@@ -2993,6 +2993,8 @@ static const struct seq_operations locks
static int __init proc_locks_init(void)
{

View File

@ -71,7 +71,7 @@ Signed-off-by: Tobias Wolf <dev-NTEO@vplace.de>
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -6951,7 +6951,7 @@ static void __ref alloc_node_mem_map(str
@@ -7026,7 +7026,7 @@ static void __ref alloc_node_mem_map(str
if (pgdat == NODE_DATA(0)) {
mem_map = NODE_DATA(0)->node_mem_map;
if (page_to_pfn(mem_map) != pgdat->node_start_pfn)

View File

@ -28,7 +28,7 @@ Add .ndo_fill_forward_path for dsa slave port devices
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1582,6 +1582,21 @@ static struct devlink_port *dsa_slave_ge
@@ -1617,6 +1617,21 @@ static struct devlink_port *dsa_slave_ge
return dp->ds->devlink ? &dp->devlink_port : NULL;
}
@ -50,7 +50,7 @@ Add .ndo_fill_forward_path for dsa slave port devices
static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_open = dsa_slave_open,
.ndo_stop = dsa_slave_close,
@@ -1607,6 +1622,7 @@ static const struct net_device_ops dsa_s
@@ -1642,6 +1657,7 @@ static const struct net_device_ops dsa_s
.ndo_vlan_rx_kill_vid = dsa_slave_vlan_rx_kill_vid,
.ndo_get_devlink_port = dsa_slave_get_devlink_port,
.ndo_change_mtu = dsa_slave_change_mtu,

View File

@ -17,7 +17,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1202,14 +1202,32 @@ static int dsa_slave_setup_tc_block(stru
@@ -1237,14 +1237,32 @@ static int dsa_slave_setup_tc_block(stru
}
}

View File

@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1644,6 +1644,9 @@ void phy_detach(struct phy_device *phyde
@@ -1642,6 +1642,9 @@ void phy_detach(struct phy_device *phyde
struct module *ndev_owner = NULL;
struct mii_bus *bus;

View File

@ -18,7 +18,7 @@ Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2144,10 +2144,12 @@ static int dsa_slave_switchdev_event(str
@@ -2189,10 +2189,12 @@ static int dsa_slave_switchdev_event(str
fdb_info = ptr;
if (dsa_slave_dev_check(dev)) {

View File

@ -15,7 +15,7 @@ Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2158,7 +2158,11 @@ static int dsa_slave_switchdev_event(str
@@ -2203,7 +2203,11 @@ static int dsa_slave_switchdev_event(str
struct net_device *br_dev;
struct dsa_slave_priv *p;

View File

@ -28,7 +28,7 @@ Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2151,9 +2151,12 @@ static int dsa_slave_switchdev_event(str
@@ -2196,9 +2196,12 @@ static int dsa_slave_switchdev_event(str
else if (!fdb_info->added_by_user)
return NOTIFY_OK;
} else {
@ -44,7 +44,7 @@ Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
*/
struct net_device *br_dev;
struct dsa_slave_priv *p;
@@ -2175,7 +2178,8 @@ static int dsa_slave_switchdev_event(str
@@ -2220,7 +2223,8 @@ static int dsa_slave_switchdev_event(str
dp = p->dp->cpu_dp;

View File

@ -75,12 +75,17 @@ define Device/bananapi_bpi-r64
DEVICE_DTS := mt7622-bananapi-bpi-r64
DEVICE_DTS_OVERLAY := mt7622-bananapi-bpi-r64-pcie1 mt7622-bananapi-bpi-r64-sata
DEVICE_PACKAGES := kmod-ata-ahci-mtk kmod-btmtkuart kmod-usb3 e2fsprogs mkf2fs f2fsck
ARTIFACTS := sdcard.img
ARTIFACTS := sdcard.img.gz
IMAGES := sysupgrade.itb
KERNEL_INITRAMFS_SUFFIX := -recovery.itb
ARTIFACT/sdcard.img := mt7622-gpt sdmmc | pad-to 128k | mt7622-gpt emmc | pad-to 256k |\
bl2 emmc-2ddr | pad-to 512k | bl2 sdmmc-2ddr | pad-to 1024k | bl31-uboot bananapi_bpi-r64-emmc | pad-to 2048k |\
bl31-uboot bananapi_bpi-r64-sdmmc | pad-to 6144k
ARTIFACT/sdcard.img.gz := mt7622-gpt sdmmc |\
pad-to 128k | mt7622-gpt emmc |\
pad-to 256k | bl2 emmc-2ddr |\
pad-to 512k | bl2 sdmmc-2ddr |\
pad-to 1024k | bl31-uboot bananapi_bpi-r64-emmc |\
pad-to 2048k | bl31-uboot bananapi_bpi-r64-sdmmc |\
pad-to 6144k | append-image initramfs-recovery.itb |\
pad-to 40960k | append-image squashfs-sysupgrade.itb | gzip
KERNEL := kernel-bin | gzip
KERNEL_INITRAMFS := kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb with-initrd | pad-to 128k
IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb external-static-with-rootfs | append-metadata

View File

@ -69,7 +69,7 @@
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <25000000>;
spi-max-frequency = <80000000>;
m25p,fast-read;
partitions {

View File

@ -33,7 +33,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
phy_led_trigger_change_speed(phydev);
}
@@ -616,7 +616,7 @@ int phy_start_cable_test(struct phy_devi
@@ -618,7 +618,7 @@ int phy_start_cable_test(struct phy_devi
goto out;
/* Mark the carrier down until the test is complete */
@ -42,7 +42,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
netif_testing_on(dev);
err = phydev->drv->cable_test_start(phydev);
@@ -687,7 +687,7 @@ int phy_start_cable_test_tdr(struct phy_
@@ -689,7 +689,7 @@ int phy_start_cable_test_tdr(struct phy_
goto out;
/* Mark the carrier down until the test is complete */
@ -51,7 +51,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
netif_testing_on(dev);
err = phydev->drv->cable_test_tdr_start(phydev, config);
@@ -758,7 +758,7 @@ static int phy_check_link_status(struct
@@ -760,7 +760,7 @@ static int phy_check_link_status(struct
phy_link_up(phydev);
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
phydev->state = PHY_NOLINK;
@ -60,7 +60,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
}
return 0;
@@ -1162,7 +1162,7 @@ void phy_state_machine(struct work_struc
@@ -1164,7 +1164,7 @@ void phy_state_machine(struct work_struc
case PHY_HALTED:
if (phydev->link) {
phydev->link = 0;
@ -71,7 +71,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
break;
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -937,14 +937,16 @@ struct phy_device *phy_find_first(struct
@@ -935,14 +935,16 @@ struct phy_device *phy_find_first(struct
}
EXPORT_SYMBOL(phy_find_first);

View File

@ -11,7 +11,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -758,7 +758,10 @@ static int phy_check_link_status(struct
@@ -760,7 +760,10 @@ static int phy_check_link_status(struct
phy_link_up(phydev);
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
phydev->state = PHY_NOLINK;
@ -23,7 +23,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
}
return 0;
@@ -1162,7 +1165,10 @@ void phy_state_machine(struct work_struc
@@ -1164,7 +1167,10 @@ void phy_state_machine(struct work_struc
case PHY_HALTED:
if (phydev->link) {
phydev->link = 0;

View File

@ -141,7 +141,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
{
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -713,6 +713,7 @@ static inline void devm_acpi_dev_remove_
@@ -715,6 +715,7 @@ static inline void devm_acpi_dev_remove_
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
@ -149,7 +149,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
@@ -720,6 +721,13 @@ void gpiod_unexport(struct gpio_desc *de
@@ -722,6 +723,13 @@ void gpiod_unexport(struct gpio_desc *de
#else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */

View File

@ -6,6 +6,8 @@ include $(INCLUDE_DIR)/image.mk
KERNEL_LOADADDR = 0x80000000
KERNEL_ENTRY = 0x80000400
DEVICE_VARS += ZYXEL_VERS
define Build/zyxel-vers
( echo VERS;\
for hw in $(1); do\

View File

@ -1,19 +0,0 @@
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -477,6 +477,16 @@ static const struct dmi_system_id reboot
},
},
+ /* PC Engines */
+ { /* Handle problems with rebooting on PC Engines apu2 */
+ .callback = set_pci_reboot,
+ .ident = "PC Engines apu2",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "PC Engines"),
+ DMI_MATCH(DMI_BOARD_NAME, "apu2"),
+ },
+ },
+
/* Sony */
{ /* Handle problems with rebooting on Sony VGN-Z540N */
.callback = set_bios_reboot,

View File

@ -1,19 +0,0 @@
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -486,6 +486,16 @@ static const struct dmi_system_id reboot
},
},
+ /* PC Engines */
+ { /* Handle problems with rebooting on PC Engines apu2 */
+ .callback = set_pci_reboot,
+ .ident = "PC Engines apu2",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "PC Engines"),
+ DMI_MATCH(DMI_BOARD_NAME, "apu2"),
+ },
+ },
+
/* Sony */
{ /* Handle problems with rebooting on Sony VGN-Z540N */
.callback = set_bios_reboot,

View File

@ -27,12 +27,26 @@
#error "Unsupported endianness"
#endif
#define WFI_VERSION 0x00005732
#define WFI_VERSION_NAND_1MB_DATA 0x00005731
#define WFI_NOR_FLASH 1
#define WFI_NAND16_FLASH 2
#define WFI_NAND128_FLASH 3
#define WFI_NAND256_FLASH 4
#define WFI_NAND512_FLASH 5
#define WFI_NAND1024_FLASH 6
#define WFI_NAND2048_FLASH 7
#define WFI_FLAG_HAS_PMC 0x1
#define WFI_FLAG_SUPPORTS_BTRM 0x2
struct bcm4908img_tail {
uint32_t crc32;
uint32_t unk1;
uint32_t family;
uint32_t unk2;
uint32_t unk3;
uint32_t version;
uint32_t chip_id;
uint32_t flash_type;
uint32_t flags;
};
char *pathname;
@ -272,10 +286,10 @@ static ssize_t bcm4908img_create_align(FILE *trx, size_t cur_offset, size_t alig
static int bcm4908img_create(int argc, char **argv) {
struct bcm4908img_tail tail = {
.unk1 = cpu_to_le32(0x5732),
.family = cpu_to_le32(0x4908),
.unk2 = cpu_to_le32(0x03),
.unk3 = cpu_to_le32(0x02),
.version = cpu_to_le32(WFI_VERSION),
.chip_id = cpu_to_le32(0x4908),
.flash_type = cpu_to_le32(WFI_NAND128_FLASH),
.flags = cpu_to_le32(WFI_FLAG_SUPPORTS_BTRM),
};
uint32_t crc32 = 0xffffffff;
size_t cur_offset = 0;

View File

@ -27,11 +27,11 @@
#endif
struct bcm4908kernel_header {
uint32_t unk1;
uint32_t unk2;
uint32_t length;
uint32_t boot_load_addr; /* AKA la_address */
uint32_t boot_addr; /* AKA la_entrypt */
uint32_t data_len;
uint8_t magic[4];
uint32_t unused;
uint32_t uncomplen; /* Empty for LZMA, used for LZ4 */
};
static void usage() {
@ -103,14 +103,14 @@ int main(int argc, char **argv) {
length += bytes;
}
header.unk1 = cpu_to_le32(0x00080000);
header.unk2 = cpu_to_le32(0x00080000);
header.length = cpu_to_le32(length);
header.boot_load_addr = cpu_to_le32(0x00080000);
header.boot_addr = cpu_to_le32(0x00080000);
header.data_len = cpu_to_le32(length);
header.magic[0] = 'B';
header.magic[1] = 'R';
header.magic[2] = 'C';
header.magic[3] = 'M';
header.unused = 0;
header.uncomplen = 0;
fseek(out, 0, SEEK_SET);