ath79: add 5.15 support for generic subtarget
Add Kernel 5.15 patches + config. This is currently only available for the generic subtarget, as it was exclusively tested with this target. Tested-on: Siemens WS-AP3610, Enterasys WS-AP3705i Signed-off-by: David Bauer <mail@david-bauer.net>
This commit is contained in:
		
							
								
								
									
										207
									
								
								target/linux/ath79/config-5.15
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								target/linux/ath79/config-5.15
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| CONFIG_AF_UNIX_OOB=y | ||||
| CONFIG_AG71XX=y | ||||
| # CONFIG_AG71XX_DEBUG is not set | ||||
| CONFIG_AG71XX_DEBUG_FS=y | ||||
| CONFIG_AR8216_PHY=y | ||||
| CONFIG_AR8216_PHY_LEDS=y | ||||
| CONFIG_ARCH_32BIT_OFF_T=y | ||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||
| CONFIG_ARCH_KEEP_MEMBLOCK=y | ||||
| CONFIG_ARCH_MMAP_RND_BITS_MAX=15 | ||||
| CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_AT803X_PHY=y | ||||
| CONFIG_ATH79=y | ||||
| CONFIG_ATH79_WDT=y | ||||
| CONFIG_BINARY_PRINTF=y | ||||
| CONFIG_BLK_MQ_PCI=y | ||||
| CONFIG_CEVT_R4K=y | ||||
| CONFIG_CLONE_BACKWARDS=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,jffs2" | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| # CONFIG_CMDLINE_OVERRIDE is not set | ||||
| CONFIG_COMMON_CLK=y | ||||
| # CONFIG_COMMON_CLK_BOSTON is not set | ||||
| CONFIG_COMPAT_32BIT_TIME=y | ||||
| CONFIG_CPU_BIG_ENDIAN=y | ||||
| CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||
| CONFIG_CPU_HAS_DIEI=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_RIXI=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| CONFIG_CPU_MIPS32=y | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||
| CONFIG_CPU_R4K_CACHE_TLB=y | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| CONFIG_DTC=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_FIXED_PHY=y | ||||
| CONFIG_FWNODE_MDIO=y | ||||
| CONFIG_FW_LOADER_PAGED_BUF=y | ||||
| CONFIG_GENERIC_ATOMIC64=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_CPU_AUTOPROBE=y | ||||
| CONFIG_GENERIC_FIND_FIRST_BIT=y | ||||
| CONFIG_GENERIC_GETTIMEOFDAY=y | ||||
| CONFIG_GENERIC_IOMAP=y | ||||
| CONFIG_GENERIC_IRQ_CHIP=y | ||||
| CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y | ||||
| CONFIG_GENERIC_IRQ_SHOW=y | ||||
| CONFIG_GENERIC_LIB_ASHLDI3=y | ||||
| CONFIG_GENERIC_LIB_ASHRDI3=y | ||||
| CONFIG_GENERIC_LIB_CMPDI2=y | ||||
| CONFIG_GENERIC_LIB_LSHRDI3=y | ||||
| CONFIG_GENERIC_LIB_UCMPDI2=y | ||||
| CONFIG_GENERIC_PCI_IOMAP=y | ||||
| CONFIG_GENERIC_PHY=y | ||||
| CONFIG_GENERIC_PINCONF=y | ||||
| CONFIG_GENERIC_PINCTRL_GROUPS=y | ||||
| CONFIG_GENERIC_PINMUX_FUNCTIONS=y | ||||
| CONFIG_GENERIC_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_TIME_VSYSCALL=y | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIOLIB_IRQCHIP=y | ||||
| CONFIG_GPIO_74X164=y | ||||
| CONFIG_GPIO_ATH79=y | ||||
| CONFIG_GPIO_CDEV=y | ||||
| CONFIG_GPIO_GENERIC=y | ||||
| # CONFIG_GPIO_LATCH is not set | ||||
| # CONFIG_GPIO_RB91X_KEY is not set | ||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT_MAP=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_IMAGE_CMDLINE_HACK=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_MIPS_CPU=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| CONFIG_LEDS_GPIO=y | ||||
| # CONFIG_LEDS_RESET is not set | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_LOCK_DEBUGGING_SUPPORT=y | ||||
| CONFIG_LTO_NONE=y | ||||
| CONFIG_MDIO_BITBANG=y | ||||
| CONFIG_MDIO_BUS=y | ||||
| CONFIG_MDIO_DEVICE=y | ||||
| CONFIG_MDIO_DEVRES=y | ||||
| CONFIG_MDIO_GPIO=y | ||||
| CONFIG_MEMFD_CREATE=y | ||||
| # CONFIG_MFD_RB4XX_CPLD is not set | ||||
| CONFIG_MFD_SYSCON=y | ||||
| CONFIG_MIGRATION=y | ||||
| CONFIG_MIPS=y | ||||
| CONFIG_MIPS_ASID_BITS=8 | ||||
| CONFIG_MIPS_ASID_SHIFT=0 | ||||
| CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||
| # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||
| CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||
| CONFIG_MIPS_EBPF_JIT=y | ||||
| # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||
| CONFIG_MIPS_LD_CAN_LINK_VDSO=y | ||||
| # CONFIG_MIPS_NO_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_RAW_APPENDED_DTB=y | ||||
| CONFIG_MIPS_SPRAM=y | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| CONFIG_MTD_CFI_ADV_OPTIONS=y | ||||
| CONFIG_MTD_CFI_GEOMETRY=y | ||||
| # CONFIG_MTD_CFI_I2 is not set | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| # CONFIG_MTD_MAP_BANK_WIDTH_1 is not set | ||||
| # CONFIG_MTD_MAP_BANK_WIDTH_4 is not set | ||||
| CONFIG_MTD_PARSER_CYBERTAN=y | ||||
| CONFIG_MTD_PHYSMAP=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPLIT_ELF_FW=y | ||||
| CONFIG_MTD_SPLIT_LZMA_FW=y | ||||
| CONFIG_MTD_SPLIT_SEAMA_FW=y | ||||
| CONFIG_MTD_SPLIT_TPLINK_FW=y | ||||
| CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||
| CONFIG_MTD_SPLIT_WRGG_FW=y | ||||
| CONFIG_MTD_VIRT_CONCAT=y | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NEED_PER_CPU_KM=y | ||||
| CONFIG_NET_SELFTESTS=y | ||||
| CONFIG_NET_SOCK_MSG=y | ||||
| CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||
| CONFIG_NVMEM=y | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_KOBJ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_AR71XX=y | ||||
| CONFIG_PCI_AR724X=y | ||||
| CONFIG_PCI_DISABLE_COMMON_QUIRKS=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
| CONFIG_PCI_DRIVERS_LEGACY=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| # CONFIG_PHY_AR7100_USB is not set | ||||
| # CONFIG_PHY_AR7200_USB is not set | ||||
| # CONFIG_PHY_ATH79_USB is not set | ||||
| CONFIG_PINCTRL=y | ||||
| # CONFIG_PINCTRL_PISTACHIO is not set | ||||
| CONFIG_PTP_1588_CLOCK_OPTIONAL=y | ||||
| CONFIG_RATIONAL=y | ||||
| CONFIG_REGMAP=y | ||||
| CONFIG_REGMAP_MMIO=y | ||||
| CONFIG_REGULATOR=y | ||||
| CONFIG_RESET_ATH79=y | ||||
| CONFIG_RESET_CONTROLLER=y | ||||
| CONFIG_SERIAL_8250_NR_UARTS=1 | ||||
| CONFIG_SERIAL_8250_RUNTIME_UARTS=1 | ||||
| CONFIG_SERIAL_AR933X=y | ||||
| CONFIG_SERIAL_AR933X_CONSOLE=y | ||||
| CONFIG_SERIAL_AR933X_NR_UARTS=2 | ||||
| CONFIG_SERIAL_MCTRL_GPIO=y | ||||
| CONFIG_SERIAL_OF_PLATFORM=y | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_AR934X=y | ||||
| CONFIG_SPI_ATH79=y | ||||
| CONFIG_SPI_BITBANG=y | ||||
| CONFIG_SPI_GPIO=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| CONFIG_SPI_MEM=y | ||||
| # CONFIG_SPI_RB4XX is not set | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWCONFIG_LEDS=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS16=y | ||||
| CONFIG_SYS_SUPPORTS_ZBOOT=y | ||||
| CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM=y | ||||
| CONFIG_TARGET_ISA_REV=2 | ||||
| CONFIG_TICK_CPU_ACCOUNTING=y | ||||
| CONFIG_TINY_SRCU=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| CONFIG_USE_OF=y | ||||
| @@ -2,6 +2,8 @@ BOARDNAME:=Generic | ||||
|  | ||||
| DEFAULT_PACKAGES += wpad-basic-wolfssl | ||||
|  | ||||
| KERNEL_TESTING_PATCHVER:=5.15 | ||||
|  | ||||
| define Target/Description | ||||
| 	Build firmware images for generic Atheros AR71xx/AR913x/AR934x based boards. | ||||
| endef | ||||
|   | ||||
| @@ -0,0 +1,186 @@ | ||||
| From ecbd9c87f073f097d9fe56390353e64e963e866a Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Tue, 6 Mar 2018 10:03:03 +0100 | ||||
| Subject: [PATCH 03/27] leds: add reset-controller based driver | ||||
|  | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  drivers/leds/Kconfig      |  11 ++++ | ||||
|  drivers/leds/Makefile     |   1 + | ||||
|  drivers/leds/leds-reset.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  3 files changed, 149 insertions(+) | ||||
|  create mode 100644 drivers/leds/leds-reset.c | ||||
|  | ||||
| --- a/drivers/leds/Kconfig | ||||
| +++ b/drivers/leds/Kconfig | ||||
| @@ -876,6 +876,17 @@ source "drivers/leds/blink/Kconfig" | ||||
|  comment "Flash and Torch LED drivers" | ||||
|  source "drivers/leds/flash/Kconfig" | ||||
|   | ||||
| +config LEDS_RESET | ||||
| +	tristate "LED support for reset-controller API" | ||||
| +	depends on LEDS_CLASS | ||||
| +	depends on RESET_CONTROLLER | ||||
| +	help | ||||
| +	  This option enables support for LEDs connected to pins driven by reset | ||||
| +	  controllers. Yes, DNI actual built HW like that. | ||||
| + | ||||
| +	  To compile this driver as a module, choose M here: the module | ||||
| +	  will be called leds-reset. | ||||
| + | ||||
|  comment "LED Triggers" | ||||
|  source "drivers/leds/trigger/Kconfig" | ||||
|   | ||||
| --- /dev/null | ||||
| +++ b/drivers/leds/leds-reset.c | ||||
| @@ -0,0 +1,140 @@ | ||||
| +/* | ||||
| + * Copyright (C) 2018 John Crispin <john@phrozen.org> | ||||
| + * | ||||
| + * This program is free software; you can redistribute it and/or modify | ||||
| + * it under the terms of the GNU General Public License version 2 as | ||||
| + * published by the Free Software Foundation. | ||||
| + * | ||||
| + */ | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/reset.h> | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/leds.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/of.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/reset.h> | ||||
| + | ||||
| +struct reset_led_data { | ||||
| +	struct led_classdev cdev; | ||||
| +	struct reset_control *rst; | ||||
| +}; | ||||
| + | ||||
| +static inline struct reset_led_data * | ||||
| +			cdev_to_reset_led_data(struct led_classdev *led_cdev) | ||||
| +{ | ||||
| +	return container_of(led_cdev, struct reset_led_data, cdev); | ||||
| +} | ||||
| + | ||||
| +static void reset_led_set(struct led_classdev *led_cdev, | ||||
| +	enum led_brightness value) | ||||
| +{ | ||||
| +	struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); | ||||
| + | ||||
| +	if (value == LED_OFF) | ||||
| +		reset_control_assert(led_dat->rst); | ||||
| +	else | ||||
| +		reset_control_deassert(led_dat->rst); | ||||
| +} | ||||
| + | ||||
| +struct reset_leds_priv { | ||||
| +	int num_leds; | ||||
| +	struct reset_led_data leds[]; | ||||
| +}; | ||||
| + | ||||
| +static inline int sizeof_reset_leds_priv(int num_leds) | ||||
| +{ | ||||
| +	return sizeof(struct reset_leds_priv) + | ||||
| +		(sizeof(struct reset_led_data) * num_leds); | ||||
| +} | ||||
| + | ||||
| +static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct device *dev = &pdev->dev; | ||||
| +	struct fwnode_handle *child; | ||||
| +	struct reset_leds_priv *priv; | ||||
| +	int count, ret; | ||||
| + | ||||
| +	count = device_get_child_node_count(dev); | ||||
| +	if (!count) | ||||
| +		return ERR_PTR(-ENODEV); | ||||
| + | ||||
| +	priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); | ||||
| +	if (!priv) | ||||
| +		return ERR_PTR(-ENOMEM); | ||||
| + | ||||
| +	device_for_each_child_node(dev, child) { | ||||
| +		struct reset_led_data *led = &priv->leds[priv->num_leds]; | ||||
| +		struct device_node *np = to_of_node(child); | ||||
| + | ||||
| +		ret = fwnode_property_read_string(child, "label", &led->cdev.name); | ||||
| +		if (!led->cdev.name) { | ||||
| +			fwnode_handle_put(child); | ||||
| +			return ERR_PTR(-EINVAL); | ||||
| +		} | ||||
| +		led->rst = __of_reset_control_get(np, NULL, 0, 0, 0, true); | ||||
| +		if (IS_ERR(led->rst)) | ||||
| +			return ERR_PTR(-EINVAL); | ||||
| + | ||||
| +		fwnode_property_read_string(child, "linux,default-trigger", | ||||
| +						&led->cdev.default_trigger); | ||||
| + | ||||
| +		led->cdev.brightness_set = reset_led_set; | ||||
| +		ret = devm_led_classdev_register(&pdev->dev, &led->cdev); | ||||
| +		if (ret < 0) | ||||
| +			return ERR_PTR(ret); | ||||
| +		led->cdev.dev->of_node = np; | ||||
| +		priv->num_leds++; | ||||
| +	} | ||||
| + | ||||
| +	return priv; | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id of_reset_leds_match[] = { | ||||
| +	{ .compatible = "reset-leds", }, | ||||
| +	{}, | ||||
| +}; | ||||
| + | ||||
| +MODULE_DEVICE_TABLE(of, of_reset_leds_match); | ||||
| + | ||||
| +static int reset_led_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct reset_leds_priv *priv; | ||||
| + | ||||
| +	priv = reset_leds_create(pdev); | ||||
| +	if (IS_ERR(priv)) | ||||
| +		return PTR_ERR(priv); | ||||
| + | ||||
| +	platform_set_drvdata(pdev, priv); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static void reset_led_shutdown(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct reset_leds_priv *priv = platform_get_drvdata(pdev); | ||||
| +	int i; | ||||
| + | ||||
| +	for (i = 0; i < priv->num_leds; i++) { | ||||
| +		struct reset_led_data *led = &priv->leds[i]; | ||||
| + | ||||
| +		if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) | ||||
| +			reset_led_set(&led->cdev, LED_OFF); | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static struct platform_driver reset_led_driver = { | ||||
| +	.probe		= reset_led_probe, | ||||
| +	.shutdown	= reset_led_shutdown, | ||||
| +	.driver		= { | ||||
| +		.name	= "leds-reset", | ||||
| +		.of_match_table = of_reset_leds_match, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +module_platform_driver(reset_led_driver); | ||||
| + | ||||
| +MODULE_AUTHOR("John Crispin <john@phrozen.org>"); | ||||
| +MODULE_DESCRIPTION("reset controller LED driver"); | ||||
| +MODULE_LICENSE("GPL"); | ||||
| +MODULE_ALIAS("platform:leds-reset"); | ||||
| --- a/drivers/leds/Makefile | ||||
| +++ b/drivers/leds/Makefile | ||||
| @@ -87,6 +87,7 @@ obj-$(CONFIG_LEDS_TURRIS_OMNIA)		+= leds | ||||
|  obj-$(CONFIG_LEDS_WM831X_STATUS)	+= leds-wm831x-status.o | ||||
|  obj-$(CONFIG_LEDS_WM8350)		+= leds-wm8350.o | ||||
|  obj-$(CONFIG_LEDS_WRAP)			+= leds-wrap.o | ||||
| +obj-$(CONFIG_LEDS_RESET)		+= leds-reset.o | ||||
|   | ||||
|  # LED SPI Drivers | ||||
|  obj-$(CONFIG_LEDS_CR0014114)		+= leds-cr0014114.o | ||||
| @@ -0,0 +1,333 @@ | ||||
| From 08c9d6ceef01893678a5d2e8a15517c745417f21 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Tue, 6 Mar 2018 10:04:05 +0100 | ||||
| Subject: [PATCH 04/27] phy: add ath79 usb phys | ||||
|  | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  drivers/phy/Kconfig          |  16 ++++++ | ||||
|  drivers/phy/Makefile         |   2 + | ||||
|  drivers/phy/phy-ar7100-usb.c | 124 +++++++++++++++++++++++++++++++++++++++++++ | ||||
|  drivers/phy/phy-ar7200-usb.c | 108 +++++++++++++++++++++++++++++++++++++ | ||||
|  4 files changed, 250 insertions(+) | ||||
|  create mode 100644 drivers/phy/phy-ar7100-usb.c | ||||
|  create mode 100644 drivers/phy/phy-ar7200-usb.c | ||||
|  | ||||
| --- a/drivers/phy/Kconfig | ||||
| +++ b/drivers/phy/Kconfig | ||||
| @@ -24,6 +24,22 @@ config GENERIC_PHY_MIPI_DPHY | ||||
|  	  Provides a number of helpers a core functions for MIPI D-PHY | ||||
|  	  drivers to us. | ||||
|   | ||||
| +config PHY_AR7100_USB | ||||
| +	tristate "Atheros AR7100 USB PHY driver" | ||||
| +	depends on ATH79 || COMPILE_TEST | ||||
| +	default y if USB_EHCI_HCD_PLATFORM | ||||
| +	select GENERIC_PHY | ||||
| +	help | ||||
| +	  Enable this to support the USB PHY on Atheros AR7100 SoCs. | ||||
| + | ||||
| +config PHY_AR7200_USB | ||||
| +	tristate "Atheros AR7200 USB PHY driver" | ||||
| +	depends on ATH79 || COMPILE_TEST | ||||
| +	default y if USB_EHCI_HCD_PLATFORM | ||||
| +	select GENERIC_PHY | ||||
| +	help | ||||
| +	  Enable this to support the USB PHY on Atheros AR7200 SoCs. | ||||
| + | ||||
|  config PHY_LPC18XX_USB_OTG | ||||
|  	tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" | ||||
|  	depends on OF && (ARCH_LPC18XX || COMPILE_TEST) | ||||
| --- a/drivers/phy/Makefile | ||||
| +++ b/drivers/phy/Makefile | ||||
| @@ -4,6 +4,8 @@ | ||||
|  # | ||||
|   | ||||
|  obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o | ||||
| +obj-$(CONFIG_PHY_AR7100_USB)		+= phy-ar7100-usb.o | ||||
| +obj-$(CONFIG_PHY_AR7200_USB)		+= phy-ar7200-usb.o | ||||
|  obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY)	+= phy-core-mipi-dphy.o | ||||
|  obj-$(CONFIG_PHY_CAN_TRANSCEIVER)	+= phy-can-transceiver.o | ||||
|  obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/phy/phy-ar7100-usb.c | ||||
| @@ -0,0 +1,140 @@ | ||||
| +/* | ||||
| + * Copyright (C) 2018 John Crispin <john@phrozen.org> | ||||
| + * | ||||
| + * This program is free software; you can redistribute it and/or modify | ||||
| + * it under the terms of the GNU General Public License as published by | ||||
| + * the Free Software Foundation; either version 2 of the License, or | ||||
| + * (at your option) any later version. | ||||
| + */ | ||||
| + | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/phy/phy.h> | ||||
| +#include <linux/delay.h> | ||||
| +#include <linux/reset.h> | ||||
| +#include <linux/of_gpio.h> | ||||
| + | ||||
| +#include <asm/mach-ath79/ath79.h> | ||||
| +#include <asm/mach-ath79/ar71xx_regs.h> | ||||
| + | ||||
| +struct ar7100_usb_phy { | ||||
| +	struct reset_control	*rst_phy; | ||||
| +	struct reset_control	*rst_host; | ||||
| +	struct reset_control	*rst_ohci_dll; | ||||
| +	void __iomem		*io_base; | ||||
| +	struct phy		*phy; | ||||
| +	int			gpio; | ||||
| +}; | ||||
| + | ||||
| +static int ar7100_usb_phy_power_off(struct phy *phy) | ||||
| +{ | ||||
| +	struct ar7100_usb_phy *priv = phy_get_drvdata(phy); | ||||
| +	int err = 0; | ||||
| + | ||||
| +	err |= reset_control_assert(priv->rst_host); | ||||
| +	err |= reset_control_assert(priv->rst_phy); | ||||
| +	err |= reset_control_assert(priv->rst_ohci_dll); | ||||
| + | ||||
| +	return err; | ||||
| +} | ||||
| + | ||||
| +static int ar7100_usb_phy_power_on(struct phy *phy) | ||||
| +{ | ||||
| +	struct ar7100_usb_phy *priv = phy_get_drvdata(phy); | ||||
| +	int err = 0; | ||||
| + | ||||
| +	err |= ar7100_usb_phy_power_off(phy); | ||||
| +	mdelay(100); | ||||
| +	err |= reset_control_deassert(priv->rst_ohci_dll); | ||||
| +	err |= reset_control_deassert(priv->rst_phy); | ||||
| +	err |= reset_control_deassert(priv->rst_host); | ||||
| +	mdelay(500); | ||||
| +	iowrite32(0xf0000, priv->io_base + AR71XX_USB_CTRL_REG_CONFIG); | ||||
| +	iowrite32(0x20c00, priv->io_base + AR71XX_USB_CTRL_REG_FLADJ); | ||||
| + | ||||
| +	return err; | ||||
| +} | ||||
| + | ||||
| +static const struct phy_ops ar7100_usb_phy_ops = { | ||||
| +	.power_on	= ar7100_usb_phy_power_on, | ||||
| +	.power_off	= ar7100_usb_phy_power_off, | ||||
| +	.owner		= THIS_MODULE, | ||||
| +}; | ||||
| + | ||||
| +static int ar7100_usb_phy_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct phy_provider *phy_provider; | ||||
| +	struct resource *res; | ||||
| +	struct ar7100_usb_phy *priv; | ||||
| + | ||||
| +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||||
| +	if (!priv) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| +	priv->io_base = devm_ioremap_resource(&pdev->dev, res); | ||||
| +	if (IS_ERR(priv->io_base)) | ||||
| +		return PTR_ERR(priv->io_base); | ||||
| + | ||||
| +	priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy"); | ||||
| +	if (IS_ERR(priv->rst_phy)) { | ||||
| +		dev_err(&pdev->dev, "phy reset is missing\n"); | ||||
| +		return PTR_ERR(priv->rst_phy); | ||||
| +	} | ||||
| + | ||||
| +	priv->rst_host = devm_reset_control_get(&pdev->dev, "usb-host"); | ||||
| +	if (IS_ERR(priv->rst_host)) { | ||||
| +		dev_err(&pdev->dev, "host reset is missing\n"); | ||||
| +		return PTR_ERR(priv->rst_host); | ||||
| +	} | ||||
| + | ||||
| +	priv->rst_ohci_dll = devm_reset_control_get(&pdev->dev, "usb-ohci-dll"); | ||||
| +	if (IS_ERR(priv->rst_ohci_dll)) { | ||||
| +		dev_err(&pdev->dev, "ohci-dll reset is missing\n"); | ||||
| +		return PTR_ERR(priv->rst_host); | ||||
| +	} | ||||
| + | ||||
| +	priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7100_usb_phy_ops); | ||||
| +	if (IS_ERR(priv->phy)) { | ||||
| +		dev_err(&pdev->dev, "failed to create PHY\n"); | ||||
| +		return PTR_ERR(priv->phy); | ||||
| +	} | ||||
| + | ||||
| +	priv->gpio = of_get_gpio(pdev->dev.of_node, 0); | ||||
| +	if (priv->gpio >= 0) { | ||||
| +		int ret = devm_gpio_request(&pdev->dev, priv->gpio, dev_name(&pdev->dev)); | ||||
| + | ||||
| +		if (ret) { | ||||
| +			dev_err(&pdev->dev, "failed to request gpio\n"); | ||||
| +			return ret; | ||||
| +		} | ||||
| +		gpio_export_with_name(priv->gpio, 0, dev_name(&pdev->dev)); | ||||
| +		gpio_set_value(priv->gpio, 1); | ||||
| +	} | ||||
| + | ||||
| +	phy_set_drvdata(priv->phy, priv); | ||||
| + | ||||
| +	phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); | ||||
| + | ||||
| + | ||||
| +	return PTR_ERR_OR_ZERO(phy_provider); | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id ar7100_usb_phy_of_match[] = { | ||||
| +	{ .compatible = "qca,ar7100-usb-phy" }, | ||||
| +	{} | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, ar7100_usb_phy_of_match); | ||||
| + | ||||
| +static struct platform_driver ar7100_usb_phy_driver = { | ||||
| +	.probe	= ar7100_usb_phy_probe, | ||||
| +	.driver = { | ||||
| +		.of_match_table	= ar7100_usb_phy_of_match, | ||||
| +		.name		= "ar7100-usb-phy", | ||||
| +	} | ||||
| +}; | ||||
| +module_platform_driver(ar7100_usb_phy_driver); | ||||
| + | ||||
| +MODULE_DESCRIPTION("ATH79 USB PHY driver"); | ||||
| +MODULE_AUTHOR("Alban Bedel <albeu@free.fr>"); | ||||
| +MODULE_LICENSE("GPL"); | ||||
| --- /dev/null | ||||
| +++ b/drivers/phy/phy-ar7200-usb.c | ||||
| @@ -0,0 +1,136 @@ | ||||
| +/* | ||||
| + * Copyright (C) 2015 Alban Bedel <albeu@free.fr> | ||||
| + * | ||||
| + * This program is free software; you can redistribute it and/or modify | ||||
| + * it under the terms of the GNU General Public License as published by | ||||
| + * the Free Software Foundation; either version 2 of the License, or | ||||
| + * (at your option) any later version. | ||||
| + */ | ||||
| + | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/phy/phy.h> | ||||
| +#include <linux/reset.h> | ||||
| +#include <linux/of_gpio.h> | ||||
| + | ||||
| +struct ar7200_usb_phy { | ||||
| +	struct reset_control	*rst_phy; | ||||
| +	struct reset_control	*rst_phy_analog; | ||||
| +	struct reset_control	*suspend_override; | ||||
| +	struct phy		*phy; | ||||
| +	int			gpio; | ||||
| +}; | ||||
| + | ||||
| +static int ar7200_usb_phy_power_on(struct phy *phy) | ||||
| +{ | ||||
| +	struct ar7200_usb_phy *priv = phy_get_drvdata(phy); | ||||
| +	int err = 0; | ||||
| + | ||||
| +	if (priv->suspend_override) | ||||
| +		err = reset_control_assert(priv->suspend_override); | ||||
| +	if (priv->rst_phy) | ||||
| +		err |= reset_control_deassert(priv->rst_phy); | ||||
| +	if (priv->rst_phy_analog) | ||||
| +		err |= reset_control_deassert(priv->rst_phy_analog); | ||||
| + | ||||
| +	return err; | ||||
| +} | ||||
| + | ||||
| +static int ar7200_usb_phy_power_off(struct phy *phy) | ||||
| +{ | ||||
| +	struct ar7200_usb_phy *priv = phy_get_drvdata(phy); | ||||
| +	int err = 0; | ||||
| + | ||||
| +	if (priv->suspend_override) | ||||
| +		err = reset_control_deassert(priv->suspend_override); | ||||
| +	if (priv->rst_phy) | ||||
| +		err |= reset_control_assert(priv->rst_phy); | ||||
| +	if (priv->rst_phy_analog) | ||||
| +		err |= reset_control_assert(priv->rst_phy_analog); | ||||
| + | ||||
| +	return err; | ||||
| +} | ||||
| + | ||||
| +static const struct phy_ops ar7200_usb_phy_ops = { | ||||
| +	.power_on	= ar7200_usb_phy_power_on, | ||||
| +	.power_off	= ar7200_usb_phy_power_off, | ||||
| +	.owner		= THIS_MODULE, | ||||
| +}; | ||||
| + | ||||
| +static int ar7200_usb_phy_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct phy_provider *phy_provider; | ||||
| +	struct ar7200_usb_phy *priv; | ||||
| + | ||||
| +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||||
| +	if (!priv) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy"); | ||||
| +	if (IS_ERR(priv->rst_phy)) { | ||||
| +		if (PTR_ERR(priv->rst_phy) != -EPROBE_DEFER) | ||||
| +			dev_err(&pdev->dev, "phy reset is missing\n"); | ||||
| +		return PTR_ERR(priv->rst_phy); | ||||
| +	} | ||||
| + | ||||
| +	priv->rst_phy_analog = devm_reset_control_get_optional( | ||||
| +		&pdev->dev, "usb-phy-analog"); | ||||
| +	if (IS_ERR(priv->rst_phy_analog)) { | ||||
| +		if (PTR_ERR(priv->rst_phy_analog) == -ENOENT) | ||||
| +			priv->rst_phy_analog = NULL; | ||||
| +		else | ||||
| +			return PTR_ERR(priv->rst_phy_analog); | ||||
| +	} | ||||
| + | ||||
| +	priv->suspend_override = devm_reset_control_get_optional( | ||||
| +		&pdev->dev, "usb-suspend-override"); | ||||
| +	if (IS_ERR(priv->suspend_override)) { | ||||
| +		if (PTR_ERR(priv->suspend_override) == -ENOENT) | ||||
| +			priv->suspend_override = NULL; | ||||
| +		else | ||||
| +			return PTR_ERR(priv->suspend_override); | ||||
| +	} | ||||
| + | ||||
| +	priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7200_usb_phy_ops); | ||||
| +	if (IS_ERR(priv->phy)) { | ||||
| +		dev_err(&pdev->dev, "failed to create PHY\n"); | ||||
| +		return PTR_ERR(priv->phy); | ||||
| +	} | ||||
| + | ||||
| +	priv->gpio = of_get_gpio(pdev->dev.of_node, 0); | ||||
| +	if (priv->gpio >= 0) { | ||||
| +		int ret = devm_gpio_request(&pdev->dev, priv->gpio, dev_name(&pdev->dev)); | ||||
| + | ||||
| +		if (ret) { | ||||
| +			dev_err(&pdev->dev, "failed to request gpio\n"); | ||||
| +			return ret; | ||||
| +		} | ||||
| +		gpio_export_with_name(priv->gpio, 0, dev_name(&pdev->dev)); | ||||
| +		gpio_set_value(priv->gpio, 1); | ||||
| +	} | ||||
| + | ||||
| +	phy_set_drvdata(priv->phy, priv); | ||||
| + | ||||
| +	phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); | ||||
| + | ||||
| +	return PTR_ERR_OR_ZERO(phy_provider); | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id ar7200_usb_phy_of_match[] = { | ||||
| +	{ .compatible = "qca,ar7200-usb-phy" }, | ||||
| +	{} | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, ar7200_usb_phy_of_match); | ||||
| + | ||||
| +static struct platform_driver ar7200_usb_phy_driver = { | ||||
| +	.probe	= ar7200_usb_phy_probe, | ||||
| +	.driver = { | ||||
| +		.of_match_table	= ar7200_usb_phy_of_match, | ||||
| +		.name		= "ar7200-usb-phy", | ||||
| +	} | ||||
| +}; | ||||
| +module_platform_driver(ar7200_usb_phy_driver); | ||||
| + | ||||
| +MODULE_DESCRIPTION("ATH79 USB PHY driver"); | ||||
| +MODULE_AUTHOR("Alban Bedel <albeu@free.fr>"); | ||||
| +MODULE_LICENSE("GPL"); | ||||
| @@ -0,0 +1,24 @@ | ||||
| From 2201818e5bd33f389beceb3943fdfcf5a698fc5b Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Tue, 6 Mar 2018 10:01:43 +0100 | ||||
| Subject: [PATCH 05/27] usb: add more OF/quirk properties | ||||
|  | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  drivers/usb/host/ehci-platform.c | 5 +++++ | ||||
|  1 file changed, 5 insertions(+) | ||||
|  | ||||
| --- a/drivers/usb/host/ehci-platform.c | ||||
| +++ b/drivers/usb/host/ehci-platform.c | ||||
| @@ -277,6 +277,11 @@ static int ehci_platform_probe(struct pl | ||||
|  	ehci = hcd_to_ehci(hcd); | ||||
|   | ||||
|  	if (pdata == &ehci_platform_defaults && dev->dev.of_node) { | ||||
| +		of_property_read_u32(dev->dev.of_node, "caps-offset", &pdata->caps_offset); | ||||
| + | ||||
| +		if (of_property_read_bool(dev->dev.of_node, "has-synopsys-hc-bug")) | ||||
| +			pdata->has_synopsys_hc_bug = 1; | ||||
| + | ||||
|  		if (of_property_read_bool(dev->dev.of_node, "big-endian-regs")) | ||||
|  			ehci->big_endian_mmio = 1; | ||||
|   | ||||
| @@ -0,0 +1,168 @@ | ||||
| From f3eacff2310a60348a755c50a8da6fc251fc8587 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Tue, 6 Mar 2018 09:55:13 +0100 | ||||
| Subject: [PATCH 07/33] irqchip/irq-ath79-intc: add irq cascade driver for | ||||
|  QCA9556 SoCs | ||||
|  | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  drivers/irqchip/Makefile         |   1 + | ||||
|  drivers/irqchip/irq-ath79-intc.c | 142 +++++++++++++++++++++++++++++++++++++++ | ||||
|  2 files changed, 143 insertions(+) | ||||
|  create mode 100644 drivers/irqchip/irq-ath79-intc.c | ||||
|  | ||||
| --- a/drivers/irqchip/Makefile | ||||
| +++ b/drivers/irqchip/Makefile | ||||
| @@ -4,6 +4,7 @@ obj-$(CONFIG_IRQCHIP)			+= irqchip.o | ||||
|  obj-$(CONFIG_AL_FIC)			+= irq-al-fic.o | ||||
|  obj-$(CONFIG_ALPINE_MSI)		+= irq-alpine-msi.o | ||||
|  obj-$(CONFIG_ATH79)			+= irq-ath79-cpu.o | ||||
| +obj-$(CONFIG_ATH79)			+= irq-ath79-intc.o | ||||
|  obj-$(CONFIG_ATH79)			+= irq-ath79-misc.o | ||||
|  obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o | ||||
|  obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2836.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/irqchip/irq-ath79-intc.c | ||||
| @@ -0,0 +1,142 @@ | ||||
| +/* | ||||
| + *  Atheros AR71xx/AR724x/AR913x specific interrupt handling | ||||
| + * | ||||
| + *  Copyright (C) 2018 John Crispin <john@phrozen.org> | ||||
| + * | ||||
| + *  This program is free software; you can redistribute it and/or modify it | ||||
| + *  under the terms of the GNU General Public License version 2 as published | ||||
| + *  by the Free Software Foundation. | ||||
| + */ | ||||
| + | ||||
| +#include <linux/interrupt.h> | ||||
| +#include <linux/irqchip.h> | ||||
| +#include <linux/of.h> | ||||
| +#include <linux/of_irq.h> | ||||
| +#include <linux/irqdomain.h> | ||||
| + | ||||
| +#include <asm/irq_cpu.h> | ||||
| +#include <asm/mach-ath79/ath79.h> | ||||
| +#include <asm/mach-ath79/ar71xx_regs.h> | ||||
| + | ||||
| +#define ATH79_MAX_INTC_CASCADE	3 | ||||
| + | ||||
| +struct ath79_intc { | ||||
| +	struct irq_chip chip; | ||||
| +	u32 irq; | ||||
| +	u32 pending_mask; | ||||
| +	u32 int_status; | ||||
| +	u32 irq_mask[ATH79_MAX_INTC_CASCADE]; | ||||
| +	u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; | ||||
| +}; | ||||
| + | ||||
| +static void ath79_intc_irq_handler(struct irq_desc *desc) | ||||
| +{ | ||||
| +	struct irq_domain *domain = irq_desc_get_handler_data(desc); | ||||
| +	struct ath79_intc *intc = domain->host_data; | ||||
| +	u32 pending; | ||||
| + | ||||
| +	pending = ath79_reset_rr(intc->int_status); | ||||
| +	pending &= intc->pending_mask; | ||||
| + | ||||
| +	if (pending) { | ||||
| +		int i; | ||||
| + | ||||
| +		for (i = 0; i < domain->hwirq_max; i++) | ||||
| +			if (pending & intc->irq_mask[i]) { | ||||
| +				if (intc->irq_wb_chan[i] != 0xffffffff) | ||||
| +					ath79_ddr_wb_flush(intc->irq_wb_chan[i]); | ||||
| +				generic_handle_irq(irq_find_mapping(domain, i)); | ||||
| +			} | ||||
| +	} else { | ||||
| +		spurious_interrupt(); | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static void ath79_intc_irq_enable(struct irq_data *d) | ||||
| +{ | ||||
| +	struct ath79_intc *intc = d->domain->host_data; | ||||
| +	enable_irq(intc->irq); | ||||
| +} | ||||
| + | ||||
| +static void ath79_intc_irq_disable(struct irq_data *d) | ||||
| +{ | ||||
| +	struct ath79_intc *intc = d->domain->host_data; | ||||
| +	disable_irq(intc->irq); | ||||
| +} | ||||
| + | ||||
| +static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | ||||
| +{ | ||||
| +	struct ath79_intc *intc = d->host_data; | ||||
| + | ||||
| +	irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct irq_domain_ops ath79_irq_domain_ops = { | ||||
| +	.xlate = irq_domain_xlate_onecell, | ||||
| +	.map = ath79_intc_map, | ||||
| +}; | ||||
| + | ||||
| +static int __init ath79_intc_of_init( | ||||
| +	struct device_node *node, struct device_node *parent) | ||||
| +{ | ||||
| +	struct irq_domain *domain; | ||||
| +	struct ath79_intc *intc; | ||||
| +	int cnt, cntwb, i, err; | ||||
| + | ||||
| +	cnt = of_property_count_u32_elems(node, "qca,pending-bits"); | ||||
| +	if (cnt > ATH79_MAX_INTC_CASCADE) | ||||
| +		panic("Too many INTC pending bits\n"); | ||||
| + | ||||
| +	intc = kzalloc(sizeof(*intc), GFP_KERNEL); | ||||
| +	if (!intc) | ||||
| +		panic("Failed to allocate INTC memory\n"); | ||||
| +	intc->chip = dummy_irq_chip; | ||||
| +	intc->chip.name = "INTC"; | ||||
| +	intc->chip.irq_disable = ath79_intc_irq_disable; | ||||
| +	intc->chip.irq_enable = ath79_intc_irq_enable; | ||||
| + | ||||
| +	if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { | ||||
| +		panic("Missing address of interrupt status register\n"); | ||||
| +	} | ||||
| + | ||||
| +	of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); | ||||
| +	for (i = 0; i < cnt; i++) { | ||||
| +		intc->pending_mask |= intc->irq_mask[i]; | ||||
| +		intc->irq_wb_chan[i] = 0xffffffff; | ||||
| +	} | ||||
| + | ||||
| +	cntwb = of_count_phandle_with_args( | ||||
| +		node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); | ||||
| + | ||||
| +	for (i = 0; i < cntwb; i++) { | ||||
| +		struct of_phandle_args args; | ||||
| +		u32 irq = i; | ||||
| + | ||||
| +		of_property_read_u32_index( | ||||
| +			node, "qca,ddr-wb-channel-interrupts", i, &irq); | ||||
| +		if (irq >= ATH79_MAX_INTC_CASCADE) | ||||
| +			continue; | ||||
| + | ||||
| +		err = of_parse_phandle_with_args( | ||||
| +			node, "qca,ddr-wb-channels", | ||||
| +			"#qca,ddr-wb-channel-cells", | ||||
| +			i, &args); | ||||
| +		if (err) | ||||
| +			return err; | ||||
| + | ||||
| +		intc->irq_wb_chan[irq] = args.args[0]; | ||||
| +	} | ||||
| + | ||||
| +	intc->irq = irq_of_parse_and_map(node, 0); | ||||
| +	if (!intc->irq) | ||||
| +		panic("Failed to get INTC IRQ"); | ||||
| + | ||||
| +	domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); | ||||
| +	irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| +IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", | ||||
| +		ath79_intc_of_init); | ||||
| @@ -0,0 +1,23 @@ | ||||
| From e029f998594f151008ecbfa024e2957edd2a5189 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Tue, 6 Mar 2018 09:58:19 +0100 | ||||
| Subject: [PATCH 08/33] irqchip/irq-ath79-cpu: drop !OF init helper | ||||
|  | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  drivers/irqchip/irq-ath79-cpu.c | 7 ------- | ||||
|  1 file changed, 7 deletions(-) | ||||
|  | ||||
| --- a/drivers/irqchip/irq-ath79-cpu.c | ||||
| +++ b/drivers/irqchip/irq-ath79-cpu.c | ||||
| @@ -85,10 +85,3 @@ static int __init ar79_cpu_intc_of_init( | ||||
|  } | ||||
|  IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", | ||||
|  		ar79_cpu_intc_of_init); | ||||
| - | ||||
| -void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3) | ||||
| -{ | ||||
| -	irq_wb_chan[2] = irq_wb_chan2; | ||||
| -	irq_wb_chan[3] = irq_wb_chan3; | ||||
| -	mips_cpu_irq_init(); | ||||
| -} | ||||
| @@ -0,0 +1,57 @@ | ||||
| From 4a4f869ec58ed8910b9b2e68d0eee50957e9bb20 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Mon, 25 Jun 2018 15:52:10 +0200 | ||||
| Subject: [PATCH 17/33] dt-bindings: PCI: qcom,ar7100: adds binding doc | ||||
|  | ||||
| With the driver being converted from platform_data to pure OF, we need to | ||||
| also add some docs. | ||||
|  | ||||
| Cc: Rob Herring <robh+dt@kernel.org> | ||||
| Cc: devicetree@vger.kernel.org | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  .../devicetree/bindings/pci/qcom,ar7100-pci.txt    | 38 ++++++++++++++++++++++ | ||||
|  1 file changed, 38 insertions(+) | ||||
|  create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt | ||||
| @@ -0,0 +1,38 @@ | ||||
| +* Qualcomm Atheros AR7100 PCI express root complex | ||||
| + | ||||
| +Required properties: | ||||
| +- compatible: should contain "qcom,ar7100-pci" to identify the core. | ||||
| +- reg: Should contain the register ranges as listed in the reg-names property. | ||||
| +- reg-names: Definition: Must include the following entries | ||||
| +	- "cfg_base"	IO Memory | ||||
| +- #address-cells: set to <3> | ||||
| +- #size-cells: set to <2> | ||||
| +- ranges: ranges for the PCI memory and I/O regions | ||||
| +- interrupt-map-mask and interrupt-map: standard PCI | ||||
| +	properties to define the mapping of the PCIe interface to interrupt | ||||
| +	numbers. | ||||
| +- #interrupt-cells: set to <1> | ||||
| +- interrupt-controller: define to enable the builtin IRQ cascade. | ||||
| + | ||||
| +Optional properties: | ||||
| +- interrupt-parent: phandle to the MIPS IRQ controller | ||||
| + | ||||
| +* Example for ar7100 | ||||
| +	pcie-controller@180c0000 { | ||||
| +		compatible = "qca,ar7100-pci"; | ||||
| +		#address-cells = <3>; | ||||
| +		#size-cells = <2>; | ||||
| +		bus-range = <0x0 0x0>; | ||||
| +		reg = <0x17010000 0x100>; | ||||
| +		reg-names = "cfg_base"; | ||||
| +		ranges = <0x2000000 0 0x10000000 0x10000000 0 0x07000000 | ||||
| +			  0x1000000 0 0x00000000 0x00000000 0 0x00000001>; | ||||
| +		interrupt-parent = <&cpuintc>; | ||||
| +		interrupts = <2>; | ||||
| + | ||||
| +		interrupt-controller; | ||||
| +		#interrupt-cells = <1>; | ||||
| + | ||||
| +		interrupt-map-mask = <0 0 0 1>; | ||||
| +		interrupt-map = <0 0 0 0 &pcie0 0>; | ||||
| +	}; | ||||
| @@ -0,0 +1,202 @@ | ||||
| From 1855ab6b1d27f5b38a648baf57ff6a534afec26d Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Sat, 23 Jun 2018 15:07:23 +0200 | ||||
| Subject: [PATCH 18/33] MIPS: pci-ar71xx: convert to OF | ||||
|  | ||||
| With the ath79 target getting converted to pure OF, we can drop all the | ||||
| platform data code and add the missing OF bits to the driver. We also add | ||||
| a irq domain for the PCI/e controllers cascade, thus making it usable from | ||||
| dts files. | ||||
|  | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  arch/mips/pci/pci-ar71xx.c | 82 +++++++++++++++++++++++----------------------- | ||||
|  1 file changed, 41 insertions(+), 41 deletions(-) | ||||
|  | ||||
| --- a/arch/mips/pci/pci-ar71xx.c | ||||
| +++ b/arch/mips/pci/pci-ar71xx.c | ||||
| @@ -15,8 +15,11 @@ | ||||
|  #include <linux/pci.h> | ||||
|  #include <linux/pci_regs.h> | ||||
|  #include <linux/interrupt.h> | ||||
| +#include <linux/irqchip/chained_irq.h> | ||||
|  #include <linux/init.h> | ||||
|  #include <linux/platform_device.h> | ||||
| +#include <linux/of_irq.h> | ||||
| +#include <linux/of_pci.h> | ||||
|   | ||||
|  #include <asm/mach-ath79/ar71xx_regs.h> | ||||
|  #include <asm/mach-ath79/ath79.h> | ||||
| @@ -46,12 +49,13 @@ | ||||
|  #define AR71XX_PCI_IRQ_COUNT		5 | ||||
|   | ||||
|  struct ar71xx_pci_controller { | ||||
| +	struct device_node *np; | ||||
|  	void __iomem *cfg_base; | ||||
|  	int irq; | ||||
| -	int irq_base; | ||||
|  	struct pci_controller pci_ctrl; | ||||
|  	struct resource io_res; | ||||
|  	struct resource mem_res; | ||||
| +	struct irq_domain *domain; | ||||
|  }; | ||||
|   | ||||
|  /* Byte lane enable bits */ | ||||
| @@ -225,29 +229,30 @@ static struct pci_ops ar71xx_pci_ops = { | ||||
|   | ||||
|  static void ar71xx_pci_irq_handler(struct irq_desc *desc) | ||||
|  { | ||||
| -	struct ar71xx_pci_controller *apc; | ||||
|  	void __iomem *base = ath79_reset_base; | ||||
| +	struct irq_chip *chip = irq_desc_get_chip(desc); | ||||
| +	struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc); | ||||
|  	u32 pending; | ||||
|   | ||||
| -	apc = irq_desc_get_handler_data(desc); | ||||
| - | ||||
| +	chained_irq_enter(chip, desc); | ||||
|  	pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & | ||||
|  		  __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
|   | ||||
|  	if (pending & AR71XX_PCI_INT_DEV0) | ||||
| -		generic_handle_irq(apc->irq_base + 0); | ||||
| +		generic_handle_irq(irq_linear_revmap(apc->domain, 1)); | ||||
|   | ||||
|  	else if (pending & AR71XX_PCI_INT_DEV1) | ||||
| -		generic_handle_irq(apc->irq_base + 1); | ||||
| +		generic_handle_irq(irq_linear_revmap(apc->domain, 2)); | ||||
|   | ||||
|  	else if (pending & AR71XX_PCI_INT_DEV2) | ||||
| -		generic_handle_irq(apc->irq_base + 2); | ||||
| +		generic_handle_irq(irq_linear_revmap(apc->domain, 3)); | ||||
|   | ||||
|  	else if (pending & AR71XX_PCI_INT_CORE) | ||||
| -		generic_handle_irq(apc->irq_base + 4); | ||||
| +		generic_handle_irq(irq_linear_revmap(apc->domain, 4)); | ||||
|   | ||||
|  	else | ||||
|  		spurious_interrupt(); | ||||
| +	chained_irq_exit(chip, desc); | ||||
|  } | ||||
|   | ||||
|  static void ar71xx_pci_irq_unmask(struct irq_data *d) | ||||
| @@ -258,7 +263,7 @@ static void ar71xx_pci_irq_unmask(struct | ||||
|  	u32 t; | ||||
|   | ||||
|  	apc = irq_data_get_irq_chip_data(d); | ||||
| -	irq = d->irq - apc->irq_base; | ||||
| +	irq = irq_linear_revmap(apc->domain, d->irq); | ||||
|   | ||||
|  	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
|  	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| @@ -275,7 +280,7 @@ static void ar71xx_pci_irq_mask(struct i | ||||
|  	u32 t; | ||||
|   | ||||
|  	apc = irq_data_get_irq_chip_data(d); | ||||
| -	irq = d->irq - apc->irq_base; | ||||
| +	irq = irq_linear_revmap(apc->domain, d->irq); | ||||
|   | ||||
|  	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
|  	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| @@ -291,24 +296,31 @@ static struct irq_chip ar71xx_pci_irq_ch | ||||
|  	.irq_mask_ack	= ar71xx_pci_irq_mask, | ||||
|  }; | ||||
|   | ||||
| +static int ar71xx_pci_irq_map(struct irq_domain *d, | ||||
| +			      unsigned int irq, irq_hw_number_t hw) | ||||
| +{ | ||||
| +	struct ar71xx_pci_controller *apc = d->host_data; | ||||
| + | ||||
| +	irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq); | ||||
| +	irq_set_chip_data(irq, apc); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct irq_domain_ops ar71xx_pci_domain_ops = { | ||||
| +	.xlate = irq_domain_xlate_onecell, | ||||
| +	.map = ar71xx_pci_irq_map, | ||||
| +}; | ||||
| + | ||||
|  static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc) | ||||
|  { | ||||
|  	void __iomem *base = ath79_reset_base; | ||||
| -	int i; | ||||
|   | ||||
|  	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
|  	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); | ||||
|   | ||||
| -	BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT); | ||||
| - | ||||
| -	apc->irq_base = ATH79_PCI_IRQ_BASE; | ||||
| -	for (i = apc->irq_base; | ||||
| -	     i < apc->irq_base + AR71XX_PCI_IRQ_COUNT; i++) { | ||||
| -		irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip, | ||||
| -					 handle_level_irq); | ||||
| -		irq_set_chip_data(i, apc); | ||||
| -	} | ||||
| - | ||||
| +	apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT, | ||||
| +					    &ar71xx_pci_domain_ops, apc); | ||||
|  	irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler, | ||||
|  					 apc); | ||||
|  } | ||||
| @@ -325,6 +337,11 @@ static void ar71xx_pci_reset(void) | ||||
|  	mdelay(100); | ||||
|  } | ||||
|   | ||||
| +static const struct of_device_id ar71xx_pci_ids[] = { | ||||
| +	{ .compatible = "qca,ar7100-pci" }, | ||||
| +	{}, | ||||
| +}; | ||||
| + | ||||
|  static int ar71xx_pci_probe(struct platform_device *pdev) | ||||
|  { | ||||
|  	struct ar71xx_pci_controller *apc; | ||||
| @@ -345,26 +362,6 @@ static int ar71xx_pci_probe(struct platf | ||||
|  	if (apc->irq < 0) | ||||
|  		return -EINVAL; | ||||
|   | ||||
| -	res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); | ||||
| -	if (!res) | ||||
| -		return -EINVAL; | ||||
| - | ||||
| -	apc->io_res.parent = res; | ||||
| -	apc->io_res.name = "PCI IO space"; | ||||
| -	apc->io_res.start = res->start; | ||||
| -	apc->io_res.end = res->end; | ||||
| -	apc->io_res.flags = IORESOURCE_IO; | ||||
| - | ||||
| -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); | ||||
| -	if (!res) | ||||
| -		return -EINVAL; | ||||
| - | ||||
| -	apc->mem_res.parent = res; | ||||
| -	apc->mem_res.name = "PCI memory space"; | ||||
| -	apc->mem_res.start = res->start; | ||||
| -	apc->mem_res.end = res->end; | ||||
| -	apc->mem_res.flags = IORESOURCE_MEM; | ||||
| - | ||||
|  	ar71xx_pci_reset(); | ||||
|   | ||||
|  	/* setup COMMAND register */ | ||||
| @@ -377,9 +374,11 @@ static int ar71xx_pci_probe(struct platf | ||||
|   | ||||
|  	ar71xx_pci_irq_init(apc); | ||||
|   | ||||
| +	apc->np = pdev->dev.of_node; | ||||
|  	apc->pci_ctrl.pci_ops = &ar71xx_pci_ops; | ||||
|  	apc->pci_ctrl.mem_resource = &apc->mem_res; | ||||
|  	apc->pci_ctrl.io_resource = &apc->io_res; | ||||
| +	pci_load_of_ranges(&apc->pci_ctrl, pdev->dev.of_node); | ||||
|   | ||||
|  	register_pci_controller(&apc->pci_ctrl); | ||||
|   | ||||
| @@ -390,6 +389,7 @@ static struct platform_driver ar71xx_pci | ||||
|  	.probe = ar71xx_pci_probe, | ||||
|  	.driver = { | ||||
|  		.name = "ar71xx-pci", | ||||
| +		.of_match_table = of_match_ptr(ar71xx_pci_ids), | ||||
|  	}, | ||||
|  }; | ||||
|   | ||||
| @@ -0,0 +1,61 @@ | ||||
| From ea27764bc3ef2a05decf3ae05edffc289cd0d93c Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Mon, 25 Jun 2018 15:52:02 +0200 | ||||
| Subject: [PATCH 19/33] dt-bindings: PCI: qcom,ar7240: adds binding doc | ||||
|  | ||||
| With the driver being converted from platform_data to pure OF, we need to | ||||
| also add some docs. | ||||
|  | ||||
| Cc: Rob Herring <robh+dt@kernel.org> | ||||
| Cc: devicetree@vger.kernel.org | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  .../devicetree/bindings/pci/qcom,ar7240-pci.txt    | 42 ++++++++++++++++++++++ | ||||
|  1 file changed, 42 insertions(+) | ||||
|  create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt | ||||
| @@ -0,0 +1,42 @@ | ||||
| +* Qualcomm Atheros AR724X PCI express root complex | ||||
| + | ||||
| +Required properties: | ||||
| +- compatible: should contain "qcom,ar7240-pci" to identify the core. | ||||
| +- reg: Should contain the register ranges as listed in the reg-names property. | ||||
| +- reg-names: Definition: Must include the following entries | ||||
| +	- "crp_base"	Configuration registers | ||||
| +	- "ctrl_base"	Control registers | ||||
| +	- "cfg_base"	IO Memory | ||||
| +- #address-cells: set to <3> | ||||
| +- #size-cells: set to <2> | ||||
| +- ranges: ranges for the PCI memory and I/O regions | ||||
| +- interrupt-map-mask and interrupt-map: standard PCI | ||||
| +	properties to define the mapping of the PCIe interface to interrupt | ||||
| +	numbers. | ||||
| +- #interrupt-cells: set to <1> | ||||
| +- interrupt-parent: phandle to the MIPS IRQ controller | ||||
| + | ||||
| +Optional properties: | ||||
| +- interrupt-controller: define to enable the builtin IRQ cascade. | ||||
| + | ||||
| +* Example for qca9557 | ||||
| +	pcie-controller@180c0000 { | ||||
| +		compatible = "qcom,ar7240-pci"; | ||||
| +		#address-cells = <3>; | ||||
| +		#size-cells = <2>; | ||||
| +		bus-range = <0x0 0x0>; | ||||
| +		reg = <0x180c0000 0x1000>, | ||||
| +		      <0x180f0000 0x100>, | ||||
| +		      <0x14000000 0x1000>; | ||||
| +		reg-names = "crp_base", "ctrl_base", "cfg_base"; | ||||
| +		ranges = <0x2000000 0 0x10000000 0x10000000 0 0x04000000 | ||||
| +			  0x1000000 0 0x00000000 0x00000000 0 0x00000001>; | ||||
| +		interrupt-parent = <&intc2>; | ||||
| +		interrupts = <1>; | ||||
| + | ||||
| +		interrupt-controller; | ||||
| +		#interrupt-cells = <1>; | ||||
| + | ||||
| +		interrupt-map-mask = <0 0 0 1>; | ||||
| +		interrupt-map = <0 0 0 0 &pcie0 0>; | ||||
| +	}; | ||||
| @@ -0,0 +1,205 @@ | ||||
| From a522ee0199d5d3ea114ca2e211f6ac398d3e8e0b Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Sat, 23 Jun 2018 15:07:37 +0200 | ||||
| Subject: [PATCH 20/33] MIPS: pci-ar724x: convert to OF | ||||
|  | ||||
| With the ath79 target getting converted to pure OF, we can drop all the | ||||
| platform data code and add the missing OF bits to the driver. We also add | ||||
| a irq domain for the PCI/e controllers cascade, thus making it usable from | ||||
| dts files. | ||||
|  | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  arch/mips/pci/pci-ar724x.c | 88 ++++++++++++++++++++++------------------------ | ||||
|  1 file changed, 42 insertions(+), 46 deletions(-) | ||||
|  | ||||
| --- a/arch/mips/pci/pci-ar724x.c | ||||
| +++ b/arch/mips/pci/pci-ar724x.c | ||||
| @@ -11,8 +11,11 @@ | ||||
|  #include <linux/init.h> | ||||
|  #include <linux/delay.h> | ||||
|  #include <linux/platform_device.h> | ||||
| +#include <linux/irqchip/chained_irq.h> | ||||
|  #include <asm/mach-ath79/ath79.h> | ||||
|  #include <asm/mach-ath79/ar71xx_regs.h> | ||||
| +#include <linux/of_irq.h> | ||||
| +#include <linux/of_pci.h> | ||||
|   | ||||
|  #define AR724X_PCI_REG_APP		0x00 | ||||
|  #define AR724X_PCI_REG_RESET		0x18 | ||||
| @@ -42,17 +45,20 @@ struct ar724x_pci_controller { | ||||
|  	void __iomem *crp_base; | ||||
|   | ||||
|  	int irq; | ||||
| -	int irq_base; | ||||
|   | ||||
|  	bool link_up; | ||||
|  	bool bar0_is_cached; | ||||
|  	u32  bar0_value; | ||||
|   | ||||
| +	struct device_node *np; | ||||
|  	struct pci_controller pci_controller; | ||||
| +	struct irq_domain *domain; | ||||
|  	struct resource io_res; | ||||
|  	struct resource mem_res; | ||||
|  }; | ||||
|   | ||||
| +static struct irq_chip ar724x_pci_irq_chip; | ||||
| + | ||||
|  static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc) | ||||
|  { | ||||
|  	u32 reset; | ||||
| @@ -228,35 +234,31 @@ static struct pci_ops ar724x_pci_ops = { | ||||
|   | ||||
|  static void ar724x_pci_irq_handler(struct irq_desc *desc) | ||||
|  { | ||||
| -	struct ar724x_pci_controller *apc; | ||||
| -	void __iomem *base; | ||||
| +	struct irq_chip *chip = irq_desc_get_chip(desc); | ||||
| +	struct ar724x_pci_controller *apc = irq_desc_get_handler_data(desc); | ||||
|  	u32 pending; | ||||
|   | ||||
| -	apc = irq_desc_get_handler_data(desc); | ||||
| -	base = apc->ctrl_base; | ||||
| - | ||||
| -	pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & | ||||
| -		  __raw_readl(base + AR724X_PCI_REG_INT_MASK); | ||||
| +	chained_irq_enter(chip, desc); | ||||
| +	pending = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_STATUS) & | ||||
| +		  __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_MASK); | ||||
|   | ||||
|  	if (pending & AR724X_PCI_INT_DEV0) | ||||
| -		generic_handle_irq(apc->irq_base + 0); | ||||
| - | ||||
| +		generic_handle_irq(irq_linear_revmap(apc->domain, 1)); | ||||
|  	else | ||||
|  		spurious_interrupt(); | ||||
| +	chained_irq_exit(chip, desc); | ||||
|  } | ||||
|   | ||||
|  static void ar724x_pci_irq_unmask(struct irq_data *d) | ||||
|  { | ||||
|  	struct ar724x_pci_controller *apc; | ||||
|  	void __iomem *base; | ||||
| -	int offset; | ||||
|  	u32 t; | ||||
|   | ||||
|  	apc = irq_data_get_irq_chip_data(d); | ||||
|  	base = apc->ctrl_base; | ||||
| -	offset = apc->irq_base - d->irq; | ||||
|   | ||||
| -	switch (offset) { | ||||
| +	switch (irq_linear_revmap(apc->domain, d->irq)) { | ||||
|  	case 0: | ||||
|  		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); | ||||
|  		__raw_writel(t | AR724X_PCI_INT_DEV0, | ||||
| @@ -270,14 +272,12 @@ static void ar724x_pci_irq_mask(struct i | ||||
|  { | ||||
|  	struct ar724x_pci_controller *apc; | ||||
|  	void __iomem *base; | ||||
| -	int offset; | ||||
|  	u32 t; | ||||
|   | ||||
|  	apc = irq_data_get_irq_chip_data(d); | ||||
|  	base = apc->ctrl_base; | ||||
| -	offset = apc->irq_base - d->irq; | ||||
|   | ||||
| -	switch (offset) { | ||||
| +	switch (irq_linear_revmap(apc->domain, d->irq)) { | ||||
|  	case 0: | ||||
|  		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); | ||||
|  		__raw_writel(t & ~AR724X_PCI_INT_DEV0, | ||||
| @@ -302,26 +302,34 @@ static struct irq_chip ar724x_pci_irq_ch | ||||
|  	.irq_mask_ack	= ar724x_pci_irq_mask, | ||||
|  }; | ||||
|   | ||||
| +static int ar724x_pci_irq_map(struct irq_domain *d, | ||||
| +			      unsigned int irq, irq_hw_number_t hw) | ||||
| +{ | ||||
| +	struct ar724x_pci_controller *apc = d->host_data; | ||||
| + | ||||
| +	irq_set_chip_and_handler(irq, &ar724x_pci_irq_chip, handle_level_irq); | ||||
| +	irq_set_chip_data(irq, apc); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct irq_domain_ops ar724x_pci_domain_ops = { | ||||
| +	.xlate = irq_domain_xlate_onecell, | ||||
| +	.map = ar724x_pci_irq_map, | ||||
| +}; | ||||
| + | ||||
|  static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc, | ||||
|  				int id) | ||||
|  { | ||||
|  	void __iomem *base; | ||||
| -	int i; | ||||
|   | ||||
|  	base = apc->ctrl_base; | ||||
|   | ||||
|  	__raw_writel(0, base + AR724X_PCI_REG_INT_MASK); | ||||
|  	__raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); | ||||
|   | ||||
| -	apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT); | ||||
| - | ||||
| -	for (i = apc->irq_base; | ||||
| -	     i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) { | ||||
| -		irq_set_chip_and_handler(i, &ar724x_pci_irq_chip, | ||||
| -					 handle_level_irq); | ||||
| -		irq_set_chip_data(i, apc); | ||||
| -	} | ||||
| - | ||||
| +	apc->domain = irq_domain_add_linear(apc->np, 2, | ||||
| +					    &ar724x_pci_domain_ops, apc); | ||||
|  	irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler, | ||||
|  					 apc); | ||||
|  } | ||||
| @@ -388,29 +396,11 @@ static int ar724x_pci_probe(struct platf | ||||
|  	if (apc->irq < 0) | ||||
|  		return -EINVAL; | ||||
|   | ||||
| -	res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); | ||||
| -	if (!res) | ||||
| -		return -EINVAL; | ||||
| - | ||||
| -	apc->io_res.parent = res; | ||||
| -	apc->io_res.name = "PCI IO space"; | ||||
| -	apc->io_res.start = res->start; | ||||
| -	apc->io_res.end = res->end; | ||||
| -	apc->io_res.flags = IORESOURCE_IO; | ||||
| - | ||||
| -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); | ||||
| -	if (!res) | ||||
| -		return -EINVAL; | ||||
| - | ||||
| -	apc->mem_res.parent = res; | ||||
| -	apc->mem_res.name = "PCI memory space"; | ||||
| -	apc->mem_res.start = res->start; | ||||
| -	apc->mem_res.end = res->end; | ||||
| -	apc->mem_res.flags = IORESOURCE_MEM; | ||||
| - | ||||
| +	apc->np = pdev->dev.of_node; | ||||
|  	apc->pci_controller.pci_ops = &ar724x_pci_ops; | ||||
|  	apc->pci_controller.io_resource = &apc->io_res; | ||||
|  	apc->pci_controller.mem_resource = &apc->mem_res; | ||||
| +	pci_load_of_ranges(&apc->pci_controller, pdev->dev.of_node); | ||||
|   | ||||
|  	/* | ||||
|  	 * Do the full PCIE Root Complex Initialization Sequence if the PCIe | ||||
| @@ -432,10 +422,16 @@ static int ar724x_pci_probe(struct platf | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static const struct of_device_id ar724x_pci_ids[] = { | ||||
| +	{ .compatible = "qcom,ar7240-pci" }, | ||||
| +	{}, | ||||
| +}; | ||||
| + | ||||
|  static struct platform_driver ar724x_pci_driver = { | ||||
|  	.probe = ar724x_pci_probe, | ||||
|  	.driver = { | ||||
|  		.name = "ar724x-pci", | ||||
| +		.of_match_table = of_match_ptr(ar724x_pci_ids), | ||||
|  	}, | ||||
|  }; | ||||
|   | ||||
| @@ -0,0 +1,93 @@ | ||||
| From 3fc8585cf76022dba7496627074d42af88c30718 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <john@phrozen.org> | ||||
| Date: Sat, 23 Jun 2018 15:16:55 +0200 | ||||
| Subject: [PATCH 32/33] MIPS: ath79: sanitize symbols | ||||
|  | ||||
| We no longer need to select which SoCs are supported as the whole arch | ||||
| code is always built. So lets drop all the SoC symbols | ||||
|  | ||||
| Signed-off-by: John Crispin <john@phrozen.org> | ||||
| --- | ||||
|  arch/mips/Kconfig       |  2 ++ | ||||
|  arch/mips/ath79/Kconfig | 44 +++++--------------------------------------- | ||||
|  arch/mips/pci/Makefile  |  2 +- | ||||
|  3 files changed, 8 insertions(+), 40 deletions(-) | ||||
|  | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -256,6 +256,8 @@ config ATH79 | ||||
|  	select SYS_SUPPORTS_BIG_ENDIAN | ||||
|  	select SYS_SUPPORTS_MIPS16 | ||||
|  	select SYS_SUPPORTS_ZBOOT_UART_PROM | ||||
| +	select HAVE_PCI | ||||
| +	select USB_ARCH_HAS_EHCI | ||||
|  	select USE_OF | ||||
|  	select USB_EHCI_ROOT_HUB_TT if USB_EHCI_HCD_PLATFORM | ||||
|  	help | ||||
| --- a/arch/mips/ath79/Kconfig | ||||
| +++ b/arch/mips/ath79/Kconfig | ||||
| @@ -1,48 +1,14 @@ | ||||
|  # SPDX-License-Identifier: GPL-2.0 | ||||
|  if ATH79 | ||||
|   | ||||
| -config SOC_AR71XX | ||||
| -	select HAVE_PCI | ||||
| -	def_bool n | ||||
| - | ||||
| -config SOC_AR724X | ||||
| -	select HAVE_PCI | ||||
| -	select PCI_AR724X if PCI | ||||
| -	def_bool n | ||||
| - | ||||
| -config SOC_AR913X | ||||
| -	def_bool n | ||||
| - | ||||
| -config SOC_AR933X | ||||
| -	def_bool n | ||||
| - | ||||
| -config SOC_AR934X | ||||
| -	select HAVE_PCI | ||||
| -	select PCI_AR724X if PCI | ||||
| -	def_bool n | ||||
| - | ||||
| -config SOC_QCA955X | ||||
| -	select HAVE_PCI | ||||
| -	select PCI_AR724X if PCI | ||||
| +config PCI_AR71XX | ||||
| +	bool "PCI support for AR7100 type SoCs" | ||||
| +	depends on PCI | ||||
|  	def_bool n | ||||
|   | ||||
|  config PCI_AR724X | ||||
| -	def_bool n | ||||
| - | ||||
| -config ATH79_DEV_GPIO_BUTTONS | ||||
| -	def_bool n | ||||
| - | ||||
| -config ATH79_DEV_LEDS_GPIO | ||||
| -	def_bool n | ||||
| - | ||||
| -config ATH79_DEV_SPI | ||||
| -	def_bool n | ||||
| - | ||||
| -config ATH79_DEV_USB | ||||
| -	def_bool n | ||||
| - | ||||
| -config ATH79_DEV_WMAC | ||||
| -	depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA955X) | ||||
| +	bool "PCI support for AR724x type SoCs" | ||||
| +	depends on PCI | ||||
|  	def_bool n | ||||
|   | ||||
|  endif | ||||
| --- a/arch/mips/pci/Makefile | ||||
| +++ b/arch/mips/pci/Makefile | ||||
| @@ -21,7 +21,7 @@ obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o | ||||
|  					ops-bcm63xx.o | ||||
|  obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o | ||||
|  obj-$(CONFIG_PCI_AR2315)	+= pci-ar2315.o | ||||
| -obj-$(CONFIG_SOC_AR71XX)	+= pci-ar71xx.o | ||||
| +obj-$(CONFIG_PCI_AR71XX)	+= pci-ar71xx.o | ||||
|  obj-$(CONFIG_PCI_AR724X)	+= pci-ar724x.o | ||||
|  obj-$(CONFIG_PCI_XTALK_BRIDGE)	+= pci-xtalk-bridge.o | ||||
|  # | ||||
| @@ -0,0 +1,27 @@ | ||||
| --- a/arch/mips/ath79/common.c | ||||
| +++ b/arch/mips/ath79/common.c | ||||
| @@ -31,11 +31,13 @@ EXPORT_SYMBOL_GPL(ath79_ddr_freq); | ||||
|   | ||||
|  enum ath79_soc_type ath79_soc; | ||||
|  unsigned int ath79_soc_rev; | ||||
| +EXPORT_SYMBOL_GPL(ath79_soc_rev); | ||||
|   | ||||
|  void __iomem *ath79_pll_base; | ||||
|  void __iomem *ath79_reset_base; | ||||
|  EXPORT_SYMBOL_GPL(ath79_reset_base); | ||||
| -static void __iomem *ath79_ddr_base; | ||||
| +void __iomem *ath79_ddr_base; | ||||
| +EXPORT_SYMBOL_GPL(ath79_ddr_base); | ||||
|  static void __iomem *ath79_ddr_wb_flush_base; | ||||
|  static void __iomem *ath79_ddr_pci_win_base; | ||||
|   | ||||
| --- a/arch/mips/include/asm/mach-ath79/ath79.h | ||||
| +++ b/arch/mips/include/asm/mach-ath79/ath79.h | ||||
| @@ -149,6 +149,7 @@ void ath79_ddr_wb_flush(unsigned int reg | ||||
|  void ath79_ddr_set_pci_windows(void); | ||||
|   | ||||
|  extern void __iomem *ath79_pll_base; | ||||
| +extern void __iomem *ath79_ddr_base; | ||||
|  extern void __iomem *ath79_reset_base; | ||||
|   | ||||
|  static inline void ath79_pll_wr(unsigned reg, u32 val) | ||||
| @@ -0,0 +1,139 @@ | ||||
| --- a/arch/mips/pci/pci-ar71xx.c | ||||
| +++ b/arch/mips/pci/pci-ar71xx.c | ||||
| @@ -51,11 +51,9 @@ | ||||
|  struct ar71xx_pci_controller { | ||||
|  	struct device_node *np; | ||||
|  	void __iomem *cfg_base; | ||||
| -	int irq; | ||||
|  	struct pci_controller pci_ctrl; | ||||
|  	struct resource io_res; | ||||
|  	struct resource mem_res; | ||||
| -	struct irq_domain *domain; | ||||
|  }; | ||||
|   | ||||
|  /* Byte lane enable bits */ | ||||
| @@ -227,104 +225,6 @@ static struct pci_ops ar71xx_pci_ops = { | ||||
|  	.write	= ar71xx_pci_write_config, | ||||
|  }; | ||||
|   | ||||
| -static void ar71xx_pci_irq_handler(struct irq_desc *desc) | ||||
| -{ | ||||
| -	void __iomem *base = ath79_reset_base; | ||||
| -	struct irq_chip *chip = irq_desc_get_chip(desc); | ||||
| -	struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc); | ||||
| -	u32 pending; | ||||
| - | ||||
| -	chained_irq_enter(chip, desc); | ||||
| -	pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & | ||||
| -		  __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| - | ||||
| -	if (pending & AR71XX_PCI_INT_DEV0) | ||||
| -		generic_handle_irq(irq_linear_revmap(apc->domain, 1)); | ||||
| - | ||||
| -	else if (pending & AR71XX_PCI_INT_DEV1) | ||||
| -		generic_handle_irq(irq_linear_revmap(apc->domain, 2)); | ||||
| - | ||||
| -	else if (pending & AR71XX_PCI_INT_DEV2) | ||||
| -		generic_handle_irq(irq_linear_revmap(apc->domain, 3)); | ||||
| - | ||||
| -	else if (pending & AR71XX_PCI_INT_CORE) | ||||
| -		generic_handle_irq(irq_linear_revmap(apc->domain, 4)); | ||||
| - | ||||
| -	else | ||||
| -		spurious_interrupt(); | ||||
| -	chained_irq_exit(chip, desc); | ||||
| -} | ||||
| - | ||||
| -static void ar71xx_pci_irq_unmask(struct irq_data *d) | ||||
| -{ | ||||
| -	struct ar71xx_pci_controller *apc; | ||||
| -	unsigned int irq; | ||||
| -	void __iomem *base = ath79_reset_base; | ||||
| -	u32 t; | ||||
| - | ||||
| -	apc = irq_data_get_irq_chip_data(d); | ||||
| -	irq = irq_linear_revmap(apc->domain, d->irq); | ||||
| - | ||||
| -	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| -	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| - | ||||
| -	/* flush write */ | ||||
| -	__raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| -} | ||||
| - | ||||
| -static void ar71xx_pci_irq_mask(struct irq_data *d) | ||||
| -{ | ||||
| -	struct ar71xx_pci_controller *apc; | ||||
| -	unsigned int irq; | ||||
| -	void __iomem *base = ath79_reset_base; | ||||
| -	u32 t; | ||||
| - | ||||
| -	apc = irq_data_get_irq_chip_data(d); | ||||
| -	irq = irq_linear_revmap(apc->domain, d->irq); | ||||
| - | ||||
| -	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| -	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| - | ||||
| -	/* flush write */ | ||||
| -	__raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| -} | ||||
| - | ||||
| -static struct irq_chip ar71xx_pci_irq_chip = { | ||||
| -	.name		= "AR71XX PCI", | ||||
| -	.irq_mask	= ar71xx_pci_irq_mask, | ||||
| -	.irq_unmask	= ar71xx_pci_irq_unmask, | ||||
| -	.irq_mask_ack	= ar71xx_pci_irq_mask, | ||||
| -}; | ||||
| - | ||||
| -static int ar71xx_pci_irq_map(struct irq_domain *d, | ||||
| -			      unsigned int irq, irq_hw_number_t hw) | ||||
| -{ | ||||
| -	struct ar71xx_pci_controller *apc = d->host_data; | ||||
| - | ||||
| -	irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq); | ||||
| -	irq_set_chip_data(irq, apc); | ||||
| - | ||||
| -	return 0; | ||||
| -} | ||||
| - | ||||
| -static const struct irq_domain_ops ar71xx_pci_domain_ops = { | ||||
| -	.xlate = irq_domain_xlate_onecell, | ||||
| -	.map = ar71xx_pci_irq_map, | ||||
| -}; | ||||
| - | ||||
| -static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc) | ||||
| -{ | ||||
| -	void __iomem *base = ath79_reset_base; | ||||
| - | ||||
| -	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); | ||||
| -	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); | ||||
| - | ||||
| -	apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT, | ||||
| -					    &ar71xx_pci_domain_ops, apc); | ||||
| -	irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler, | ||||
| -					 apc); | ||||
| -} | ||||
| - | ||||
|  static void ar71xx_pci_reset(void) | ||||
|  { | ||||
|  	ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); | ||||
| @@ -358,10 +258,6 @@ static int ar71xx_pci_probe(struct platf | ||||
|  	if (IS_ERR(apc->cfg_base)) | ||||
|  		return PTR_ERR(apc->cfg_base); | ||||
|   | ||||
| -	apc->irq = platform_get_irq(pdev, 0); | ||||
| -	if (apc->irq < 0) | ||||
| -		return -EINVAL; | ||||
| - | ||||
|  	ar71xx_pci_reset(); | ||||
|   | ||||
|  	/* setup COMMAND register */ | ||||
| @@ -372,8 +268,6 @@ static int ar71xx_pci_probe(struct platf | ||||
|  	/* clear bus errors */ | ||||
|  	ar71xx_pci_check_error(apc, 1); | ||||
|   | ||||
| -	ar71xx_pci_irq_init(apc); | ||||
| - | ||||
|  	apc->np = pdev->dev.of_node; | ||||
|  	apc->pci_ctrl.pci_ops = &ar71xx_pci_ops; | ||||
|  	apc->pci_ctrl.mem_resource = &apc->mem_res; | ||||
							
								
								
									
										21
									
								
								target/linux/ath79/patches-5.15/0037-missing-registers.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								target/linux/ath79/patches-5.15/0037-missing-registers.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| commit f3ffac90bc7266b7d917616f3233f58e8c08a196 | ||||
| Author: Christian Lamparter <chunkeey@gmail.com> | ||||
| Date:   Fri Aug 10 23:24:47 2018 +0200 | ||||
|  | ||||
|     ath79: gmac: add parsers for rxd(v)- and tx(d|en)-delay for AR9344 | ||||
|  | ||||
|     Signed-off-by: Christian Lamparter <chunkeey@gmail.com> | ||||
|  | ||||
| --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| @@ -1226,6 +1226,10 @@ | ||||
|  #define AR934X_ETH_CFG_RDV_DELAY        BIT(16) | ||||
|  #define AR934X_ETH_CFG_RDV_DELAY_MASK   0x3 | ||||
|  #define AR934X_ETH_CFG_RDV_DELAY_SHIFT  16 | ||||
| +#define AR934X_ETH_CFG_TXD_DELAY_MASK   0x3 | ||||
| +#define AR934X_ETH_CFG_TXD_DELAY_SHIFT  18 | ||||
| +#define AR934X_ETH_CFG_TXE_DELAY_MASK   0x3 | ||||
| +#define AR934X_ETH_CFG_TXE_DELAY_SHIFT  20 | ||||
|   | ||||
|  /* | ||||
|   * QCA953X GMAC Interface | ||||
| @@ -0,0 +1,90 @@ | ||||
| From 60efe35257b063ce584968f9f80b437030ce6ba6 Mon Sep 17 00:00:00 2001 | ||||
| From: David Bauer <mail@david-bauer.net> | ||||
| Date: Mon, 18 Mar 2019 00:54:06 +0100 | ||||
| Subject: [PATCH] MIPS: ath79: add missing QCA955x GMAC registers | ||||
|  | ||||
| This adds missing GMAC register definitions for the Qualcomm Atheros | ||||
| QCA955X series MIPS SoCs. | ||||
|  | ||||
| They originate from the platforms U-Boot code and the AVM FRITZ!WLAN | ||||
| Repeater 450E's GPL tarball. | ||||
|  | ||||
| Signed-off-by: David Bauer <mail@david-bauer.net> | ||||
| --- | ||||
|  .../mips/include/asm/mach-ath79/ar71xx_regs.h | 54 +++++++++++++++++++ | ||||
|  1 file changed, 54 insertions(+) | ||||
|  | ||||
| --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| @@ -1246,7 +1246,12 @@ | ||||
|   */ | ||||
|   | ||||
|  #define QCA955X_GMAC_REG_ETH_CFG	0x00 | ||||
| +#define QCA955X_GMAC_REG_SGMII_RESET	0x14 | ||||
|  #define QCA955X_GMAC_REG_SGMII_SERDES	0x18 | ||||
| +#define QCA955X_GMAC_REG_MR_AN_CONTROL	0x1c | ||||
| +#define QCA955X_GMAC_REG_MR_AN_STATUS	0x20 | ||||
| +#define QCA955X_GMAC_REG_SGMII_CONFIG	0x34 | ||||
| +#define QCA955X_GMAC_REG_SGMII_DEBUG	0x58 | ||||
|   | ||||
|  #define QCA955X_ETH_CFG_RGMII_EN	BIT(0) | ||||
|  #define QCA955X_ETH_CFG_MII_GE0		BIT(1) | ||||
| @@ -1268,9 +1273,58 @@ | ||||
|  #define QCA955X_ETH_CFG_TXE_DELAY_MASK	0x3 | ||||
|  #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT	20 | ||||
|   | ||||
| +#define QCA955X_SGMII_RESET_RX_CLK_N_RESET	0 | ||||
| +#define QCA955X_SGMII_RESET_RX_CLK_N		BIT(0) | ||||
| +#define QCA955X_SGMII_RESET_TX_CLK_N		BIT(1) | ||||
| +#define QCA955X_SGMII_RESET_RX_125M_N		BIT(2) | ||||
| +#define QCA955X_SGMII_RESET_TX_125M_N		BIT(3) | ||||
| +#define QCA955X_SGMII_RESET_HW_RX_125M_N	BIT(4) | ||||
| + | ||||
|  #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS	BIT(15) | ||||
|  #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23 | ||||
|  #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf | ||||
| + | ||||
| +#define QCA955X_MR_AN_CONTROL_SPEED_SEL1	BIT(6) | ||||
| +#define QCA955X_MR_AN_CONTROL_DUPLEX_MODE	BIT(8) | ||||
| +#define QCA955X_MR_AN_CONTROL_RESTART_AN	BIT(9) | ||||
| +#define QCA955X_MR_AN_CONTROL_POWER_DOWN	BIT(11) | ||||
| +#define QCA955X_MR_AN_CONTROL_AN_ENABLE		BIT(12) | ||||
| +#define QCA955X_MR_AN_CONTROL_SPEED_SEL0	BIT(13) | ||||
| +#define QCA955X_MR_AN_CONTROL_LOOPBACK		BIT(14) | ||||
| +#define QCA955X_MR_AN_CONTROL_PHY_RESET		BIT(15) | ||||
| + | ||||
| +#define QCA955X_MR_AN_STATUS_EXT_CAP		BIT(0) | ||||
| +#define QCA955X_MR_AN_STATUS_LINK_UP		BIT(2) | ||||
| +#define QCA955X_MR_AN_STATUS_AN_ABILITY		BIT(3) | ||||
| +#define QCA955X_MR_AN_STATUS_REMOTE_FAULT	BIT(4) | ||||
| +#define QCA955X_MR_AN_STATUS_AN_COMPLETE	BIT(5) | ||||
| +#define QCA955X_MR_AN_STATUS_NO_PREAMBLE	BIT(6) | ||||
| +#define QCA955X_MR_AN_STATUS_BASE_PAGE		BIT(7) | ||||
| + | ||||
| +#define QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT		0 | ||||
| +#define QCA955X_SGMII_CONFIG_MODE_CTRL_MASK		0x7 | ||||
| +#define QCA955X_SGMII_CONFIG_ENABLE_SGMII_TX_PAUSE	BIT(3) | ||||
| +#define QCA955X_SGMII_CONFIG_MR_REG4_CHANGED		BIT(4) | ||||
| +#define QCA955X_SGMII_CONFIG_FORCE_SPEED		BIT(5) | ||||
| +#define QCA955X_SGMII_CONFIG_SPEED_SHIFT		6 | ||||
| +#define QCA955X_SGMII_CONFIG_SPEED_MASK			0xc0 | ||||
| +#define QCA955X_SGMII_CONFIG_REMOTE_PHY_LOOPBACK	BIT(8) | ||||
| +#define QCA955X_SGMII_CONFIG_NEXT_PAGE_LOADED		BIT(9) | ||||
| +#define QCA955X_SGMII_CONFIG_MDIO_ENABLE		BIT(10) | ||||
| +#define QCA955X_SGMII_CONFIG_MDIO_PULSE			BIT(11) | ||||
| +#define QCA955X_SGMII_CONFIG_MDIO_COMPLETE		BIT(12) | ||||
| +#define QCA955X_SGMII_CONFIG_PRBS_ENABLE		BIT(13) | ||||
| +#define QCA955X_SGMII_CONFIG_BERT_ENABLE		BIT(14) | ||||
| + | ||||
| +#define QCA955X_SGMII_DEBUG_TX_STATE_MASK	0xff | ||||
| +#define QCA955X_SGMII_DEBUG_TX_STATE_SHIFT	0 | ||||
| +#define QCA955X_SGMII_DEBUG_RX_STATE_MASK	0xff00 | ||||
| +#define QCA955X_SGMII_DEBUG_RX_STATE_SHIFT	8 | ||||
| +#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_MASK	0xff0000 | ||||
| +#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_SHIFT	16 | ||||
| +#define QCA955X_SGMII_DEBUG_ARB_STATE_MASK	0xf000000 | ||||
| +#define QCA955X_SGMII_DEBUG_ARB_STATE_SHIFT	24 | ||||
| + | ||||
|  /* | ||||
|   * QCA956X GMAC Interface | ||||
|   */ | ||||
| @@ -0,0 +1,52 @@ | ||||
| --- a/arch/mips/ath79/clock.c | ||||
| +++ b/arch/mips/ath79/clock.c | ||||
| @@ -40,6 +40,7 @@ static const char * const clk_names[ATH7 | ||||
|  	[ATH79_CLK_AHB] = "ahb", | ||||
|  	[ATH79_CLK_REF] = "ref", | ||||
|  	[ATH79_CLK_MDIO] = "mdio", | ||||
| +	[ATH79_CLK_UART1] = "uart1", | ||||
|  }; | ||||
|   | ||||
|  static const char * __init ath79_clk_name(int type) | ||||
| @@ -344,6 +345,9 @@ static void __init ar934x_clocks_init(vo | ||||
|  	if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) | ||||
|  		ath79_set_clk(ATH79_CLK_MDIO, 100 * 1000 * 1000); | ||||
|   | ||||
| +	if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL) | ||||
| +		ath79_set_clk(ATH79_CLK_UART1, 100 * 1000 * 1000); | ||||
| + | ||||
|  	iounmap(dpll_base); | ||||
|  } | ||||
|   | ||||
| @@ -649,6 +653,9 @@ static void __init ath79_clocks_init_dt( | ||||
|  	if (!clks[ATH79_CLK_MDIO]) | ||||
|  		clks[ATH79_CLK_MDIO] = clks[ATH79_CLK_REF]; | ||||
|   | ||||
| +	if (!clks[ATH79_CLK_UART1]) | ||||
| +		clks[ATH79_CLK_UART1] = clks[ATH79_CLK_REF]; | ||||
| + | ||||
|  	if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { | ||||
|  		pr_err("%pOF: could not register clk provider\n", np); | ||||
|  		goto err_iounmap; | ||||
| --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| @@ -348,6 +348,7 @@ | ||||
|  #define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL	BIT(24) | ||||
|   | ||||
|  #define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL	BIT(6) | ||||
| +#define AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL	BIT(7) | ||||
|   | ||||
|  #define QCA953X_PLL_CPU_CONFIG_REG		0x00 | ||||
|  #define QCA953X_PLL_DDR_CONFIG_REG		0x04 | ||||
| --- a/include/dt-bindings/clock/ath79-clk.h | ||||
| +++ b/include/dt-bindings/clock/ath79-clk.h | ||||
| @@ -11,7 +11,8 @@ | ||||
|  #define ATH79_CLK_AHB		2 | ||||
|  #define ATH79_CLK_REF		3 | ||||
|  #define ATH79_CLK_MDIO		4 | ||||
| +#define ATH79_CLK_UART1		5 | ||||
|   | ||||
| -#define ATH79_CLK_END		5 | ||||
| +#define ATH79_CLK_END		6 | ||||
|   | ||||
|  #endif /* __DT_BINDINGS_ATH79_CLK_H */ | ||||
| @@ -0,0 +1,18 @@ | ||||
| HACK: register the GPIO driver earlier to ensure that gpio_request calls | ||||
| from mach files succeed. | ||||
|  | ||||
| --- a/drivers/gpio/gpio-ath79.c | ||||
| +++ b/drivers/gpio/gpio-ath79.c | ||||
| @@ -297,7 +297,11 @@ static struct platform_driver ath79_gpio | ||||
|  	.probe = ath79_gpio_probe, | ||||
|  }; | ||||
|   | ||||
| -module_platform_driver(ath79_gpio_driver); | ||||
| +static int __init ath79_gpio_init(void) | ||||
| +{ | ||||
| +	return platform_driver_register(&ath79_gpio_driver); | ||||
| +} | ||||
| +postcore_initcall(ath79_gpio_init); | ||||
|   | ||||
|  MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support"); | ||||
|  MODULE_LICENSE("GPL v2"); | ||||
| @@ -0,0 +1,9 @@ | ||||
| --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| @@ -1376,5 +1376,6 @@ | ||||
|   | ||||
|  #define QCA956X_SGMII_CONFIG_MODE_CTRL_SHIFT	0 | ||||
|  #define QCA956X_SGMII_CONFIG_MODE_CTRL_MASK	0x7 | ||||
| +#define QCA956X_SGMII_CONFIG_MODE_CTRL_SGMII_MAC	0x2 | ||||
|   | ||||
|  #endif /* __ASM_MACH_AR71XX_REGS_H */ | ||||
| @@ -0,0 +1,130 @@ | ||||
| From: David Bauer <mail@david-bauer.net> | ||||
| Date: Sat, 11 Apr 2020 14:03:12 +0200 | ||||
| Subject: MIPS: pci-ar724x: add QCA9550 reset sequence | ||||
|  | ||||
| The QCA9550 family of SoCs have a slightly different reset | ||||
| sequence compared to older chips. | ||||
|  | ||||
| Normally the bootloader performs this sequence, however | ||||
| some bootloader implementation expect the operating system | ||||
| to clear the reset. | ||||
|  | ||||
| Also get the resets from OF to support handling of the second | ||||
| PCIe root-complex on the QCA9558. | ||||
|  | ||||
| Signed-off-by: David Bauer <mail@david-bauer.net> | ||||
|  | ||||
| --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| @@ -391,6 +391,7 @@ | ||||
|  #define QCA955X_PLL_CPU_CONFIG_REG		0x00 | ||||
|  #define QCA955X_PLL_DDR_CONFIG_REG		0x04 | ||||
|  #define QCA955X_PLL_CLK_CTRL_REG		0x08 | ||||
| +#define QCA955X_PLL_PCIE_CONFIG_REG		0x0c | ||||
|  #define QCA955X_PLL_ETH_XMII_CONTROL_REG	0x28 | ||||
|  #define QCA955X_PLL_ETH_SGMII_CONTROL_REG	0x48 | ||||
|  #define QCA955X_PLL_ETH_SGMII_SERDES_REG	0x4c | ||||
| @@ -476,6 +477,9 @@ | ||||
|  #define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL	BIT(21) | ||||
|  #define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL		BIT(24) | ||||
|   | ||||
| +#define QCA955X_PLL_PCIE_CONFIG_PLL_PWD			BIT(30) | ||||
| +#define QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS		BIT(16) | ||||
| + | ||||
|  #define QCA956X_PLL_SWITCH_CLOCK_SPARE_I2C_CLK_SELB		BIT(5) | ||||
|  #define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL0_1		BIT(6) | ||||
|  #define QCA956X_PLL_SWITCH_CLOCK_SPARE_UART1_CLK_SEL		BIT(7) | ||||
| --- a/arch/mips/pci/pci-ar724x.c | ||||
| +++ b/arch/mips/pci/pci-ar724x.c | ||||
| @@ -8,6 +8,7 @@ | ||||
|   | ||||
|  #include <linux/irq.h> | ||||
|  #include <linux/pci.h> | ||||
| +#include <linux/reset.h> | ||||
|  #include <linux/init.h> | ||||
|  #include <linux/delay.h> | ||||
|  #include <linux/platform_device.h> | ||||
| @@ -55,6 +56,9 @@ struct ar724x_pci_controller { | ||||
|  	struct irq_domain *domain; | ||||
|  	struct resource io_res; | ||||
|  	struct resource mem_res; | ||||
| + | ||||
| +	struct reset_control *hc_reset; | ||||
| +	struct reset_control *phy_reset; | ||||
|  }; | ||||
|   | ||||
|  static struct irq_chip ar724x_pci_irq_chip; | ||||
| @@ -340,18 +344,30 @@ static void ar724x_pci_hw_init(struct ar | ||||
|  	int wait = 0; | ||||
|   | ||||
|  	/* deassert PCIe host controller and PCIe PHY reset */ | ||||
| -	ath79_device_reset_clear(AR724X_RESET_PCIE); | ||||
| -	ath79_device_reset_clear(AR724X_RESET_PCIE_PHY); | ||||
| +	reset_control_deassert(apc->hc_reset); | ||||
| +	reset_control_deassert(apc->phy_reset); | ||||
|   | ||||
| -	/* remove the reset of the PCIE PLL */ | ||||
| -	ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); | ||||
| -	ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; | ||||
| -	ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); | ||||
| - | ||||
| -	/* deassert bypass for the PCIE PLL */ | ||||
| -	ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); | ||||
| -	ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; | ||||
| -	ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); | ||||
| +	if (of_device_is_compatible(apc->np, "qcom,qca9550-pci")) { | ||||
| +		/* remove the reset of the PCIE PLL */ | ||||
| +		ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG); | ||||
| +		ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_PWD; | ||||
| +		ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl); | ||||
| + | ||||
| +		/* deassert bypass for the PCIE PLL */ | ||||
| +		ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG); | ||||
| +		ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS; | ||||
| +		ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl); | ||||
| +	} else { | ||||
| +		/* remove the reset of the PCIE PLL */ | ||||
| +		ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); | ||||
| +		ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; | ||||
| +		ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); | ||||
| + | ||||
| +		/* deassert bypass for the PCIE PLL */ | ||||
| +		ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); | ||||
| +		ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; | ||||
| +		ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); | ||||
| +	} | ||||
|   | ||||
|  	/* set PCIE Application Control to ready */ | ||||
|  	app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP); | ||||
| @@ -396,6 +412,14 @@ static int ar724x_pci_probe(struct platf | ||||
|  	if (apc->irq < 0) | ||||
|  		return -EINVAL; | ||||
|   | ||||
| +	apc->hc_reset = devm_reset_control_get_exclusive(&pdev->dev, "hc"); | ||||
| +	if (IS_ERR(apc->hc_reset)) | ||||
| +		return PTR_ERR(apc->hc_reset); | ||||
| + | ||||
| +	apc->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, "phy"); | ||||
| +	if (IS_ERR(apc->phy_reset)) | ||||
| +		return PTR_ERR(apc->phy_reset); | ||||
| + | ||||
|  	apc->np = pdev->dev.of_node; | ||||
|  	apc->pci_controller.pci_ops = &ar724x_pci_ops; | ||||
|  	apc->pci_controller.io_resource = &apc->io_res; | ||||
| @@ -406,7 +430,7 @@ static int ar724x_pci_probe(struct platf | ||||
|  	 * Do the full PCIE Root Complex Initialization Sequence if the PCIe | ||||
|  	 * host controller is in reset. | ||||
|  	 */ | ||||
| -	if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE) | ||||
| +	if (reset_control_status(apc->hc_reset)) | ||||
|  		ar724x_pci_hw_init(apc); | ||||
|   | ||||
|  	apc->link_up = ar724x_pci_check_link(apc); | ||||
| @@ -424,6 +448,7 @@ static int ar724x_pci_probe(struct platf | ||||
|   | ||||
|  static const struct of_device_id ar724x_pci_ids[] = { | ||||
|  	{ .compatible = "qcom,ar7240-pci" }, | ||||
| +	{ .compatible = "qcom,qca9550-pci" }, | ||||
|  	{}, | ||||
|  }; | ||||
|   | ||||
| @@ -0,0 +1,54 @@ | ||||
| From f32bc2aa01edcba2f2ed5db151cf183eac9ef919 Mon Sep 17 00:00:00 2001 | ||||
| From: Abhimanyu Vishwakarma <Abhimanyu.Vishwakarma@imgtec.com> | ||||
| Date: Sat, 25 Feb 2017 16:42:50 +0000 | ||||
| Subject: mtd: nor: support mtd name from device tree | ||||
|  | ||||
| Signed-off-by: Abhimanyu Vishwakarma <Abhimanyu.Vishwakarma@imgtec.com> | ||||
| --- | ||||
|  drivers/mtd/spi-nor/spi-nor.c | 8 +++++++- | ||||
|  1 file changed, 7 insertions(+), 1 deletion(-) | ||||
|  | ||||
| --- a/drivers/mtd/spi-nor/core.c | ||||
| +++ b/drivers/mtd/spi-nor/core.c | ||||
| @@ -3101,6 +3101,7 @@ int spi_nor_scan(struct spi_nor *nor, co | ||||
|  	struct device *dev = nor->dev; | ||||
|  	struct mtd_info *mtd = &nor->mtd; | ||||
|  	struct device_node *np = spi_nor_get_flash_node(nor); | ||||
| +	const char __maybe_unused *of_mtd_name = NULL; | ||||
|  	int ret; | ||||
|  	int i; | ||||
|   | ||||
| @@ -3155,7 +3156,12 @@ int spi_nor_scan(struct spi_nor *nor, co | ||||
|  	if (ret) | ||||
|  		return ret; | ||||
|   | ||||
| -	if (!mtd->name) | ||||
| +#ifdef CONFIG_MTD_OF_PARTS | ||||
| +	of_property_read_string(np, "linux,mtd-name", &of_mtd_name); | ||||
| +#endif | ||||
| +	if (of_mtd_name) | ||||
| +		mtd->name = of_mtd_name; | ||||
| +	else if (!mtd->name) | ||||
|  		mtd->name = dev_name(dev); | ||||
|  	mtd->priv = nor; | ||||
|  	mtd->type = MTD_NORFLASH; | ||||
| --- a/drivers/mtd/mtdcore.c | ||||
| +++ b/drivers/mtd/mtdcore.c | ||||
| @@ -778,6 +778,17 @@ out_error: | ||||
|   */ | ||||
|  static void mtd_set_dev_defaults(struct mtd_info *mtd) | ||||
|  { | ||||
| +#ifdef CONFIG_MTD_OF_PARTS | ||||
| +	const char __maybe_unused *of_mtd_name = NULL; | ||||
| +	struct device_node *np; | ||||
| + | ||||
| +	np = mtd_get_of_node(mtd); | ||||
| +	if (np && !mtd->name) { | ||||
| +		of_property_read_string(np, "linux,mtd-name", &of_mtd_name); | ||||
| +		if (of_mtd_name) | ||||
| +			mtd->name = of_mtd_name; | ||||
| +	} else | ||||
| +#endif | ||||
|  	if (mtd->dev.parent) { | ||||
|  		if (!mtd->owner && mtd->dev.parent->driver) | ||||
|  			mtd->owner = mtd->dev.parent->driver->owner; | ||||
| @@ -0,0 +1,27 @@ | ||||
| --- a/drivers/mtd/parsers/Makefile | ||||
| +++ b/drivers/mtd/parsers/Makefile | ||||
| @@ -8,6 +8,7 @@ obj-$(CONFIG_MTD_OF_PARTS)		+= ofpart.o | ||||
|  ofpart-y				+= ofpart_core.o | ||||
|  ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908)	+= ofpart_bcm4908.o | ||||
|  ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o | ||||
| +obj-$(CONFIG_MTD_PARSER_CYBERTAN)	+= parser_cybertan.o | ||||
|  obj-$(CONFIG_MTD_PARSER_IMAGETAG)	+= parser_imagetag.o | ||||
|  obj-$(CONFIG_MTD_AFS_PARTS)		+= afs.o | ||||
|  obj-$(CONFIG_MTD_PARSER_TRX)		+= parser_trx.o | ||||
| --- a/drivers/mtd/parsers/Kconfig | ||||
| +++ b/drivers/mtd/parsers/Kconfig | ||||
| @@ -102,6 +102,14 @@ config MTD_OF_PARTS_LINKSYS_NS | ||||
|  	  two "firmware" partitions. Currently used firmware has to be detected | ||||
|  	  using CFE environment variable. | ||||
|   | ||||
| +config MTD_PARSER_CYBERTAN | ||||
| +	tristate "Parser for Cybertan format partitions" | ||||
| +	depends on MTD && (ATH79 || COMPILE_TEST) | ||||
| +	help | ||||
| +	  Cybertan has a proprietory header than encompasses a Broadcom trx | ||||
| +	  header. This driver will parse the header and take care of the | ||||
| +	  special offsets that result in the extra headers. | ||||
| + | ||||
|  config MTD_PARSER_IMAGETAG | ||||
|  	tristate "Parser for BCM963XX Image Tag format partitions" | ||||
|  	depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST | ||||
| @@ -0,0 +1,45 @@ | ||||
| --- a/drivers/mtd/parsers/redboot.c | ||||
| +++ b/drivers/mtd/parsers/redboot.c | ||||
| @@ -90,12 +90,18 @@ static int parse_redboot_partitions(stru | ||||
|   | ||||
|  	parse_redboot_of(master); | ||||
|   | ||||
| +	buf = vmalloc(master->erasesize); | ||||
| +	if (!buf) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| + restart: | ||||
|  	if (directory < 0) { | ||||
|  		offset = master->size + directory * master->erasesize; | ||||
|  		while (mtd_block_isbad(master, offset)) { | ||||
|  			if (!offset) { | ||||
|  nogood: | ||||
|  				pr_notice("Failed to find a non-bad block to check for RedBoot partition table\n"); | ||||
| +				vfree(buf); | ||||
|  				return -EIO; | ||||
|  			} | ||||
|  			offset -= master->erasesize; | ||||
| @@ -108,10 +113,6 @@ nogood: | ||||
|  				goto nogood; | ||||
|  		} | ||||
|  	} | ||||
| -	buf = vmalloc(master->erasesize); | ||||
| - | ||||
| -	if (!buf) | ||||
| -		return -ENOMEM; | ||||
|   | ||||
|  	pr_notice("Searching for RedBoot partition table in %s at offset 0x%lx\n", | ||||
|  		  master->name, offset); | ||||
| @@ -183,6 +184,12 @@ nogood: | ||||
|  	} | ||||
|  	if (i == numslots) { | ||||
|  		/* Didn't find it */ | ||||
| +		if (offset + master->erasesize < master->size) { | ||||
| +			/* not at the end of the flash yet, maybe next block :) */ | ||||
| +			directory++; | ||||
| +			goto restart; | ||||
| +		} | ||||
| + | ||||
|  		pr_notice("No RedBoot partition table detected in %s\n", | ||||
|  			  master->name); | ||||
|  		ret = 0; | ||||
| @@ -0,0 +1,68 @@ | ||||
| From 8d8cdb4a6ccee5b62cc0dc64651c3946364514dc Mon Sep 17 00:00:00 2001 | ||||
| From: Luiz Angelo Daros de Luca <luizluca@gmail.com> | ||||
| Date: Mon, 10 Feb 2020 16:11:27 -0300 | ||||
| Subject: [PATCH] spi: ath79: Implement the spi_mem interface | ||||
|  | ||||
| Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com> | ||||
| --- | ||||
|  drivers/spi/spi-ath79.c | 35 +++++++++++++++++++++++++++++++++++ | ||||
|  1 file changed, 35 insertions(+) | ||||
|  | ||||
| --- a/drivers/spi/spi-ath79.c | ||||
| +++ b/drivers/spi/spi-ath79.c | ||||
| @@ -15,6 +15,7 @@ | ||||
|  #include <linux/platform_device.h> | ||||
|  #include <linux/io.h> | ||||
|  #include <linux/spi/spi.h> | ||||
| +#include <linux/spi/spi-mem.h> | ||||
|  #include <linux/spi/spi_bitbang.h> | ||||
|  #include <linux/bitops.h> | ||||
|  #include <linux/clk.h> | ||||
| @@ -133,6 +134,39 @@ static u32 ath79_spi_txrx_mode0(struct s | ||||
|  	return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS); | ||||
|  } | ||||
|   | ||||
| +static int ath79_exec_mem_op(struct spi_mem *mem, | ||||
| +                              const struct spi_mem_op *op) | ||||
| +{ | ||||
| +	struct ath79_spi *sp = ath79_spidev_to_sp(mem->spi); | ||||
| + | ||||
| +	/* Ensures that reading is performed on device connected | ||||
| +	   to hardware cs0 */ | ||||
| +	if (mem->spi->chip_select || mem->spi->cs_gpiod) | ||||
| +		return -ENOTSUPP; | ||||
| + | ||||
| +	/* Only use for fast-read op. */ | ||||
| +	if (op->cmd.opcode != 0x0b || op->data.dir != SPI_MEM_DATA_IN || | ||||
| +	    op->addr.nbytes != 3 || op->dummy.nbytes != 1) | ||||
| +		return -ENOTSUPP; | ||||
| + | ||||
| +	/* disable GPIO mode */ | ||||
| +	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); | ||||
| + | ||||
| +	memcpy_fromio(op->data.buf.in, sp->base + op->addr.val, op->data.nbytes); | ||||
| + | ||||
| +	/* enable GPIO mode */ | ||||
| +	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); | ||||
| + | ||||
| +	/* restore IOC register */ | ||||
| +	ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct spi_controller_mem_ops ath79_mem_ops = { | ||||
| +	.exec_op = ath79_exec_mem_op, | ||||
| +}; | ||||
| + | ||||
|  static int ath79_spi_probe(struct platform_device *pdev) | ||||
|  { | ||||
|  	struct spi_master *master; | ||||
| @@ -165,6 +199,7 @@ static int ath79_spi_probe(struct platfo | ||||
|  		ret = PTR_ERR(sp->base); | ||||
|  		goto err_put_master; | ||||
|  	} | ||||
| +	master->mem_ops = &ath79_mem_ops; | ||||
|   | ||||
|  	sp->clk = devm_clk_get(&pdev->dev, "ahb"); | ||||
|  	if (IS_ERR(sp->clk)) { | ||||
| @@ -0,0 +1,29 @@ | ||||
| --- a/drivers/net/ethernet/atheros/Kconfig | ||||
| +++ b/drivers/net/ethernet/atheros/Kconfig | ||||
| @@ -17,14 +17,7 @@ config NET_VENDOR_ATHEROS | ||||
|   | ||||
|  if NET_VENDOR_ATHEROS | ||||
|   | ||||
| -config AG71XX | ||||
| -	tristate "Atheros AR7XXX/AR9XXX built-in ethernet mac support" | ||||
| -	depends on ATH79 | ||||
| -	select PHYLINK | ||||
| -	imply NET_SELFTESTS | ||||
| -	help | ||||
| -	  If you wish to compile a kernel for AR7XXX/91XXX and enable | ||||
| -	  ethernet support, then you should always answer Y to this. | ||||
| +source "drivers/net/ethernet/atheros/ag71xx/Kconfig" | ||||
|   | ||||
|  config ATL2 | ||||
|  	tristate "Atheros L2 Fast Ethernet support" | ||||
| --- a/drivers/net/ethernet/atheros/Makefile | ||||
| +++ b/drivers/net/ethernet/atheros/Makefile | ||||
| @@ -3,7 +3,7 @@ | ||||
|  # Makefile for the Atheros network device drivers. | ||||
|  # | ||||
|   | ||||
| -obj-$(CONFIG_AG71XX) += ag71xx.o | ||||
| +obj-$(CONFIG_AG71XX) += ag71xx/ | ||||
|  obj-$(CONFIG_ATL1) += atlx/ | ||||
|  obj-$(CONFIG_ATL2) += atlx/ | ||||
|  obj-$(CONFIG_ATL1E) += atl1e/ | ||||
| @@ -0,0 +1,12 @@ | ||||
| --- a/drivers/Makefile | ||||
| +++ b/drivers/Makefile | ||||
| @@ -80,8 +80,8 @@ obj-y				+= scsi/ | ||||
|  obj-y				+= nvme/ | ||||
|  obj-$(CONFIG_ATA)		+= ata/ | ||||
|  obj-$(CONFIG_TARGET_CORE)	+= target/ | ||||
| -obj-$(CONFIG_MTD)		+= mtd/ | ||||
|  obj-$(CONFIG_SPI)		+= spi/ | ||||
| +obj-$(CONFIG_MTD)		+= mtd/ | ||||
|  obj-$(CONFIG_SPMI)		+= spmi/ | ||||
|  obj-$(CONFIG_HSI)		+= hsi/ | ||||
|  obj-$(CONFIG_SLIMBUS)		+= slimbus/ | ||||
| @@ -0,0 +1,25 @@ | ||||
| --- a/drivers/mtd/nand/raw/Kconfig | ||||
| +++ b/drivers/mtd/nand/raw/Kconfig | ||||
| @@ -555,4 +555,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE | ||||
|  	  load time (assuming you build diskonchip as a module) with the module | ||||
|  	  parameter "inftl_bbt_write=1". | ||||
|   | ||||
| +config MTD_NAND_AR934X | ||||
| +	tristate "Support for NAND controller on Qualcomm Atheros AR934x/QCA955x SoCs" | ||||
| +	depends on ATH79 || COMPILE_TEST | ||||
| +	depends on HAS_IOMEM | ||||
| +	help | ||||
| +	  Enables support for NAND controller on Qualcomm Atheros SoCs. | ||||
| +	  This controller is found on AR934x and QCA955x SoCs. | ||||
| + | ||||
|  endif # MTD_RAW_NAND | ||||
| --- a/drivers/mtd/nand/raw/Makefile | ||||
| +++ b/drivers/mtd/nand/raw/Makefile | ||||
| @@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_ARASAN)		+= arasan | ||||
|  obj-$(CONFIG_MTD_NAND_INTEL_LGM)	+= intel-nand-controller.o | ||||
|  obj-$(CONFIG_MTD_NAND_ROCKCHIP)		+= rockchip-nand-controller.o | ||||
|  obj-$(CONFIG_MTD_NAND_PL35X)		+= pl35x-nand-controller.o | ||||
| +obj-$(CONFIG_MTD_NAND_AR934X)		+= ar934x_nand.o | ||||
|   | ||||
|  nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o | ||||
|  nand-objs += nand_onfi.o | ||||
| @@ -0,0 +1,98 @@ | ||||
| --- /dev/null | ||||
| +++ b/arch/mips/include/asm/mach-ath79/mangle-port.h | ||||
| @@ -0,0 +1,37 @@ | ||||
| +/* | ||||
| + *  Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org> | ||||
| + * | ||||
| + *  This file was derived from: inlude/asm-mips/mach-generic/mangle-port.h | ||||
| + *      Copyright (C) 2003, 2004 Ralf Baechle | ||||
| + * | ||||
| + *  This program is free software; you can redistribute it and/or modify it | ||||
| + *  under the terms of the GNU General Public License version 2 as published | ||||
| + *  by the Free Software Foundation. | ||||
| + */ | ||||
| + | ||||
| +#ifndef __ASM_MACH_ATH79_MANGLE_PORT_H | ||||
| +#define __ASM_MACH_ATH79_MANGLE_PORT_H | ||||
| + | ||||
| +#ifdef CONFIG_PCI_AR71XX | ||||
| +extern unsigned long (ath79_pci_swizzle_b)(unsigned long port); | ||||
| +extern unsigned long (ath79_pci_swizzle_w)(unsigned long port); | ||||
| +#else | ||||
| +#define ath79_pci_swizzle_b(port) (port) | ||||
| +#define ath79_pci_swizzle_w(port) (port) | ||||
| +#endif | ||||
| + | ||||
| +#define __swizzle_addr_b(port)	ath79_pci_swizzle_b(port) | ||||
| +#define __swizzle_addr_w(port)	ath79_pci_swizzle_w(port) | ||||
| +#define __swizzle_addr_l(port)	(port) | ||||
| +#define __swizzle_addr_q(port)	(port) | ||||
| + | ||||
| +# define ioswabb(a, x)           (x) | ||||
| +# define __mem_ioswabb(a, x)     (x) | ||||
| +# define ioswabw(a, x)           (x) | ||||
| +# define __mem_ioswabw(a, x)     cpu_to_le16(x) | ||||
| +# define ioswabl(a, x)           (x) | ||||
| +# define __mem_ioswabl(a, x)     cpu_to_le32(x) | ||||
| +# define ioswabq(a, x)           (x) | ||||
| +# define __mem_ioswabq(a, x)     cpu_to_le64(x) | ||||
| + | ||||
| +#endif /* __ASM_MACH_ATH79_MANGLE_PORT_H */ | ||||
| --- a/arch/mips/pci/pci-ar71xx.c | ||||
| +++ b/arch/mips/pci/pci-ar71xx.c | ||||
| @@ -68,6 +68,45 @@ static const u32 ar71xx_pci_read_mask[8] | ||||
|  	0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0 | ||||
|  }; | ||||
|   | ||||
| +static unsigned long (*__ath79_pci_swizzle_b)(unsigned long port); | ||||
| +static unsigned long (*__ath79_pci_swizzle_w)(unsigned long port); | ||||
| + | ||||
| +static inline bool ar71xx_is_pci_addr(unsigned long port) | ||||
| +{ | ||||
| +	unsigned long phys = CPHYSADDR(port); | ||||
| + | ||||
| +	return (phys >= AR71XX_PCI_MEM_BASE && | ||||
| +		phys < AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE); | ||||
| +} | ||||
| + | ||||
| +static unsigned long ar71xx_pci_swizzle_b(unsigned long port) | ||||
| +{ | ||||
| +	return ar71xx_is_pci_addr(port) ? port ^ 3 : port; | ||||
| +} | ||||
| + | ||||
| +static unsigned long ar71xx_pci_swizzle_w(unsigned long port) | ||||
| +{ | ||||
| +	return ar71xx_is_pci_addr(port) ? port ^ 2 : port; | ||||
| +} | ||||
| + | ||||
| +unsigned long ath79_pci_swizzle_b(unsigned long port) | ||||
| +{ | ||||
| +	if (__ath79_pci_swizzle_b) | ||||
| +		return __ath79_pci_swizzle_b(port); | ||||
| + | ||||
| +	return port; | ||||
| +} | ||||
| +EXPORT_SYMBOL(ath79_pci_swizzle_b); | ||||
| + | ||||
| +unsigned long ath79_pci_swizzle_w(unsigned long port) | ||||
| +{ | ||||
| +	if (__ath79_pci_swizzle_w) | ||||
| +		return __ath79_pci_swizzle_w(port); | ||||
| + | ||||
| +	return port; | ||||
| +} | ||||
| +EXPORT_SYMBOL(ath79_pci_swizzle_w); | ||||
| + | ||||
|  static inline u32 ar71xx_pci_get_ble(int where, int size, int local) | ||||
|  { | ||||
|  	u32 t; | ||||
| @@ -276,6 +315,9 @@ static int ar71xx_pci_probe(struct platf | ||||
|   | ||||
|  	register_pci_controller(&apc->pci_ctrl); | ||||
|   | ||||
| +	__ath79_pci_swizzle_b = ar71xx_pci_swizzle_b; | ||||
| +	__ath79_pci_swizzle_w = ar71xx_pci_swizzle_w; | ||||
| + | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| @@ -0,0 +1,32 @@ | ||||
| --- a/drivers/net/mdio/mdio-bitbang.c | ||||
| +++ b/drivers/net/mdio/mdio-bitbang.c | ||||
| @@ -152,7 +152,7 @@ static int mdiobb_cmd_addr(struct mdiobb | ||||
|  int mdiobb_read(struct mii_bus *bus, int phy, int reg) | ||||
|  { | ||||
|  	struct mdiobb_ctrl *ctrl = bus->priv; | ||||
| -	int ret, i; | ||||
| +	int ret; | ||||
|   | ||||
|  	if (reg & MII_ADDR_C45) { | ||||
|  		reg = mdiobb_cmd_addr(ctrl, phy, reg); | ||||
| @@ -162,19 +162,7 @@ int mdiobb_read(struct mii_bus *bus, int | ||||
|   | ||||
|  	ctrl->ops->set_mdio_dir(ctrl, 0); | ||||
|   | ||||
| -	/* check the turnaround bit: the PHY should be driving it to zero, if this | ||||
| -	 * PHY is listed in phy_ignore_ta_mask as having broken TA, skip that | ||||
| -	 */ | ||||
| -	if (mdiobb_get_bit(ctrl) != 0 && | ||||
| -	    !(bus->phy_ignore_ta_mask & (1 << phy))) { | ||||
| -		/* PHY didn't drive TA low -- flush any bits it | ||||
| -		 * may be trying to send. | ||||
| -		 */ | ||||
| -		for (i = 0; i < 32; i++) | ||||
| -			mdiobb_get_bit(ctrl); | ||||
| - | ||||
| -		return 0xffff; | ||||
| -	} | ||||
| +	mdiobb_get_bit(ctrl); | ||||
|   | ||||
|  	ret = mdiobb_get_num(ctrl, 16); | ||||
|  	mdiobb_get_bit(ctrl); | ||||
| @@ -0,0 +1,61 @@ | ||||
| From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001 | ||||
| From: Jonas Gorski <jogo@openwrt.org> | ||||
| Date: Tue, 16 Jun 2015 13:15:08 +0200 | ||||
| Subject: [PATCH] phy/mdio-bitbang: prevent rescheduling during command | ||||
|  | ||||
| It seems some phys have some maximum timings for accessing the MDIO line, | ||||
| resulting in bit errors under cpu stress. Prevent this from happening by | ||||
| disabling interrupts when sending commands. | ||||
|  | ||||
| Signed-off-by: Jonas Gorski <jogo@openwrt.org> | ||||
| --- | ||||
|  drivers/net/mdio/mdio-bitbang.c | 9 +++++++++ | ||||
|  1 file changed, 9 insertions(+) | ||||
|  | ||||
| --- a/drivers/net/mdio/mdio-bitbang.c | ||||
| +++ b/drivers/net/mdio/mdio-bitbang.c | ||||
| @@ -14,6 +14,7 @@ | ||||
|   * Vitaly Bordug <vbordug@ru.mvista.com> | ||||
|   */ | ||||
|   | ||||
| +#include <linux/irqflags.h> | ||||
|  #include <linux/delay.h> | ||||
|  #include <linux/mdio-bitbang.h> | ||||
|  #include <linux/module.h> | ||||
| @@ -153,7 +154,9 @@ int mdiobb_read(struct mii_bus *bus, int | ||||
|  { | ||||
|  	struct mdiobb_ctrl *ctrl = bus->priv; | ||||
|  	int ret; | ||||
| +	unsigned long flags; | ||||
|   | ||||
| +	local_irq_save(flags); | ||||
|  	if (reg & MII_ADDR_C45) { | ||||
|  		reg = mdiobb_cmd_addr(ctrl, phy, reg); | ||||
|  		mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); | ||||
| @@ -166,6 +169,7 @@ int mdiobb_read(struct mii_bus *bus, int | ||||
|   | ||||
|  	ret = mdiobb_get_num(ctrl, 16); | ||||
|  	mdiobb_get_bit(ctrl); | ||||
| +	local_irq_restore(flags); | ||||
|  	return ret; | ||||
|  } | ||||
|  EXPORT_SYMBOL(mdiobb_read); | ||||
| @@ -173,7 +177,9 @@ EXPORT_SYMBOL(mdiobb_read); | ||||
|  int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) | ||||
|  { | ||||
|  	struct mdiobb_ctrl *ctrl = bus->priv; | ||||
| +	unsigned long flags; | ||||
|   | ||||
| +	local_irq_save(flags); | ||||
|  	if (reg & MII_ADDR_C45) { | ||||
|  		reg = mdiobb_cmd_addr(ctrl, phy, reg); | ||||
|  		mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); | ||||
| @@ -188,6 +194,8 @@ int mdiobb_write(struct mii_bus *bus, in | ||||
|   | ||||
|  	ctrl->ops->set_mdio_dir(ctrl, 0); | ||||
|  	mdiobb_get_bit(ctrl); | ||||
| +	local_irq_restore(flags); | ||||
| + | ||||
|  	return 0; | ||||
|  } | ||||
|  EXPORT_SYMBOL(mdiobb_write); | ||||
							
								
								
									
										855
									
								
								target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										855
									
								
								target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,855 @@ | ||||
| --- a/arch/mips/include/asm/checksum.h | ||||
| +++ b/arch/mips/include/asm/checksum.h | ||||
| @@ -100,26 +100,30 @@ static inline __sum16 ip_fast_csum(const | ||||
|  	const unsigned int *stop = word + ihl; | ||||
|  	unsigned int csum; | ||||
|  	int carry; | ||||
| +	unsigned int w; | ||||
|   | ||||
| -	csum = word[0]; | ||||
| -	csum += word[1]; | ||||
| -	carry = (csum < word[1]); | ||||
| +	csum = net_hdr_word(word++); | ||||
| + | ||||
| +	w = net_hdr_word(word++); | ||||
| +	csum += w; | ||||
| +	carry = (csum < w); | ||||
|  	csum += carry; | ||||
|   | ||||
| -	csum += word[2]; | ||||
| -	carry = (csum < word[2]); | ||||
| +	w = net_hdr_word(word++); | ||||
| +	csum += w; | ||||
| +	carry = (csum < w); | ||||
|  	csum += carry; | ||||
|   | ||||
| -	csum += word[3]; | ||||
| -	carry = (csum < word[3]); | ||||
| +	w = net_hdr_word(word++); | ||||
| +	csum += w; | ||||
| +	carry = (csum < w); | ||||
|  	csum += carry; | ||||
|   | ||||
| -	word += 4; | ||||
|  	do { | ||||
| -		csum += *word; | ||||
| -		carry = (csum < *word); | ||||
| +		w = net_hdr_word(word++); | ||||
| +		csum += w; | ||||
| +		carry = (csum < w); | ||||
|  		csum += carry; | ||||
| -		word++; | ||||
|  	} while (word != stop); | ||||
|   | ||||
|  	return csum_fold(csum); | ||||
| @@ -182,73 +186,6 @@ static inline __sum16 ip_compute_csum(co | ||||
|  	return csum_fold(csum_partial(buff, len, 0)); | ||||
|  } | ||||
|   | ||||
| -#define _HAVE_ARCH_IPV6_CSUM | ||||
| -static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, | ||||
| -					  const struct in6_addr *daddr, | ||||
| -					  __u32 len, __u8 proto, | ||||
| -					  __wsum sum) | ||||
| -{ | ||||
| -	__wsum tmp; | ||||
| - | ||||
| -	__asm__( | ||||
| -	"	.set	push		# csum_ipv6_magic\n" | ||||
| -	"	.set	noreorder	\n" | ||||
| -	"	.set	noat		\n" | ||||
| -	"	addu	%0, %5		# proto (long in network byte order)\n" | ||||
| -	"	sltu	$1, %0, %5	\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| - | ||||
| -	"	addu	%0, %6		# csum\n" | ||||
| -	"	sltu	$1, %0, %6	\n" | ||||
| -	"	lw	%1, 0(%2)	# four words source address\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| -	"	addu	%0, %1		\n" | ||||
| -	"	sltu	$1, %0, %1	\n" | ||||
| - | ||||
| -	"	lw	%1, 4(%2)	\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| -	"	addu	%0, %1		\n" | ||||
| -	"	sltu	$1, %0, %1	\n" | ||||
| - | ||||
| -	"	lw	%1, 8(%2)	\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| -	"	addu	%0, %1		\n" | ||||
| -	"	sltu	$1, %0, %1	\n" | ||||
| - | ||||
| -	"	lw	%1, 12(%2)	\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| -	"	addu	%0, %1		\n" | ||||
| -	"	sltu	$1, %0, %1	\n" | ||||
| - | ||||
| -	"	lw	%1, 0(%3)	\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| -	"	addu	%0, %1		\n" | ||||
| -	"	sltu	$1, %0, %1	\n" | ||||
| - | ||||
| -	"	lw	%1, 4(%3)	\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| -	"	addu	%0, %1		\n" | ||||
| -	"	sltu	$1, %0, %1	\n" | ||||
| - | ||||
| -	"	lw	%1, 8(%3)	\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| -	"	addu	%0, %1		\n" | ||||
| -	"	sltu	$1, %0, %1	\n" | ||||
| - | ||||
| -	"	lw	%1, 12(%3)	\n" | ||||
| -	"	addu	%0, $1		\n" | ||||
| -	"	addu	%0, %1		\n" | ||||
| -	"	sltu	$1, %0, %1	\n" | ||||
| - | ||||
| -	"	addu	%0, $1		# Add final carry\n" | ||||
| -	"	.set	pop" | ||||
| -	: "=&r" (sum), "=&r" (tmp) | ||||
| -	: "r" (saddr), "r" (daddr), | ||||
| -	  "0" (htonl(len)), "r" (htonl(proto)), "r" (sum)); | ||||
| - | ||||
| -	return csum_fold(sum); | ||||
| -} | ||||
| - | ||||
|  #include <asm-generic/checksum.h> | ||||
|  #endif /* CONFIG_GENERIC_CSUM */ | ||||
|   | ||||
| --- a/include/uapi/linux/ip.h | ||||
| +++ b/include/uapi/linux/ip.h | ||||
| @@ -103,7 +103,7 @@ struct iphdr { | ||||
|  	__be32	saddr; | ||||
|  	__be32	daddr; | ||||
|  	/*The options start here. */ | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|   | ||||
|  struct ip_auth_hdr { | ||||
| --- a/include/uapi/linux/ipv6.h | ||||
| +++ b/include/uapi/linux/ipv6.h | ||||
| @@ -132,7 +132,7 @@ struct ipv6hdr { | ||||
|   | ||||
|  	struct	in6_addr	saddr; | ||||
|  	struct	in6_addr	daddr; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|   | ||||
|  /* index values for the variables in ipv6_devconf */ | ||||
| --- a/include/uapi/linux/tcp.h | ||||
| +++ b/include/uapi/linux/tcp.h | ||||
| @@ -55,7 +55,7 @@ struct tcphdr { | ||||
|  	__be16	window; | ||||
|  	__sum16	check; | ||||
|  	__be16	urg_ptr; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  /* | ||||
|   *	The union cast uses a gcc extension to avoid aliasing problems | ||||
| @@ -65,7 +65,7 @@ struct tcphdr { | ||||
|  union tcp_word_hdr { | ||||
|  	struct tcphdr hdr; | ||||
|  	__be32        words[5]; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  #define tcp_flag_word(tp) (((union tcp_word_hdr *)(tp))->words[3]) | ||||
|   | ||||
| --- a/include/uapi/linux/udp.h | ||||
| +++ b/include/uapi/linux/udp.h | ||||
| @@ -25,7 +25,7 @@ struct udphdr { | ||||
|  	__be16	dest; | ||||
|  	__be16	len; | ||||
|  	__sum16	check; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  /* UDP socket options */ | ||||
|  #define UDP_CORK	1	/* Never send partially complete segments */ | ||||
| --- a/net/netfilter/nf_conntrack_core.c | ||||
| +++ b/net/netfilter/nf_conntrack_core.c | ||||
| @@ -292,8 +292,8 @@ nf_ct_get_tuple(const struct sk_buff *sk | ||||
|   | ||||
|  	switch (l3num) { | ||||
|  	case NFPROTO_IPV4: | ||||
| -		tuple->src.u3.ip = ap[0]; | ||||
| -		tuple->dst.u3.ip = ap[1]; | ||||
| +		tuple->src.u3.ip = net_hdr_word(ap++); | ||||
| +		tuple->dst.u3.ip = net_hdr_word(ap); | ||||
|  		break; | ||||
|  	case NFPROTO_IPV6: | ||||
|  		memcpy(tuple->src.u3.ip6, ap, sizeof(tuple->src.u3.ip6)); | ||||
| --- a/include/uapi/linux/icmp.h | ||||
| +++ b/include/uapi/linux/icmp.h | ||||
| @@ -102,7 +102,7 @@ struct icmphdr { | ||||
|  	} frag; | ||||
|  	__u8	reserved[4]; | ||||
|    } un; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|   | ||||
|  /* | ||||
| --- a/include/uapi/linux/in6.h | ||||
| +++ b/include/uapi/linux/in6.h | ||||
| @@ -43,7 +43,7 @@ struct in6_addr { | ||||
|  #define s6_addr16		in6_u.u6_addr16 | ||||
|  #define s6_addr32		in6_u.u6_addr32 | ||||
|  #endif | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|  #endif /* __UAPI_DEF_IN6_ADDR */ | ||||
|   | ||||
|  #if __UAPI_DEF_SOCKADDR_IN6 | ||||
| --- a/net/ipv6/tcp_ipv6.c | ||||
| +++ b/net/ipv6/tcp_ipv6.c | ||||
| @@ -35,6 +35,7 @@ | ||||
|  #include <linux/ipsec.h> | ||||
|  #include <linux/times.h> | ||||
|  #include <linux/slab.h> | ||||
| +#include <asm/unaligned.h> | ||||
|  #include <linux/uaccess.h> | ||||
|  #include <linux/ipv6.h> | ||||
|  #include <linux/icmpv6.h> | ||||
| @@ -941,10 +942,10 @@ static void tcp_v6_send_response(const s | ||||
|  	topt = (__be32 *)(t1 + 1); | ||||
|   | ||||
|  	if (tsecr) { | ||||
| -		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | ||||
| -				(TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); | ||||
| -		*topt++ = htonl(tsval); | ||||
| -		*topt++ = htonl(tsecr); | ||||
| +		put_unaligned_be32((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | ||||
| +				(TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP, topt++); | ||||
| +		put_unaligned_be32(tsval, topt++); | ||||
| +		put_unaligned_be32(tsecr, topt++); | ||||
|  	} | ||||
|   | ||||
|  	if (mrst) | ||||
| --- a/include/linux/ipv6.h | ||||
| +++ b/include/linux/ipv6.h | ||||
| @@ -6,6 +6,7 @@ | ||||
|   | ||||
|  #define ipv6_optlen(p)  (((p)->hdrlen+1) << 3) | ||||
|  #define ipv6_authlen(p) (((p)->hdrlen+2) << 2) | ||||
| + | ||||
|  /* | ||||
|   * This structure contains configuration options per IPv6 link. | ||||
|   */ | ||||
| --- a/net/ipv6/datagram.c | ||||
| +++ b/net/ipv6/datagram.c | ||||
| @@ -492,7 +492,7 @@ int ipv6_recv_error(struct sock *sk, str | ||||
|  				ipv6_iface_scope_id(&sin->sin6_addr, | ||||
|  						    IP6CB(skb)->iif); | ||||
|  		} else { | ||||
| -			ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset), | ||||
| +			ipv6_addr_set_v4mapped(net_hdr_word(nh + serr->addr_offset), | ||||
|  					       &sin->sin6_addr); | ||||
|  			sin->sin6_scope_id = 0; | ||||
|  		} | ||||
| @@ -846,12 +846,12 @@ int ip6_datagram_send_ctl(struct net *ne | ||||
|  			} | ||||
|   | ||||
|  			if (fl6->flowlabel&IPV6_FLOWINFO_MASK) { | ||||
| -				if ((fl6->flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { | ||||
| +				if ((fl6->flowlabel^net_hdr_word(CMSG_DATA(cmsg)))&~IPV6_FLOWINFO_MASK) { | ||||
|  					err = -EINVAL; | ||||
|  					goto exit_f; | ||||
|  				} | ||||
|  			} | ||||
| -			fl6->flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg); | ||||
| +			fl6->flowlabel = IPV6_FLOWINFO_MASK & net_hdr_word(CMSG_DATA(cmsg)); | ||||
|  			break; | ||||
|   | ||||
|  		case IPV6_2292HOPOPTS: | ||||
| --- a/net/ipv6/exthdrs.c | ||||
| +++ b/net/ipv6/exthdrs.c | ||||
| @@ -1009,7 +1009,7 @@ static bool ipv6_hop_jumbo(struct sk_buf | ||||
|  		goto drop; | ||||
|  	} | ||||
|   | ||||
| -	pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); | ||||
| +	pkt_len = ntohl(net_hdr_word(nh + optoff + 2)); | ||||
|  	if (pkt_len <= IPV6_MAXPLEN) { | ||||
|  		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); | ||||
|  		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); | ||||
| --- a/include/linux/types.h | ||||
| +++ b/include/linux/types.h | ||||
| @@ -231,5 +231,11 @@ typedef void (*swap_func_t)(void *a, voi | ||||
|  typedef int (*cmp_r_func_t)(const void *a, const void *b, const void *priv); | ||||
|  typedef int (*cmp_func_t)(const void *a, const void *b); | ||||
|   | ||||
| +struct net_hdr_word { | ||||
| +       u32 words[1]; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
| + | ||||
| +#define net_hdr_word(_p) (((struct net_hdr_word *) (_p))->words[0]) | ||||
| + | ||||
|  #endif /*  __ASSEMBLY__ */ | ||||
|  #endif /* _LINUX_TYPES_H */ | ||||
| --- a/net/ipv4/af_inet.c | ||||
| +++ b/net/ipv4/af_inet.c | ||||
| @@ -1475,8 +1475,8 @@ struct sk_buff *inet_gro_receive(struct | ||||
|  	if (unlikely(ip_fast_csum((u8 *)iph, 5))) | ||||
|  		goto out_unlock; | ||||
|   | ||||
| -	id = ntohl(*(__be32 *)&iph->id); | ||||
| -	flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF)); | ||||
| +	id = ntohl(net_hdr_word(&iph->id)); | ||||
| +	flush = (u16)((ntohl(net_hdr_word(iph)) ^ skb_gro_len(skb)) | (id & ~IP_DF)); | ||||
|  	id >>= 16; | ||||
|   | ||||
|  	list_for_each_entry(p, head, list) { | ||||
| --- a/net/ipv4/tcp_output.c | ||||
| +++ b/net/ipv4/tcp_output.c | ||||
| @@ -612,48 +612,53 @@ static void tcp_options_write(__be32 *pt | ||||
|  	u16 options = opts->options;	/* mungable copy */ | ||||
|   | ||||
|  	if (unlikely(OPTION_MD5 & options)) { | ||||
| -		*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | ||||
| -			       (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); | ||||
| +		net_hdr_word(ptr++) = | ||||
| +			htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | ||||
| +			      (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); | ||||
|  		/* overload cookie hash location */ | ||||
|  		opts->hash_location = (__u8 *)ptr; | ||||
|  		ptr += 4; | ||||
|  	} | ||||
|   | ||||
|  	if (unlikely(opts->mss)) { | ||||
| -		*ptr++ = htonl((TCPOPT_MSS << 24) | | ||||
| -			       (TCPOLEN_MSS << 16) | | ||||
| -			       opts->mss); | ||||
| +		net_hdr_word(ptr++) = | ||||
| +			htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | | ||||
| +			      opts->mss); | ||||
|  	} | ||||
|   | ||||
|  	if (likely(OPTION_TS & options)) { | ||||
|  		if (unlikely(OPTION_SACK_ADVERTISE & options)) { | ||||
| -			*ptr++ = htonl((TCPOPT_SACK_PERM << 24) | | ||||
| -				       (TCPOLEN_SACK_PERM << 16) | | ||||
| -				       (TCPOPT_TIMESTAMP << 8) | | ||||
| -				       TCPOLEN_TIMESTAMP); | ||||
| +			net_hdr_word(ptr++) = | ||||
| +				htonl((TCPOPT_SACK_PERM << 24) | | ||||
| +				      (TCPOLEN_SACK_PERM << 16) | | ||||
| +				      (TCPOPT_TIMESTAMP << 8) | | ||||
| +				      TCPOLEN_TIMESTAMP); | ||||
|  			options &= ~OPTION_SACK_ADVERTISE; | ||||
|  		} else { | ||||
| -			*ptr++ = htonl((TCPOPT_NOP << 24) | | ||||
| -				       (TCPOPT_NOP << 16) | | ||||
| -				       (TCPOPT_TIMESTAMP << 8) | | ||||
| -				       TCPOLEN_TIMESTAMP); | ||||
| +			net_hdr_word(ptr++) = | ||||
| +				htonl((TCPOPT_NOP << 24) | | ||||
| +				      (TCPOPT_NOP << 16) | | ||||
| +				      (TCPOPT_TIMESTAMP << 8) | | ||||
| +				      TCPOLEN_TIMESTAMP); | ||||
|  		} | ||||
| -		*ptr++ = htonl(opts->tsval); | ||||
| -		*ptr++ = htonl(opts->tsecr); | ||||
| +		net_hdr_word(ptr++) = htonl(opts->tsval); | ||||
| +		net_hdr_word(ptr++) = htonl(opts->tsecr); | ||||
|  	} | ||||
|   | ||||
|  	if (unlikely(OPTION_SACK_ADVERTISE & options)) { | ||||
| -		*ptr++ = htonl((TCPOPT_NOP << 24) | | ||||
| -			       (TCPOPT_NOP << 16) | | ||||
| -			       (TCPOPT_SACK_PERM << 8) | | ||||
| -			       TCPOLEN_SACK_PERM); | ||||
| +		net_hdr_word(ptr++) = | ||||
| +			htonl((TCPOPT_NOP << 24) | | ||||
| +			      (TCPOPT_NOP << 16) | | ||||
| +			      (TCPOPT_SACK_PERM << 8) | | ||||
| +			      TCPOLEN_SACK_PERM); | ||||
|  	} | ||||
|   | ||||
|  	if (unlikely(OPTION_WSCALE & options)) { | ||||
| -		*ptr++ = htonl((TCPOPT_NOP << 24) | | ||||
| -			       (TCPOPT_WINDOW << 16) | | ||||
| -			       (TCPOLEN_WINDOW << 8) | | ||||
| -			       opts->ws); | ||||
| +		net_hdr_word(ptr++) = | ||||
| +			htonl((TCPOPT_NOP << 24) | | ||||
| +			      (TCPOPT_WINDOW << 16) | | ||||
| +			      (TCPOLEN_WINDOW << 8) | | ||||
| +			      opts->ws); | ||||
|  	} | ||||
|   | ||||
|  	if (unlikely(opts->num_sack_blocks)) { | ||||
| @@ -661,16 +666,17 @@ static void tcp_options_write(__be32 *pt | ||||
|  			tp->duplicate_sack : tp->selective_acks; | ||||
|  		int this_sack; | ||||
|   | ||||
| -		*ptr++ = htonl((TCPOPT_NOP  << 24) | | ||||
| -			       (TCPOPT_NOP  << 16) | | ||||
| -			       (TCPOPT_SACK <<  8) | | ||||
| -			       (TCPOLEN_SACK_BASE + (opts->num_sack_blocks * | ||||
| +		net_hdr_word(ptr++) = | ||||
| +			htonl((TCPOPT_NOP << 24) | | ||||
| +			      (TCPOPT_NOP << 16) | | ||||
| +			      (TCPOPT_SACK << 8) | | ||||
| +			      (TCPOLEN_SACK_BASE + (opts->num_sack_blocks * | ||||
|  						     TCPOLEN_SACK_PERBLOCK))); | ||||
|   | ||||
|  		for (this_sack = 0; this_sack < opts->num_sack_blocks; | ||||
|  		     ++this_sack) { | ||||
| -			*ptr++ = htonl(sp[this_sack].start_seq); | ||||
| -			*ptr++ = htonl(sp[this_sack].end_seq); | ||||
| +			net_hdr_word(ptr++) = htonl(sp[this_sack].start_seq); | ||||
| +			net_hdr_word(ptr++) = htonl(sp[this_sack].end_seq); | ||||
|  		} | ||||
|   | ||||
|  		tp->rx_opt.dsack = 0; | ||||
| @@ -683,13 +689,14 @@ static void tcp_options_write(__be32 *pt | ||||
|   | ||||
|  		if (foc->exp) { | ||||
|  			len = TCPOLEN_EXP_FASTOPEN_BASE + foc->len; | ||||
| -			*ptr = htonl((TCPOPT_EXP << 24) | (len << 16) | | ||||
| +			net_hdr_word(ptr) = | ||||
| +				htonl((TCPOPT_EXP << 24) | (len << 16) | | ||||
|  				     TCPOPT_FASTOPEN_MAGIC); | ||||
|  			p += TCPOLEN_EXP_FASTOPEN_BASE; | ||||
|  		} else { | ||||
|  			len = TCPOLEN_FASTOPEN_BASE + foc->len; | ||||
| -			*p++ = TCPOPT_FASTOPEN; | ||||
| -			*p++ = len; | ||||
| +			net_hdr_word(p++) = TCPOPT_FASTOPEN; | ||||
| +			net_hdr_word(p++) = len; | ||||
|  		} | ||||
|   | ||||
|  		memcpy(p, foc->val, foc->len); | ||||
| --- a/include/uapi/linux/igmp.h | ||||
| +++ b/include/uapi/linux/igmp.h | ||||
| @@ -33,7 +33,7 @@ struct igmphdr { | ||||
|  	__u8 code;		/* For newer IGMP */ | ||||
|  	__sum16 csum; | ||||
|  	__be32 group; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  /* V3 group record types [grec_type] */ | ||||
|  #define IGMPV3_MODE_IS_INCLUDE		1 | ||||
| @@ -49,7 +49,7 @@ struct igmpv3_grec { | ||||
|  	__be16	grec_nsrcs; | ||||
|  	__be32	grec_mca; | ||||
|  	__be32	grec_src[0]; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  struct igmpv3_report { | ||||
|  	__u8 type; | ||||
| @@ -58,7 +58,7 @@ struct igmpv3_report { | ||||
|  	__be16 resv2; | ||||
|  	__be16 ngrec; | ||||
|  	struct igmpv3_grec grec[0]; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  struct igmpv3_query { | ||||
|  	__u8 type; | ||||
| @@ -79,7 +79,7 @@ struct igmpv3_query { | ||||
|  	__u8 qqic; | ||||
|  	__be16 nsrcs; | ||||
|  	__be32 srcs[0]; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  #define IGMP_HOST_MEMBERSHIP_QUERY	0x11	/* From RFC1112 */ | ||||
|  #define IGMP_HOST_MEMBERSHIP_REPORT	0x12	/* Ditto */ | ||||
| --- a/net/core/flow_dissector.c | ||||
| +++ b/net/core/flow_dissector.c | ||||
| @@ -129,7 +129,7 @@ __be32 __skb_flow_get_ports(const struct | ||||
|  		ports = __skb_header_pointer(skb, thoff + poff, | ||||
|  					     sizeof(_ports), data, hlen, &_ports); | ||||
|  		if (ports) | ||||
| -			return *ports; | ||||
| +			return (__be32)net_hdr_word(ports); | ||||
|  	} | ||||
|   | ||||
|  	return 0; | ||||
| --- a/include/uapi/linux/icmpv6.h | ||||
| +++ b/include/uapi/linux/icmpv6.h | ||||
| @@ -78,7 +78,7 @@ struct icmp6hdr { | ||||
|  #define icmp6_addrconf_other	icmp6_dataun.u_nd_ra.other | ||||
|  #define icmp6_rt_lifetime	icmp6_dataun.u_nd_ra.rt_lifetime | ||||
|  #define icmp6_router_pref	icmp6_dataun.u_nd_ra.router_pref | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|   | ||||
|  #define ICMPV6_ROUTER_PREF_LOW		0x3 | ||||
| --- a/include/net/ndisc.h | ||||
| +++ b/include/net/ndisc.h | ||||
| @@ -93,7 +93,7 @@ struct ra_msg { | ||||
|          struct icmp6hdr		icmph; | ||||
|  	__be32			reachable_time; | ||||
|  	__be32			retrans_timer; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  struct rd_msg { | ||||
|  	struct icmp6hdr icmph; | ||||
| @@ -372,10 +372,10 @@ static inline u32 ndisc_hashfn(const voi | ||||
|  { | ||||
|  	const u32 *p32 = pkey; | ||||
|   | ||||
| -	return (((p32[0] ^ hash32_ptr(dev)) * hash_rnd[0]) + | ||||
| -		(p32[1] * hash_rnd[1]) + | ||||
| -		(p32[2] * hash_rnd[2]) + | ||||
| -		(p32[3] * hash_rnd[3])); | ||||
| +	return (((net_hdr_word(&p32[0]) ^ hash32_ptr(dev)) * hash_rnd[0]) + | ||||
| +		(net_hdr_word(&p32[1]) * hash_rnd[1]) + | ||||
| +		(net_hdr_word(&p32[2]) * hash_rnd[2]) + | ||||
| +		(net_hdr_word(&p32[3]) * hash_rnd[3])); | ||||
|  } | ||||
|   | ||||
|  static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey) | ||||
| --- a/net/sched/cls_u32.c | ||||
| +++ b/net/sched/cls_u32.c | ||||
| @@ -155,7 +155,7 @@ next_knode: | ||||
|  			data = skb_header_pointer(skb, toff, 4, &hdata); | ||||
|  			if (!data) | ||||
|  				goto out; | ||||
| -			if ((*data ^ key->val) & key->mask) { | ||||
| +			if ((net_hdr_word(data) ^ key->val) & key->mask) { | ||||
|  				n = rcu_dereference_bh(n->next); | ||||
|  				goto next_knode; | ||||
|  			} | ||||
| @@ -206,8 +206,8 @@ check_terminal: | ||||
|  						  &hdata); | ||||
|  			if (!data) | ||||
|  				goto out; | ||||
| -			sel = ht->divisor & u32_hash_fold(*data, &n->sel, | ||||
| -							  n->fshift); | ||||
| +			sel = ht->divisor & u32_hash_fold(net_hdr_word(data), | ||||
| +							  &n->sel, n->fshift); | ||||
|  		} | ||||
|  		if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT))) | ||||
|  			goto next_ht; | ||||
| --- a/net/ipv6/ip6_offload.c | ||||
| +++ b/net/ipv6/ip6_offload.c | ||||
| @@ -241,7 +241,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff * | ||||
|  			continue; | ||||
|   | ||||
|  		iph2 = (struct ipv6hdr *)(p->data + off); | ||||
| -		first_word = *(__be32 *)iph ^ *(__be32 *)iph2; | ||||
| +		first_word = net_hdr_word(iph) ^ net_hdr_word(iph2); | ||||
|   | ||||
|  		/* All fields must match except length and Traffic Class. | ||||
|  		 * XXX skbs on the gro_list have all been parsed and pulled | ||||
| --- a/include/net/addrconf.h | ||||
| +++ b/include/net/addrconf.h | ||||
| @@ -47,7 +47,7 @@ struct prefix_info { | ||||
|  	__be32			reserved2; | ||||
|   | ||||
|  	struct in6_addr		prefix; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  #include <linux/ipv6.h> | ||||
|  #include <linux/netdevice.h> | ||||
| --- a/include/net/inet_ecn.h | ||||
| +++ b/include/net/inet_ecn.h | ||||
| @@ -138,9 +138,9 @@ static inline int IP6_ECN_set_ce(struct | ||||
|  	if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) | ||||
|  		return 0; | ||||
|   | ||||
| -	from = *(__be32 *)iph; | ||||
| +	from = net_hdr_word(iph); | ||||
|  	to = from | htonl(INET_ECN_CE << 20); | ||||
| -	*(__be32 *)iph = to; | ||||
| +	net_hdr_word(iph) = to; | ||||
|  	if (skb->ip_summed == CHECKSUM_COMPLETE) | ||||
|  		skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from), | ||||
|  				     (__force __wsum)to); | ||||
| --- a/include/net/ipv6.h | ||||
| +++ b/include/net/ipv6.h | ||||
| @@ -147,7 +147,7 @@ struct frag_hdr { | ||||
|  	__u8	reserved; | ||||
|  	__be16	frag_off; | ||||
|  	__be32	identification; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|   | ||||
|  #define	IP6_MF		0x0001 | ||||
|  #define	IP6_OFFSET	0xFFF8 | ||||
| @@ -561,8 +561,8 @@ static inline void __ipv6_addr_set_half( | ||||
|  	} | ||||
|  #endif | ||||
|  #endif | ||||
| -	addr[0] = wh; | ||||
| -	addr[1] = wl; | ||||
| +	net_hdr_word(&addr[0]) = wh; | ||||
| +	net_hdr_word(&addr[1]) = wl; | ||||
|  } | ||||
|   | ||||
|  static inline void ipv6_addr_set(struct in6_addr *addr, | ||||
| @@ -621,6 +621,8 @@ static inline bool ipv6_prefix_equal(con | ||||
|  	const __be32 *a1 = addr1->s6_addr32; | ||||
|  	const __be32 *a2 = addr2->s6_addr32; | ||||
|  	unsigned int pdw, pbi; | ||||
| +	/* Used for last <32-bit fraction of prefix */ | ||||
| +	u32 pbia1, pbia2; | ||||
|   | ||||
|  	/* check complete u32 in prefix */ | ||||
|  	pdw = prefixlen >> 5; | ||||
| @@ -629,7 +631,9 @@ static inline bool ipv6_prefix_equal(con | ||||
|   | ||||
|  	/* check incomplete u32 in prefix */ | ||||
|  	pbi = prefixlen & 0x1f; | ||||
| -	if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi)))) | ||||
| +	pbia1 = net_hdr_word(&a1[pdw]); | ||||
| +	pbia2 = net_hdr_word(&a2[pdw]); | ||||
| +	if (pbi && ((pbia1 ^ pbia2) & htonl((0xffffffff) << (32 - pbi)))) | ||||
|  		return false; | ||||
|   | ||||
|  	return true; | ||||
| @@ -750,13 +754,13 @@ static inline void ipv6_addr_set_v4mappe | ||||
|   */ | ||||
|  static inline int __ipv6_addr_diff32(const void *token1, const void *token2, int addrlen) | ||||
|  { | ||||
| -	const __be32 *a1 = token1, *a2 = token2; | ||||
| +	const struct in6_addr *a1 = token1, *a2 = token2; | ||||
|  	int i; | ||||
|   | ||||
|  	addrlen >>= 2; | ||||
|   | ||||
|  	for (i = 0; i < addrlen; i++) { | ||||
| -		__be32 xb = a1[i] ^ a2[i]; | ||||
| +		__be32 xb = a1->s6_addr32[i] ^ a2->s6_addr32[i]; | ||||
|  		if (xb) | ||||
|  			return i * 32 + 31 - __fls(ntohl(xb)); | ||||
|  	} | ||||
| @@ -950,17 +954,18 @@ static inline u32 ip6_multipath_hash_fie | ||||
|  static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass, | ||||
|  				__be32 flowlabel) | ||||
|  { | ||||
| -	*(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel; | ||||
| +	net_hdr_word((__be32 *)hdr) = | ||||
| +		htonl(0x60000000 | (tclass << 20)) | flowlabel; | ||||
|  } | ||||
|   | ||||
|  static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr) | ||||
|  { | ||||
| -	return *(__be32 *)hdr & IPV6_FLOWINFO_MASK; | ||||
| +	return net_hdr_word((__be32 *)hdr) & IPV6_FLOWINFO_MASK; | ||||
|  } | ||||
|   | ||||
|  static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr) | ||||
|  { | ||||
| -	return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK; | ||||
| +	return net_hdr_word((__be32 *)hdr) & IPV6_FLOWLABEL_MASK; | ||||
|  } | ||||
|   | ||||
|  static inline u8 ip6_tclass(__be32 flowinfo) | ||||
| --- a/include/net/secure_seq.h | ||||
| +++ b/include/net/secure_seq.h | ||||
| @@ -3,6 +3,7 @@ | ||||
|  #define _NET_SECURE_SEQ | ||||
|   | ||||
|  #include <linux/types.h> | ||||
| +#include <linux/in6.h> | ||||
|   | ||||
|  u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); | ||||
|  u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, | ||||
| --- a/include/uapi/linux/in.h | ||||
| +++ b/include/uapi/linux/in.h | ||||
| @@ -88,7 +88,7 @@ enum { | ||||
|  /* Internet address. */ | ||||
|  struct in_addr { | ||||
|  	__be32	s_addr; | ||||
| -}; | ||||
| +} __attribute__((packed, aligned(2))); | ||||
|  #endif | ||||
|   | ||||
|  #define IP_TOS		1 | ||||
| --- a/net/ipv6/ip6_fib.c | ||||
| +++ b/net/ipv6/ip6_fib.c | ||||
| @@ -141,7 +141,7 @@ static __be32 addr_bit_set(const void *t | ||||
|  	 * See include/asm-generic/bitops/le.h. | ||||
|  	 */ | ||||
|  	return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) & | ||||
| -	       addr[fn_bit >> 5]; | ||||
| +	       net_hdr_word(&addr[fn_bit >> 5]); | ||||
|  } | ||||
|   | ||||
|  struct fib6_info *fib6_info_alloc(gfp_t gfp_flags, bool with_fib6_nh) | ||||
| --- a/net/netfilter/nf_conntrack_proto_tcp.c | ||||
| +++ b/net/netfilter/nf_conntrack_proto_tcp.c | ||||
| @@ -400,7 +400,7 @@ static void tcp_sack(const struct sk_buf | ||||
|   | ||||
|  	/* Fast path for timestamp-only option */ | ||||
|  	if (length == TCPOLEN_TSTAMP_ALIGNED | ||||
| -	    && *(__be32 *)ptr == htonl((TCPOPT_NOP << 24) | ||||
| +	    && net_hdr_word(ptr) == htonl((TCPOPT_NOP << 24) | ||||
|  				       | (TCPOPT_NOP << 16) | ||||
|  				       | (TCPOPT_TIMESTAMP << 8) | ||||
|  				       | TCPOLEN_TIMESTAMP)) | ||||
| --- a/net/xfrm/xfrm_input.c | ||||
| +++ b/net/xfrm/xfrm_input.c | ||||
| @@ -165,8 +165,8 @@ int xfrm_parse_spi(struct sk_buff *skb, | ||||
|  	if (!pskb_may_pull(skb, hlen)) | ||||
|  		return -EINVAL; | ||||
|   | ||||
| -	*spi = *(__be32 *)(skb_transport_header(skb) + offset); | ||||
| -	*seq = *(__be32 *)(skb_transport_header(skb) + offset_seq); | ||||
| +	*spi = net_hdr_word(skb_transport_header(skb) + offset); | ||||
| +	*seq = net_hdr_word(skb_transport_header(skb) + offset_seq); | ||||
|  	return 0; | ||||
|  } | ||||
|  EXPORT_SYMBOL(xfrm_parse_spi); | ||||
| --- a/net/ipv4/tcp_input.c | ||||
| +++ b/net/ipv4/tcp_input.c | ||||
| @@ -4129,14 +4129,16 @@ static bool tcp_parse_aligned_timestamp( | ||||
|  { | ||||
|  	const __be32 *ptr = (const __be32 *)(th + 1); | ||||
|   | ||||
| -	if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | ||||
| -			  | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { | ||||
| +	if (net_hdr_word(ptr) == | ||||
| +	    htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | ||||
| +		  (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { | ||||
|  		tp->rx_opt.saw_tstamp = 1; | ||||
|  		++ptr; | ||||
| -		tp->rx_opt.rcv_tsval = ntohl(*ptr); | ||||
| +		tp->rx_opt.rcv_tsval = get_unaligned_be32(ptr); | ||||
|  		++ptr; | ||||
| -		if (*ptr) | ||||
| -			tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset; | ||||
| +		if (net_hdr_word(ptr)) | ||||
| +			tp->rx_opt.rcv_tsecr = get_unaligned_be32(ptr) - | ||||
| +					       tp->tsoffset; | ||||
|  		else | ||||
|  			tp->rx_opt.rcv_tsecr = 0; | ||||
|  		return true; | ||||
| --- a/include/uapi/linux/if_pppox.h | ||||
| +++ b/include/uapi/linux/if_pppox.h | ||||
| @@ -51,6 +51,7 @@ struct pppoe_addr { | ||||
|   */ | ||||
|  struct pptp_addr { | ||||
|  	__u16		call_id; | ||||
| +	__u16		pad; | ||||
|  	struct in_addr	sin_addr; | ||||
|  }; | ||||
|   | ||||
| --- a/include/net/neighbour.h | ||||
| +++ b/include/net/neighbour.h | ||||
| @@ -275,8 +275,10 @@ static inline bool neigh_key_eq128(const | ||||
|  	const u32 *n32 = (const u32 *)n->primary_key; | ||||
|  	const u32 *p32 = pkey; | ||||
|   | ||||
| -	return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) | | ||||
| -		(n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0; | ||||
| +	return ((n32[0] ^ net_hdr_word(&p32[0])) | | ||||
| +		(n32[1] ^ net_hdr_word(&p32[1])) | | ||||
| +		(n32[2] ^ net_hdr_word(&p32[2])) | | ||||
| +		(n32[3] ^ net_hdr_word(&p32[3]))) == 0; | ||||
|  } | ||||
|   | ||||
|  static inline struct neighbour *___neigh_lookup_noref( | ||||
| --- a/include/uapi/linux/netfilter_arp/arp_tables.h | ||||
| +++ b/include/uapi/linux/netfilter_arp/arp_tables.h | ||||
| @@ -70,7 +70,7 @@ struct arpt_arp { | ||||
|  	__u8 flags; | ||||
|  	/* Inverse flags */ | ||||
|  	__u16 invflags; | ||||
| -}; | ||||
| +} __attribute__((aligned(4))); | ||||
|   | ||||
|  /* Values for "flag" field in struct arpt_ip (general arp structure). | ||||
|   * No flags defined yet. | ||||
| --- a/net/core/utils.c | ||||
| +++ b/net/core/utils.c | ||||
| @@ -460,8 +460,14 @@ void inet_proto_csum_replace16(__sum16 * | ||||
|  			       bool pseudohdr) | ||||
|  { | ||||
|  	__be32 diff[] = { | ||||
| -		~from[0], ~from[1], ~from[2], ~from[3], | ||||
| -		to[0], to[1], to[2], to[3], | ||||
| +		~net_hdr_word(&from[0]), | ||||
| +		~net_hdr_word(&from[1]), | ||||
| +		~net_hdr_word(&from[2]), | ||||
| +		~net_hdr_word(&from[3]), | ||||
| +		net_hdr_word(&to[0]), | ||||
| +		net_hdr_word(&to[1]), | ||||
| +		net_hdr_word(&to[2]), | ||||
| +		net_hdr_word(&to[3]), | ||||
|  	}; | ||||
|  	if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||||
|  		*sum = csum_fold(csum_partial(diff, sizeof(diff), | ||||
| --- a/include/linux/etherdevice.h | ||||
| +++ b/include/linux/etherdevice.h | ||||
| @@ -512,7 +512,7 @@ static inline bool is_etherdev_addr(cons | ||||
|   * @b: Pointer to Ethernet header | ||||
|   * | ||||
|   * Compare two Ethernet headers, returns 0 if equal. | ||||
| - * This assumes that the network header (i.e., IP header) is 4-byte | ||||
| + * This assumes that the network header (i.e., IP header) is 2-byte | ||||
|   * aligned OR the platform can handle unaligned access.  This is the | ||||
|   * case for all packets coming into netif_receive_skb or similar | ||||
|   * entry points. | ||||
| @@ -535,11 +535,12 @@ static inline unsigned long compare_ethe | ||||
|  	fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); | ||||
|  	return fold; | ||||
|  #else | ||||
| -	u32 *a32 = (u32 *)((u8 *)a + 2); | ||||
| -	u32 *b32 = (u32 *)((u8 *)b + 2); | ||||
| +	const u16 *a16 = a; | ||||
| +	const u16 *b16 = b; | ||||
|   | ||||
| -	return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | | ||||
| -	       (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); | ||||
| +	return (a16[0] ^ b16[0]) | (a16[1] ^ b16[1]) | (a16[2] ^ b16[2]) | | ||||
| +	       (a16[3] ^ b16[3]) | (a16[4] ^ b16[4]) | (a16[5] ^ b16[5]) | | ||||
| +	       (a16[6] ^ b16[6]); | ||||
|  #endif | ||||
|  } | ||||
|   | ||||
| --- a/net/ipv4/tcp_offload.c | ||||
| +++ b/net/ipv4/tcp_offload.c | ||||
| @@ -223,7 +223,7 @@ struct sk_buff *tcp_gro_receive(struct l | ||||
|   | ||||
|  		th2 = tcp_hdr(p); | ||||
|   | ||||
| -		if (*(u32 *)&th->source ^ *(u32 *)&th2->source) { | ||||
| +		if (net_hdr_word(&th->source) ^ net_hdr_word(&th2->source)) { | ||||
|  			NAPI_GRO_CB(p)->same_flow = 0; | ||||
|  			continue; | ||||
|  		} | ||||
| @@ -241,8 +241,8 @@ found: | ||||
|  		  ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); | ||||
|  	flush |= (__force int)(th->ack_seq ^ th2->ack_seq); | ||||
|  	for (i = sizeof(*th); i < thlen; i += 4) | ||||
| -		flush |= *(u32 *)((u8 *)th + i) ^ | ||||
| -			 *(u32 *)((u8 *)th2 + i); | ||||
| +		flush |= net_hdr_word((u8 *)th + i) ^ | ||||
| +			 net_hdr_word((u8 *)th2 + i); | ||||
|   | ||||
|  	/* When we receive our second frame we can made a decision on if we | ||||
|  	 * continue this flow as an atomic flow with a fixed ID or if we use | ||||
| --- a/net/ipv6/netfilter/ip6table_mangle.c | ||||
| +++ b/net/ipv6/netfilter/ip6table_mangle.c | ||||
| @@ -44,7 +44,7 @@ ip6t_mangle_out(struct sk_buff *skb, con | ||||
|  	hop_limit = ipv6_hdr(skb)->hop_limit; | ||||
|   | ||||
|  	/* flowlabel and prio (includes version, which shouldn't change either */ | ||||
| -	flowlabel = *((u_int32_t *)ipv6_hdr(skb)); | ||||
| +	flowlabel = net_hdr_word(ipv6_hdr(skb)); | ||||
|   | ||||
|  	ret = ip6t_do_table(skb, state, priv); | ||||
|   | ||||
| @@ -53,7 +53,7 @@ ip6t_mangle_out(struct sk_buff *skb, con | ||||
|  	     !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || | ||||
|  	     skb->mark != mark || | ||||
|  	     ipv6_hdr(skb)->hop_limit != hop_limit || | ||||
| -	     flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { | ||||
| +	     flowlabel != net_hdr_word(ipv6_hdr(skb)))) { | ||||
|  		err = ip6_route_me_harder(state->net, state->sk, skb); | ||||
|  		if (err < 0) | ||||
|  			ret = NF_DROP_ERR(err); | ||||
							
								
								
									
										76
									
								
								target/linux/ath79/patches-5.15/920-mikrotik-rb4xx.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								target/linux/ath79/patches-5.15/920-mikrotik-rb4xx.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| --- a/drivers/mfd/Kconfig | ||||
| +++ b/drivers/mfd/Kconfig | ||||
| @@ -2174,6 +2174,14 @@ config RAVE_SP_CORE | ||||
|  	  Select this to get support for the Supervisory Processor | ||||
|  	  device found on several devices in RAVE line of hardware. | ||||
|   | ||||
| +config MFD_RB4XX_CPLD | ||||
| +	tristate "CPLD driver for Mikrotik RB4xx series boards" | ||||
| +	select MFD_CORE | ||||
| +	depends on ATH79 || COMPILE_TEST | ||||
| +	help | ||||
| +	  Enables support for the CPLD chip (NAND & GPIO) on Mikrotik | ||||
| +	  Routerboard RB4xx series. | ||||
| + | ||||
|  config SGI_MFD_IOC3 | ||||
|  	bool "SGI IOC3 core driver" | ||||
|  	depends on PCI && MIPS && 64BIT | ||||
| --- a/drivers/mfd/Makefile | ||||
| +++ b/drivers/mfd/Makefile | ||||
| @@ -267,6 +267,7 @@ obj-$(CONFIG_MFD_KHADAS_MCU) 	+= khadas- | ||||
|  obj-$(CONFIG_MFD_ACER_A500_EC)	+= acer-ec-a500.o | ||||
|  obj-$(CONFIG_MFD_QCOM_PM8008)	+= qcom-pm8008.o | ||||
|   | ||||
| +obj-$(CONFIG_MFD_RB4XX_CPLD)	+= rb4xx-cpld.o | ||||
|  obj-$(CONFIG_SGI_MFD_IOC3)	+= ioc3.o | ||||
|  obj-$(CONFIG_MFD_SIMPLE_MFD_I2C)	+= simple-mfd-i2c.o | ||||
|  obj-$(CONFIG_MFD_INTEL_M10_BMC)   += intel-m10-bmc.o | ||||
| --- a/drivers/gpio/Kconfig | ||||
| +++ b/drivers/gpio/Kconfig | ||||
| @@ -1574,6 +1574,12 @@ config GPIO_SODAVILLE | ||||
|  	help | ||||
|  	  Say Y here to support Intel Sodaville GPIO. | ||||
|   | ||||
| +config GPIO_RB4XX | ||||
| +	tristate "GPIO expander for Mikrotik RB4xx series boards" | ||||
| +	depends on MFD_RB4XX_CPLD | ||||
| +	help | ||||
| +	  GPIO driver for Mikrotik Routerboard RB4xx series. | ||||
| + | ||||
|  endmenu | ||||
|   | ||||
|  menu "SPI GPIO expanders" | ||||
| --- a/drivers/gpio/Makefile | ||||
| +++ b/drivers/gpio/Makefile | ||||
| @@ -122,6 +122,7 @@ obj-$(CONFIG_GPIO_PL061)		+= gpio-pl061. | ||||
|  obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)	+= gpio-pmic-eic-sprd.o | ||||
|  obj-$(CONFIG_GPIO_PXA)			+= gpio-pxa.o | ||||
|  obj-$(CONFIG_GPIO_RASPBERRYPI_EXP)	+= gpio-raspberrypi-exp.o | ||||
| +obj-$(CONFIG_GPIO_RB4XX)		+= gpio-rb4xx.o | ||||
|  obj-$(CONFIG_GPIO_RC5T583)		+= gpio-rc5t583.o | ||||
|  obj-$(CONFIG_GPIO_RCAR)			+= gpio-rcar.o | ||||
|  obj-$(CONFIG_GPIO_RDA)			+= gpio-rda.o | ||||
| --- a/drivers/mtd/nand/raw/Kconfig | ||||
| +++ b/drivers/mtd/nand/raw/Kconfig | ||||
| @@ -563,4 +563,11 @@ config MTD_NAND_AR934X | ||||
|  	  Enables support for NAND controller on Qualcomm Atheros SoCs. | ||||
|  	  This controller is found on AR934x and QCA955x SoCs. | ||||
|   | ||||
| +config MTD_NAND_RB4XX | ||||
| +	tristate "Support for NAND driver for Mikrotik RB4xx series boards" | ||||
| +	depends on MFD_RB4XX_CPLD | ||||
| +	help | ||||
| +	  Enables support for the NAND flash chip on Mikrotik Routerboard | ||||
| +	  RB4xx series. | ||||
| + | ||||
|  endif # MTD_RAW_NAND | ||||
| --- a/drivers/mtd/nand/raw/Makefile | ||||
| +++ b/drivers/mtd/nand/raw/Makefile | ||||
| @@ -59,6 +59,7 @@ obj-$(CONFIG_MTD_NAND_INTEL_LGM)	+= inte | ||||
|  obj-$(CONFIG_MTD_NAND_ROCKCHIP)		+= rockchip-nand-controller.o | ||||
|  obj-$(CONFIG_MTD_NAND_PL35X)		+= pl35x-nand-controller.o | ||||
|  obj-$(CONFIG_MTD_NAND_AR934X)		+= ar934x_nand.o | ||||
| +obj-$(CONFIG_MTD_NAND_RB4XX)		+= nand_rb4xx.o | ||||
|   | ||||
|  nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o | ||||
|  nand-objs += nand_onfi.o | ||||
| @@ -0,0 +1,59 @@ | ||||
| From b3797d1a92afe97c173b00fdb7824cedba24eef0 Mon Sep 17 00:00:00 2001 | ||||
| From: Chuanhong Guo <gch981213@gmail.com> | ||||
| Date: Sun, 20 Sep 2020 01:00:45 +0800 | ||||
| Subject: [PATCH] ath79: ar8216: make switch register access atomic | ||||
|  | ||||
| due to some unknown reason these register accesses sometimes fail | ||||
| on the integrated switch without this patch. | ||||
|  | ||||
| THIS ONLY WORKS ON ATH79 AND MAY BREAK THE DRIVER ON OTHER PLATFORMS! | ||||
| The mdio bus on ath79 works in polling mode and doesn't rely on | ||||
| any interrupt. This patch breaks the driver on any mdio master | ||||
| with interrupts used. | ||||
|  | ||||
| --- | ||||
| --- a/drivers/net/phy/ar8216.c | ||||
| +++ b/drivers/net/phy/ar8216.c | ||||
| @@ -252,6 +252,7 @@ ar8xxx_mii_write32(struct ar8xxx_priv *p | ||||
|  u32 | ||||
|  ar8xxx_read(struct ar8xxx_priv *priv, int reg) | ||||
|  { | ||||
| +	unsigned long flags; | ||||
|  	struct mii_bus *bus = priv->mii_bus; | ||||
|  	u16 r1, r2, page; | ||||
|  	u32 val; | ||||
| @@ -259,11 +260,13 @@ ar8xxx_read(struct ar8xxx_priv *priv, in | ||||
|  	split_addr((u32) reg, &r1, &r2, &page); | ||||
|   | ||||
|  	mutex_lock(&bus->mdio_lock); | ||||
| +	local_irq_save(flags); | ||||
|   | ||||
|  	bus->write(bus, 0x18, 0, page); | ||||
|  	wait_for_page_switch(); | ||||
|  	val = ar8xxx_mii_read32(priv, 0x10 | r2, r1); | ||||
|   | ||||
| +	local_irq_restore(flags); | ||||
|  	mutex_unlock(&bus->mdio_lock); | ||||
|   | ||||
|  	return val; | ||||
| @@ -272,17 +275,20 @@ ar8xxx_read(struct ar8xxx_priv *priv, in | ||||
|  void | ||||
|  ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val) | ||||
|  { | ||||
| +	unsigned long flags; | ||||
|  	struct mii_bus *bus = priv->mii_bus; | ||||
|  	u16 r1, r2, page; | ||||
|   | ||||
|  	split_addr((u32) reg, &r1, &r2, &page); | ||||
|   | ||||
|  	mutex_lock(&bus->mdio_lock); | ||||
| +	local_irq_save(flags); | ||||
|   | ||||
|  	bus->write(bus, 0x18, 0, page); | ||||
|  	wait_for_page_switch(); | ||||
|  	ar8xxx_mii_write32(priv, 0x10 | r2, r1, val); | ||||
|   | ||||
| +	local_irq_restore(flags); | ||||
|  	mutex_unlock(&bus->mdio_lock); | ||||
|  } | ||||
|   | ||||
							
								
								
									
										68
									
								
								target/linux/ath79/patches-5.15/939-mikrotik-rb91x.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								target/linux/ath79/patches-5.15/939-mikrotik-rb91x.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| --- a/drivers/gpio/Kconfig | ||||
| +++ b/drivers/gpio/Kconfig | ||||
| @@ -353,6 +353,13 @@ config GPIO_IXP4XX | ||||
|  	  IXP4xx series of chips. | ||||
|   | ||||
|  	  If unsure, say N. | ||||
| + | ||||
| +config GPIO_LATCH | ||||
| +	tristate "MikroTik RouterBOARD GPIO latch support" | ||||
| +	depends on ATH79 | ||||
| +	help | ||||
| +	  GPIO driver for latch on some MikroTik RouterBOARDs. | ||||
| + | ||||
|  config GPIO_LOGICVC | ||||
|  	tristate "Xylon LogiCVC GPIO support" | ||||
|  	depends on MFD_SYSCON && OF | ||||
| @@ -529,6 +536,10 @@ config GPIO_ROCKCHIP | ||||
|  	help | ||||
|  	  Say yes here to support GPIO on Rockchip SoCs. | ||||
|   | ||||
| +config GPIO_RB91X_KEY | ||||
| +	tristate "MikroTik RB91x board series reset key support" | ||||
| +	depends on ATH79 | ||||
| + | ||||
|  config GPIO_SAMA5D2_PIOBU | ||||
|  	tristate "SAMA5D2 PIOBU GPIO support" | ||||
|  	depends on MFD_SYSCON | ||||
| --- a/drivers/gpio/Makefile | ||||
| +++ b/drivers/gpio/Makefile | ||||
| @@ -75,6 +75,7 @@ obj-$(CONFIG_GPIO_IT87)			+= gpio-it87.o | ||||
|  obj-$(CONFIG_GPIO_IXP4XX)		+= gpio-ixp4xx.o | ||||
|  obj-$(CONFIG_GPIO_JANZ_TTL)		+= gpio-janz-ttl.o | ||||
|  obj-$(CONFIG_GPIO_KEMPLD)		+= gpio-kempld.o | ||||
| +obj-$(CONFIG_GPIO_LATCH)		+= gpio-latch.o | ||||
|  obj-$(CONFIG_GPIO_LOGICVC)		+= gpio-logicvc.o | ||||
|  obj-$(CONFIG_GPIO_LOONGSON1)		+= gpio-loongson1.o | ||||
|  obj-$(CONFIG_GPIO_LOONGSON)		+= gpio-loongson.o | ||||
| @@ -123,6 +124,7 @@ obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)	+= gpio | ||||
|  obj-$(CONFIG_GPIO_PXA)			+= gpio-pxa.o | ||||
|  obj-$(CONFIG_GPIO_RASPBERRYPI_EXP)	+= gpio-raspberrypi-exp.o | ||||
|  obj-$(CONFIG_GPIO_RB4XX)		+= gpio-rb4xx.o | ||||
| +obj-$(CONFIG_GPIO_RB91X_KEY)		+= gpio-rb91x-key.o | ||||
|  obj-$(CONFIG_GPIO_RC5T583)		+= gpio-rc5t583.o | ||||
|  obj-$(CONFIG_GPIO_RCAR)			+= gpio-rcar.o | ||||
|  obj-$(CONFIG_GPIO_RDA)			+= gpio-rda.o | ||||
| --- a/drivers/mtd/nand/raw/Kconfig | ||||
| +++ b/drivers/mtd/nand/raw/Kconfig | ||||
| @@ -570,4 +570,10 @@ config MTD_NAND_RB4XX | ||||
|  	  Enables support for the NAND flash chip on Mikrotik Routerboard | ||||
|  	  RB4xx series. | ||||
|   | ||||
| +config MTD_NAND_RB91X | ||||
| +	tristate "MikroTik RB91x NAND driver support" | ||||
| +	depends on ATH79 && MTD_RAW_NAND | ||||
| +	help | ||||
| +	  Enables support for the NAND flash chip on MikroTik RB91x series. | ||||
| + | ||||
|  endif # MTD_RAW_NAND | ||||
| --- a/drivers/mtd/nand/raw/Makefile | ||||
| +++ b/drivers/mtd/nand/raw/Makefile | ||||
| @@ -60,6 +60,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP)		+= rock | ||||
|  obj-$(CONFIG_MTD_NAND_PL35X)		+= pl35x-nand-controller.o | ||||
|  obj-$(CONFIG_MTD_NAND_AR934X)		+= ar934x_nand.o | ||||
|  obj-$(CONFIG_MTD_NAND_RB4XX)		+= nand_rb4xx.o | ||||
| +obj-$(CONFIG_MTD_NAND_RB91X)		+= rb91x_nand.o | ||||
|   | ||||
|  nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o | ||||
|  nand-objs += nand_onfi.o | ||||
| @@ -0,0 +1,48 @@ | ||||
| From: Wenli Looi <wlooi@ucalgary.ca> | ||||
| Date: Sun, 20 Jun 2021 23:32:28 -0700 | ||||
| Subject: [PATCH] ath79: add support for booting QCN550x | ||||
|  | ||||
| Based on wikidevi, QCN550x is a "Dragonfly" like QCA9561 and QCA9563. | ||||
| Treating it as QCA956x seems to work. | ||||
| Tested on Netgear EX7300v2 which boots successfully with | ||||
| the same CPU clock as the stock firmware. | ||||
|  | ||||
| Link: https://wikidevi.wi-cat.ru/Qualcomm#bgn | ||||
| Link: https://wikidevi.wi-cat.ru/Qualcomm_Atheros#.28a.29bgn_2 | ||||
| Signed-off-by: Wenli Looi <wlooi@ucalgary.ca> | ||||
|  | ||||
| --- a/arch/mips/ath79/early_printk.c | ||||
| +++ b/arch/mips/ath79/early_printk.c | ||||
| @@ -121,6 +121,7 @@ static void prom_putchar_init(void) | ||||
|  	case REV_ID_MAJOR_QCA9558: | ||||
|  	case REV_ID_MAJOR_TP9343: | ||||
|  	case REV_ID_MAJOR_QCA956X: | ||||
| +	case REV_ID_MAJOR_QCN550X: | ||||
|  		_prom_putchar = prom_putchar_ar71xx; | ||||
|  		break; | ||||
|   | ||||
| --- a/arch/mips/ath79/setup.c | ||||
| +++ b/arch/mips/ath79/setup.c | ||||
| @@ -168,6 +168,12 @@ static void __init ath79_detect_sys_type | ||||
|  		rev = id & QCA956X_REV_ID_REVISION_MASK; | ||||
|  		break; | ||||
|   | ||||
| +	case REV_ID_MAJOR_QCN550X: | ||||
| +		ath79_soc = ATH79_SOC_QCA956X; | ||||
| +		chip = "550X"; | ||||
| +		rev = id & QCA956X_REV_ID_REVISION_MASK; | ||||
| +		break; | ||||
| + | ||||
|  	case REV_ID_MAJOR_TP9343: | ||||
|  		ath79_soc = ATH79_SOC_TP9343; | ||||
|  		chip = "9343"; | ||||
| --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h | ||||
| @@ -867,6 +867,7 @@ | ||||
|  #define REV_ID_MAJOR_QCA9558		0x1130 | ||||
|  #define REV_ID_MAJOR_TP9343		0x0150 | ||||
|  #define REV_ID_MAJOR_QCA956X		0x1150 | ||||
| +#define REV_ID_MAJOR_QCN550X		0x2170 | ||||
|   | ||||
|  #define AR71XX_REV_ID_MINOR_MASK	0x3 | ||||
|  #define AR71XX_REV_ID_MINOR_AR7130	0x0 | ||||
		Reference in New Issue
	
	Block a user
	 David Bauer
					David Bauer