diff options
author | Zoltan HERPAI <wigyori@uid0.hu> | 2016-06-23 18:51:35 +0200 |
---|---|---|
committer | Zoltan HERPAI <wigyori@uid0.hu> | 2016-06-23 18:51:35 +0200 |
commit | 880fddf86bfb0bb2452a33da6622d9d29c71d9bd (patch) | |
tree | 2e1945fd7539b4a3c614297d5fcf45ecde4a794a /target | |
parent | 993ba6b10921e6842d3cd09f9ef2f86cfddfc46a (diff) | |
download | master-187ad058-880fddf86bfb0bb2452a33da6622d9d29c71d9bd.tar.gz master-187ad058-880fddf86bfb0bb2452a33da6622d9d29c71d9bd.tar.bz2 master-187ad058-880fddf86bfb0bb2452a33da6622d9d29c71d9bd.zip |
ipq806x: update bomb
ipq806x: Add support for linux-4.4
ipq806x: Add Archer C2600 to image/Makefile
ipq806x/base-files: Add Archer C2600 LEDs and board
ipq806x/base-files: Add support for Archer C2600
ipq806x/base-files: extract ath10k caldata
ipq806x/dts: Add Archer C2600 DTS
ipq806x: enable PM support
ipq806x: add a default profile
ipq806x: add diag.sh script
ipq806x: qcom rpm fix support for smb208
mtd: add linksys_bootcount for ipq806x
uboot-envtools: add ipq806x support
Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
Diffstat (limited to 'target')
75 files changed, 4291 insertions, 5072 deletions
diff --git a/target/linux/ipq806x/Makefile b/target/linux/ipq806x/Makefile index 689ba64973..253ae16fe9 100644 --- a/target/linux/ipq806x/Makefile +++ b/target/linux/ipq806x/Makefile @@ -17,7 +17,10 @@ KERNELNAME:=zImage Image dtbs include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ kmod-leds-gpio kmod-gpio-button-hotplug swconfig \ - kmod-ata-core kmod-ata-ahci kmod-ata-ahci-platform - + kmod-ata-core kmod-ata-ahci kmod-ata-ahci-platform \ + kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ + kmod-usb3 kmod-usb-dwc3-qcom kmod-usb-phy-qcom-dwc3 \ + kmod-ath10k ath10k-firmware-qca99x0 wpad-mini \ + uboot-envtools $(eval $(call BuildTarget)) diff --git a/target/linux/ipq806x/base-files/etc/board.d/01_leds b/target/linux/ipq806x/base-files/etc/board.d/01_leds index b32c1cc21d..392dc8b5e7 100755 --- a/target/linux/ipq806x/base-files/etc/board.d/01_leds +++ b/target/linux/ipq806x/base-files/etc/board.d/01_leds @@ -11,6 +11,13 @@ board_config_update board=$(ipq806x_board_name) case "$board" in +c2600) + ucidef_set_led_usbdev "usb1" "USB 1" "usb_2:blue" "2-1" + ucidef_set_led_usbdev "usb2" "USB 2" "usb_4:blue" "4-1" + ucidef_set_led_netdev "wan" "WAN" "wan:blue" "eth0" + ucidef_set_led_netdev "lan" "LAN" "lan:blue" "br-lan" + ucidef_set_led_default "general" "general" "ledgnr:blue" "1" + ;; d7800 |\ r7500) ucidef_set_led_usbdev "usb1" "USB 1" "r7500:white:usb1" "1-1" diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index 6e18297e99..e3c9137a5a 100755 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -13,6 +13,7 @@ board=$(ipq806x_board_name) case "$board" in ap148 |\ +c2600 |\ d7800 |\ r7500) ucidef_add_switch "switch0" \ diff --git a/target/linux/ipq806x/base-files/etc/diag.sh b/target/linux/ipq806x/base-files/etc/diag.sh new file mode 100755 index 0000000000..b19012c4e5 --- /dev/null +++ b/target/linux/ipq806x/base-files/etc/diag.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +. /lib/functions/leds.sh +. /lib/ipq806x.sh + +get_status_led() { + case $(ipq806x_board_name) in + c2600) + status_led="status:blue" + ;; + esac +} + +set_state() { + get_status_led + + case "$1" in + preinit) + status_led_blink_preinit + ;; + failsafe) + status_led_blink_failsafe + ;; + preinit_regular) + status_led_blink_preinit_regular + ;; + done) + status_led_on + ;; + esac +} diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata new file mode 100644 index 0000000000..5f604e1a26 --- /dev/null +++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -0,0 +1,68 @@ +#!/bin/sh + +ath10kcal_die() { + echo "ath10cal: " "$*" + exit 1 +} + +ath10kcal_from_file() { + local source=$1 + local offset=$2 + local count=$3 + + dd if=$source of=/lib/firmware/$FIRMWARE bs=1 skip=$offset count=$count 2>/dev/null || \ + ath10kcal_die "failed to extract calibration data from $source" +} + +ath10kcal_extract() { + local part=$1 + local offset=$2 + local count=$3 + local mtd + + mtd=$(find_mtd_chardev $part) + [ -n "$mtd" ] || \ + ath10kcal_die "no mtd device found for partition $part" + + dd if=$mtd of=/lib/firmware/$FIRMWARE bs=1 skip=$offset count=$count 2>/dev/null || \ + ath10kcal_die "failed to extract calibration data from $mtd" +} + +ath10kcal_patch_mac() { + local mac=$1 + + [ -z "$mac" ] && return + + macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=6 count=6 +} + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + +. /lib/ipq806x.sh +. /lib/functions.sh +. /lib/functions/system.sh + +board=$(ipq806x_board_name) + + +case "$FIRMWARE" in +"ath10k/cal-pci-0000:01:00.0.bin") + case $board in + c2600) + ath10kcal_extract "radio" 4096 12064 +# ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1) + ;; + esac + ;; +"ath10k/cal-pci-0001:01:00.0.bin") + case $board in + c2600) + ath10kcal_extract "radio" 20480 12064 +# ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -2) + ;; + esac + ;; +*) + exit 1 + ;; +esac diff --git a/target/linux/ipq806x/base-files/lib/ipq806x.sh b/target/linux/ipq806x/base-files/lib/ipq806x.sh index db227087f4..73202c0b88 100644 --- a/target/linux/ipq806x/base-files/lib/ipq806x.sh +++ b/target/linux/ipq806x/base-files/lib/ipq806x.sh @@ -17,6 +17,9 @@ ipq806x_board_detect() { *"AP148") name="ap148" ;; + *"C2600") + name="c2600" + ;; *"D7800") name="d7800" ;; diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 542b5cecde..a181f13b43 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -12,6 +12,14 @@ platform_check_image() { nand_do_platform_check $board $1 return $?; ;; + c2600) + local magic_long="$(get_magic_long "$1")" + [ "$magic_long" != "27051956" ] && { + echo "Invalid image, bad magic: $magic_long" + return 1 + } + return 0; + ;; *) return 1; esac @@ -29,4 +37,14 @@ platform_pre_upgrade() { esac } -# use default for platform_do_upgrade() +platform_do_upgrade() { + local board=$(ipq806x_board_name) + + case "$board" in + c2600) + PART_NAME="os-image:rootfs" + MTD_CONFIG_ARGS="-s 0x200000" + default_do_upgrade "$ARGV" + ;; + esac +} diff --git a/target/linux/ipq806x/config-3.18 b/target/linux/ipq806x/config-3.18 index 40e3a75f8c..68a8933748 100644 --- a/target/linux/ipq806x/config-3.18 +++ b/target/linux/ipq806x/config-3.18 @@ -314,6 +314,7 @@ CONFIG_PCI=y CONFIG_PCIEAER=y CONFIG_PCIEPORTBUS=y CONFIG_PCIE_DW=y +CONFIG_PCIE_PME=y CONFIG_PCIE_QCOM=y CONFIG_PCI_DOMAINS=y CONFIG_PCI_MSI=y @@ -334,6 +335,7 @@ CONFIG_PM=y CONFIG_PM_CLK=y # CONFIG_PM_DEBUG is not set CONFIG_PM_OPP=y +CONFIG_PM_RUNTIME=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y CONFIG_POWER_RESET=y diff --git a/target/linux/ipq806x/config-4.1 b/target/linux/ipq806x/config-4.4 index b9ce6e79fd..408fc6d3e9 100644 --- a/target/linux/ipq806x/config-4.1 +++ b/target/linux/ipq806x/config-4.4 @@ -41,7 +41,7 @@ CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y CONFIG_ARM_CCI=y CONFIG_ARM_CCI400_COMMON=y CONFIG_ARM_CCI400_PMU=y -# CONFIG_ARM_CPUIDLE is not set +CONFIG_ARM_CCI_PMU=y CONFIG_ARM_CPU_SUSPEND=y CONFIG_ARM_GIC=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -49,6 +49,7 @@ CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_L1_CACHE_SHIFT_6=y # CONFIG_ARM_LPAE is not set CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_PMU=y CONFIG_ARM_QCOM_CPUFREQ=y # CONFIG_ARM_SMMU is not set # CONFIG_ARM_SP805_WATCHDOG is not set @@ -65,6 +66,7 @@ CONFIG_BUILD_BIN2C=y CONFIG_CLEANCACHE=y CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y CONFIG_CLKSRC_QCOM=y CONFIG_CLONE_BACKWARDS=y CONFIG_COMMON_CLK=y @@ -83,18 +85,13 @@ CONFIG_CPU_COPY_V6=y CONFIG_CPU_CP15=y CONFIG_CPU_CP15_MMU=y CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_GOV_USERSPACE is not set CONFIG_CPU_FREQ_STAT=y -# CONFIG_CPU_FREQ_STAT_DETAILS is not set CONFIG_CPU_HAS_ASID=y # CONFIG_CPU_ICACHE_DISABLE is not set CONFIG_CPU_IDLE=y @@ -131,16 +128,14 @@ CONFIG_DMA_VIRTUAL_CHANNELS=y CONFIG_DTC=y # CONFIG_DWMAC_GENERIC is not set CONFIG_DWMAC_IPQ806X=y -# CONFIG_DWMAC_LPC18XX is not set -# CONFIG_DWMAC_MESON is not set -# CONFIG_DWMAC_ROCKCHIP is not set -# CONFIG_DWMAC_SOCFPGA is not set -# CONFIG_DWMAC_STI is not set # CONFIG_DWMAC_SUNXI is not set # CONFIG_DW_DMAC_PCI is not set CONFIG_DYNAMIC_DEBUG=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y CONFIG_ETHERNET_PACKET_MANGLE=y CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y CONFIG_FREEZER=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_BUG=y @@ -163,7 +158,6 @@ CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GPIOLIB=y CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_DEVRES=y -# CONFIG_GPIO_MSM_V2 is not set CONFIG_GPIO_SYSFS=y CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDIRQS_SW_RESEND=y @@ -221,7 +215,6 @@ CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HIGHMEM=y CONFIG_HIGHPTE=y CONFIG_HOTPLUG_CPU=y -# CONFIG_HSU_DMA_PCI is not set CONFIG_HWMON=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y @@ -265,6 +258,7 @@ CONFIG_MFD_SYSCON=y CONFIG_MIGHT_HAVE_CACHE_L2X0=y CONFIG_MIGHT_HAVE_PCI=y CONFIG_MIGRATION=y +CONFIG_MODULES_TREE_LOOKUP=y CONFIG_MODULES_USE_ELF_REL=y CONFIG_MSM_GCC_8660=y # CONFIG_MSM_GCC_8916 is not set @@ -292,9 +286,12 @@ CONFIG_MULTI_IRQ_HANDLER=y CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEON=y +CONFIG_NET_DSA=y +# CONFIG_NET_DSA_AR8XXX is not set +CONFIG_NET_DSA_HWMON=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_PTP_CLASSIFY=y -CONFIG_NET_VENDOR_WIZNET=y +CONFIG_NET_SWITCHDEV=y CONFIG_NO_BOOTMEM=y CONFIG_NO_HZ=y CONFIG_NO_HZ_COMMON=y @@ -315,13 +312,11 @@ CONFIG_OF_PCI_IRQ=y CONFIG_OF_RESERVED_MEM=y CONFIG_OLD_SIGACTION=y CONFIG_OLD_SIGSUSPEND3=y -CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PCI=y CONFIG_PCIEAER=y CONFIG_PCIEPORTBUS=y CONFIG_PCIE_DW=y -# CONFIG_PCIE_IPROC is not set CONFIG_PCIE_PME=y CONFIG_PCIE_QCOM=y CONFIG_PCI_DEBUG=y @@ -340,19 +335,23 @@ CONFIG_PINCTRL_APQ8064=y # CONFIG_PINCTRL_APQ8084 is not set CONFIG_PINCTRL_IPQ8064=y CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_MSM8660 is not set # CONFIG_PINCTRL_MSM8916 is not set # CONFIG_PINCTRL_MSM8960 is not set CONFIG_PINCTRL_MSM8X74=y # CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set +# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set # CONFIG_PL330_DMA is not set CONFIG_PM=y CONFIG_PM_CLK=y # CONFIG_PM_DEBUG is not set +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y CONFIG_PM_OPP=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_BRCMSTB is not set CONFIG_POWER_RESET_MSM=y CONFIG_POWER_SUPPLY=y CONFIG_PPS=y @@ -365,12 +364,17 @@ CONFIG_PROC_PAGE_MONITOR=y CONFIG_PTP_1588_CLOCK=y CONFIG_QCOM_ADM=y CONFIG_QCOM_BAM_DMA=y +CONFIG_QCOM_GDSC=y CONFIG_QCOM_GSBI=y CONFIG_QCOM_HFPLL=y +# CONFIG_QCOM_PM is not set CONFIG_QCOM_SCM=y +CONFIG_QCOM_SCM_32=y +# CONFIG_QCOM_SMD is not set CONFIG_QCOM_SMEM=y CONFIG_QCOM_WDT=y CONFIG_RAS=y +CONFIG_RATIONAL=y # CONFIG_RCU_BOOST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=21 CONFIG_RCU_STALL_COMMON=y @@ -379,6 +383,7 @@ CONFIG_REGMAP=y CONFIG_REGMAP_MMIO=y CONFIG_REGULATOR=y CONFIG_REGULATOR_QCOM_RPM=y +# CONFIG_REGULATOR_QCOM_SPMI is not set CONFIG_RESET_CONTROLLER=y CONFIG_RFS_ACCEL=y CONFIG_RPS=y @@ -387,14 +392,13 @@ CONFIG_RTC_CLASS=y CONFIG_RWSEM_SPIN_ON_OWNER=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_SCHED_HRTICK=y +# CONFIG_SCHED_INFO is not set # CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_FSL=y # CONFIG_SERIAL_AMBA_PL010 is not set # CONFIG_SERIAL_AMBA_PL011 is not set CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_CONSOLE=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y -CONFIG_SLUB_CPU_PARTIAL=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y CONFIG_SPARSE_IRQ=y @@ -406,7 +410,6 @@ CONFIG_SPMI_MSM_PMIC_ARB=y CONFIG_SRCU=y CONFIG_STMMAC_ETH=y CONFIG_STMMAC_PLATFORM=y -CONFIG_STOP_MACHINE=y # CONFIG_STRIP_ASM_SYMS is not set CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y @@ -415,13 +418,8 @@ CONFIG_SWIOTLB=y CONFIG_SWP_EMULATE=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_THERMAL=y -# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -# CONFIG_THERMAL_EMULATION is not set -# CONFIG_THERMAL_GOV_FAIR_SHARE is not set CONFIG_THERMAL_GOV_STEP_WISE=y -# CONFIG_THERMAL_GOV_USER_SPACE is not set CONFIG_THERMAL_HWMON=y CONFIG_THERMAL_OF=y # CONFIG_THUMB2_KERNEL is not set @@ -433,7 +431,6 @@ CONFIG_UBIFS_FS_LZO=y CONFIG_UBIFS_FS_XZ=y CONFIG_UBIFS_FS_ZLIB=y CONFIG_UEVENT_HELPER_PATH="" -CONFIG_UID16=y CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_USB_SUPPORT=y @@ -444,8 +441,6 @@ CONFIG_VFP=y CONFIG_VFPv3=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_WATCHDOG_CORE=y -# CONFIG_WIZNET_W5100 is not set -# CONFIG_WIZNET_W5300 is not set # CONFIG_WL_TI is not set # CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set CONFIG_XPS=y diff --git a/target/linux/ipq806x/image/Makefile b/target/linux/ipq806x/image/Makefile index ff8b2c7d9b..77391d043f 100644 --- a/target/linux/ipq806x/image/Makefile +++ b/target/linux/ipq806x/image/Makefile @@ -86,6 +86,19 @@ define Device/DniImage endef DEVICE_VARS += KERNEL_SIZE NETGEAR_BOARD_ID NETGEAR_HW_ID DEVICE_BLOCK_SIZE DEVICE_PAGE_SIZE +define Device/TpSafeImage + PROFILES += $$(DEVICE_NAME) + FILESYSTEMS := squashfs + KERNEL_SUFFIX := -uImage + KERNEL = kernel-bin | append-dtb | uImage none + KERNEL_NAME := zImage + TPLINK_BOARD_NAME := + IMAGES := factory.bin sysupgrade.bin + IMAGE/factory.bin := append-rootfs | tplink-safeloader factory + IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade +endef +DEVICE_VARS += TPLINK_BOARD_NAME + define Device/AP148 $(call Device/FitImage) $(call Device/UbiFit) @@ -93,6 +106,7 @@ define Device/AP148 BLOCKSIZE := 128KiB PAGESIZE := 2048 BOARD_NAME := ap148 + DEVICE_TITLE := Qualcom AP148 endef define Device/AP148-legacy @@ -102,6 +116,17 @@ define Device/AP148-legacy BLOCKSIZE := 128KiB PAGESIZE := 2048 BOARD_NAME := ap148 + DEVICE_TITLE := Qualcom AP148 (legacy) +endef + +define Device/C2600 + $(call Device/TpSafeImage) + DEVICE_DTS := qcom-ipq8064-c2600 + BLOCKSIZE := 128KiB + PAGESIZE := 2048 + BOARD_NAME := c2600 + TPLINK_BOARD_NAME := C2600 + DEVICE_TITLE := TP-Link Archer C2600 endef define Device/D7800 @@ -113,6 +138,7 @@ define Device/D7800 BLOCKSIZE := 128KiB PAGESIZE := 2048 BOARD_NAME := d7800 + DEVICE_TITLE := Netgear Nighthawk X4 D7800 endef define Device/DB149 @@ -120,6 +146,7 @@ define Device/DB149 DEVICE_DTS := qcom-ipq8064-db149 KERNEL_INSTALL := 1 BOARD_NAME := db149 + DEVICE_TITLE := Qualcom DB149 endef define Device/R7500 @@ -131,8 +158,9 @@ define Device/R7500 BLOCKSIZE := 128KiB PAGESIZE := 2048 BOARD_NAME := r7500 + DEVICE_TITLE := Netgear Nighthawk X4 R7500 endef -TARGET_DEVICES += AP148 AP148-legacy D7800 DB149 R7500 +TARGET_DEVICES += AP148 AP148-legacy C2600 D7800 DB149 R7500 $(eval $(call BuildImage)) diff --git a/target/linux/ipq806x/patches-3.18/802-ARM-qcom-add-TPLink-C2600-device-tree.patch b/target/linux/ipq806x/patches-3.18/802-ARM-qcom-add-TPLink-C2600-device-tree.patch new file mode 100644 index 0000000000..8952f3339d --- /dev/null +++ b/target/linux/ipq806x/patches-3.18/802-ARM-qcom-add-TPLink-C2600-device-tree.patch @@ -0,0 +1,425 @@ +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -506,6 +506,7 @@ + qcom-apq8084-ifc6540.dtb \ + qcom-apq8084-mtp.dtb \ + qcom-ipq8064-ap148.dtb \ ++ qcom-ipq8064-c2600.dtb \ + qcom-ipq8064-db149.dtb \ + qcom-ipq8064-r7500.dtb \ + qcom-ipq8064-d7800.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/qcom-ipq8064-c2600.dts +@@ -0,0 +1,412 @@ ++#include "qcom-ipq8064-v1.0.dtsi" ++#include <dt-bindings/input/input.h> ++ ++/ { ++ model = "TP-Link Archer C2600"; ++ compatible = "tplink,c2600", "qcom,ipq8064"; ++ ++ memory@0 { ++ reg = <0x42000000 0x1e000000>; ++ device_type = "memory"; ++ }; ++ ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ rsvd@41200000 { ++ reg = <0x41200000 0x300000>; ++ no-map; ++ }; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ mdio-gpio0 = &mdio0; ++ }; ++ ++ chosen { ++ linux,stdout-path = "serial0:115200n8"; ++ }; ++ ++ soc { ++ pinmux@800000 { ++ i2c4_pins: i2c4_pinmux { ++ pins = "gpio12", "gpio13"; ++ function = "gsbi4"; ++ bias-disable; ++ }; ++ ++ spi_pins: spi_pins { ++ mux { ++ pins = "gpio18", "gpio19", "gpio21"; ++ function = "gsbi5"; ++ drive-strength = <10>; ++ bias-none; ++ }; ++ }; ++ ++ nand_pins: nand_pins { ++ mux { ++ pins = "gpio34", "gpio35", "gpio36", ++ "gpio37", "gpio38", "gpio39", ++ "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ function = "nand"; ++ drive-strength = <10>; ++ bias-disable; ++ }; ++ ++ pullups { ++ pins = "gpio39"; ++ bias-pull-up; ++ }; ++ ++ hold { ++ pins = "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ bias-bus-hold; ++ }; ++ }; ++ ++ mdio0_pins: mdio0_pins { ++ mux { ++ pins = "gpio0", "gpio1"; ++ function = "gpio"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ ++ rgmii2_pins: rgmii2_pins { ++ mux { ++ pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", ++ "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; ++ function = "rgmii2"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ }; ++ ++ gsbi@16300000 { ++ qcom,mode = <GSBI_PROT_I2C_UART>; ++ status = "ok"; ++ serial@16340000 { ++ status = "ok"; ++ }; ++ /* ++ * The i2c device on gsbi4 should not be enabled. ++ * On ipq806x designs gsbi4 i2c is meant for exclusive ++ * RPM usage. Turning this on in kernel manifests as ++ * i2c failure for the RPM. ++ */ ++ }; ++ ++ gsbi5: gsbi@1a200000 { ++ qcom,mode = <GSBI_PROT_SPI>; ++ status = "ok"; ++ ++ spi4: spi@1a280000 { ++ status = "ok"; ++ spi-max-frequency = <50000000>; ++ ++ pinctrl-0 = <&spi_pins>; ++ pinctrl-names = "default"; ++ ++ cs-gpios = <&qcom_pinmux 20 0>; ++ ++ flash: m25p80@0 { ++ compatible = "s25fl256s1"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ spi-max-frequency = <50000000>; ++ reg = <0>; ++ ++ SBL1@0 { ++ label = "SBL1"; ++ reg = <0x0 0x20000>; ++ read-only; ++ }; ++ MIBIB@20000 { ++ label = "MIBIB"; ++ reg = <0x20000 0x20000>; ++ read-only; ++ }; ++ SBL2@40000 { ++ label = "SBL2"; ++ reg = <0x40000 0x20000>; ++ read-only; ++ }; ++ SBL3@60000 { ++ label = "SBL3"; ++ reg = <0x60000 0x30000>; ++ read-only; ++ }; ++ DDRCONFIG@90000 { ++ label = "DDRCONFIG"; ++ reg = <0x90000 0x10000>; ++ read-only; ++ }; ++ SSD@a0000 { ++ label = "SSD"; ++ reg = <0xa0000 0x10000>; ++ read-only; ++ }; ++ TZ@b0000 { ++ label = "TZ"; ++ reg = <0xb0000 0x30000>; ++ read-only; ++ }; ++ RPM@e0000 { ++ label = "RPM"; ++ reg = <0xe0000 0x20000>; ++ read-only; ++ }; ++ fs-uboot@100000 { ++ label = "fs-uboot"; ++ reg = <0x100000 0x70000>; ++ read-only; ++ }; ++ uboot-env@170000 { ++ label = "uboot-env"; ++ reg = <0x170000 0x40000>; ++ read-only; ++ }; ++ radio@1b0000 { ++ label = "radio"; ++ reg = <0x1b0000 0x40000>; ++ read-only; ++ }; ++ os-image@1f0000 { ++ label = "os-image"; ++ reg = <0x1f0000 0x200000>; ++ }; ++ rootfs@3f0000 { ++ label = "rootfs"; ++ reg = <0x3f0000 0x1b00000>; ++ }; ++ defaultmac: default-mac@1ef0000 { ++ label = "default-mac"; ++ reg = <0x1ef0000 0x00200>; ++ read-only; ++ }; ++ pin@1ef0200 { ++ label = "pin"; ++ reg = <0x1ef0200 0x00200>; ++ read-only; ++ }; ++ product-info@1ef0400 { ++ label = "product-info"; ++ reg = <0x1ef0400 0x0fc00>; ++ read-only; ++ }; ++ partition-table@1f00000 { ++ label = "partition-table"; ++ reg = <0x1f00000 0x10000>; ++ read-only; ++ }; ++ soft-version@1f10000 { ++ label = "soft-version"; ++ reg = <0x1f10000 0x10000>; ++ read-only; ++ }; ++ support-list@1f20000 { ++ label = "support-list"; ++ reg = <0x1f20000 0x10000>; ++ read-only; ++ }; ++ profile@1f30000 { ++ label = "profile"; ++ reg = <0x1f30000 0x10000>; ++ read-only; ++ }; ++ default-config@1f40000 { ++ label = "default-config"; ++ reg = <0x1f40000 0x10000>; ++ read-only; ++ }; ++ user-config@1f50000 { ++ label = "user-config"; ++ reg = <0x1f50000 0x40000>; ++ read-only; ++ }; ++ qos-db@1f90000 { ++ label = "qos-db"; ++ reg = <0x1f90000 0x40000>; ++ read-only; ++ }; ++ usb-config@1fd0000 { ++ label = "usb-config"; ++ reg = <0x1fd0000 0x10000>; ++ read-only; ++ }; ++ log@1fe0000 { ++ label = "log"; ++ reg = <0x1fe0000 0x20000>; ++ read-only; ++ }; ++ }; ++ }; ++ }; ++ ++ phy@100f8800 { /* USB3 port 1 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@100f8830 { /* USB3 port 1 SS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8800 { /* USB3 port 0 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8830 { /* USB3 port 0 SS phy */ ++ status = "ok"; ++ }; ++ ++ usb30@0 { ++ status = "ok"; ++ }; ++ ++ usb30@1 { ++ status = "ok"; ++ }; ++ ++ pcie0: pci@1b500000 { ++ status = "ok"; ++ phy-tx0-term-offset = <7>; ++ }; ++ ++ pcie1: pci@1b700000 { ++ status = "ok"; ++ phy-tx0-term-offset = <7>; ++ }; ++ ++ mdio0: mdio { ++ compatible = "virtual,mdio-gpio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>; ++ pinctrl-0 = <&mdio0_pins>; ++ pinctrl-names = "default"; ++ ++ phy0: ethernet-phy@0 { ++ device_type = "ethernet-phy"; ++ reg = <0>; ++ qca,ar8327-initvals = < ++ 0x00004 0x7600000 /* PAD0_MODE */ ++ 0x00008 0x1000000 /* PAD5_MODE */ ++ 0x0000c 0x80 /* PAD6_MODE */ ++ 0x000e4 0xaa545 /* MAC_POWER_SEL */ ++ 0x000e0 0xc74164de /* SGMII_CTRL */ ++ 0x0007c 0x4e /* PORT0_STATUS */ ++ 0x00094 0x4e /* PORT6_STATUS */ ++ >; ++ }; ++ ++ phy4: ethernet-phy@4 { ++ device_type = "ethernet-phy"; ++ reg = <4>; ++ }; ++ }; ++ ++ gmac1: ethernet@37200000 { ++ status = "ok"; ++ phy-mode = "rgmii"; ++ qcom,id = <1>; ++ ++ pinctrl-0 = <&rgmii2_pins>; ++ pinctrl-names = "default"; ++ ++ mtd-mac-address = <&defaultmac 0x8>; ++ mtd-mac-address-increment = <1>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ gmac2: ethernet@37400000 { ++ status = "ok"; ++ phy-mode = "sgmii"; ++ qcom,id = <2>; ++ ++ mtd-mac-address = <&defaultmac 0x8>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ wifi { ++ label = "wifi"; ++ gpios = <&qcom_pinmux 49 1>; ++ linux,code = <KEY_WLAN>; ++ }; ++ ++ reset { ++ label = "reset"; ++ gpios = <&qcom_pinmux 64 1>; ++ linux,code = <KEY_RESTART>; ++ }; ++ ++ wps { ++ label = "wps"; ++ gpios = <&qcom_pinmux 65 1>; ++ linux,code = <KEY_WPS_BUTTON>; ++ }; ++ ledgeneral { ++ label = "ledgeneral"; ++ gpios = <&qcom_pinmux 16 1>; ++ linux,code = <KEY_DOLLAR>; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ lan { ++ label = "lan:blue"; ++ gpios = <&qcom_pinmux 6 0>; ++ }; ++ usb4 { ++ label = "usb_4:blue"; ++ gpios = <&qcom_pinmux 7 0>; ++ }; ++ usb2 { ++ label = "usb_2:blue"; ++ gpios = <&qcom_pinmux 8 0>; ++ }; ++ wps { ++ label = "wps:blue"; ++ gpios = <&qcom_pinmux 9 0>; ++ }; ++ wan_blue { ++ label = "wan:blue"; ++ gpios = <&qcom_pinmux 33 1>; ++ }; ++ status { ++ label = "status:blue"; ++ gpios = <&qcom_pinmux 53 0>; ++ default-state = "on"; ++ }; ++ ledgnr { ++ label = "ledgnr:blue"; ++ gpios = <&qcom_pinmux 66 0>; ++ }; ++ }; ++}; ++ ++&adm_dma { ++ status = "ok"; ++}; diff --git a/target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch b/target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch deleted file mode 100644 index 04f35b7ec7..0000000000 --- a/target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch +++ /dev/null @@ -1,167 +0,0 @@ -From fb7737e949e31d8a71acee6bbb670f32dbd2a2c0 Mon Sep 17 00:00:00 2001 -From: Suman Anna <s-anna@ti.com> -Date: Wed, 4 Mar 2015 20:01:14 -0600 -Subject: [PATCH] hwspinlock/core: add device tree support - -This patch adds a new OF-friendly API of_hwspin_lock_get_id() -for hwspinlock clients to use/request locks from a hwspinlock -device instantiated through a device-tree blob. This new API -can be used by hwspinlock clients to get the id for a specific -lock using the phandle + args specifier, so that it can be -requested using the available hwspin_lock_request_specific() -API. - -Signed-off-by: Suman Anna <s-anna@ti.com> -Reviewed-by: Bjorn Andersson <bjorn.andersson@sonymobile.com> -[small comment clarification] -Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> ---- - Documentation/hwspinlock.txt | 10 +++++ - drivers/hwspinlock/hwspinlock_core.c | 79 ++++++++++++++++++++++++++++++++++++ - include/linux/hwspinlock.h | 7 ++++ - 3 files changed, 96 insertions(+) - ---- a/Documentation/hwspinlock.txt -+++ b/Documentation/hwspinlock.txt -@@ -48,6 +48,16 @@ independent, drivers. - ids for predefined purposes. - Should be called from a process context (might sleep). - -+ int of_hwspin_lock_get_id(struct device_node *np, int index); -+ - retrieve the global lock id for an OF phandle-based specific lock. -+ This function provides a means for DT users of a hwspinlock module -+ to get the global lock id of a specific hwspinlock, so that it can -+ be requested using the normal hwspin_lock_request_specific() API. -+ The function returns a lock id number on success, -EPROBE_DEFER if -+ the hwspinlock device is not yet registered with the core, or other -+ error values. -+ Should be called from a process context (might sleep). -+ - int hwspin_lock_free(struct hwspinlock *hwlock); - - free a previously-assigned hwspinlock; returns 0 on success, or an - appropriate error code on failure (e.g. -EINVAL if the hwspinlock ---- a/drivers/hwspinlock/hwspinlock_core.c -+++ b/drivers/hwspinlock/hwspinlock_core.c -@@ -27,6 +27,7 @@ - #include <linux/hwspinlock.h> - #include <linux/pm_runtime.h> - #include <linux/mutex.h> -+#include <linux/of.h> - - #include "hwspinlock_internal.h" - -@@ -257,6 +258,84 @@ void __hwspin_unlock(struct hwspinlock * - } - EXPORT_SYMBOL_GPL(__hwspin_unlock); - -+/** -+ * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id -+ * @bank: the hwspinlock device bank -+ * @hwlock_spec: hwlock specifier as found in the device tree -+ * -+ * This is a simple translation function, suitable for hwspinlock platform -+ * drivers that only has a lock specifier length of 1. -+ * -+ * Returns a relative index of the lock within a specified bank on success, -+ * or -EINVAL on invalid specifier cell count. -+ */ -+static inline int -+of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec) -+{ -+ if (WARN_ON(hwlock_spec->args_count != 1)) -+ return -EINVAL; -+ -+ return hwlock_spec->args[0]; -+} -+ -+/** -+ * of_hwspin_lock_get_id() - get lock id for an OF phandle-based specific lock -+ * @np: device node from which to request the specific hwlock -+ * @index: index of the hwlock in the list of values -+ * -+ * This function provides a means for DT users of the hwspinlock module to -+ * get the global lock id of a specific hwspinlock using the phandle of the -+ * hwspinlock device, so that it can be requested using the normal -+ * hwspin_lock_request_specific() API. -+ * -+ * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock -+ * device is not yet registered, -EINVAL on invalid args specifier value or an -+ * appropriate error as returned from the OF parsing of the DT client node. -+ */ -+int of_hwspin_lock_get_id(struct device_node *np, int index) -+{ -+ struct of_phandle_args args; -+ struct hwspinlock *hwlock; -+ struct radix_tree_iter iter; -+ void **slot; -+ int id; -+ int ret; -+ -+ ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index, -+ &args); -+ if (ret) -+ return ret; -+ -+ /* Find the hwspinlock device: we need its base_id */ -+ ret = -EPROBE_DEFER; -+ rcu_read_lock(); -+ radix_tree_for_each_slot(slot, &hwspinlock_tree, &iter, 0) { -+ hwlock = radix_tree_deref_slot(slot); -+ if (unlikely(!hwlock)) -+ continue; -+ -+ if (hwlock->bank->dev->of_node == args.np) { -+ ret = 0; -+ break; -+ } -+ } -+ rcu_read_unlock(); -+ if (ret < 0) -+ goto out; -+ -+ id = of_hwspin_lock_simple_xlate(&args); -+ if (id < 0 || id >= hwlock->bank->num_locks) { -+ ret = -EINVAL; -+ goto out; -+ } -+ id += hwlock->bank->base_id; -+ -+out: -+ of_node_put(args.np); -+ return ret ? ret : id; -+} -+EXPORT_SYMBOL_GPL(of_hwspin_lock_get_id); -+ - static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id) - { - struct hwspinlock *tmp; ---- a/include/linux/hwspinlock.h -+++ b/include/linux/hwspinlock.h -@@ -26,6 +26,7 @@ - #define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */ - - struct device; -+struct device_node; - struct hwspinlock; - struct hwspinlock_device; - struct hwspinlock_ops; -@@ -66,6 +67,7 @@ int hwspin_lock_unregister(struct hwspin - struct hwspinlock *hwspin_lock_request(void); - struct hwspinlock *hwspin_lock_request_specific(unsigned int id); - int hwspin_lock_free(struct hwspinlock *hwlock); -+int of_hwspin_lock_get_id(struct device_node *np, int index); - int hwspin_lock_get_id(struct hwspinlock *hwlock); - int __hwspin_lock_timeout(struct hwspinlock *, unsigned int, int, - unsigned long *); -@@ -120,6 +122,11 @@ void __hwspin_unlock(struct hwspinlock * - { - } - -+static inline int of_hwspin_lock_get_id(struct device_node *np, int index) -+{ -+ return 0; -+} -+ - static inline int hwspin_lock_get_id(struct hwspinlock *hwlock) - { - return 0; diff --git a/target/linux/ipq806x/patches-4.1/031-hwspinlock-qcom-Add-support-for-Qualcomm-HW-Mutex-bl.patch b/target/linux/ipq806x/patches-4.1/031-hwspinlock-qcom-Add-support-for-Qualcomm-HW-Mutex-bl.patch deleted file mode 100644 index 581b199d7f..0000000000 --- a/target/linux/ipq806x/patches-4.1/031-hwspinlock-qcom-Add-support-for-Qualcomm-HW-Mutex-bl.patch +++ /dev/null @@ -1,234 +0,0 @@ -From 19a0f61224d2d91860fa8291ab63cb104ee86bdd Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson <bjorn.andersson@sonymobile.com> -Date: Tue, 24 Mar 2015 10:11:05 -0700 -Subject: [PATCH] hwspinlock: qcom: Add support for Qualcomm HW Mutex block - -Add driver for Qualcomm Hardware Mutex block found in many Qualcomm -SoCs. - -Based on initial effort by Kumar Gala <galak@codeaurora.org> - -Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com> -Reviewed-by: Andy Gross <agross@codeaurora.org> -Reviewed-by: Jeffrey Hugo <jhugo@codeaurora.org> -Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> ---- - drivers/hwspinlock/Kconfig | 12 +++ - drivers/hwspinlock/Makefile | 1 + - drivers/hwspinlock/qcom_hwspinlock.c | 181 +++++++++++++++++++++++++++++++++++ - 3 files changed, 194 insertions(+) - create mode 100644 drivers/hwspinlock/qcom_hwspinlock.c - ---- a/drivers/hwspinlock/Kconfig -+++ b/drivers/hwspinlock/Kconfig -@@ -18,6 +18,18 @@ config HWSPINLOCK_OMAP - - If unsure, say N. - -+config HWSPINLOCK_QCOM -+ tristate "Qualcomm Hardware Spinlock device" -+ depends on ARCH_QCOM -+ select HWSPINLOCK -+ select MFD_SYSCON -+ help -+ Say y here to support the Qualcomm Hardware Mutex functionality, which -+ provides a synchronisation mechanism for the various processors on -+ the SoC. -+ -+ If unsure, say N. -+ - config HSEM_U8500 - tristate "STE Hardware Semaphore functionality" - depends on ARCH_U8500 ---- a/drivers/hwspinlock/Makefile -+++ b/drivers/hwspinlock/Makefile -@@ -4,4 +4,5 @@ - - obj-$(CONFIG_HWSPINLOCK) += hwspinlock_core.o - obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o -+obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o - obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o ---- /dev/null -+++ b/drivers/hwspinlock/qcom_hwspinlock.c -@@ -0,0 +1,181 @@ -+/* -+ * Copyright (c) 2013, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2015, Sony Mobile Communications AB -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/hwspinlock.h> -+#include <linux/io.h> -+#include <linux/kernel.h> -+#include <linux/mfd/syscon.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/of_device.h> -+#include <linux/platform_device.h> -+#include <linux/pm_runtime.h> -+#include <linux/regmap.h> -+ -+#include "hwspinlock_internal.h" -+ -+#define QCOM_MUTEX_APPS_PROC_ID 1 -+#define QCOM_MUTEX_NUM_LOCKS 32 -+ -+static int qcom_hwspinlock_trylock(struct hwspinlock *lock) -+{ -+ struct regmap_field *field = lock->priv; -+ u32 lock_owner; -+ int ret; -+ -+ ret = regmap_field_write(field, QCOM_MUTEX_APPS_PROC_ID); -+ if (ret) -+ return ret; -+ -+ ret = regmap_field_read(field, &lock_owner); -+ if (ret) -+ return ret; -+ -+ return lock_owner == QCOM_MUTEX_APPS_PROC_ID; -+} -+ -+static void qcom_hwspinlock_unlock(struct hwspinlock *lock) -+{ -+ struct regmap_field *field = lock->priv; -+ u32 lock_owner; -+ int ret; -+ -+ ret = regmap_field_read(field, &lock_owner); -+ if (ret) { -+ pr_err("%s: unable to query spinlock owner\n", __func__); -+ return; -+ } -+ -+ if (lock_owner != QCOM_MUTEX_APPS_PROC_ID) { -+ pr_err("%s: spinlock not owned by us (actual owner is %d)\n", -+ __func__, lock_owner); -+ } -+ -+ ret = regmap_field_write(field, 0); -+ if (ret) -+ pr_err("%s: failed to unlock spinlock\n", __func__); -+} -+ -+static const struct hwspinlock_ops qcom_hwspinlock_ops = { -+ .trylock = qcom_hwspinlock_trylock, -+ .unlock = qcom_hwspinlock_unlock, -+}; -+ -+static const struct of_device_id qcom_hwspinlock_of_match[] = { -+ { .compatible = "qcom,sfpb-mutex" }, -+ { .compatible = "qcom,tcsr-mutex" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, qcom_hwspinlock_of_match); -+ -+static int qcom_hwspinlock_probe(struct platform_device *pdev) -+{ -+ struct hwspinlock_device *bank; -+ struct device_node *syscon; -+ struct reg_field field; -+ struct regmap *regmap; -+ size_t array_size; -+ u32 stride; -+ u32 base; -+ int ret; -+ int i; -+ -+ syscon = of_parse_phandle(pdev->dev.of_node, "syscon", 0); -+ if (!syscon) { -+ dev_err(&pdev->dev, "no syscon property\n"); -+ return -ENODEV; -+ } -+ -+ regmap = syscon_node_to_regmap(syscon); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1, &base); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "no offset in syscon\n"); -+ return -EINVAL; -+ } -+ -+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 2, &stride); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "no stride syscon\n"); -+ return -EINVAL; -+ } -+ -+ array_size = QCOM_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock); -+ bank = devm_kzalloc(&pdev->dev, sizeof(*bank) + array_size, GFP_KERNEL); -+ if (!bank) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, bank); -+ -+ for (i = 0; i < QCOM_MUTEX_NUM_LOCKS; i++) { -+ field.reg = base + i * stride; -+ field.lsb = 0; -+ field.msb = 32; -+ -+ bank->lock[i].priv = devm_regmap_field_alloc(&pdev->dev, -+ regmap, field); -+ } -+ -+ pm_runtime_enable(&pdev->dev); -+ -+ ret = hwspin_lock_register(bank, &pdev->dev, &qcom_hwspinlock_ops, -+ 0, QCOM_MUTEX_NUM_LOCKS); -+ if (ret) -+ pm_runtime_disable(&pdev->dev); -+ -+ return ret; -+} -+ -+static int qcom_hwspinlock_remove(struct platform_device *pdev) -+{ -+ struct hwspinlock_device *bank = platform_get_drvdata(pdev); -+ int ret; -+ -+ ret = hwspin_lock_unregister(bank); -+ if (ret) { -+ dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret); -+ return ret; -+ } -+ -+ pm_runtime_disable(&pdev->dev); -+ -+ return 0; -+} -+ -+static struct platform_driver qcom_hwspinlock_driver = { -+ .probe = qcom_hwspinlock_probe, -+ .remove = qcom_hwspinlock_remove, -+ .driver = { -+ .name = "qcom_hwspinlock", -+ .of_match_table = qcom_hwspinlock_of_match, -+ }, -+}; -+ -+static int __init qcom_hwspinlock_init(void) -+{ -+ return platform_driver_register(&qcom_hwspinlock_driver); -+} -+/* board init code might need to reserve hwspinlocks for predefined purposes */ -+postcore_initcall(qcom_hwspinlock_init); -+ -+static void __exit qcom_hwspinlock_exit(void) -+{ -+ platform_driver_unregister(&qcom_hwspinlock_driver); -+} -+module_exit(qcom_hwspinlock_exit); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_DESCRIPTION("Hardware spinlock driver for Qualcomm SoCs"); diff --git a/target/linux/ipq806x/patches-4.1/032-hwspinlock-qcom-Correct-msb-in-regmap_field.patch b/target/linux/ipq806x/patches-4.1/032-hwspinlock-qcom-Correct-msb-in-regmap_field.patch deleted file mode 100644 index 70d5a58248..0000000000 --- a/target/linux/ipq806x/patches-4.1/032-hwspinlock-qcom-Correct-msb-in-regmap_field.patch +++ /dev/null @@ -1,26 +0,0 @@ -From bd5717a4632cdecafe82d03de7dcb3b1876e2828 Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson <bjorn.andersson@sonymobile.com> -Date: Fri, 26 Jun 2015 14:47:21 -0700 -Subject: [PATCH] hwspinlock: qcom: Correct msb in regmap_field - -msb of the regmap_field was mistakenly given the value 32, to set all bits -in the regmap update mask; although incorrect this worked until 921cc294, -where the mask calculation was corrected. - -Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com> -Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> ---- - drivers/hwspinlock/qcom_hwspinlock.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/hwspinlock/qcom_hwspinlock.c -+++ b/drivers/hwspinlock/qcom_hwspinlock.c -@@ -123,7 +123,7 @@ static int qcom_hwspinlock_probe(struct - for (i = 0; i < QCOM_MUTEX_NUM_LOCKS; i++) { - field.reg = base + i * stride; - field.lsb = 0; -- field.msb = 32; -+ field.msb = 31; - - bank->lock[i].priv = devm_regmap_field_alloc(&pdev->dev, - regmap, field); diff --git a/target/linux/ipq806x/patches-4.1/034-soc-qcom-Add-device-tree-binding-for-SMEM.patch b/target/linux/ipq806x/patches-4.1/034-soc-qcom-Add-device-tree-binding-for-SMEM.patch deleted file mode 100644 index d22db2226e..0000000000 --- a/target/linux/ipq806x/patches-4.1/034-soc-qcom-Add-device-tree-binding-for-SMEM.patch +++ /dev/null @@ -1,82 +0,0 @@ -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v2,1/2] soc: qcom: Add device tree binding for SMEM -From: Bjorn Andersson <bjorn.andersson@sonymobile.com> -X-Patchwork-Id: 6202201 -Message-Id: <1428795178-24312-1-git-send-email-bjorn.andersson@sonymobile.com> -To: Rob Herring <robh+dt@kernel.org>, Pawel Moll <pawel.moll@arm.com>, - Mark Rutland <mark.rutland@arm.com>, - Ian Campbell <ijc+devicetree@hellion.org.uk>, - Kumar Gala <galak@codeaurora.org>, Jeffrey Hugo <jhugo@codeaurora.org>, - Andry Gross <agross@codeaurora.org> -Cc: <devicetree@vger.kernel.org>, - linux-arm-msm <linux-arm-msm@vger.kernel.org>, - <linux-kernel@vger.kernel.org> -Date: Sat, 11 Apr 2015 16:32:57 -0700 - -Add device tree binding documentation for the Qualcom Shared Memory -manager. - -Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com> - ---- -Changes since v1: -- None - - .../devicetree/bindings/soc/qcom/qcom,smem.txt | 49 ++++++++++++++++++++++ - 1 file changed, 49 insertions(+) - create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt -@@ -0,0 +1,49 @@ -+Qualcomm Shared Memory binding -+ -+This binding describes the Qualcomm Shared Memory, used to share data between -+various subsystems and OSes in Qualcomm platforms. -+ -+- compatible: -+ Usage: required -+ Value type: <stringlist> -+ Definition: must be: -+ "qcom,smem" -+ -+- memory-region: -+ Usage: required -+ Value type: <prop-encoded-array> -+ Definition: handle to memory reservation for main smem memory region. -+ -+- reg: -+ Usage: optional -+ Value type: <prop-encoded-array> -+ Definition: base address and size pair for any additional memory areas -+ of the shared memory. -+ -+- hwspinlocks: -+ Usage: required -+ Value type: <prop-encoded-array> -+ Definition: reference to a hwspinlock used to protect allocations from -+ the shared memory -+ -+= EXAMPLE -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ smem_region: smem@fa00000 { -+ reg = <0xfa00000 0x200000>; -+ no-map; -+ }; -+ }; -+ -+ smem@fa00000 { -+ compatible = "qcom,smem"; -+ -+ memory-region = <&smem_region>; -+ reg = <0xfc428000 0x4000>; -+ -+ hwlocks = <&tcsr_mutex 3>; -+ }; diff --git a/target/linux/ipq806x/patches-4.1/035-soc-qcom-Add-Shared-Memory-Manager-driver.patch b/target/linux/ipq806x/patches-4.1/035-soc-qcom-Add-Shared-Memory-Manager-driver.patch deleted file mode 100644 index 5598da26d8..0000000000 --- a/target/linux/ipq806x/patches-4.1/035-soc-qcom-Add-Shared-Memory-Manager-driver.patch +++ /dev/null @@ -1,841 +0,0 @@ -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v2,2/2] soc: qcom: Add Shared Memory Manager driver -From: Bjorn Andersson <bjorn.andersson@sonymobile.com> -X-Patchwork-Id: 6202211 -Message-Id: <1428795178-24312-2-git-send-email-bjorn.andersson@sonymobile.com> -To: Kumar Gala <galak@codeaurora.org>, Andy Gross <agross@codeaurora.org>, - David Brown <davidb@codeaurora.org>, Jeffrey Hugo <jhugo@codeaurora.org> -Cc: <linux-kernel@vger.kernel.org>, <linux-arm-msm@vger.kernel.org>, - <linux-soc@vger.kernel.org> -Date: Sat, 11 Apr 2015 16:32:58 -0700 - -The Shared Memory Manager driver implements an interface for allocating -and accessing items in the memory area shared among all of the -processors in a Qualcomm platform. - -Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com> -Reviewed-by: Andy Gross <agross@codeaurora.org> -Tested-by: Andy Gross <agross@codeaurora.org> - ---- -Changes since v1: -- ioremapping the regions nocache -- improved documentation of the two regions of partitions -- corrected free space check in private allocator - - drivers/soc/qcom/Kconfig | 7 + - drivers/soc/qcom/Makefile | 1 + - drivers/soc/qcom/smem.c | 768 ++++++++++++++++++++++++++++++++++++++++++ - include/linux/soc/qcom/smem.h | 14 + - 4 files changed, 790 insertions(+) - create mode 100644 drivers/soc/qcom/smem.c - create mode 100644 include/linux/soc/qcom/smem.h - ---- a/drivers/soc/qcom/Kconfig -+++ b/drivers/soc/qcom/Kconfig -@@ -10,3 +10,10 @@ config QCOM_GSBI - functions for connecting the underlying serial UART, SPI, and I2C - devices to the output pins. - -+config QCOM_SMEM -+ tristate "Qualcomm Shared Memory Manager (SMEM)" -+ depends on ARCH_QCOM -+ help -+ Say y here to enable support for the Qualcomm Shared Memory Manager. -+ The driver provides an interface to items in a heap shared among all -+ processors in a Qualcomm platform. ---- a/drivers/soc/qcom/Makefile -+++ b/drivers/soc/qcom/Makefile -@@ -1 +1,2 @@ - obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o -+obj-$(CONFIG_QCOM_SMEM) += smem.o ---- /dev/null -+++ b/drivers/soc/qcom/smem.c -@@ -0,0 +1,768 @@ -+/* -+ * Copyright (c) 2015, Sony Mobile Communications AB. -+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/hwspinlock.h> -+#include <linux/io.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/of_address.h> -+#include <linux/platform_device.h> -+#include <linux/slab.h> -+#include <linux/soc/qcom/smem.h> -+ -+/* -+ * The Qualcomm shared memory system is a allocate only heap structure that -+ * consists of one of more memory areas that can be accessed by the processors -+ * in the SoC. -+ * -+ * All systems contains a global heap, accessible by all processors in the SoC, -+ * with a table of contents data structure (@smem_header) at the beginning of -+ * the main shared memory block. -+ * -+ * The global header contains metadata for allocations as well as a fixed list -+ * of 512 entries (@smem_global_entry) that can be initialized to reference -+ * parts of the shared memory space. -+ * -+ * -+ * In addition to this global heap a set of "private" heaps can be set up at -+ * boot time with access restrictions so that only certain processor pairs can -+ * access the data. -+ * -+ * These partitions are referenced from an optional partition table -+ * (@smem_ptable), that is found 4kB from the end of the main smem region. The -+ * partition table entries (@smem_ptable_entry) lists the involved processors -+ * (or hosts) and their location in the main shared memory region. -+ * -+ * Each partition starts with a header (@smem_partition_header) that identifies -+ * the partition and holds properties for the two internal memory regions. The -+ * two regions are cached and non-cached memory respectively. Each region -+ * contain a link list of allocation headers (@smem_private_entry) followed by -+ * their data. -+ * -+ * Items in the non-cached region are allocated from the start of the partition -+ * while items in the cached region are allocated from the end. The free area -+ * is hence the region between the cached and non-cached offsets. -+ * -+ * -+ * To synchronize allocations in the shared memory heaps a remote spinlock must -+ * be held - currently lock number 3 of the sfpb or tcsr is used for this on all -+ * platforms. -+ * -+ */ -+ -+/** -+ * struct smem_proc_comm - proc_comm communication struct (legacy) -+ * @command: current command to be executed -+ * @status: status of the currently requested command -+ * @params: parameters to the command -+ */ -+struct smem_proc_comm { -+ u32 command; -+ u32 status; -+ u32 params[2]; -+}; -+ -+/** -+ * struct smem_global_entry - entry to reference smem items on the heap -+ * @allocated: boolean to indicate if this entry is used -+ * @offset: offset to the allocated space -+ * @size: size of the allocated space, 8 byte aligned -+ * @aux_base: base address for the memory region used by this unit, or 0 for -+ * the default region. bits 0,1 are reserved -+ */ -+struct smem_global_entry { -+ u32 allocated; -+ u32 offset; -+ u32 size; -+ u32 aux_base; /* bits 1:0 reserved */ -+}; -+#define AUX_BASE_MASK 0xfffffffc -+ -+/** -+ * struct smem_header - header found in beginning of primary smem region -+ * @proc_comm: proc_comm communication interface (legacy) -+ * @version: array of versions for the various subsystems -+ * @initialized: boolean to indicate that smem is initialized -+ * @free_offset: index of the first unallocated byte in smem -+ * @available: number of bytes available for allocation -+ * @reserved: reserved field, must be 0 -+ * toc: array of references to items -+ */ -+struct smem_header { -+ struct smem_proc_comm proc_comm[4]; -+ u32 version[32]; -+ u32 initialized; -+ u32 free_offset; -+ u32 available; -+ u32 reserved; -+ struct smem_global_entry toc[]; -+}; -+ -+/** -+ * struct smem_ptable_entry - one entry in the @smem_ptable list -+ * @offset: offset, within the main shared memory region, of the partition -+ * @size: size of the partition -+ * @flags: flags for the partition (currently unused) -+ * @host0: first processor/host with access to this partition -+ * @host1: second processor/host with access to this partition -+ * @reserved: reserved entries for later use -+ */ -+struct smem_ptable_entry { -+ u32 offset; -+ u32 size; -+ u32 flags; -+ u16 host0; -+ u16 host1; -+ u32 reserved[8]; -+}; -+ -+/** -+ * struct smem_ptable - partition table for the private partitions -+ * @magic: magic number, must be SMEM_PTABLE_MAGIC -+ * @version: version of the partition table -+ * @num_entries: number of partitions in the table -+ * @reserved: for now reserved entries -+ * @entry: list of @smem_ptable_entry for the @num_entries partitions -+ */ -+struct smem_ptable { -+ u32 magic; -+ u32 version; -+ u32 num_entries; -+ u32 reserved[5]; -+ struct smem_ptable_entry entry[]; -+}; -+#define SMEM_PTABLE_MAGIC 0x434f5424 /* "$TOC" */ -+ -+/** -+ * struct smem_partition_header - header of the partitions -+ * @magic: magic number, must be SMEM_PART_MAGIC -+ * @host0: first processor/host with access to this partition -+ * @host1: second processor/host with access to this partition -+ * @size: size of the partition -+ * @offset_free_uncached: offset to the first free byte of uncached memory in -+ * this partition -+ * @offset_free_cached: offset to the first free byte of cached memory in this -+ * partition -+ * @reserved: for now reserved entries -+ */ -+struct smem_partition_header { -+ u32 magic; -+ u16 host0; -+ u16 host1; -+ u32 size; -+ u32 offset_free_uncached; -+ u32 offset_free_cached; -+ u32 reserved[3]; -+}; -+#define SMEM_PART_MAGIC 0x54525024 /* "$PRT" */ -+ -+/** -+ * struct smem_private_entry - header of each item in the private partition -+ * @canary: magic number, must be SMEM_PRIVATE_CANARY -+ * @item: identifying number of the smem item -+ * @size: size of the data, including padding bytes -+ * @padding_data: number of bytes of padding of data -+ * @padding_hdr: number of bytes of padding between the header and the data -+ * @reserved: for now reserved entry -+ */ -+struct smem_private_entry { -+ u16 canary; -+ u16 item; -+ u32 size; /* includes padding bytes */ -+ u16 padding_data; -+ u16 padding_hdr; -+ u32 reserved; -+}; -+#define SMEM_PRIVATE_CANARY 0xa5a5 -+ -+/* -+ * Item 3 of the global heap contains an array of versions for the various -+ * software components in the SoC. We verify that the boot loader version is -+ * what the expected version (SMEM_EXPECTED_VERSION) as a sanity check. -+ */ -+#define SMEM_ITEM_VERSION 3 -+#define SMEM_MASTER_SBL_VERSION_INDEX 7 -+#define SMEM_EXPECTED_VERSION 11 -+ -+/* -+ * The first 8 items are only to be allocated by the boot loader while -+ * initializing the heap. -+ */ -+#define SMEM_ITEM_LAST_FIXED 8 -+ -+/* Highest accepted item number, for both global and private heaps */ -+#define SMEM_ITEM_LAST 512 -+ -+/* Processor/host identifier for the application processor */ -+#define SMEM_HOST_APPS 0 -+ -+/* Max number of processors/hosts in a system */ -+#define SMEM_HOST_COUNT 7 -+ -+/** -+ * struct smem_region - representation of a chunk of memory used for smem -+ * @aux_base: identifier of aux_mem base -+ * @virt_base: virtual base address of memory with this aux_mem identifier -+ * @size: size of the memory region -+ */ -+struct smem_region { -+ u32 aux_base; -+ void __iomem *virt_base; -+ size_t size; -+}; -+ -+/** -+ * struct qcom_smem - device data for the smem device -+ * @dev: device pointer -+ * @hwlock: reference to a hwspinlock -+ * @partitions: list of pointers to partitions affecting the current -+ * processor/host -+ * @num_regions: number of @regions -+ * @regions: list of the memory regions defining the shared memory -+ */ -+struct qcom_smem { -+ struct device *dev; -+ -+ struct hwspinlock *hwlock; -+ -+ struct smem_partition_header *partitions[SMEM_HOST_COUNT]; -+ -+ unsigned num_regions; -+ struct smem_region regions[0]; -+}; -+ -+/* Pointer to the one and only smem handle */ -+static struct qcom_smem *__smem; -+ -+/* Timeout (ms) for the trylock of remote spinlocks */ -+#define HWSPINLOCK_TIMEOUT 1000 -+ -+static int qcom_smem_alloc_private(struct qcom_smem *smem, -+ unsigned host, -+ unsigned item, -+ size_t size) -+{ -+ struct smem_partition_header *phdr; -+ struct smem_private_entry *hdr; -+ size_t alloc_size; -+ void *p; -+ -+ /* We're not going to find it if there's no matching partition */ -+ if (host >= SMEM_HOST_COUNT || !smem->partitions[host]) -+ return -ENOENT; -+ -+ phdr = smem->partitions[host]; -+ -+ p = (void *)phdr + sizeof(*phdr); -+ while (p < (void *)phdr + phdr->offset_free_uncached) { -+ hdr = p; -+ -+ if (hdr->canary != SMEM_PRIVATE_CANARY) { -+ dev_err(smem->dev, -+ "Found invalid canary in host %d partition\n", -+ host); -+ return -EINVAL; -+ } -+ -+ if (hdr->item == item) -+ return -EEXIST; -+ -+ p += sizeof(*hdr) + hdr->padding_hdr + hdr->size; -+ } -+ -+ /* Check that we don't grow into the cached region */ -+ alloc_size = sizeof(*hdr) + ALIGN(size, 8); -+ if (p + alloc_size >= (void *)phdr + phdr->offset_free_cached) { -+ dev_err(smem->dev, "Out of memory\n"); -+ return -ENOSPC; -+ } -+ -+ hdr = p; -+ hdr->canary = SMEM_PRIVATE_CANARY; -+ hdr->item = item; -+ hdr->size = ALIGN(size, 8); -+ hdr->padding_data = hdr->size - size; -+ hdr->padding_hdr = 0; -+ -+ /* -+ * Ensure the header is written before we advance the free offset, so -+ * that remote processors that does not take the remote spinlock still -+ * gets a consistent view of the linked list. -+ */ -+ wmb(); -+ phdr->offset_free_uncached += alloc_size; -+ -+ return 0; -+} -+ -+static int qcom_smem_alloc_global(struct qcom_smem *smem, -+ unsigned item, -+ size_t size) -+{ -+ struct smem_header *header; -+ struct smem_global_entry *entry; -+ -+ if (WARN_ON(item >= SMEM_ITEM_LAST)) -+ return -EINVAL; -+ -+ header = smem->regions[0].virt_base; -+ entry = &header->toc[item]; -+ if (entry->allocated) -+ return -EEXIST; -+ -+ size = ALIGN(size, 8); -+ if (WARN_ON(size > header->available)) -+ return -ENOMEM; -+ -+ entry->offset = header->free_offset; -+ entry->size = size; -+ -+ /* -+ * Ensure the header is consistent before we mark the item allocated, -+ * so that remote processors will get a consistent view of the item -+ * even though they do not take the spinlock on read. -+ */ -+ wmb(); -+ entry->allocated = 1; -+ -+ header->free_offset += size; -+ header->available -= size; -+ -+ return 0; -+} -+ -+/** -+ * qcom_smem_alloc - allocate space for a smem item -+ * @host: remote processor id, or -1 -+ * @item: smem item handle -+ * @size: number of bytes to be allocated -+ * -+ * Allocate space for a given smem item of size @size, given that the item is -+ * not yet allocated. -+ */ -+int qcom_smem_alloc(unsigned host, unsigned item, size_t size) -+{ -+ unsigned long flags; -+ int ret; -+ -+ if (!__smem) -+ return -EPROBE_DEFER; -+ -+ if (item < SMEM_ITEM_LAST_FIXED) { -+ dev_err(__smem->dev, -+ "Rejecting allocation of static entry %d\n", item); -+ return -EINVAL; -+ } -+ -+ ret = hwspin_lock_timeout_irqsave(__smem->hwlock, -+ HWSPINLOCK_TIMEOUT, -+ &flags); -+ if (ret) -+ return ret; -+ -+ ret = qcom_smem_alloc_private(__smem, host, item, size); -+ if (ret == -ENOENT) -+ ret = qcom_smem_alloc_global(__smem, item, size); -+ -+ hwspin_unlock_irqrestore(__smem->hwlock, &flags); -+ -+ return ret; -+} -+EXPORT_SYMBOL(qcom_smem_alloc); -+ -+static int qcom_smem_get_global(struct qcom_smem *smem, -+ unsigned item, -+ void **ptr, -+ size_t *size) -+{ -+ struct smem_header *header; -+ struct smem_region *area; -+ struct smem_global_entry *entry; -+ u32 aux_base; -+ unsigned i; -+ -+ if (WARN_ON(item >= SMEM_ITEM_LAST)) -+ return -EINVAL; -+ -+ header = smem->regions[0].virt_base; -+ entry = &header->toc[item]; -+ if (!entry->allocated) -+ return -ENXIO; -+ -+ if (ptr != NULL) { -+ aux_base = entry->aux_base & AUX_BASE_MASK; -+ -+ for (i = 0; i < smem->num_regions; i++) { -+ area = &smem->regions[i]; -+ -+ if (area->aux_base == aux_base || !aux_base) { -+ *ptr = area->virt_base + entry->offset; -+ break; -+ } -+ } -+ } -+ if (size != NULL) -+ *size = entry->size; -+ -+ return 0; -+} -+ -+static int qcom_smem_get_private(struct qcom_smem *smem, -+ unsigned host, -+ unsigned item, -+ void **ptr, -+ size_t *size) -+{ -+ struct smem_partition_header *phdr; -+ struct smem_private_entry *hdr; -+ void *p; -+ -+ /* We're not going to find it if there's no matching partition */ -+ if (host >= SMEM_HOST_COUNT || !smem->partitions[host]) -+ return -ENOENT; -+ -+ phdr = smem->partitions[host]; -+ -+ p = (void *)phdr + sizeof(*phdr); -+ while (p < (void *)phdr + phdr->offset_free_uncached) { -+ hdr = p; -+ -+ if (hdr->canary != SMEM_PRIVATE_CANARY) { -+ dev_err(smem->dev, -+ "Found invalid canary in host %d partition\n", -+ host); -+ return -EINVAL; -+ } -+ -+ if (hdr->item == item) { -+ if (ptr != NULL) -+ *ptr = p + sizeof(*hdr) + hdr->padding_hdr; -+ -+ if (size != NULL) -+ *size = hdr->size - hdr->padding_data; -+ -+ return 0; -+ } -+ -+ p += sizeof(*hdr) + hdr->padding_hdr + hdr->size; -+ } -+ -+ return -ENOENT; -+} -+ -+/** -+ * qcom_smem_get - resolve ptr of size of a smem item -+ * @host: the remote processor, or -1 -+ * @item: smem item handle -+ * @ptr: pointer to be filled out with address of the item -+ * @size: pointer to be filled out with size of the item -+ * -+ * Looks up pointer and size of a smem item. -+ */ -+int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size) -+{ -+ unsigned long flags; -+ int ret; -+ -+ if (!__smem) -+ return -EPROBE_DEFER; -+ -+ ret = hwspin_lock_timeout_irqsave(__smem->hwlock, -+ HWSPINLOCK_TIMEOUT, -+ &flags); -+ if (ret) -+ return ret; -+ -+ ret = qcom_smem_get_private(__smem, host, item, ptr, size); -+ if (ret == -ENOENT) -+ ret = qcom_smem_get_global(__smem, item, ptr, size); -+ -+ hwspin_unlock_irqrestore(__smem->hwlock, &flags); -+ return ret; -+ -+} -+EXPORT_SYMBOL(qcom_smem_get); -+ -+/** -+ * qcom_smem_get_free_space - retrieve amont of free space in a partition -+ * @host: the remote processor identifing a partition, or -1 -+ * -+ * To be used by smem clients as a quick way to determine if any new -+ * allocations has been made. -+ */ -+int qcom_smem_get_free_space(unsigned host) -+{ -+ struct smem_partition_header *phdr; -+ struct smem_header *header; -+ unsigned ret; -+ -+ if (!__smem) -+ return -EPROBE_DEFER; -+ -+ if (host < SMEM_HOST_COUNT && __smem->partitions[host]) { -+ phdr = __smem->partitions[host]; -+ ret = phdr->offset_free_uncached; -+ } else { -+ header = __smem->regions[0].virt_base; -+ ret = header->available; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL(qcom_smem_get_free_space); -+ -+static int qcom_smem_get_sbl_version(struct qcom_smem *smem) -+{ -+ unsigned *versions; -+ size_t size; -+ int ret; -+ -+ ret = qcom_smem_get_global(smem, SMEM_ITEM_VERSION, -+ (void **)&versions, &size); -+ if (ret < 0) { -+ dev_err(smem->dev, "Unable to read the version item\n"); -+ return -ENOENT; -+ } -+ -+ if (size < sizeof(unsigned) * SMEM_MASTER_SBL_VERSION_INDEX) { -+ dev_err(smem->dev, "Version item is too small\n"); -+ return -EINVAL; -+ } -+ -+ return versions[SMEM_MASTER_SBL_VERSION_INDEX]; -+} -+ -+static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, -+ unsigned local_host) -+{ -+ struct smem_partition_header *header; -+ struct smem_ptable_entry *entry; -+ struct smem_ptable *ptable; -+ unsigned remote_host; -+ int i; -+ -+ ptable = smem->regions[0].virt_base + smem->regions[0].size - 4 * 1024; -+ if (ptable->magic != SMEM_PTABLE_MAGIC) -+ return 0; -+ -+ if (ptable->version != 1) { -+ dev_err(smem->dev, -+ "Unsupported partition header version %d\n", -+ ptable->version); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < ptable->num_entries; i++) { -+ entry = &ptable->entry[i]; -+ -+ if (entry->host0 != local_host && entry->host1 != local_host) -+ continue; -+ -+ if (!entry->offset) -+ continue; -+ -+ if (!entry->size) -+ continue; -+ -+ if (entry->host0 == local_host) -+ remote_host = entry->host1; -+ else -+ remote_host = entry->host0; -+ -+ if (smem->partitions[remote_host]) { -+ dev_err(smem->dev, -+ "Already found a partition for host %d\n", -+ remote_host); -+ return -EINVAL; -+ } -+ -+ header = smem->regions[0].virt_base + entry->offset; -+ -+ if (header->magic != SMEM_PART_MAGIC) { -+ dev_err(smem->dev, -+ "Partition %d has invalid magic\n", i); -+ return -EINVAL; -+ } -+ -+ if (header->host0 != local_host && header->host1 != local_host) { -+ dev_err(smem->dev, -+ "Partition %d hosts are invalid\n", i); -+ return -EINVAL; -+ } -+ -+ if (header->host0 != remote_host && header->host1 != remote_host) { -+ dev_err(smem->dev, -+ "Partition %d hosts are invalid\n", i); -+ return -EINVAL; -+ } -+ -+ if (header->size != entry->size) { -+ dev_err(smem->dev, -+ "Partition %d has invalid size\n", i); -+ return -EINVAL; -+ } -+ -+ if (header->offset_free_uncached > header->size) { -+ dev_err(smem->dev, -+ "Partition %d has invalid free pointer\n", i); -+ return -EINVAL; -+ } -+ -+ smem->partitions[remote_host] = header; -+ } -+ -+ return 0; -+} -+ -+static int qcom_smem_count_mem_regions(struct platform_device *pdev) -+{ -+ struct resource *res; -+ int num_regions = 0; -+ int i; -+ -+ for (i = 0; i < pdev->num_resources; i++) { -+ res = &pdev->resource[i]; -+ -+ if (resource_type(res) == IORESOURCE_MEM) -+ num_regions++; -+ } -+ -+ return num_regions; -+} -+ -+static int qcom_smem_probe(struct platform_device *pdev) -+{ -+ struct smem_header *header; -+ struct device_node *np; -+ struct qcom_smem *smem; -+ struct resource *res; -+ struct resource r; -+ size_t array_size; -+ int num_regions = 0; -+ int hwlock_id; -+ u32 version; -+ int ret; -+ int i; -+ -+ num_regions = qcom_smem_count_mem_regions(pdev) + 1; -+ -+ array_size = num_regions * sizeof(struct smem_region); -+ smem = devm_kzalloc(&pdev->dev, sizeof(*smem) + array_size, GFP_KERNEL); -+ if (!smem) -+ return -ENOMEM; -+ -+ smem->dev = &pdev->dev; -+ smem->num_regions = num_regions; -+ -+ np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); -+ if (!np) { -+ dev_err(&pdev->dev, "No memory-region specified\n"); -+ return -EINVAL; -+ } -+ -+ ret = of_address_to_resource(np, 0, &r); -+ of_node_put(np); -+ if (ret) -+ return ret; -+ -+ smem->regions[0].aux_base = (u32)r.start; -+ smem->regions[0].size = resource_size(&r); -+ smem->regions[0].virt_base = devm_ioremap_nocache(&pdev->dev, -+ r.start, -+ resource_size(&r)); -+ if (!smem->regions[0].virt_base) -+ return -ENOMEM; -+ -+ for (i = 1; i < num_regions; i++) { -+ res = platform_get_resource(pdev, IORESOURCE_MEM, i - 1); -+ -+ smem->regions[i].aux_base = (u32)res->start; -+ smem->regions[i].size = resource_size(res); -+ smem->regions[i].virt_base = devm_ioremap_nocache(&pdev->dev, -+ res->start, -+ resource_size(res)); -+ if (!smem->regions[i].virt_base) -+ return -ENOMEM; -+ } -+ -+ header = smem->regions[0].virt_base; -+ if (header->initialized != 1 || header->reserved) { -+ dev_err(&pdev->dev, "SMEM is not initilized by SBL\n"); -+ return -EINVAL; -+ } -+ -+ version = qcom_smem_get_sbl_version(smem); -+ if (version >> 16 != SMEM_EXPECTED_VERSION) { -+ dev_err(&pdev->dev, "Unsupported smem version 0x%x\n", version); -+ return -EINVAL; -+ } -+ -+ ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS); -+ if (ret < 0) -+ return ret; -+ -+ hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0); -+ if (hwlock_id < 0) { -+ dev_err(&pdev->dev, "failed to retrieve hwlock\n"); -+ return hwlock_id; -+ } -+ -+ smem->hwlock = hwspin_lock_request_specific(hwlock_id); -+ if (!smem->hwlock) -+ return -ENXIO; -+ -+ __smem = smem; -+ -+ return 0; -+} -+ -+static int qcom_smem_remove(struct platform_device *pdev) -+{ -+ hwspin_lock_free(__smem->hwlock); -+ __smem = NULL; -+ -+ return 0; -+} -+ -+static const struct of_device_id qcom_smem_of_match[] = { -+ { .compatible = "qcom,smem" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, qcom_smem_of_match); -+ -+static struct platform_driver qcom_smem_driver = { -+ .probe = qcom_smem_probe, -+ .remove = qcom_smem_remove, -+ .driver = { -+ .name = "qcom_smem", -+ .of_match_table = qcom_smem_of_match, -+ .suppress_bind_attrs = true, -+ }, -+}; -+ -+static int __init qcom_smem_init(void) -+{ -+ return platform_driver_register(&qcom_smem_driver); -+} -+arch_initcall(qcom_smem_init); -+ -+static void __exit qcom_smem_exit(void) -+{ -+ platform_driver_unregister(&qcom_smem_driver); -+} -+module_exit(qcom_smem_exit) -+ -+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>"); -+MODULE_DESCRIPTION("Qualcomm Shared Memory Manager"); -+MODULE_LICENSE("GPLv2"); ---- /dev/null -+++ b/include/linux/soc/qcom/smem.h -@@ -0,0 +1,14 @@ -+#ifndef __QCOM_SMEM_H__ -+#define __QCOM_SMEM_H__ -+ -+struct device_node; -+struct qcom_smem; -+ -+#define QCOM_SMEM_HOST_ANY -1 -+ -+int qcom_smem_alloc(unsigned host, unsigned item, size_t size); -+int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size); -+ -+int qcom_smem_get_free_space(unsigned host); -+ -+#endif diff --git a/target/linux/ipq806x/patches-4.1/136-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.1/136-clk-Add-safe-switch-hook.patch deleted file mode 100644 index b0d89a9681..0000000000 --- a/target/linux/ipq806x/patches-4.1/136-clk-Add-safe-switch-hook.patch +++ /dev/null @@ -1,164 +0,0 @@ -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v3,04/13] clk: Add safe switch hook -From: Stephen Boyd <sboyd@codeaurora.org> -X-Patchwork-Id: 6063211 -Message-Id: <1426920332-9340-5-git-send-email-sboyd@codeaurora.org> -To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org> -Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, - linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, - Viresh Kumar <viresh.kumar@linaro.org> -Date: Fri, 20 Mar 2015 23:45:23 -0700 - -Sometimes clocks can't accept their parent source turning off -while the source is reprogrammed to a different rate. Most -notably CPU clocks require a way to switch away from the current -PLL they're running on, reprogram that PLL to a new rate, and -then switch back to the PLL with the new rate once they're done. -Add a hook that drivers can implement allowing them to return a -'safe parent' that they can switch their parent to while the -upstream source is reprogrammed to support this. - -Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> - ---- -This patch is good enough for Krait, but soon I'll need to -support a "safe rate" where we ask a clock what rate it needs to be running -at to be sure it's within voltage constraints. Right now safe parent -handles that problem on Krait, but on other platforms it won't work. - - drivers/clk/clk.c | 61 ++++++++++++++++++++++++++++++++++++++------ - include/linux/clk-provider.h | 1 + - 2 files changed, 54 insertions(+), 8 deletions(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -56,9 +56,12 @@ struct clk_core { - struct clk_core **parents; - u8 num_parents; - u8 new_parent_index; -+ u8 safe_parent_index; - unsigned long rate; - unsigned long req_rate; -+ unsigned long old_rate; - unsigned long new_rate; -+ struct clk_core *safe_parent; - struct clk_core *new_parent; - struct clk_core *new_child; - unsigned long flags; -@@ -1596,7 +1599,8 @@ out: - static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate, - struct clk_core *new_parent, u8 p_index) - { -- struct clk_core *child; -+ struct clk_core *child, *parent; -+ struct clk_hw *parent_hw; - - clk->new_rate = new_rate; - clk->new_parent = new_parent; -@@ -1606,6 +1610,18 @@ static void clk_calc_subtree(struct clk_ - if (new_parent && new_parent != clk->parent) - new_parent->new_child = clk; - -+ if (clk->ops->get_safe_parent) { -+ parent_hw = clk->ops->get_safe_parent(clk->hw); -+ if (parent_hw) { -+ parent = parent_hw->core; -+ p_index = clk_fetch_parent_index(clk, parent); -+ clk->safe_parent_index = p_index; -+ clk->safe_parent = parent; -+ } -+ } else { -+ clk->safe_parent = NULL; -+ } -+ - hlist_for_each_entry(child, &clk->children, child_node) { - child->new_rate = clk_recalc(child, new_rate); - clk_calc_subtree(child, child->new_rate, NULL, 0); -@@ -1710,14 +1726,43 @@ static struct clk_core *clk_propagate_ra - unsigned long event) - { - struct clk_core *child, *tmp_clk, *fail_clk = NULL; -+ struct clk_core *old_parent; - int ret = NOTIFY_DONE; - -- if (clk->rate == clk->new_rate) -+ if (clk->rate == clk->new_rate && event != POST_RATE_CHANGE) - return NULL; - -+ switch (event) { -+ case PRE_RATE_CHANGE: -+ if (clk->safe_parent) -+ clk->ops->set_parent(clk->hw, clk->safe_parent_index); -+ clk->old_rate = clk->rate; -+ break; -+ case POST_RATE_CHANGE: -+ if (clk->safe_parent) { -+ old_parent = __clk_set_parent_before(clk, -+ clk->new_parent); -+ if (clk->ops->set_rate_and_parent) { -+ clk->ops->set_rate_and_parent(clk->hw, -+ clk->new_rate, -+ clk->new_parent ? -+ clk->new_parent->rate : 0, -+ clk->new_parent_index); -+ } else if (clk->ops->set_parent) { -+ clk->ops->set_parent(clk->hw, -+ clk->new_parent_index); -+ } -+ __clk_set_parent_after(clk, clk->new_parent, -+ old_parent); -+ } -+ break; -+ } -+ - if (clk->notifier_count) { -- ret = __clk_notify(clk, event, clk->rate, clk->new_rate); -- if (ret & NOTIFY_STOP_MASK) -+ if (event != POST_RATE_CHANGE || clk->old_rate != clk->rate) -+ ret = __clk_notify(clk, event, clk->old_rate, -+ clk->new_rate); -+ if (ret & NOTIFY_STOP_MASK && event != POST_RATE_CHANGE) - fail_clk = clk; - } - -@@ -1763,7 +1808,8 @@ clk_change_rate(struct clk_core *clk, un - - old_rate = clk->rate; - -- if (clk->new_parent && clk->new_parent != clk->parent) { -+ if (clk->new_parent && clk->new_parent != clk->parent && -+ !clk->safe_parent) { - old_parent = __clk_set_parent_before(clk, clk->new_parent); - trace_clk_set_parent(clk, clk->new_parent); - -@@ -1789,9 +1835,6 @@ clk_change_rate(struct clk_core *clk, un - - clk->rate = clk->new_rate; - -- if (clk->notifier_count && old_rate != clk->rate) -- __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); -- - /* - * Use safe iteration, as change_rate can actually swap parents - * for certain clock types. -@@ -1851,6 +1894,8 @@ static int clk_core_set_rate_nolock(stru - - clk->req_rate = req_rate; - -+ clk_propagate_rate_change(top, POST_RATE_CHANGE); -+ - return ret; - } - ---- a/include/linux/clk-provider.h -+++ b/include/linux/clk-provider.h -@@ -183,6 +183,7 @@ struct clk_ops { - struct clk_hw **best_parent_hw); - int (*set_parent)(struct clk_hw *hw, u8 index); - u8 (*get_parent)(struct clk_hw *hw); -+ struct clk_hw *(*get_safe_parent)(struct clk_hw *hw); - int (*set_rate)(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); - int (*set_rate_and_parent)(struct clk_hw *hw, diff --git a/target/linux/ipq806x/patches-4.1/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch b/target/linux/ipq806x/patches-4.1/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch deleted file mode 100644 index dfe716953f..0000000000 --- a/target/linux/ipq806x/patches-4.1/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch +++ /dev/null @@ -1,734 +0,0 @@ -From 2fbb18f85826a9ba308fedb2cf90d3a661a39fd7 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd <sboyd@codeaurora.org> -Date: Fri, 27 Mar 2015 00:16:14 -0700 -Subject: [PATCH] clk: qcom: Add support for NSS/GMAC clocks and resets - -Add the NSS/GMAC clocks and the TCM clock and NSS resets. - -Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> ---- - drivers/clk/qcom/gcc-ipq806x.c | 594 ++++++++++++++++++++++++++- - drivers/clk/qcom/gcc-ipq806x.c.rej | 50 +++ - include/dt-bindings/clock/qcom,gcc-ipq806x.h | 2 + - include/dt-bindings/reset/qcom,gcc-ipq806x.h | 43 ++ - 4 files changed, 688 insertions(+), 1 deletion(-) - create mode 100644 drivers/clk/qcom/gcc-ipq806x.c.rej - ---- a/drivers/clk/qcom/gcc-ipq806x.c -+++ b/drivers/clk/qcom/gcc-ipq806x.c -@@ -220,12 +220,47 @@ static struct clk_regmap pll14_vote = { - }, - }; - -+#define NSS_PLL_RATE(f, _l, _m, _n, i) \ -+ { \ -+ .freq = f, \ -+ .l = _l, \ -+ .m = _m, \ -+ .n = _n, \ -+ .ibits = i, \ -+ } -+ -+static struct pll_freq_tbl pll18_freq_tbl[] = { -+ NSS_PLL_RATE(550000000, 44, 0, 1, 0x01495625), -+ NSS_PLL_RATE(733000000, 58, 16, 25, 0x014b5625), -+}; -+ -+static struct clk_pll pll18 = { -+ .l_reg = 0x31a4, -+ .m_reg = 0x31a8, -+ .n_reg = 0x31ac, -+ .config_reg = 0x31b4, -+ .mode_reg = 0x31a0, -+ .status_reg = 0x31b8, -+ .status_bit = 16, -+ .post_div_shift = 16, -+ .post_div_width = 1, -+ .freq_tbl = pll18_freq_tbl, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "pll18", -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .ops = &clk_pll_ops, -+ }, -+}; -+ - enum { - P_PXO, - P_PLL8, - P_PLL3, - P_PLL0, - P_CXO, -+ P_PLL14, -+ P_PLL18, - }; - - static const struct parent_map gcc_pxo_pll8_map[] = { -@@ -277,6 +312,22 @@ static const char *gcc_pxo_pll8_pll0_map - "pll0_vote", - }; - -+static const struct parent_map gcc_pxo_pll8_pll14_pll18_pll0_map[] = { -+ { P_PXO, 0 }, -+ { P_PLL8, 4 }, -+ { P_PLL0, 2 }, -+ { P_PLL14, 5 }, -+ { P_PLL18, 1 }, -+}; -+ -+static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = { -+ "pxo", -+ "pll8_vote", -+ "pll0_vote", -+ "pll14", -+ "pll18", -+}; -+ - static struct freq_tbl clk_tbl_gsbi_uart[] = { - { 1843200, P_PLL8, 2, 6, 625 }, - { 3686400, P_PLL8, 2, 12, 625 }, -@@ -2282,6 +2333,472 @@ static struct clk_branch ebi2_aon_clk = - }, - }; - -+static const struct freq_tbl clk_tbl_gmac[] = { -+ { 133000000, P_PLL0, 1, 50, 301 }, -+ { 266000000, P_PLL0, 1, 127, 382 }, -+ { } -+}; -+ -+static struct clk_dyn_rcg gmac_core1_src = { -+ .ns_reg[0] = 0x3cac, -+ .ns_reg[1] = 0x3cb0, -+ .md_reg[0] = 0x3ca4, -+ .md_reg[1] = 0x3ca8, -+ .bank_reg = 0x3ca0, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_gmac, -+ .clkr = { -+ .enable_reg = 0x3ca0, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core1_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gmac_core1_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 4, -+ .hwcg_reg = 0x3cb4, -+ .hwcg_bit = 6, -+ .clkr = { -+ .enable_reg = 0x3cb4, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core1_clk", -+ .parent_names = (const char *[]){ -+ "gmac_core1_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_dyn_rcg gmac_core2_src = { -+ .ns_reg[0] = 0x3ccc, -+ .ns_reg[1] = 0x3cd0, -+ .md_reg[0] = 0x3cc4, -+ .md_reg[1] = 0x3cc8, -+ .bank_reg = 0x3ca0, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_gmac, -+ .clkr = { -+ .enable_reg = 0x3cc0, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core2_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gmac_core2_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 5, -+ .hwcg_reg = 0x3cd4, -+ .hwcg_bit = 6, -+ .clkr = { -+ .enable_reg = 0x3cd4, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core2_clk", -+ .parent_names = (const char *[]){ -+ "gmac_core2_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_dyn_rcg gmac_core3_src = { -+ .ns_reg[0] = 0x3cec, -+ .ns_reg[1] = 0x3cf0, -+ .md_reg[0] = 0x3ce4, -+ .md_reg[1] = 0x3ce8, -+ .bank_reg = 0x3ce0, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_gmac, -+ .clkr = { -+ .enable_reg = 0x3ce0, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core3_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gmac_core3_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 6, -+ .hwcg_reg = 0x3cf4, -+ .hwcg_bit = 6, -+ .clkr = { -+ .enable_reg = 0x3cf4, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core3_clk", -+ .parent_names = (const char *[]){ -+ "gmac_core3_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_dyn_rcg gmac_core4_src = { -+ .ns_reg[0] = 0x3d0c, -+ .ns_reg[1] = 0x3d10, -+ .md_reg[0] = 0x3d04, -+ .md_reg[1] = 0x3d08, -+ .bank_reg = 0x3d00, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_gmac, -+ .clkr = { -+ .enable_reg = 0x3d00, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core4_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gmac_core4_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 7, -+ .hwcg_reg = 0x3d14, -+ .hwcg_bit = 6, -+ .clkr = { -+ .enable_reg = 0x3d14, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core4_clk", -+ .parent_names = (const char *[]){ -+ "gmac_core4_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_nss_tcm[] = { -+ { 266000000, P_PLL0, 3, 0, 0 }, -+ { 400000000, P_PLL0, 2, 0, 0 }, -+ { } -+}; -+ -+static struct clk_dyn_rcg nss_tcm_src = { -+ .ns_reg[0] = 0x3dc4, -+ .ns_reg[1] = 0x3dc8, -+ .bank_reg = 0x3dc0, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_nss_tcm, -+ .clkr = { -+ .enable_reg = 0x3dc0, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "nss_tcm_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_tcm_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 14, -+ .clkr = { -+ .enable_reg = 0x3dd0, -+ .enable_mask = BIT(6) | BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "nss_tcm_clk", -+ .parent_names = (const char *[]){ -+ "nss_tcm_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_nss[] = { -+ { 110000000, P_PLL18, 1, 1, 5 }, -+ { 275000000, P_PLL18, 2, 0, 0 }, -+ { 550000000, P_PLL18, 1, 0, 0 }, -+ { 733000000, P_PLL18, 1, 0, 0 }, -+ { } -+}; -+ -+static struct clk_dyn_rcg ubi32_core1_src_clk = { -+ .ns_reg[0] = 0x3d2c, -+ .ns_reg[1] = 0x3d30, -+ .md_reg[0] = 0x3d24, -+ .md_reg[1] = 0x3d28, -+ .bank_reg = 0x3d20, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_nss, -+ .clkr = { -+ .enable_reg = 0x3d20, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "ubi32_core1_src_clk", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, -+ }, -+ }, -+}; -+ -+static struct clk_dyn_rcg ubi32_core2_src_clk = { -+ .ns_reg[0] = 0x3d4c, -+ .ns_reg[1] = 0x3d50, -+ .md_reg[0] = 0x3d44, -+ .md_reg[1] = 0x3d48, -+ .bank_reg = 0x3d40, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_nss, -+ .clkr = { -+ .enable_reg = 0x3d40, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "ubi32_core2_src_clk", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, -+ }, -+ }, -+}; -+ - static struct clk_regmap *gcc_ipq806x_clks[] = { - [PLL0] = &pll0.clkr, - [PLL0_VOTE] = &pll0_vote, -@@ -2291,6 +2808,7 @@ static struct clk_regmap *gcc_ipq806x_cl - [PLL8_VOTE] = &pll8_vote, - [PLL14] = &pll14.clkr, - [PLL14_VOTE] = &pll14_vote, -+ [PLL18] = &pll18.clkr, - [GSBI1_UART_SRC] = &gsbi1_uart_src.clkr, - [GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr, - [GSBI2_UART_SRC] = &gsbi2_uart_src.clkr, -@@ -2390,6 +2908,18 @@ static struct clk_regmap *gcc_ipq806x_cl - [PLL9] = &hfpll0.clkr, - [PLL10] = &hfpll1.clkr, - [PLL12] = &hfpll_l2.clkr, -+ [GMAC_CORE1_CLK_SRC] = &gmac_core1_src.clkr, -+ [GMAC_CORE1_CLK] = &gmac_core1_clk.clkr, -+ [GMAC_CORE2_CLK_SRC] = &gmac_core2_src.clkr, -+ [GMAC_CORE2_CLK] = &gmac_core2_clk.clkr, -+ [GMAC_CORE3_CLK_SRC] = &gmac_core3_src.clkr, -+ [GMAC_CORE3_CLK] = &gmac_core3_clk.clkr, -+ [GMAC_CORE4_CLK_SRC] = &gmac_core4_src.clkr, -+ [GMAC_CORE4_CLK] = &gmac_core4_clk.clkr, -+ [UBI32_CORE1_CLK_SRC] = &ubi32_core1_src_clk.clkr, -+ [UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr, -+ [NSSTCM_CLK_SRC] = &nss_tcm_src.clkr, -+ [NSSTCM_CLK] = &nss_tcm_clk.clkr, - }; - - static const struct qcom_reset_map gcc_ipq806x_resets[] = { -@@ -2508,6 +3038,48 @@ static const struct qcom_reset_map gcc_i - [USB30_1_PHY_RESET] = { 0x3b58, 0 }, - [NSSFB0_RESET] = { 0x3b60, 6 }, - [NSSFB1_RESET] = { 0x3b60, 7 }, -+ [UBI32_CORE1_CLKRST_CLAMP_RESET] = { 0x3d3c, 3}, -+ [UBI32_CORE1_CLAMP_RESET] = { 0x3d3c, 2 }, -+ [UBI32_CORE1_AHB_RESET] = { 0x3d3c, 1 }, -+ [UBI32_CORE1_AXI_RESET] = { 0x3d3c, 0 }, -+ [UBI32_CORE2_CLKRST_CLAMP_RESET] = { 0x3d5c, 3 }, -+ [UBI32_CORE2_CLAMP_RESET] = { 0x3d5c, 2 }, -+ [UBI32_CORE2_AHB_RESET] = { 0x3d5c, 1 }, -+ [UBI32_CORE2_AXI_RESET] = { 0x3d5c, 0 }, -+ [GMAC_CORE1_RESET] = { 0x3cbc, 0 }, -+ [GMAC_CORE2_RESET] = { 0x3cdc, 0 }, -+ [GMAC_CORE3_RESET] = { 0x3cfc, 0 }, -+ [GMAC_CORE4_RESET] = { 0x3d1c, 0 }, -+ [GMAC_AHB_RESET] = { 0x3e24, 0 }, -+ [NSS_CH0_RST_RX_CLK_N_RESET] = { 0x3b60, 0 }, -+ [NSS_CH0_RST_TX_CLK_N_RESET] = { 0x3b60, 1 }, -+ [NSS_CH0_RST_RX_125M_N_RESET] = { 0x3b60, 2 }, -+ [NSS_CH0_HW_RST_RX_125M_N_RESET] = { 0x3b60, 3 }, -+ [NSS_CH0_RST_TX_125M_N_RESET] = { 0x3b60, 4 }, -+ [NSS_CH1_RST_RX_CLK_N_RESET] = { 0x3b60, 5 }, -+ [NSS_CH1_RST_TX_CLK_N_RESET] = { 0x3b60, 6 }, -+ [NSS_CH1_RST_RX_125M_N_RESET] = { 0x3b60, 7 }, -+ [NSS_CH1_HW_RST_RX_125M_N_RESET] = { 0x3b60, 8 }, -+ [NSS_CH1_RST_TX_125M_N_RESET] = { 0x3b60, 9 }, -+ [NSS_CH2_RST_RX_CLK_N_RESET] = { 0x3b60, 10 }, -+ [NSS_CH2_RST_TX_CLK_N_RESET] = { 0x3b60, 11 }, -+ [NSS_CH2_RST_RX_125M_N_RESET] = { 0x3b60, 12 }, -+ [NSS_CH2_HW_RST_RX_125M_N_RESET] = { 0x3b60, 13 }, -+ [NSS_CH2_RST_TX_125M_N_RESET] = { 0x3b60, 14 }, -+ [NSS_CH3_RST_RX_CLK_N_RESET] = { 0x3b60, 15 }, -+ [NSS_CH3_RST_TX_CLK_N_RESET] = { 0x3b60, 16 }, -+ [NSS_CH3_RST_RX_125M_N_RESET] = { 0x3b60, 17 }, -+ [NSS_CH3_HW_RST_RX_125M_N_RESET] = { 0x3b60, 18 }, -+ [NSS_CH3_RST_TX_125M_N_RESET] = { 0x3b60, 19 }, -+ [NSS_RST_RX_250M_125M_N_RESET] = { 0x3b60, 20 }, -+ [NSS_RST_TX_250M_125M_N_RESET] = { 0x3b60, 21 }, -+ [NSS_QSGMII_TXPI_RST_N_RESET] = { 0x3b60, 22 }, -+ [NSS_QSGMII_CDR_RST_N_RESET] = { 0x3b60, 23 }, -+ [NSS_SGMII2_CDR_RST_N_RESET] = { 0x3b60, 24 }, -+ [NSS_SGMII3_CDR_RST_N_RESET] = { 0x3b60, 25 }, -+ [NSS_CAL_PRBS_RST_N_RESET] = { 0x3b60, 26 }, -+ [NSS_LCKDT_RST_N_RESET] = { 0x3b60, 27 }, -+ [NSS_SRDS_N_RESET] = { 0x3b60, 28 }, - }; - - static const struct regmap_config gcc_ipq806x_regmap_config = { -@@ -2536,6 +3108,8 @@ static int gcc_ipq806x_probe(struct plat - { - struct clk *clk; - struct device *dev = &pdev->dev; -+ struct regmap *regmap; -+ int ret; - - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000); -@@ -2546,7 +3120,25 @@ static int gcc_ipq806x_probe(struct plat - if (IS_ERR(clk)) - return PTR_ERR(clk); - -- return qcom_cc_probe(pdev, &gcc_ipq806x_desc); -+ ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc); -+ if (ret) -+ return ret; -+ -+ regmap = dev_get_regmap(dev, NULL); -+ if (!regmap) -+ return -ENODEV; -+ -+ /* Setup PLL18 static bits */ -+ regmap_update_bits(regmap, 0x31a4, 0xffffffc0, 0x40000400); -+ regmap_write(regmap, 0x31b0, 0x3080); -+ -+ /* Set GMAC footswitch sleep/wakeup values */ -+ regmap_write(regmap, 0x3cb8, 8); -+ regmap_write(regmap, 0x3cd8, 8); -+ regmap_write(regmap, 0x3cf8, 8); -+ regmap_write(regmap, 0x3d18, 8); -+ -+ return 0; - } - - static int gcc_ipq806x_remove(struct platform_device *pdev) ---- a/include/dt-bindings/reset/qcom,gcc-ipq806x.h -+++ b/include/dt-bindings/reset/qcom,gcc-ipq806x.h -@@ -129,4 +129,47 @@ - #define USB30_1_PHY_RESET 112 - #define NSSFB0_RESET 113 - #define NSSFB1_RESET 114 -+#define UBI32_CORE1_CLKRST_CLAMP_RESET 115 -+#define UBI32_CORE1_CLAMP_RESET 116 -+#define UBI32_CORE1_AHB_RESET 117 -+#define UBI32_CORE1_AXI_RESET 118 -+#define UBI32_CORE2_CLKRST_CLAMP_RESET 119 -+#define UBI32_CORE2_CLAMP_RESET 120 -+#define UBI32_CORE2_AHB_RESET 121 -+#define UBI32_CORE2_AXI_RESET 122 -+#define GMAC_CORE1_RESET 123 -+#define GMAC_CORE2_RESET 124 -+#define GMAC_CORE3_RESET 125 -+#define GMAC_CORE4_RESET 126 -+#define GMAC_AHB_RESET 127 -+#define NSS_CH0_RST_RX_CLK_N_RESET 128 -+#define NSS_CH0_RST_TX_CLK_N_RESET 129 -+#define NSS_CH0_RST_RX_125M_N_RESET 130 -+#define NSS_CH0_HW_RST_RX_125M_N_RESET 131 -+#define NSS_CH0_RST_TX_125M_N_RESET 132 -+#define NSS_CH1_RST_RX_CLK_N_RESET 133 -+#define NSS_CH1_RST_TX_CLK_N_RESET 134 -+#define NSS_CH1_RST_RX_125M_N_RESET 135 -+#define NSS_CH1_HW_RST_RX_125M_N_RESET 136 -+#define NSS_CH1_RST_TX_125M_N_RESET 137 -+#define NSS_CH2_RST_RX_CLK_N_RESET 138 -+#define NSS_CH2_RST_TX_CLK_N_RESET 139 -+#define NSS_CH2_RST_RX_125M_N_RESET 140 -+#define NSS_CH2_HW_RST_RX_125M_N_RESET 141 -+#define NSS_CH2_RST_TX_125M_N_RESET 142 -+#define NSS_CH3_RST_RX_CLK_N_RESET 143 -+#define NSS_CH3_RST_TX_CLK_N_RESET 144 -+#define NSS_CH3_RST_RX_125M_N_RESET 145 -+#define NSS_CH3_HW_RST_RX_125M_N_RESET 146 -+#define NSS_CH3_RST_TX_125M_N_RESET 147 -+#define NSS_RST_RX_250M_125M_N_RESET 148 -+#define NSS_RST_TX_250M_125M_N_RESET 149 -+#define NSS_QSGMII_TXPI_RST_N_RESET 150 -+#define NSS_QSGMII_CDR_RST_N_RESET 151 -+#define NSS_SGMII2_CDR_RST_N_RESET 152 -+#define NSS_SGMII3_CDR_RST_N_RESET 153 -+#define NSS_CAL_PRBS_RST_N_RESET 154 -+#define NSS_LCKDT_RST_N_RESET 155 -+#define NSS_SRDS_N_RESET 156 -+ - #endif ---- a/include/dt-bindings/clock/qcom,gcc-ipq806x.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h -@@ -289,5 +289,7 @@ - #define UBI32_CORE1_CLK 279 - #define UBI32_CORE2_CLK 280 - #define EBI2_AON_CLK 281 -+#define NSSTCM_CLK_SRC 282 -+#define NSSTCM_CLK 283 - - #endif diff --git a/target/linux/ipq806x/patches-4.1/701-stmmac_update_to_4.3.patch b/target/linux/ipq806x/patches-4.1/701-stmmac_update_to_4.3.patch deleted file mode 100644 index 22450d4bbe..0000000000 --- a/target/linux/ipq806x/patches-4.1/701-stmmac_update_to_4.3.patch +++ /dev/null @@ -1,2355 +0,0 @@ ---- a/drivers/net/ethernet/stmicro/Kconfig -+++ b/drivers/net/ethernet/stmicro/Kconfig -@@ -7,9 +7,7 @@ config NET_VENDOR_STMICRO - default y - depends on HAS_IOMEM - ---help--- -- If you have a network (Ethernet) card belonging to this class, say Y -- and read the Ethernet-HOWTO, available from -- <http://www.tldp.org/docs.html#howto>. -+ If you have a network (Ethernet) card belonging to this class, say Y. - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all ---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig -+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig -@@ -16,6 +16,7 @@ if STMMAC_ETH - config STMMAC_PLATFORM - tristate "STMMAC Platform bus support" - depends on STMMAC_ETH -+ select MFD_SYSCON - default y - ---help--- - This selects the platform specific bus support for the stmmac driver. -@@ -26,6 +27,95 @@ config STMMAC_PLATFORM - - If unsure, say N. - -+if STMMAC_PLATFORM -+ -+config DWMAC_GENERIC -+ tristate "Generic driver for DWMAC" -+ default STMMAC_PLATFORM -+ ---help--- -+ Generic DWMAC driver for platforms that don't require any -+ platform specific code to function or is using platform -+ data for setup. -+ -+config DWMAC_IPQ806X -+ tristate "QCA IPQ806x DWMAC support" -+ default ARCH_QCOM -+ depends on OF -+ select MFD_SYSCON -+ help -+ Support for QCA IPQ806X DWMAC Ethernet. -+ -+ This selects the IPQ806x SoC glue layer support for the stmmac -+ device driver. This driver does not use any of the hardware -+ acceleration features available on this SoC. Network devices -+ will behave like standard non-accelerated ethernet interfaces. -+ -+config DWMAC_LPC18XX -+ tristate "NXP LPC18xx/43xx DWMAC support" -+ default ARCH_LPC18XX -+ depends on OF -+ select MFD_SYSCON -+ ---help--- -+ Support for NXP LPC18xx/43xx DWMAC Ethernet. -+ -+config DWMAC_MESON -+ tristate "Amlogic Meson dwmac support" -+ default ARCH_MESON -+ depends on OF -+ help -+ Support for Ethernet controller on Amlogic Meson SoCs. -+ -+ This selects the Amlogic Meson SoC glue layer support for -+ the stmmac device driver. This driver is used for Meson6 and -+ Meson8 SoCs. -+ -+config DWMAC_ROCKCHIP -+ tristate "Rockchip dwmac support" -+ default ARCH_ROCKCHIP -+ depends on OF -+ select MFD_SYSCON -+ help -+ Support for Ethernet controller on Rockchip RK3288 SoC. -+ -+ This selects the Rockchip RK3288 SoC glue layer support for -+ the stmmac device driver. -+ -+config DWMAC_SOCFPGA -+ tristate "SOCFPGA dwmac support" -+ default ARCH_SOCFPGA -+ depends on OF -+ select MFD_SYSCON -+ help -+ Support for ethernet controller on Altera SOCFPGA -+ -+ This selects the Altera SOCFPGA SoC glue layer support -+ for the stmmac device driver. This driver is used for -+ arria5 and cyclone5 FPGA SoCs. -+ -+config DWMAC_STI -+ tristate "STi GMAC support" -+ default ARCH_STI -+ depends on OF -+ select MFD_SYSCON -+ ---help--- -+ Support for ethernet controller on STi SOCs. -+ -+ This selects STi SoC glue layer support for the stmmac -+ device driver. This driver is used on for the STi series -+ SOCs GMAC ethernet controller. -+ -+config DWMAC_SUNXI -+ tristate "Allwinner GMAC support" -+ default ARCH_SUNXI -+ depends on OF -+ ---help--- -+ Support for Allwinner A20/A31 GMAC ethernet controllers. -+ -+ This selects Allwinner SoC glue layer support for the -+ stmmac device driver. This driver is used for A20/A31 -+ GMAC ethernet controller. -+endif -+ - config STMMAC_PCI - tristate "STMMAC PCI bus support" - depends on STMMAC_ETH && PCI ---- a/drivers/net/ethernet/stmicro/stmmac/Makefile -+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile -@@ -4,9 +4,17 @@ stmmac-objs:= stmmac_main.o stmmac_ethto - dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ - mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y) - --obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o --stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o \ -- dwmac-sti.o dwmac-socfpga.o dwmac-rk.o -+# Ordering matters. Generic driver must be last. -+obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o -+obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o -+obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o -+obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o -+obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o -+obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o -+obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o -+obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o -+obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o -+stmmac-platform-objs:= stmmac_platform.o - - obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o - stmmac-pci-objs:= stmmac_pci.o ---- /dev/null -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c -@@ -0,0 +1,81 @@ -+/* -+ * Generic DWMAC platform driver -+ * -+ * Copyright (C) 2007-2011 STMicroelectronics Ltd -+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/platform_device.h> -+ -+#include "stmmac.h" -+#include "stmmac_platform.h" -+ -+static int dwmac_generic_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ int ret; -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ if (pdev->dev.of_node) { -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) { -+ dev_err(&pdev->dev, "dt configuration failed\n"); -+ return PTR_ERR(plat_dat); -+ } -+ } else { -+ plat_dat = dev_get_platdata(&pdev->dev); -+ if (!plat_dat) { -+ dev_err(&pdev->dev, "no platform data provided\n"); -+ return -EINVAL; -+ } -+ -+ /* Set default value for multicast hash bins */ -+ plat_dat->multicast_filter_bins = HASH_TABLE_SIZE; -+ -+ /* Set default value for unicast filter entries */ -+ plat_dat->unicast_filter_entries = 1; -+ } -+ -+ /* Custom initialisation (if needed) */ -+ if (plat_dat->init) { -+ ret = plat_dat->init(pdev, plat_dat->bsp_priv); -+ if (ret) -+ return ret; -+ } -+ -+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+} -+ -+static const struct of_device_id dwmac_generic_match[] = { -+ { .compatible = "st,spear600-gmac"}, -+ { .compatible = "snps,dwmac-3.610"}, -+ { .compatible = "snps,dwmac-3.70a"}, -+ { .compatible = "snps,dwmac-3.710"}, -+ { .compatible = "snps,dwmac"}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, dwmac_generic_match); -+ -+static struct platform_driver dwmac_generic_driver = { -+ .probe = dwmac_generic_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = STMMAC_RESOURCE_NAME, -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = of_match_ptr(dwmac_generic_match), -+ }, -+}; -+module_platform_driver(dwmac_generic_driver); -+ -+MODULE_DESCRIPTION("Generic dwmac driver"); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c -@@ -0,0 +1,373 @@ -+/* -+ * Qualcomm Atheros IPQ806x GMAC glue layer -+ * -+ * Copyright (C) 2015 The Linux Foundation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include <linux/device.h> -+#include <linux/platform_device.h> -+#include <linux/phy.h> -+#include <linux/regmap.h> -+#include <linux/clk.h> -+#include <linux/reset.h> -+#include <linux/of_net.h> -+#include <linux/mfd/syscon.h> -+#include <linux/stmmac.h> -+#include <linux/of_mdio.h> -+#include <linux/module.h> -+ -+#include "stmmac_platform.h" -+ -+#define NSS_COMMON_CLK_GATE 0x8 -+#define NSS_COMMON_CLK_GATE_PTP_EN(x) BIT(0x10 + x) -+#define NSS_COMMON_CLK_GATE_RGMII_RX_EN(x) BIT(0x9 + (x * 2)) -+#define NSS_COMMON_CLK_GATE_RGMII_TX_EN(x) BIT(0x8 + (x * 2)) -+#define NSS_COMMON_CLK_GATE_GMII_RX_EN(x) BIT(0x4 + x) -+#define NSS_COMMON_CLK_GATE_GMII_TX_EN(x) BIT(0x0 + x) -+ -+#define NSS_COMMON_CLK_DIV0 0xC -+#define NSS_COMMON_CLK_DIV_OFFSET(x) (x * 8) -+#define NSS_COMMON_CLK_DIV_MASK 0x7f -+ -+#define NSS_COMMON_CLK_SRC_CTRL 0x14 -+#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x) (x) -+/* Mode is coded on 1 bit but is different depending on the MAC ID: -+ * MAC0: QSGMII=0 RGMII=1 -+ * MAC1: QSGMII=0 SGMII=0 RGMII=1 -+ * MAC2 & MAC3: QSGMII=0 SGMII=1 -+ */ -+#define NSS_COMMON_CLK_SRC_CTRL_RGMII(x) 1 -+#define NSS_COMMON_CLK_SRC_CTRL_SGMII(x) ((x >= 2) ? 1 : 0) -+ -+#define NSS_COMMON_MACSEC_CTL 0x28 -+#define NSS_COMMON_MACSEC_CTL_EXT_BYPASS_EN(x) (1 << x) -+ -+#define NSS_COMMON_GMAC_CTL(x) (0x30 + (x * 4)) -+#define NSS_COMMON_GMAC_CTL_CSYS_REQ BIT(19) -+#define NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL BIT(16) -+#define NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET 8 -+#define NSS_COMMON_GMAC_CTL_IFG_OFFSET 0 -+#define NSS_COMMON_GMAC_CTL_IFG_MASK 0x3f -+ -+#define NSS_COMMON_CLK_DIV_RGMII_1000 1 -+#define NSS_COMMON_CLK_DIV_RGMII_100 9 -+#define NSS_COMMON_CLK_DIV_RGMII_10 99 -+#define NSS_COMMON_CLK_DIV_SGMII_1000 0 -+#define NSS_COMMON_CLK_DIV_SGMII_100 4 -+#define NSS_COMMON_CLK_DIV_SGMII_10 49 -+ -+#define QSGMII_PCS_MODE_CTL 0x68 -+#define QSGMII_PCS_MODE_CTL_AUTONEG_EN(x) BIT((x * 8) + 7) -+ -+#define QSGMII_PCS_CAL_LCKDT_CTL 0x120 -+#define QSGMII_PCS_CAL_LCKDT_CTL_RST BIT(19) -+ -+/* Only GMAC1/2/3 support SGMII and their CTL register are not contiguous */ -+#define QSGMII_PHY_SGMII_CTL(x) ((x == 1) ? 0x134 : \ -+ (0x13c + (4 * (x - 2)))) -+#define QSGMII_PHY_CDR_EN BIT(0) -+#define QSGMII_PHY_RX_FRONT_EN BIT(1) -+#define QSGMII_PHY_RX_SIGNAL_DETECT_EN BIT(2) -+#define QSGMII_PHY_TX_DRIVER_EN BIT(3) -+#define QSGMII_PHY_QSGMII_EN BIT(7) -+#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET 12 -+#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK 0x7 -+#define QSGMII_PHY_RX_DC_BIAS_OFFSET 18 -+#define QSGMII_PHY_RX_DC_BIAS_MASK 0x3 -+#define QSGMII_PHY_RX_INPUT_EQU_OFFSET 20 -+#define QSGMII_PHY_RX_INPUT_EQU_MASK 0x3 -+#define QSGMII_PHY_CDR_PI_SLEW_OFFSET 22 -+#define QSGMII_PHY_CDR_PI_SLEW_MASK 0x3 -+#define QSGMII_PHY_TX_DRV_AMP_OFFSET 28 -+#define QSGMII_PHY_TX_DRV_AMP_MASK 0xf -+ -+struct ipq806x_gmac { -+ struct platform_device *pdev; -+ struct regmap *nss_common; -+ struct regmap *qsgmii_csr; -+ uint32_t id; -+ struct clk *core_clk; -+ phy_interface_t phy_mode; -+}; -+ -+static int get_clk_div_sgmii(struct ipq806x_gmac *gmac, unsigned int speed) -+{ -+ struct device *dev = &gmac->pdev->dev; -+ int div; -+ -+ switch (speed) { -+ case SPEED_1000: -+ div = NSS_COMMON_CLK_DIV_SGMII_1000; -+ break; -+ -+ case SPEED_100: -+ div = NSS_COMMON_CLK_DIV_SGMII_100; -+ break; -+ -+ case SPEED_10: -+ div = NSS_COMMON_CLK_DIV_SGMII_10; -+ break; -+ -+ default: -+ dev_err(dev, "Speed %dMbps not supported in SGMII\n", speed); -+ return -EINVAL; -+ } -+ -+ return div; -+} -+ -+static int get_clk_div_rgmii(struct ipq806x_gmac *gmac, unsigned int speed) -+{ -+ struct device *dev = &gmac->pdev->dev; -+ int div; -+ -+ switch (speed) { -+ case SPEED_1000: -+ div = NSS_COMMON_CLK_DIV_RGMII_1000; -+ break; -+ -+ case SPEED_100: -+ div = NSS_COMMON_CLK_DIV_RGMII_100; -+ break; -+ -+ case SPEED_10: -+ div = NSS_COMMON_CLK_DIV_RGMII_10; -+ break; -+ -+ default: -+ dev_err(dev, "Speed %dMbps not supported in RGMII\n", speed); -+ return -EINVAL; -+ } -+ -+ return div; -+} -+ -+static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, unsigned int speed) -+{ -+ uint32_t clk_bits, val; -+ int div; -+ -+ switch (gmac->phy_mode) { -+ case PHY_INTERFACE_MODE_RGMII: -+ div = get_clk_div_rgmii(gmac, speed); -+ clk_bits = NSS_COMMON_CLK_GATE_RGMII_RX_EN(gmac->id) | -+ NSS_COMMON_CLK_GATE_RGMII_TX_EN(gmac->id); -+ break; -+ -+ case PHY_INTERFACE_MODE_SGMII: -+ div = get_clk_div_sgmii(gmac, speed); -+ clk_bits = NSS_COMMON_CLK_GATE_GMII_RX_EN(gmac->id) | -+ NSS_COMMON_CLK_GATE_GMII_TX_EN(gmac->id); -+ break; -+ -+ default: -+ dev_err(&gmac->pdev->dev, "Unsupported PHY mode: \"%s\"\n", -+ phy_modes(gmac->phy_mode)); -+ return -EINVAL; -+ } -+ -+ /* Disable the clocks */ -+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val); -+ val &= ~clk_bits; -+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val); -+ -+ /* Set the divider */ -+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_DIV0, &val); -+ val &= ~(NSS_COMMON_CLK_DIV_MASK -+ << NSS_COMMON_CLK_DIV_OFFSET(gmac->id)); -+ val |= div << NSS_COMMON_CLK_DIV_OFFSET(gmac->id); -+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_DIV0, val); -+ -+ /* Enable the clock back */ -+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val); -+ val |= clk_bits; -+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val); -+ -+ return 0; -+} -+ -+static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac) -+{ -+ struct device *dev = &gmac->pdev->dev; -+ -+ gmac->phy_mode = of_get_phy_mode(dev->of_node); -+ if (gmac->phy_mode < 0) { -+ dev_err(dev, "missing phy mode property\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) { -+ dev_err(dev, "missing qcom id property\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ /* The GMACs are called 1 to 4 in the documentation, but to simplify the -+ * code and keep it consistent with the Linux convention, we'll number -+ * them from 0 to 3 here. -+ */ -+ if (gmac->id < 0 || gmac->id > 3) { -+ dev_err(dev, "invalid gmac id\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ gmac->core_clk = devm_clk_get(dev, "stmmaceth"); -+ if (IS_ERR(gmac->core_clk)) { -+ dev_err(dev, "missing stmmaceth clk property\n"); -+ return gmac->core_clk; -+ } -+ clk_set_rate(gmac->core_clk, 266000000); -+ -+ /* Setup the register map for the nss common registers */ -+ gmac->nss_common = syscon_regmap_lookup_by_phandle(dev->of_node, -+ "qcom,nss-common"); -+ if (IS_ERR(gmac->nss_common)) { -+ dev_err(dev, "missing nss-common node\n"); -+ return gmac->nss_common; -+ } -+ -+ /* Setup the register map for the qsgmii csr registers */ -+ gmac->qsgmii_csr = syscon_regmap_lookup_by_phandle(dev->of_node, -+ "qcom,qsgmii-csr"); -+ if (IS_ERR(gmac->qsgmii_csr)) { -+ dev_err(dev, "missing qsgmii-csr node\n"); -+ return gmac->qsgmii_csr; -+ } -+ -+ return NULL; -+} -+ -+static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed) -+{ -+ struct ipq806x_gmac *gmac = priv; -+ -+ ipq806x_gmac_set_speed(gmac, speed); -+} -+ -+static int ipq806x_gmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ struct device *dev = &pdev->dev; -+ struct ipq806x_gmac *gmac; -+ int val; -+ void *err; -+ -+ val = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (val) -+ return val; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); -+ if (!gmac) -+ return -ENOMEM; -+ -+ gmac->pdev = pdev; -+ -+ err = ipq806x_gmac_of_parse(gmac); -+ if (IS_ERR(err)) { -+ dev_err(dev, "device tree parsing error\n"); -+ return PTR_ERR(err); -+ } -+ -+ regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL, -+ QSGMII_PCS_CAL_LCKDT_CTL_RST); -+ -+ /* Inter frame gap is set to 12 */ -+ val = 12 << NSS_COMMON_GMAC_CTL_IFG_OFFSET | -+ 12 << NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET; -+ /* We also initiate an AXI low power exit request */ -+ val |= NSS_COMMON_GMAC_CTL_CSYS_REQ; -+ switch (gmac->phy_mode) { -+ case PHY_INTERFACE_MODE_RGMII: -+ val |= NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL; -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL; -+ break; -+ default: -+ dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", -+ phy_modes(gmac->phy_mode)); -+ return -EINVAL; -+ } -+ regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val); -+ -+ /* Configure the clock src according to the mode */ -+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val); -+ val &= ~(1 << NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id)); -+ switch (gmac->phy_mode) { -+ case PHY_INTERFACE_MODE_RGMII: -+ val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) << -+ NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id); -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ val |= NSS_COMMON_CLK_SRC_CTRL_SGMII(gmac->id) << -+ NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id); -+ break; -+ default: -+ dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", -+ phy_modes(gmac->phy_mode)); -+ return -EINVAL; -+ } -+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val); -+ -+ /* Enable PTP clock */ -+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val); -+ val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id); -+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val); -+ -+ if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) { -+ regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id), -+ QSGMII_PHY_CDR_EN | -+ QSGMII_PHY_RX_FRONT_EN | -+ QSGMII_PHY_RX_SIGNAL_DETECT_EN | -+ QSGMII_PHY_TX_DRIVER_EN | -+ QSGMII_PHY_QSGMII_EN | -+ 0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET | -+ 0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET | -+ 0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET | -+ 0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET | -+ 0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET); -+ } -+ -+ plat_dat->has_gmac = true; -+ plat_dat->bsp_priv = gmac; -+ plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; -+ -+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+} -+ -+static const struct of_device_id ipq806x_gmac_dwmac_match[] = { -+ { .compatible = "qcom,ipq806x-gmac" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match); -+ -+static struct platform_driver ipq806x_gmac_dwmac_driver = { -+ .probe = ipq806x_gmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "ipq806x-gmac-dwmac", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = ipq806x_gmac_dwmac_match, -+ }, -+}; -+module_platform_driver(ipq806x_gmac_dwmac_driver); -+ -+MODULE_AUTHOR("Mathieu Olivari <mathieu@codeaurora.org>"); -+MODULE_DESCRIPTION("Qualcomm Atheros IPQ806x DWMAC specific glue layer"); -+MODULE_LICENSE("Dual BSD/GPL"); ---- /dev/null -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c -@@ -0,0 +1,86 @@ -+/* -+ * DWMAC glue for NXP LPC18xx/LPC43xx Ethernet -+ * -+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include <linux/mfd/syscon.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/of_net.h> -+#include <linux/phy.h> -+#include <linux/platform_device.h> -+#include <linux/regmap.h> -+#include <linux/stmmac.h> -+ -+#include "stmmac_platform.h" -+ -+/* Register defines for CREG syscon */ -+#define LPC18XX_CREG_CREG6 0x12c -+# define LPC18XX_CREG_CREG6_ETHMODE_MASK 0x7 -+# define LPC18XX_CREG_CREG6_ETHMODE_MII 0x0 -+# define LPC18XX_CREG_CREG6_ETHMODE_RMII 0x4 -+ -+static int lpc18xx_dwmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ struct regmap *reg; -+ u8 ethmode; -+ int ret; -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ plat_dat->has_gmac = true; -+ -+ reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg"); -+ if (IS_ERR(reg)) { -+ dev_err(&pdev->dev, "syscon lookup failed\n"); -+ return PTR_ERR(reg); -+ } -+ -+ if (plat_dat->interface == PHY_INTERFACE_MODE_MII) { -+ ethmode = LPC18XX_CREG_CREG6_ETHMODE_MII; -+ } else if (plat_dat->interface == PHY_INTERFACE_MODE_RMII) { -+ ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII; -+ } else { -+ dev_err(&pdev->dev, "Only MII and RMII mode supported\n"); -+ return -EINVAL; -+ } -+ -+ regmap_update_bits(reg, LPC18XX_CREG_CREG6, -+ LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode); -+ -+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+} -+ -+static const struct of_device_id lpc18xx_dwmac_match[] = { -+ { .compatible = "nxp,lpc1850-dwmac" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, lpc18xx_dwmac_match); -+ -+static struct platform_driver lpc18xx_dwmac_driver = { -+ .probe = lpc18xx_dwmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "lpc18xx-dwmac", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = lpc18xx_dwmac_match, -+ }, -+}; -+module_platform_driver(lpc18xx_dwmac_driver); -+ -+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); -+MODULE_DESCRIPTION("DWMAC glue for LPC18xx/43xx Ethernet"); -+MODULE_LICENSE("GPL v2"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c -@@ -15,6 +15,7 @@ - #include <linux/ethtool.h> - #include <linux/io.h> - #include <linux/ioport.h> -+#include <linux/module.h> - #include <linux/platform_device.h> - #include <linux/stmmac.h> - -@@ -46,24 +47,54 @@ static void meson6_dwmac_fix_mac_speed(v - writel(val, dwmac->reg); - } - --static void *meson6_dwmac_setup(struct platform_device *pdev) -+static int meson6_dwmac_probe(struct platform_device *pdev) - { -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; - struct meson_dwmac *dwmac; - struct resource *res; -+ int ret; -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); - - dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); - if (!dwmac) -- return ERR_PTR(-ENOMEM); -+ return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dwmac->reg = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(dwmac->reg)) -- return ERR_CAST(dwmac->reg); -+ return PTR_ERR(dwmac->reg); -+ -+ plat_dat->bsp_priv = dwmac; -+ plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed; - -- return dwmac; -+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); - } - --const struct stmmac_of_data meson6_dwmac_data = { -- .setup = meson6_dwmac_setup, -- .fix_mac_speed = meson6_dwmac_fix_mac_speed, -+static const struct of_device_id meson6_dwmac_match[] = { -+ { .compatible = "amlogic,meson6-dwmac" }, -+ { } - }; -+MODULE_DEVICE_TABLE(of, meson6_dwmac_match); -+ -+static struct platform_driver meson6_dwmac_driver = { -+ .probe = meson6_dwmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "meson6-dwmac", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = meson6_dwmac_match, -+ }, -+}; -+module_platform_driver(meson6_dwmac_driver); -+ -+MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); -+MODULE_DESCRIPTION("Amlogic Meson DWMAC glue layer"); -+MODULE_LICENSE("GPL v2"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -@@ -22,17 +22,31 @@ - #include <linux/phy.h> - #include <linux/of_net.h> - #include <linux/gpio.h> -+#include <linux/module.h> - #include <linux/of_gpio.h> - #include <linux/of_device.h> -+#include <linux/platform_device.h> - #include <linux/regulator/consumer.h> - #include <linux/delay.h> - #include <linux/mfd/syscon.h> - #include <linux/regmap.h> - -+#include "stmmac_platform.h" -+ -+struct rk_priv_data; -+struct rk_gmac_ops { -+ void (*set_to_rgmii)(struct rk_priv_data *bsp_priv, -+ int tx_delay, int rx_delay); -+ void (*set_to_rmii)(struct rk_priv_data *bsp_priv); -+ void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); -+ void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed); -+}; -+ - struct rk_priv_data { - struct platform_device *pdev; - int phy_iface; - struct regulator *regulator; -+ const struct rk_gmac_ops *ops; - - bool clk_enabled; - bool clock_input; -@@ -60,103 +74,228 @@ struct rk_priv_data { - - #define RK3288_GRF_SOC_CON1 0x0248 - #define RK3288_GRF_SOC_CON3 0x0250 --#define RK3288_GRF_GPIO3D_E 0x01ec --#define RK3288_GRF_GPIO4A_E 0x01f0 --#define RK3288_GRF_GPIO4B_E 0x01f4 - - /*RK3288_GRF_SOC_CON1*/ --#define GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8)) --#define GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | GRF_BIT(8)) --#define GMAC_FLOW_CTRL GRF_BIT(9) --#define GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9) --#define GMAC_SPEED_10M GRF_CLR_BIT(10) --#define GMAC_SPEED_100M GRF_BIT(10) --#define GMAC_RMII_CLK_25M GRF_BIT(11) --#define GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11) --#define GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13)) --#define GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13)) --#define GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13)) --#define GMAC_RMII_MODE GRF_BIT(14) --#define GMAC_RMII_MODE_CLR GRF_CLR_BIT(14) -+#define RK3288_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | \ -+ GRF_CLR_BIT(8)) -+#define RK3288_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \ -+ GRF_BIT(8)) -+#define RK3288_GMAC_FLOW_CTRL GRF_BIT(9) -+#define RK3288_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9) -+#define RK3288_GMAC_SPEED_10M GRF_CLR_BIT(10) -+#define RK3288_GMAC_SPEED_100M GRF_BIT(10) -+#define RK3288_GMAC_RMII_CLK_25M GRF_BIT(11) -+#define RK3288_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11) -+#define RK3288_GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13)) -+#define RK3288_GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13)) -+#define RK3288_GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13)) -+#define RK3288_GMAC_RMII_MODE GRF_BIT(14) -+#define RK3288_GMAC_RMII_MODE_CLR GRF_CLR_BIT(14) - - /*RK3288_GRF_SOC_CON3*/ --#define GMAC_TXCLK_DLY_ENABLE GRF_BIT(14) --#define GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14) --#define GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) --#define GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) --#define GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) --#define GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) -+#define RK3288_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14) -+#define RK3288_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14) -+#define RK3288_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) -+#define RK3288_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) -+#define RK3288_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) -+#define RK3288_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) - --static void set_to_rgmii(struct rk_priv_data *bsp_priv, -- int tx_delay, int rx_delay) -+static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv, -+ int tx_delay, int rx_delay) - { - struct device *dev = &bsp_priv->pdev->dev; - - if (IS_ERR(bsp_priv->grf)) { -- dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ dev_err(dev, "Missing rockchip,grf property\n"); - return; - } - - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, -- GMAC_PHY_INTF_SEL_RGMII | GMAC_RMII_MODE_CLR); -+ RK3288_GMAC_PHY_INTF_SEL_RGMII | -+ RK3288_GMAC_RMII_MODE_CLR); - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3, -- GMAC_RXCLK_DLY_ENABLE | GMAC_TXCLK_DLY_ENABLE | -- GMAC_CLK_RX_DL_CFG(rx_delay) | -- GMAC_CLK_TX_DL_CFG(tx_delay)); -+ RK3288_GMAC_RXCLK_DLY_ENABLE | -+ RK3288_GMAC_TXCLK_DLY_ENABLE | -+ RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) | -+ RK3288_GMAC_CLK_TX_DL_CFG(tx_delay)); - } - --static void set_to_rmii(struct rk_priv_data *bsp_priv) -+static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv) - { - struct device *dev = &bsp_priv->pdev->dev; - - if (IS_ERR(bsp_priv->grf)) { -- dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ dev_err(dev, "Missing rockchip,grf property\n"); - return; - } - - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, -- GMAC_PHY_INTF_SEL_RMII | GMAC_RMII_MODE); -+ RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE); - } - --static void set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) -+static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) - { - struct device *dev = &bsp_priv->pdev->dev; - - if (IS_ERR(bsp_priv->grf)) { -- dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ dev_err(dev, "Missing rockchip,grf property\n"); - return; - } - - if (speed == 10) -- regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_2_5M); -+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, -+ RK3288_GMAC_CLK_2_5M); - else if (speed == 100) -- regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_25M); -+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, -+ RK3288_GMAC_CLK_25M); - else if (speed == 1000) -- regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_125M); -+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, -+ RK3288_GMAC_CLK_125M); - else - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - } - --static void set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -+static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) - { - struct device *dev = &bsp_priv->pdev->dev; - - if (IS_ERR(bsp_priv->grf)) { -- dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ dev_err(dev, "Missing rockchip,grf property\n"); - return; - } - - if (speed == 10) { - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, -- GMAC_RMII_CLK_2_5M | GMAC_SPEED_10M); -+ RK3288_GMAC_RMII_CLK_2_5M | -+ RK3288_GMAC_SPEED_10M); - } else if (speed == 100) { - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, -- GMAC_RMII_CLK_25M | GMAC_SPEED_100M); -+ RK3288_GMAC_RMII_CLK_25M | -+ RK3288_GMAC_SPEED_100M); -+ } else { -+ dev_err(dev, "unknown speed value for RMII! speed=%d", speed); -+ } -+} -+ -+static const struct rk_gmac_ops rk3288_ops = { -+ .set_to_rgmii = rk3288_set_to_rgmii, -+ .set_to_rmii = rk3288_set_to_rmii, -+ .set_rgmii_speed = rk3288_set_rgmii_speed, -+ .set_rmii_speed = rk3288_set_rmii_speed, -+}; -+ -+#define RK3368_GRF_SOC_CON15 0x043c -+#define RK3368_GRF_SOC_CON16 0x0440 -+ -+/* RK3368_GRF_SOC_CON15 */ -+#define RK3368_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \ -+ GRF_CLR_BIT(11)) -+#define RK3368_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \ -+ GRF_BIT(11)) -+#define RK3368_GMAC_FLOW_CTRL GRF_BIT(8) -+#define RK3368_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8) -+#define RK3368_GMAC_SPEED_10M GRF_CLR_BIT(7) -+#define RK3368_GMAC_SPEED_100M GRF_BIT(7) -+#define RK3368_GMAC_RMII_CLK_25M GRF_BIT(3) -+#define RK3368_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3) -+#define RK3368_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5)) -+#define RK3368_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5)) -+#define RK3368_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5)) -+#define RK3368_GMAC_RMII_MODE GRF_BIT(6) -+#define RK3368_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6) -+ -+/* RK3368_GRF_SOC_CON16 */ -+#define RK3368_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) -+#define RK3368_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) -+#define RK3368_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) -+#define RK3368_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) -+#define RK3368_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) -+#define RK3368_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) -+ -+static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv, -+ int tx_delay, int rx_delay) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ return; -+ } -+ -+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, -+ RK3368_GMAC_PHY_INTF_SEL_RGMII | -+ RK3368_GMAC_RMII_MODE_CLR); -+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16, -+ RK3368_GMAC_RXCLK_DLY_ENABLE | -+ RK3368_GMAC_TXCLK_DLY_ENABLE | -+ RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) | -+ RK3368_GMAC_CLK_TX_DL_CFG(tx_delay)); -+} -+ -+static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ return; -+ } -+ -+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, -+ RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE); -+} -+ -+static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ return; -+ } -+ -+ if (speed == 10) -+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, -+ RK3368_GMAC_CLK_2_5M); -+ else if (speed == 100) -+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, -+ RK3368_GMAC_CLK_25M); -+ else if (speed == 1000) -+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, -+ RK3368_GMAC_CLK_125M); -+ else -+ dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -+} -+ -+static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); -+ return; -+ } -+ -+ if (speed == 10) { -+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, -+ RK3368_GMAC_RMII_CLK_2_5M | -+ RK3368_GMAC_SPEED_10M); -+ } else if (speed == 100) { -+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, -+ RK3368_GMAC_RMII_CLK_25M | -+ RK3368_GMAC_SPEED_100M); - } else { - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - } - } - -+static const struct rk_gmac_ops rk3368_ops = { -+ .set_to_rgmii = rk3368_set_to_rgmii, -+ .set_to_rmii = rk3368_set_to_rmii, -+ .set_rgmii_speed = rk3368_set_rgmii_speed, -+ .set_rmii_speed = rk3368_set_rmii_speed, -+}; -+ - static int gmac_clk_init(struct rk_priv_data *bsp_priv) - { - struct device *dev = &bsp_priv->pdev->dev; -@@ -165,46 +304,46 @@ static int gmac_clk_init(struct rk_priv_ - - bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx"); - if (IS_ERR(bsp_priv->mac_clk_rx)) -- dev_err(dev, "%s: cannot get clock %s\n", -- __func__, "mac_clk_rx"); -+ dev_err(dev, "cannot get clock %s\n", -+ "mac_clk_rx"); - - bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx"); - if (IS_ERR(bsp_priv->mac_clk_tx)) -- dev_err(dev, "%s: cannot get clock %s\n", -- __func__, "mac_clk_tx"); -+ dev_err(dev, "cannot get clock %s\n", -+ "mac_clk_tx"); - - bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac"); - if (IS_ERR(bsp_priv->aclk_mac)) -- dev_err(dev, "%s: cannot get clock %s\n", -- __func__, "aclk_mac"); -+ dev_err(dev, "cannot get clock %s\n", -+ "aclk_mac"); - - bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac"); - if (IS_ERR(bsp_priv->pclk_mac)) -- dev_err(dev, "%s: cannot get clock %s\n", -- __func__, "pclk_mac"); -+ dev_err(dev, "cannot get clock %s\n", -+ "pclk_mac"); - - bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth"); - if (IS_ERR(bsp_priv->clk_mac)) -- dev_err(dev, "%s: cannot get clock %s\n", -- __func__, "stmmaceth"); -+ dev_err(dev, "cannot get clock %s\n", -+ "stmmaceth"); - - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) { - bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref"); - if (IS_ERR(bsp_priv->clk_mac_ref)) -- dev_err(dev, "%s: cannot get clock %s\n", -- __func__, "clk_mac_ref"); -+ dev_err(dev, "cannot get clock %s\n", -+ "clk_mac_ref"); - - if (!bsp_priv->clock_input) { - bsp_priv->clk_mac_refout = - devm_clk_get(dev, "clk_mac_refout"); - if (IS_ERR(bsp_priv->clk_mac_refout)) -- dev_err(dev, "%s: cannot get clock %s\n", -- __func__, "clk_mac_refout"); -+ dev_err(dev, "cannot get clock %s\n", -+ "clk_mac_refout"); - } - } - - if (bsp_priv->clock_input) { -- dev_info(dev, "%s: clock input from PHY\n", __func__); -+ dev_info(dev, "clock input from PHY\n"); - } else { - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) - clk_set_rate(bsp_priv->clk_mac, 50000000); -@@ -291,26 +430,25 @@ static int phy_power_on(struct rk_priv_d - struct device *dev = &bsp_priv->pdev->dev; - - if (!ldo) { -- dev_err(dev, "%s: no regulator found\n", __func__); -+ dev_err(dev, "no regulator found\n"); - return -1; - } - - if (enable) { - ret = regulator_enable(ldo); - if (ret) -- dev_err(dev, "%s: fail to enable phy-supply\n", -- __func__); -+ dev_err(dev, "fail to enable phy-supply\n"); - } else { - ret = regulator_disable(ldo); - if (ret) -- dev_err(dev, "%s: fail to disable phy-supply\n", -- __func__); -+ dev_err(dev, "fail to disable phy-supply\n"); - } - - return 0; - } - --static void *rk_gmac_setup(struct platform_device *pdev) -+static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, -+ const struct rk_gmac_ops *ops) - { - struct rk_priv_data *bsp_priv; - struct device *dev = &pdev->dev; -@@ -323,6 +461,7 @@ static void *rk_gmac_setup(struct platfo - return ERR_PTR(-ENOMEM); - - bsp_priv->phy_iface = of_get_phy_mode(dev->of_node); -+ bsp_priv->ops = ops; - - bsp_priv->regulator = devm_regulator_get_optional(dev, "phy"); - if (IS_ERR(bsp_priv->regulator)) { -@@ -336,12 +475,11 @@ static void *rk_gmac_setup(struct platfo - - ret = of_property_read_string(dev->of_node, "clock_in_out", &strings); - if (ret) { -- dev_err(dev, "%s: Can not read property: clock_in_out.\n", -- __func__); -+ dev_err(dev, "Can not read property: clock_in_out.\n"); - bsp_priv->clock_input = true; - } else { -- dev_info(dev, "%s: clock input or output? (%s).\n", -- __func__, strings); -+ dev_info(dev, "clock input or output? (%s).\n", -+ strings); - if (!strcmp(strings, "input")) - bsp_priv->clock_input = true; - else -@@ -351,22 +489,22 @@ static void *rk_gmac_setup(struct platfo - ret = of_property_read_u32(dev->of_node, "tx_delay", &value); - if (ret) { - bsp_priv->tx_delay = 0x30; -- dev_err(dev, "%s: Can not read property: tx_delay.", __func__); -- dev_err(dev, "%s: set tx_delay to 0x%x\n", -- __func__, bsp_priv->tx_delay); -+ dev_err(dev, "Can not read property: tx_delay."); -+ dev_err(dev, "set tx_delay to 0x%x\n", -+ bsp_priv->tx_delay); - } else { -- dev_info(dev, "%s: TX delay(0x%x).\n", __func__, value); -+ dev_info(dev, "TX delay(0x%x).\n", value); - bsp_priv->tx_delay = value; - } - - ret = of_property_read_u32(dev->of_node, "rx_delay", &value); - if (ret) { - bsp_priv->rx_delay = 0x10; -- dev_err(dev, "%s: Can not read property: rx_delay.", __func__); -- dev_err(dev, "%s: set rx_delay to 0x%x\n", -- __func__, bsp_priv->rx_delay); -+ dev_err(dev, "Can not read property: rx_delay."); -+ dev_err(dev, "set rx_delay to 0x%x\n", -+ bsp_priv->rx_delay); - } else { -- dev_info(dev, "%s: RX delay(0x%x).\n", __func__, value); -+ dev_info(dev, "RX delay(0x%x).\n", value); - bsp_priv->rx_delay = value; - } - -@@ -376,13 +514,14 @@ static void *rk_gmac_setup(struct platfo - - /*rmii or rgmii*/ - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) { -- dev_info(dev, "%s: init for RGMII\n", __func__); -- set_to_rgmii(bsp_priv, bsp_priv->tx_delay, bsp_priv->rx_delay); -+ dev_info(dev, "init for RGMII\n"); -+ bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay, -+ bsp_priv->rx_delay); - } else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) { -- dev_info(dev, "%s: init for RMII\n", __func__); -- set_to_rmii(bsp_priv); -+ dev_info(dev, "init for RMII\n"); -+ bsp_priv->ops->set_to_rmii(bsp_priv); - } else { -- dev_err(dev, "%s: NO interface defined!\n", __func__); -+ dev_err(dev, "NO interface defined!\n"); - } - - gmac_clk_init(bsp_priv); -@@ -420,17 +559,68 @@ static void rk_fix_speed(void *priv, uns - struct device *dev = &bsp_priv->pdev->dev; - - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) -- set_rgmii_speed(bsp_priv, speed); -+ bsp_priv->ops->set_rgmii_speed(bsp_priv, speed); - else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) -- set_rmii_speed(bsp_priv, speed); -+ bsp_priv->ops->set_rmii_speed(bsp_priv, speed); - else - dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface); - } - --const struct stmmac_of_data rk3288_gmac_data = { -- .has_gmac = 1, -- .fix_mac_speed = rk_fix_speed, -- .setup = rk_gmac_setup, -- .init = rk_gmac_init, -- .exit = rk_gmac_exit, -+static int rk_gmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ const struct rk_gmac_ops *data; -+ int ret; -+ -+ data = of_device_get_match_data(&pdev->dev); -+ if (!data) { -+ dev_err(&pdev->dev, "no of match data provided\n"); -+ return -EINVAL; -+ } -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ plat_dat->has_gmac = true; -+ plat_dat->init = rk_gmac_init; -+ plat_dat->exit = rk_gmac_exit; -+ plat_dat->fix_mac_speed = rk_fix_speed; -+ -+ plat_dat->bsp_priv = rk_gmac_setup(pdev, data); -+ if (IS_ERR(plat_dat->bsp_priv)) -+ return PTR_ERR(plat_dat->bsp_priv); -+ -+ ret = rk_gmac_init(pdev, plat_dat->bsp_priv); -+ if (ret) -+ return ret; -+ -+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+} -+ -+static const struct of_device_id rk_gmac_dwmac_match[] = { -+ { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, -+ { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops }, -+ { } - }; -+MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match); -+ -+static struct platform_driver rk_gmac_dwmac_driver = { -+ .probe = rk_gmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "rk_gmac-dwmac", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = rk_gmac_dwmac_match, -+ }, -+}; -+module_platform_driver(rk_gmac_dwmac_driver); -+ -+MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>"); -+MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer"); -+MODULE_LICENSE("GPL"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -@@ -175,31 +175,6 @@ static int socfpga_dwmac_setup(struct so - return 0; - } - --static void *socfpga_dwmac_probe(struct platform_device *pdev) --{ -- struct device *dev = &pdev->dev; -- int ret; -- struct socfpga_dwmac *dwmac; -- -- dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); -- if (!dwmac) -- return ERR_PTR(-ENOMEM); -- -- ret = socfpga_dwmac_parse_data(dwmac, dev); -- if (ret) { -- dev_err(dev, "Unable to parse OF data\n"); -- return ERR_PTR(ret); -- } -- -- ret = socfpga_dwmac_setup(dwmac); -- if (ret) { -- dev_err(dev, "couldn't setup SoC glue (%d)\n", ret); -- return ERR_PTR(ret); -- } -- -- return dwmac; --} -- - static void socfpga_dwmac_exit(struct platform_device *pdev, void *priv) - { - struct socfpga_dwmac *dwmac = priv; -@@ -257,9 +232,65 @@ static int socfpga_dwmac_init(struct pla - return ret; - } - --const struct stmmac_of_data socfpga_gmac_data = { -- .setup = socfpga_dwmac_probe, -- .init = socfpga_dwmac_init, -- .exit = socfpga_dwmac_exit, -- .fix_mac_speed = socfpga_dwmac_fix_mac_speed, -+static int socfpga_dwmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ struct device *dev = &pdev->dev; -+ int ret; -+ struct socfpga_dwmac *dwmac; -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); -+ if (!dwmac) -+ return -ENOMEM; -+ -+ ret = socfpga_dwmac_parse_data(dwmac, dev); -+ if (ret) { -+ dev_err(dev, "Unable to parse OF data\n"); -+ return ret; -+ } -+ -+ ret = socfpga_dwmac_setup(dwmac); -+ if (ret) { -+ dev_err(dev, "couldn't setup SoC glue (%d)\n", ret); -+ return ret; -+ } -+ -+ plat_dat->bsp_priv = dwmac; -+ plat_dat->init = socfpga_dwmac_init; -+ plat_dat->exit = socfpga_dwmac_exit; -+ plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; -+ -+ ret = socfpga_dwmac_init(pdev, plat_dat->bsp_priv); -+ if (ret) -+ return ret; -+ -+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+} -+ -+static const struct of_device_id socfpga_dwmac_match[] = { -+ { .compatible = "altr,socfpga-stmmac" }, -+ { } - }; -+MODULE_DEVICE_TABLE(of, socfpga_dwmac_match); -+ -+static struct platform_driver socfpga_dwmac_driver = { -+ .probe = socfpga_dwmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "socfpga-dwmac", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = socfpga_dwmac_match, -+ }, -+}; -+module_platform_driver(socfpga_dwmac_driver); -+ -+MODULE_LICENSE("GPL v2"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c -@@ -17,9 +17,11 @@ - #include <linux/stmmac.h> - #include <linux/phy.h> - #include <linux/mfd/syscon.h> -+#include <linux/module.h> - #include <linux/regmap.h> - #include <linux/clk.h> - #include <linux/of.h> -+#include <linux/of_device.h> - #include <linux/of_net.h> - - #include "stmmac_platform.h" -@@ -127,6 +129,11 @@ struct sti_dwmac { - struct device *dev; - struct regmap *regmap; - u32 speed; -+ void (*fix_retime_src)(void *priv, unsigned int speed); -+}; -+ -+struct sti_dwmac_of_data { -+ void (*fix_retime_src)(void *priv, unsigned int speed); - }; - - static u32 phy_intf_sels[] = { -@@ -221,8 +228,9 @@ static void stid127_fix_retime_src(void - regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val); - } - --static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac) -+static int sti_dwmac_init(struct platform_device *pdev, void *priv) - { -+ struct sti_dwmac *dwmac = priv; - struct regmap *regmap = dwmac->regmap; - int iface = dwmac->interface; - struct device *dev = dwmac->dev; -@@ -240,28 +248,8 @@ static void sti_dwmac_ctrl_init(struct s - - val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII; - regmap_update_bits(regmap, reg, ENMII_MASK, val); --} -- --static int stix4xx_init(struct platform_device *pdev, void *priv) --{ -- struct sti_dwmac *dwmac = priv; -- u32 spd = dwmac->speed; - -- sti_dwmac_ctrl_init(dwmac); -- -- stih4xx_fix_retime_src(priv, spd); -- -- return 0; --} -- --static int stid127_init(struct platform_device *pdev, void *priv) --{ -- struct sti_dwmac *dwmac = priv; -- u32 spd = dwmac->speed; -- -- sti_dwmac_ctrl_init(dwmac); -- -- stid127_fix_retime_src(priv, spd); -+ dwmac->fix_retime_src(priv, dwmac->speed); - - return 0; - } -@@ -333,34 +321,80 @@ static int sti_dwmac_parse_data(struct s - return 0; - } - --static void *sti_dwmac_setup(struct platform_device *pdev) -+static int sti_dwmac_probe(struct platform_device *pdev) - { -+ struct plat_stmmacenet_data *plat_dat; -+ const struct sti_dwmac_of_data *data; -+ struct stmmac_resources stmmac_res; - struct sti_dwmac *dwmac; - int ret; - -+ data = of_device_get_match_data(&pdev->dev); -+ if (!data) { -+ dev_err(&pdev->dev, "No OF match data provided\n"); -+ return -EINVAL; -+ } -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ - dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); - if (!dwmac) -- return ERR_PTR(-ENOMEM); -+ return -ENOMEM; - - ret = sti_dwmac_parse_data(dwmac, pdev); - if (ret) { - dev_err(&pdev->dev, "Unable to parse OF data\n"); -- return ERR_PTR(ret); -+ return ret; - } - -- return dwmac; -+ dwmac->fix_retime_src = data->fix_retime_src; -+ -+ plat_dat->bsp_priv = dwmac; -+ plat_dat->init = sti_dwmac_init; -+ plat_dat->exit = sti_dwmac_exit; -+ plat_dat->fix_mac_speed = data->fix_retime_src; -+ -+ ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); -+ if (ret) -+ return ret; -+ -+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); - } - --const struct stmmac_of_data stih4xx_dwmac_data = { -- .fix_mac_speed = stih4xx_fix_retime_src, -- .setup = sti_dwmac_setup, -- .init = stix4xx_init, -- .exit = sti_dwmac_exit, -+static const struct sti_dwmac_of_data stih4xx_dwmac_data = { -+ .fix_retime_src = stih4xx_fix_retime_src, -+}; -+ -+static const struct sti_dwmac_of_data stid127_dwmac_data = { -+ .fix_retime_src = stid127_fix_retime_src, - }; - --const struct stmmac_of_data stid127_dwmac_data = { -- .fix_mac_speed = stid127_fix_retime_src, -- .setup = sti_dwmac_setup, -- .init = stid127_init, -- .exit = sti_dwmac_exit, -+static const struct of_device_id sti_dwmac_match[] = { -+ { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data}, -+ { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data}, -+ { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data}, -+ { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data}, -+ { } - }; -+MODULE_DEVICE_TABLE(of, sti_dwmac_match); -+ -+static struct platform_driver sti_dwmac_driver = { -+ .probe = sti_dwmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "sti-dwmac", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = sti_dwmac_match, -+ }, -+}; -+module_platform_driver(sti_dwmac_driver); -+ -+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@st.com>"); -+MODULE_DESCRIPTION("STMicroelectronics DWMAC Specific Glue layer"); -+MODULE_LICENSE("GPL"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c -@@ -18,7 +18,9 @@ - - #include <linux/stmmac.h> - #include <linux/clk.h> -+#include <linux/module.h> - #include <linux/phy.h> -+#include <linux/platform_device.h> - #include <linux/of_net.h> - #include <linux/regulator/consumer.h> - -@@ -31,35 +33,6 @@ struct sunxi_priv_data { - struct regulator *regulator; - }; - --static void *sun7i_gmac_setup(struct platform_device *pdev) --{ -- struct sunxi_priv_data *gmac; -- struct device *dev = &pdev->dev; -- -- gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); -- if (!gmac) -- return ERR_PTR(-ENOMEM); -- -- gmac->interface = of_get_phy_mode(dev->of_node); -- -- gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx"); -- if (IS_ERR(gmac->tx_clk)) { -- dev_err(dev, "could not get tx clock\n"); -- return gmac->tx_clk; -- } -- -- /* Optional regulator for PHY */ -- gmac->regulator = devm_regulator_get_optional(dev, "phy"); -- if (IS_ERR(gmac->regulator)) { -- if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) -- return ERR_PTR(-EPROBE_DEFER); -- dev_info(dev, "no regulator found\n"); -- gmac->regulator = NULL; -- } -- -- return gmac; --} -- - #define SUN7I_GMAC_GMII_RGMII_RATE 125000000 - #define SUN7I_GMAC_MII_RATE 25000000 - -@@ -130,13 +103,76 @@ static void sun7i_fix_speed(void *priv, - } - } - --/* of_data specifying hardware features and callbacks. -- * hardware features were copied from Allwinner drivers. */ --const struct stmmac_of_data sun7i_gmac_data = { -- .has_gmac = 1, -- .tx_coe = 1, -- .fix_mac_speed = sun7i_fix_speed, -- .setup = sun7i_gmac_setup, -- .init = sun7i_gmac_init, -- .exit = sun7i_gmac_exit, -+static int sun7i_gmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ struct sunxi_priv_data *gmac; -+ struct device *dev = &pdev->dev; -+ int ret; -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); -+ if (!gmac) -+ return -ENOMEM; -+ -+ gmac->interface = of_get_phy_mode(dev->of_node); -+ -+ gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx"); -+ if (IS_ERR(gmac->tx_clk)) { -+ dev_err(dev, "could not get tx clock\n"); -+ return PTR_ERR(gmac->tx_clk); -+ } -+ -+ /* Optional regulator for PHY */ -+ gmac->regulator = devm_regulator_get_optional(dev, "phy"); -+ if (IS_ERR(gmac->regulator)) { -+ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ dev_info(dev, "no regulator found\n"); -+ gmac->regulator = NULL; -+ } -+ -+ /* platform data specifying hardware features and callbacks. -+ * hardware features were copied from Allwinner drivers. */ -+ plat_dat->tx_coe = 1; -+ plat_dat->has_gmac = true; -+ plat_dat->bsp_priv = gmac; -+ plat_dat->init = sun7i_gmac_init; -+ plat_dat->exit = sun7i_gmac_exit; -+ plat_dat->fix_mac_speed = sun7i_fix_speed; -+ -+ ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv); -+ if (ret) -+ return ret; -+ -+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+} -+ -+static const struct of_device_id sun7i_dwmac_match[] = { -+ { .compatible = "allwinner,sun7i-a20-gmac" }, -+ { } - }; -+MODULE_DEVICE_TABLE(of, sun7i_dwmac_match); -+ -+static struct platform_driver sun7i_dwmac_driver = { -+ .probe = sun7i_gmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "sun7i-dwmac", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = sun7i_dwmac_match, -+ }, -+}; -+module_platform_driver(sun7i_dwmac_driver); -+ -+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); -+MODULE_DESCRIPTION("Allwinner sunxi DWMAC specific glue layer"); -+MODULE_LICENSE("GPL"); ---- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c -@@ -73,7 +73,7 @@ - #define MMC_RX_OCTETCOUNT_G 0x00000188 - #define MMC_RX_BROADCASTFRAME_G 0x0000018c - #define MMC_RX_MULTICASTFRAME_G 0x00000190 --#define MMC_RX_CRC_ERRROR 0x00000194 -+#define MMC_RX_CRC_ERROR 0x00000194 - #define MMC_RX_ALIGN_ERROR 0x00000198 - #define MMC_RX_RUN_ERROR 0x0000019C - #define MMC_RX_JABBER_ERROR 0x000001A0 -@@ -196,7 +196,7 @@ void dwmac_mmc_read(void __iomem *ioaddr - mmc->mmc_rx_octetcount_g += readl(ioaddr + MMC_RX_OCTETCOUNT_G); - mmc->mmc_rx_broadcastframe_g += readl(ioaddr + MMC_RX_BROADCASTFRAME_G); - mmc->mmc_rx_multicastframe_g += readl(ioaddr + MMC_RX_MULTICASTFRAME_G); -- mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERRROR); -+ mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERROR); - mmc->mmc_rx_align_error += readl(ioaddr + MMC_RX_ALIGN_ERROR); - mmc->mmc_rx_run_error += readl(ioaddr + MMC_RX_RUN_ERROR); - mmc->mmc_rx_jabber_error += readl(ioaddr + MMC_RX_JABBER_ERROR); ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -34,6 +34,14 @@ - #include <linux/ptp_clock_kernel.h> - #include <linux/reset.h> - -+struct stmmac_resources { -+ void __iomem *addr; -+ const char *mac; -+ int wol_irq; -+ int lpi_irq; -+ int irq; -+}; -+ - struct stmmac_tx_info { - dma_addr_t buf; - bool map_as_page; -@@ -135,9 +143,9 @@ void stmmac_ptp_unregister(struct stmmac - int stmmac_resume(struct net_device *ndev); - int stmmac_suspend(struct net_device *ndev); - int stmmac_dvr_remove(struct net_device *ndev); --struct stmmac_priv *stmmac_dvr_probe(struct device *device, -- struct plat_stmmacenet_data *plat_dat, -- void __iomem *addr); -+int stmmac_dvr_probe(struct device *device, -+ struct plat_stmmacenet_data *plat_dat, -+ struct stmmac_resources *res); - void stmmac_disable_eee_mode(struct stmmac_priv *priv); - bool stmmac_eee_init(struct stmmac_priv *priv); - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -52,6 +52,7 @@ - #include "stmmac_ptp.h" - #include "stmmac.h" - #include <linux/reset.h> -+#include <linux/of_mdio.h> - - #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) - -@@ -816,18 +817,25 @@ static int stmmac_init_phy(struct net_de - priv->speed = 0; - priv->oldduplex = -1; - -- if (priv->plat->phy_bus_name) -- snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x", -- priv->plat->phy_bus_name, priv->plat->bus_id); -- else -- snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", -- priv->plat->bus_id); -+ if (priv->plat->phy_node) { -+ phydev = of_phy_connect(dev, priv->plat->phy_node, -+ &stmmac_adjust_link, 0, interface); -+ } else { -+ if (priv->plat->phy_bus_name) -+ snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x", -+ priv->plat->phy_bus_name, priv->plat->bus_id); -+ else -+ snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", -+ priv->plat->bus_id); - -- snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, -- priv->plat->phy_addr); -- pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id_fmt); -+ snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, -+ priv->plat->phy_addr); -+ pr_debug("stmmac_init_phy: trying to attach to %s\n", -+ phy_id_fmt); - -- phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface); -+ phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, -+ interface); -+ } - - if (IS_ERR_OR_NULL(phydev)) { - pr_err("%s: Could not attach to PHY\n", dev->name); -@@ -851,7 +859,7 @@ static int stmmac_init_phy(struct net_de - * device as well. - * Note: phydev->phy_id is the result of reading the UID PHY registers. - */ -- if (phydev->phy_id == 0) { -+ if (!priv->plat->phy_node && phydev->phy_id == 0) { - phy_disconnect(phydev); - return -ENODEV; - } -@@ -978,13 +986,11 @@ static int stmmac_init_rx_buffers(struct - { - struct sk_buff *skb; - -- skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN, -- flags); -+ skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); - if (!skb) { - pr_err("%s: Rx init fails; skb is NULL\n", __func__); - return -ENOMEM; - } -- skb_reserve(skb, NET_IP_ALIGN); - priv->rx_skbuff[i] = skb; - priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, - priv->dma_buf_sz, -@@ -2803,16 +2809,15 @@ static int stmmac_hw_init(struct stmmac_ - * stmmac_dvr_probe - * @device: device pointer - * @plat_dat: platform data pointer -- * @addr: iobase memory address -+ * @res: stmmac resource pointer - * Description: this is the main probe function used to - * call the alloc_etherdev, allocate the priv structure. - * Return: -- * on success the new private structure is returned, otherwise the error -- * pointer. -+ * returns 0 on success, otherwise errno. - */ --struct stmmac_priv *stmmac_dvr_probe(struct device *device, -- struct plat_stmmacenet_data *plat_dat, -- void __iomem *addr) -+int stmmac_dvr_probe(struct device *device, -+ struct plat_stmmacenet_data *plat_dat, -+ struct stmmac_resources *res) - { - int ret = 0; - struct net_device *ndev = NULL; -@@ -2820,7 +2825,7 @@ struct stmmac_priv *stmmac_dvr_probe(str - - ndev = alloc_etherdev(sizeof(struct stmmac_priv)); - if (!ndev) -- return ERR_PTR(-ENOMEM); -+ return -ENOMEM; - - SET_NETDEV_DEV(ndev, device); - -@@ -2831,8 +2836,17 @@ struct stmmac_priv *stmmac_dvr_probe(str - stmmac_set_ethtool_ops(ndev); - priv->pause = pause; - priv->plat = plat_dat; -- priv->ioaddr = addr; -- priv->dev->base_addr = (unsigned long)addr; -+ priv->ioaddr = res->addr; -+ priv->dev->base_addr = (unsigned long)res->addr; -+ -+ priv->dev->irq = res->irq; -+ priv->wol_irq = res->wol_irq; -+ priv->lpi_irq = res->lpi_irq; -+ -+ if (res->mac) -+ memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); -+ -+ dev_set_drvdata(device, priv->dev); - - /* Verify driver arguments */ - stmmac_verify_args(); -@@ -2947,7 +2961,7 @@ struct stmmac_priv *stmmac_dvr_probe(str - } - } - -- return priv; -+ return 0; - - error_mdio_register: - unregister_netdev(ndev); -@@ -2960,7 +2974,7 @@ error_pclk_get: - error_clk_get: - free_netdev(ndev); - -- return ERR_PTR(ret); -+ return ret; - } - EXPORT_SYMBOL_GPL(stmmac_dvr_probe); - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -@@ -161,11 +161,16 @@ int stmmac_mdio_reset(struct mii_bus *bu - - if (!gpio_request(reset_gpio, "mdio-reset")) { - gpio_direction_output(reset_gpio, active_low ? 1 : 0); -- udelay(data->delays[0]); -+ if (data->delays[0]) -+ msleep(DIV_ROUND_UP(data->delays[0], 1000)); -+ - gpio_set_value(reset_gpio, active_low ? 0 : 1); -- udelay(data->delays[1]); -+ if (data->delays[1]) -+ msleep(DIV_ROUND_UP(data->delays[1], 1000)); -+ - gpio_set_value(reset_gpio, active_low ? 1 : 0); -- udelay(data->delays[2]); -+ if (data->delays[2]) -+ msleep(DIV_ROUND_UP(data->delays[2], 1000)); - } - } - #endif ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -@@ -163,7 +163,7 @@ static int stmmac_pci_probe(struct pci_d - { - struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data; - struct plat_stmmacenet_data *plat; -- struct stmmac_priv *priv; -+ struct stmmac_resources res; - int i; - int ret; - -@@ -214,19 +214,12 @@ static int stmmac_pci_probe(struct pci_d - - pci_enable_msi(pdev); - -- priv = stmmac_dvr_probe(&pdev->dev, plat, pcim_iomap_table(pdev)[i]); -- if (IS_ERR(priv)) { -- dev_err(&pdev->dev, "%s: main driver probe failed\n", __func__); -- return PTR_ERR(priv); -- } -- priv->dev->irq = pdev->irq; -- priv->wol_irq = pdev->irq; -- -- pci_set_drvdata(pdev, priv->dev); -- -- dev_dbg(&pdev->dev, "STMMAC PCI driver registration completed\n"); -+ memset(&res, 0, sizeof(res)); -+ res.addr = pcim_iomap_table(pdev)[i]; -+ res.wol_irq = pdev->irq; -+ res.irq = pdev->irq; - -- return 0; -+ return stmmac_dvr_probe(&pdev->dev, plat, &res); - } - - /** ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -28,29 +28,11 @@ - #include <linux/of.h> - #include <linux/of_net.h> - #include <linux/of_device.h> -+#include <linux/of_mdio.h> - - #include "stmmac.h" - #include "stmmac_platform.h" - --static const struct of_device_id stmmac_dt_ids[] = { -- /* SoC specific glue layers should come before generic bindings */ -- { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_gmac_data}, -- { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data}, -- { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, -- { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data}, -- { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data}, -- { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data}, -- { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data}, -- { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data }, -- { .compatible = "st,spear600-gmac"}, -- { .compatible = "snps,dwmac-3.610"}, -- { .compatible = "snps,dwmac-3.70a"}, -- { .compatible = "snps,dwmac-3.710"}, -- { .compatible = "snps,dwmac"}, -- { /* sentinel */ } --}; --MODULE_DEVICE_TABLE(of, stmmac_dt_ids); -- - #ifdef CONFIG_OF - - /** -@@ -122,37 +104,16 @@ static int dwmac1000_validate_ucast_entr - * this function is to read the driver parameters from device-tree and - * set some private fields that will be used by the main at runtime. - */ --static int stmmac_probe_config_dt(struct platform_device *pdev, -- struct plat_stmmacenet_data *plat, -- const char **mac) -+struct plat_stmmacenet_data * -+stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) - { - struct device_node *np = pdev->dev.of_node; -+ struct plat_stmmacenet_data *plat; - struct stmmac_dma_cfg *dma_cfg; -- const struct of_device_id *device; -- -- if (!np) -- return -ENODEV; - -- device = of_match_device(stmmac_dt_ids, &pdev->dev); -- if (!device) -- return -ENODEV; -- -- if (device->data) { -- const struct stmmac_of_data *data = device->data; -- plat->has_gmac = data->has_gmac; -- plat->enh_desc = data->enh_desc; -- plat->tx_coe = data->tx_coe; -- plat->rx_coe = data->rx_coe; -- plat->bugged_jumbo = data->bugged_jumbo; -- plat->pmt = data->pmt; -- plat->riwt_off = data->riwt_off; -- plat->fix_mac_speed = data->fix_mac_speed; -- plat->bus_setup = data->bus_setup; -- plat->setup = data->setup; -- plat->free = data->free; -- plat->init = data->init; -- plat->exit = data->exit; -- } -+ plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); -+ if (!plat) -+ return ERR_PTR(-ENOMEM); - - *mac = of_get_mac_address(np); - plat->interface = of_get_phy_mode(np); -@@ -168,13 +129,24 @@ static int stmmac_probe_config_dt(struct - /* Default to phy auto-detection */ - plat->phy_addr = -1; - -+ /* If we find a phy-handle property, use it as the PHY */ -+ plat->phy_node = of_parse_phandle(np, "phy-handle", 0); -+ -+ /* If phy-handle is not specified, check if we have a fixed-phy */ -+ if (!plat->phy_node && of_phy_is_fixed_link(np)) { -+ if ((of_phy_register_fixed_link(np) < 0)) -+ return ERR_PTR(-ENODEV); -+ -+ plat->phy_node = of_node_get(np); -+ } -+ - /* "snps,phy-addr" is not a standard property. Mark it as deprecated - * and warn of its use. Remove this when phy node support is added. - */ - if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) - dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); - -- if (plat->phy_bus_name) -+ if (plat->phy_node || plat->phy_bus_name) - plat->mdio_bus_data = NULL; - else - plat->mdio_bus_data = -@@ -194,6 +166,12 @@ static int stmmac_probe_config_dt(struct - */ - plat->maxmtu = JUMBO_LEN; - -+ /* Set default value for multicast hash bins */ -+ plat->multicast_filter_bins = HASH_TABLE_SIZE; -+ -+ /* Set default value for unicast filter entries */ -+ plat->unicast_filter_entries = 1; -+ - /* - * Currently only the properties needed on SPEAr600 - * are provided. All other properties should be added -@@ -232,8 +210,10 @@ static int stmmac_probe_config_dt(struct - if (of_find_property(np, "snps,pbl", NULL)) { - dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), - GFP_KERNEL); -- if (!dma_cfg) -- return -ENOMEM; -+ if (!dma_cfg) { -+ of_node_put(np); -+ return ERR_PTR(-ENOMEM); -+ } - plat->dma_cfg = dma_cfg; - of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); - dma_cfg->fixed_burst = -@@ -250,45 +230,34 @@ static int stmmac_probe_config_dt(struct - pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set."); - } - -- return 0; -+ return plat; - } - #else --static int stmmac_probe_config_dt(struct platform_device *pdev, -- struct plat_stmmacenet_data *plat, -- const char **mac) -+struct plat_stmmacenet_data * -+stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) - { -- return -ENOSYS; -+ return ERR_PTR(-ENOSYS); - } - #endif /* CONFIG_OF */ -+EXPORT_SYMBOL_GPL(stmmac_probe_config_dt); - --/** -- * stmmac_pltfr_probe - platform driver probe. -- * @pdev: platform device pointer -- * Description: platform_device probe function. It is to allocate -- * the necessary platform resources, invoke custom helper (if required) and -- * invoke the main probe function. -- */ --static int stmmac_pltfr_probe(struct platform_device *pdev) -+int stmmac_get_platform_resources(struct platform_device *pdev, -+ struct stmmac_resources *stmmac_res) - { -- int ret = 0; - struct resource *res; -- struct device *dev = &pdev->dev; -- void __iomem *addr = NULL; -- struct stmmac_priv *priv = NULL; -- struct plat_stmmacenet_data *plat_dat = NULL; -- const char *mac = NULL; -- int irq, wol_irq, lpi_irq; -+ -+ memset(stmmac_res, 0, sizeof(*stmmac_res)); - - /* Get IRQ information early to have an ability to ask for deferred - * probe if needed before we went too far with resource allocation. - */ -- irq = platform_get_irq_byname(pdev, "macirq"); -- if (irq < 0) { -- if (irq != -EPROBE_DEFER) { -- dev_err(dev, -+ stmmac_res->irq = platform_get_irq_byname(pdev, "macirq"); -+ if (stmmac_res->irq < 0) { -+ if (stmmac_res->irq != -EPROBE_DEFER) { -+ dev_err(&pdev->dev, - "MAC IRQ configuration information not found\n"); - } -- return irq; -+ return stmmac_res->irq; - } - - /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq -@@ -298,82 +267,23 @@ static int stmmac_pltfr_probe(struct pla - * In case the wake up interrupt is not passed from the platform - * so the driver will continue to use the mac irq (ndev->irq) - */ -- wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); -- if (wol_irq < 0) { -- if (wol_irq == -EPROBE_DEFER) -+ stmmac_res->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); -+ if (stmmac_res->wol_irq < 0) { -+ if (stmmac_res->wol_irq == -EPROBE_DEFER) - return -EPROBE_DEFER; -- wol_irq = irq; -+ stmmac_res->wol_irq = stmmac_res->irq; - } - -- lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); -- if (lpi_irq == -EPROBE_DEFER) -+ stmmac_res->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); -+ if (stmmac_res->lpi_irq == -EPROBE_DEFER) - return -EPROBE_DEFER; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- addr = devm_ioremap_resource(dev, res); -- if (IS_ERR(addr)) -- return PTR_ERR(addr); -- -- plat_dat = dev_get_platdata(&pdev->dev); -- -- if (!plat_dat) -- plat_dat = devm_kzalloc(&pdev->dev, -- sizeof(struct plat_stmmacenet_data), -- GFP_KERNEL); -- if (!plat_dat) { -- pr_err("%s: ERROR: no memory", __func__); -- return -ENOMEM; -- } -- -- /* Set default value for multicast hash bins */ -- plat_dat->multicast_filter_bins = HASH_TABLE_SIZE; -+ stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res); - -- /* Set default value for unicast filter entries */ -- plat_dat->unicast_filter_entries = 1; -- -- if (pdev->dev.of_node) { -- ret = stmmac_probe_config_dt(pdev, plat_dat, &mac); -- if (ret) { -- pr_err("%s: main dt probe failed", __func__); -- return ret; -- } -- } -- -- /* Custom setup (if needed) */ -- if (plat_dat->setup) { -- plat_dat->bsp_priv = plat_dat->setup(pdev); -- if (IS_ERR(plat_dat->bsp_priv)) -- return PTR_ERR(plat_dat->bsp_priv); -- } -- -- /* Custom initialisation (if needed)*/ -- if (plat_dat->init) { -- ret = plat_dat->init(pdev, plat_dat->bsp_priv); -- if (unlikely(ret)) -- return ret; -- } -- -- priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr); -- if (IS_ERR(priv)) { -- pr_err("%s: main driver probe failed", __func__); -- return PTR_ERR(priv); -- } -- -- /* Copy IRQ values to priv structure which is now avaialble */ -- priv->dev->irq = irq; -- priv->wol_irq = wol_irq; -- priv->lpi_irq = lpi_irq; -- -- /* Get MAC address if available (DT) */ -- if (mac) -- memcpy(priv->dev->dev_addr, mac, ETH_ALEN); -- -- platform_set_drvdata(pdev, priv->dev); -- -- pr_debug("STMMAC platform driver registration completed"); -- -- return 0; -+ return PTR_ERR_OR_ZERO(stmmac_res->addr); - } -+EXPORT_SYMBOL_GPL(stmmac_get_platform_resources); - - /** - * stmmac_pltfr_remove -@@ -381,7 +291,7 @@ static int stmmac_pltfr_probe(struct pla - * Description: this function calls the main to free the net resources - * and calls the platforms hook and release the resources (e.g. mem). - */ --static int stmmac_pltfr_remove(struct platform_device *pdev) -+int stmmac_pltfr_remove(struct platform_device *pdev) - { - struct net_device *ndev = platform_get_drvdata(pdev); - struct stmmac_priv *priv = netdev_priv(ndev); -@@ -390,11 +300,9 @@ static int stmmac_pltfr_remove(struct pl - if (priv->plat->exit) - priv->plat->exit(pdev, priv->plat->bsp_priv); - -- if (priv->plat->free) -- priv->plat->free(pdev, priv->plat->bsp_priv); -- - return ret; - } -+EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); - - #ifdef CONFIG_PM_SLEEP - /** -@@ -438,21 +346,10 @@ static int stmmac_pltfr_resume(struct de - } - #endif /* CONFIG_PM_SLEEP */ - --static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, -- stmmac_pltfr_suspend, stmmac_pltfr_resume); -- --static struct platform_driver stmmac_pltfr_driver = { -- .probe = stmmac_pltfr_probe, -- .remove = stmmac_pltfr_remove, -- .driver = { -- .name = STMMAC_RESOURCE_NAME, -- .pm = &stmmac_pltfr_pm_ops, -- .of_match_table = of_match_ptr(stmmac_dt_ids), -- }, --}; -- --module_platform_driver(stmmac_pltfr_driver); -+SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend, -+ stmmac_pltfr_resume); -+EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops); - --MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); -+MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support"); - MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); - MODULE_LICENSE("GPL"); ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h -@@ -19,11 +19,15 @@ - #ifndef __STMMAC_PLATFORM_H__ - #define __STMMAC_PLATFORM_H__ - --extern const struct stmmac_of_data meson6_dwmac_data; --extern const struct stmmac_of_data sun7i_gmac_data; --extern const struct stmmac_of_data stih4xx_dwmac_data; --extern const struct stmmac_of_data stid127_dwmac_data; --extern const struct stmmac_of_data socfpga_gmac_data; --extern const struct stmmac_of_data rk3288_gmac_data; -+#include "stmmac.h" -+ -+struct plat_stmmacenet_data * -+stmmac_probe_config_dt(struct platform_device *pdev, const char **mac); -+ -+int stmmac_get_platform_resources(struct platform_device *pdev, -+ struct stmmac_resources *stmmac_res); -+ -+int stmmac_pltfr_remove(struct platform_device *pdev); -+extern const struct dev_pm_ops stmmac_pltfr_pm_ops; - - #endif /* __STMMAC_PLATFORM_H__ */ ---- a/include/linux/stmmac.h -+++ b/include/linux/stmmac.h -@@ -99,6 +99,7 @@ struct plat_stmmacenet_data { - int phy_addr; - int interface; - struct stmmac_mdio_bus_data *mdio_bus_data; -+ struct device_node *phy_node; - struct stmmac_dma_cfg *dma_cfg; - int clk_csr; - int has_gmac; -@@ -118,30 +119,8 @@ struct plat_stmmacenet_data { - int rx_fifo_size; - void (*fix_mac_speed)(void *priv, unsigned int speed); - void (*bus_setup)(void __iomem *ioaddr); -- void *(*setup)(struct platform_device *pdev); -- void (*free)(struct platform_device *pdev, void *priv); - int (*init)(struct platform_device *pdev, void *priv); - void (*exit)(struct platform_device *pdev, void *priv); -- void *custom_cfg; -- void *custom_data; - void *bsp_priv; - }; -- --/* of_data for SoC glue layer device tree bindings */ -- --struct stmmac_of_data { -- int has_gmac; -- int enh_desc; -- int tx_coe; -- int rx_coe; -- int bugged_jumbo; -- int pmt; -- int riwt_off; -- void (*fix_mac_speed)(void *priv, unsigned int speed); -- void (*bus_setup)(void __iomem *ioaddr); -- void *(*setup)(struct platform_device *pdev); -- void (*free)(struct platform_device *pdev, void *priv); -- int (*init)(struct platform_device *pdev, void *priv); -- void (*exit)(struct platform_device *pdev, void *priv); --}; - #endif diff --git a/target/linux/ipq806x/patches-4.1/709-stmac-platform-add-support-for-retreiving-mac-from-m.patch b/target/linux/ipq806x/patches-4.1/709-stmac-platform-add-support-for-retreiving-mac-from-m.patch deleted file mode 100644 index d385c9a36c..0000000000 --- a/target/linux/ipq806x/patches-4.1/709-stmac-platform-add-support-for-retreiving-mac-from-m.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 5bf2dabde1fa3af0c9082b42b6847ef3fd198b13 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski <jogo@openwrt.org> -Date: Sun, 9 Aug 2015 12:53:55 +0200 -Subject: [PATCH] stmac: platform: add support for retreiving mac from mtd - ---- - drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -116,6 +116,19 @@ stmmac_probe_config_dt(struct platform_d - return ERR_PTR(-ENOMEM); - - *mac = of_get_mac_address(np); -+ if (!*mac) { -+ u8 mtd_mac[ETH_ALEN]; -+ int ret; -+ -+ ret = of_get_mac_address_mtd(np, mtd_mac); -+ if (ret == -EPROBE_DEFER) -+ return ERR_PTR(ret); -+ -+ if (is_valid_ether_addr(mtd_mac)) -+ *mac = devm_kmemdup(&pdev->dev, mtd_mac, ETH_ALEN, -+ GFP_KERNEL); -+ } -+ - plat->interface = of_get_phy_mode(np); - - /* Get max speed of operation from device tree */ diff --git a/target/linux/ipq806x/patches-4.1/710-stmmac-fix-ipq806x-DMA-configuration.patch b/target/linux/ipq806x/patches-4.1/710-stmmac-fix-ipq806x-DMA-configuration.patch deleted file mode 100644 index c99f60768f..0000000000 --- a/target/linux/ipq806x/patches-4.1/710-stmmac-fix-ipq806x-DMA-configuration.patch +++ /dev/null @@ -1,117 +0,0 @@ ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c -@@ -259,6 +259,7 @@ static int ipq806x_gmac_probe(struct pla - { - struct plat_stmmacenet_data *plat_dat; - struct stmmac_resources stmmac_res; -+ struct stmmac_dma_cfg *dma_cfg; - struct device *dev = &pdev->dev; - struct ipq806x_gmac *gmac; - int val; -@@ -348,6 +349,17 @@ static int ipq806x_gmac_probe(struct pla - plat_dat->bsp_priv = gmac; - plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; - -+ dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), -+ GFP_KERNEL); -+ -+ dma_cfg->pbl = 32; -+ dma_cfg->aal = 1; -+ dma_cfg->burst_len = DMA_AXI_BLEN_16 | -+ (7 << DMA_AXI_RD_OSR_LMT_SHIFT) | -+ (7 << DMA_AXI_WR_OSR_LMT_SHIFT); -+ -+ plat_dat->dma_cfg = dma_cfg; -+ - return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); - } - ---- a/include/linux/stmmac.h -+++ b/include/linux/stmmac.h -@@ -73,6 +73,9 @@ - | DMA_AXI_BLEN_32 | DMA_AXI_BLEN_64 \ - | DMA_AXI_BLEN_128 | DMA_AXI_BLEN_256) - -+#define DMA_AXI_RD_OSR_LMT_SHIFT 16 -+#define DMA_AXI_WR_OSR_LMT_SHIFT 20 -+ - /* Platfrom data for platform device structure's platform_data field */ - - struct stmmac_mdio_bus_data { -@@ -88,6 +91,7 @@ struct stmmac_mdio_bus_data { - - struct stmmac_dma_cfg { - int pbl; -+ int aal; - int fixed_burst; - int mixed_burst; - int burst_len; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -@@ -31,7 +31,8 @@ - #include "dwmac_dma.h" - - static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, -- int burst_len, u32 dma_tx, u32 dma_rx, int atds) -+ int burst_len, u32 dma_tx, u32 dma_rx, int atds, -+ int aal) - { - u32 value = readl(ioaddr + DMA_BUS_MODE); - int limit; -@@ -62,6 +63,10 @@ static int dwmac1000_dma_init(void __iom - value = DMA_BUS_MODE_PBL | ((pbl << DMA_BUS_MODE_PBL_SHIFT) | - (pbl << DMA_BUS_MODE_RPBL_SHIFT)); - -+ /* Address Aligned Beats */ -+ if (aal) -+ value |= DMA_BUS_MODE_AAL; -+ - /* Set the Fixed burst mode */ - if (fb) - value |= DMA_BUS_MODE_FB; ---- a/drivers/net/ethernet/stmicro/stmmac/common.h -+++ b/drivers/net/ethernet/stmicro/stmmac/common.h -@@ -352,7 +352,7 @@ extern const struct stmmac_desc_ops ndes - struct stmmac_dma_ops { - /* DMA core initialization */ - int (*init) (void __iomem *ioaddr, int pbl, int fb, int mb, -- int burst_len, u32 dma_tx, u32 dma_rx, int atds); -+ int burst_len, u32 dma_tx, u32 dma_rx, int atds, int aal); - /* Dump DMA registers */ - void (*dump_regs) (void __iomem *ioaddr); - /* Set tx/rx threshold in the csr6 register ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -@@ -33,7 +33,8 @@ - #include "dwmac_dma.h" - - static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, -- int burst_len, u32 dma_tx, u32 dma_rx, int atds) -+ int burst_len, u32 dma_tx, u32 dma_rx, int atds, -+ int aal) - { - u32 value = readl(ioaddr + DMA_BUS_MODE); - int limit; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -1639,9 +1639,11 @@ static int stmmac_init_dma_engine(struct - int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0; - int mixed_burst = 0; - int atds = 0; -+ int aal = 0; - - if (priv->plat->dma_cfg) { - pbl = priv->plat->dma_cfg->pbl; -+ aal = priv->plat->dma_cfg->aal; - fixed_burst = priv->plat->dma_cfg->fixed_burst; - mixed_burst = priv->plat->dma_cfg->mixed_burst; - burst_len = priv->plat->dma_cfg->burst_len; -@@ -1652,7 +1654,7 @@ static int stmmac_init_dma_engine(struct - - return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst, - burst_len, priv->dma_tx_phy, -- priv->dma_rx_phy, atds); -+ priv->dma_rx_phy, atds, aal); - } - - /** diff --git a/target/linux/ipq806x/patches-4.1/020-add-ap148-bootargs.patch b/target/linux/ipq806x/patches-4.4/020-add-ap148-bootargs.patch index c0ad74c492..9c33bad5c1 100644 --- a/target/linux/ipq806x/patches-4.1/020-add-ap148-bootargs.patch +++ b/target/linux/ipq806x/patches-4.4/020-add-ap148-bootargs.patch @@ -1,6 +1,21 @@ --- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts +++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -14,6 +14,14 @@ +@@ -4,14 +4,6 @@ + model = "Qualcomm IPQ8064/AP148"; + compatible = "qcom,ipq8064-ap148", "qcom,ipq8064"; + +- aliases { +- serial0 = &gsbi4_serial; +- }; +- +- chosen { +- stdout-path = "serial0:115200n8"; +- }; +- + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; +@@ -22,6 +14,14 @@ }; }; @@ -30,7 +45,7 @@ syscon-tcsr = <&tcsr>; -- serial@16340000 { +- gsbi4_serial: serial@16340000 { + uart4: serial@16340000 { compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; reg = <0x16340000 0x1000>, diff --git a/target/linux/ipq806x/patches-4.1/021-add-ap148-partitions.patch b/target/linux/ipq806x/patches-4.4/021-add-ap148-partitions.patch index bfdb30fe14..bfdb30fe14 100644 --- a/target/linux/ipq806x/patches-4.1/021-add-ap148-partitions.patch +++ b/target/linux/ipq806x/patches-4.4/021-add-ap148-partitions.patch diff --git a/target/linux/ipq806x/patches-4.1/022-add-db149-dts.patch b/target/linux/ipq806x/patches-4.4/022-add-db149-dts.patch index 7d8c8e8a81..4d3e827b51 100644 --- a/target/linux/ipq806x/patches-4.1/022-add-db149-dts.patch +++ b/target/linux/ipq806x/patches-4.4/022-add-db149-dts.patch @@ -15,7 +15,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -451,6 +451,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \ +@@ -506,6 +506,7 @@ qcom-apq8084-ifc6540.dtb \ qcom-apq8084-mtp.dtb \ qcom-ipq8064-ap148.dtb \ diff --git a/target/linux/ipq806x/patches-4.1/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch b/target/linux/ipq806x/patches-4.4/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch index 6b296377b6..b8c527b6ae 100644 --- a/target/linux/ipq806x/patches-4.1/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch +++ b/target/linux/ipq806x/patches-4.4/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch @@ -1,10 +1,9 @@ --- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts +++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -46,15 +46,12 @@ - serial@16340000 { +@@ -47,14 +47,12 @@ status = "ok"; }; -- + - i2c4: i2c@16380000 { - status = "ok"; - @@ -14,17 +13,17 @@ - pinctrl-names = "default"; - }; + /* -+ * The i2c device on gsbi4 should not be enabled. -+ * On ipq806x designs gsbi4 i2c is meant for exclusive -+ * RPM usage. Turning this on in kernel manifests as -+ * i2c failure for the RPM. -+ */ ++ * The i2c device on gsbi4 should not be enabled. ++ * On ipq806x designs gsbi4 i2c is meant for exclusive ++ * RPM usage. Turning this on in kernel manifests as ++ * i2c failure for the RPM. ++ */ }; gsbi5: gsbi@1a200000 { --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c -@@ -807,7 +807,7 @@ static struct clk_rcg gsbi7_qup_src = { +@@ -294,7 +294,7 @@ .parent_names = gcc_pxo_pll8, .num_parents = 2, .ops = &clk_rcg_ops, @@ -33,8 +32,8 @@ }, }, }; -@@ -823,7 +823,7 @@ static struct clk_branch gsbi7_qup_clk = - .parent_names = (const char *[]){ "gsbi7_qup_src" }, +@@ -312,7 +312,7 @@ + }, .num_parents = 1, .ops = &clk_branch_ops, - .flags = CLK_SET_RATE_PARENT, @@ -42,9 +41,9 @@ }, }, }; -@@ -871,7 +871,7 @@ static struct clk_branch gsbi4_h_clk = { +@@ -890,7 +890,7 @@ .hw.init = &(struct clk_init_data){ - .name = "gsbi4_h_clk", + .name = "gsbi1_h_clk", .ops = &clk_branch_ops, - .flags = CLK_IS_ROOT, + .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED, diff --git a/target/linux/ipq806x/patches-4.1/024-ap148-add-memory-node.patch b/target/linux/ipq806x/patches-4.4/024-ap148-add-memory-node.patch index f026ed9394..f026ed9394 100644 --- a/target/linux/ipq806x/patches-4.1/024-ap148-add-memory-node.patch +++ b/target/linux/ipq806x/patches-4.4/024-ap148-add-memory-node.patch diff --git a/target/linux/ipq806x/patches-4.1/033-ARM-qcom-add-SFPB-nodes-to-IPQ806x-dts.patch b/target/linux/ipq806x/patches-4.4/033-ARM-qcom-add-SFPB-nodes-to-IPQ806x-dts.patch index a126d69441..e1d317de47 100644 --- a/target/linux/ipq806x/patches-4.1/033-ARM-qcom-add-SFPB-nodes-to-IPQ806x-dts.patch +++ b/target/linux/ipq806x/patches-4.4/033-ARM-qcom-add-SFPB-nodes-to-IPQ806x-dts.patch @@ -22,12 +22,12 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> + compatible = "syscon"; + reg = <0x01200600 0x100>; + }; - }; ++ }; + + sfpb_mutex: sfpb-mutex { + compatible = "qcom,sfpb-mutex"; + syscon = <&sfpb_mutex_block 4 4>; + + #hwlock-cells = <1>; -+ }; + }; }; diff --git a/target/linux/ipq806x/patches-4.1/036-ARM-qcom-add-SMEM-device-node-to-IPQ806x-dts.patch b/target/linux/ipq806x/patches-4.4/036-ARM-qcom-add-SMEM-device-node-to-IPQ806x-dts.patch index b55f17475e..06b14052ef 100644 --- a/target/linux/ipq806x/patches-4.1/036-ARM-qcom-add-SMEM-device-node-to-IPQ806x-dts.patch +++ b/target/linux/ipq806x/patches-4.4/036-ARM-qcom-add-SMEM-device-node-to-IPQ806x-dts.patch @@ -26,7 +26,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> @@ -341,4 +341,10 @@ #hwlock-cells = <1>; - }; + }; + + smem { + compatible = "qcom,smem"; diff --git a/target/linux/ipq806x/patches-4.1/037-mtd-add-SMEM-parser-for-QCOM-platforms.patch b/target/linux/ipq806x/patches-4.4/037-mtd-add-SMEM-parser-for-QCOM-platforms.patch index 5fc54134de..d80eb86056 100644 --- a/target/linux/ipq806x/patches-4.1/037-mtd-add-SMEM-parser-for-QCOM-platforms.patch +++ b/target/linux/ipq806x/patches-4.4/037-mtd-add-SMEM-parser-for-QCOM-platforms.patch @@ -1,23 +1,26 @@ -From 0501f76b138cf1dc11a313bb7a094da524b79337 Mon Sep 17 00:00:00 2001 +From 61e8e1b1af77f24339da3f0822a76fa65ed635c6 Mon Sep 17 00:00:00 2001 From: Mathieu Olivari <mathieu@codeaurora.org> Date: Thu, 13 Aug 2015 09:53:14 -0700 -Subject: [PATCH 3/3] mtd: add SMEM parser for QCOM platforms +Subject: [PATCH] mtd: add SMEM parser for QCOM platforms On QCOM platforms using MTD devices storage (such as IPQ806x), SMEM is used to store partition layout. This new parser can now be used to read SMEM and use it to register an MTD layout according to its content. Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org> --- drivers/mtd/Kconfig | 7 ++ drivers/mtd/Makefile | 1 + - drivers/mtd/qcom_smem_part.c | 231 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 239 insertions(+) + drivers/mtd/qcom_smem_part.c | 228 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 236 insertions(+) create mode 100644 drivers/mtd/qcom_smem_part.c +diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig +index a03ad29..debc887 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig -@@ -195,6 +195,13 @@ config MTD_MYLOADER_PARTS +@@ -190,6 +190,13 @@ You will still need the parsing functions to be called by the driver for your particular device. It won't happen automatically. @@ -31,9 +34,24 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> comment "User Modules And Translation Layers" # +diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile +index 99bb9a1..2a44a64 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -16,6 +16,7 @@ + obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o + obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o + obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o ++obj-$(CONFIG_MTD_QCOM_SMEM_PARTS) += qcom_smem_part.o + + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o +diff --git a/drivers/mtd/qcom_smem_part.c b/drivers/mtd/qcom_smem_part.c +new file mode 100644 +index 0000000..f9c1bca --- /dev/null +++ b/drivers/mtd/qcom_smem_part.c -@@ -0,0 +1,231 @@ +@@ -0,0 +1,228 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * @@ -95,13 +113,12 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> + +static int qcom_smem_get_flash_blksz(u64 **smem_blksz) +{ -+ int ret; + size_t size; + -+ ret = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_BLOCK_SIZE, -+ (void **) smem_blksz, &size); ++ *smem_blksz = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_BLOCK_SIZE, ++ &size); + -+ if (ret < 0) { ++ if (IS_ERR(*smem_blksz)) { + pr_err("Unable to read flash blksz from SMEM\n"); + return -ENOENT; + } @@ -116,13 +133,12 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> + +static int qcom_smem_get_flash_type(u64 **smem_flash_type) +{ -+ int ret; + size_t size; + -+ ret = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_TYPE, -+ (void **) smem_flash_type, &size); ++ *smem_flash_type = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_TYPE, ++ &size); + -+ if (ret < 0) { ++ if (IS_ERR(*smem_flash_type)) { + pr_err("Unable to read flash type from SMEM\n"); + return -ENOENT; + } @@ -137,13 +153,12 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> + +static int qcom_smem_get_flash_partitions(struct smem_partition_table **pparts) +{ -+ int ret; + size_t size; + -+ ret = qcom_smem_get(SMEM_HOST_APPS, SMEM_AARM_PARTITION_TABLE, -+ (void **) pparts, &size); ++ *pparts = qcom_smem_get(SMEM_HOST_APPS, SMEM_AARM_PARTITION_TABLE, ++ &size); + -+ if (ret < 0) { ++ if (IS_ERR(*pparts)) { + pr_err("Unable to read partition table from SMEM\n"); + return -ENOENT; + } @@ -265,13 +280,3 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Olivari <mathieu@codeaurora.org>"); +MODULE_DESCRIPTION("Parsing code for SMEM based partition tables"); ---- a/drivers/mtd/Makefile -+++ b/drivers/mtd/Makefile -@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o - obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o - obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o - obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o -+obj-$(CONFIG_MTD_QCOM_SMEM_PARTS) += qcom_smem_part.o - - # 'Users' - code which presents functionality to userspace. - obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o diff --git a/target/linux/ipq806x/patches-4.4/100-usb-phy-Add-Qualcomm-DWC3-HS-SS-PHY-drivers.patch b/target/linux/ipq806x/patches-4.4/100-usb-phy-Add-Qualcomm-DWC3-HS-SS-PHY-drivers.patch new file mode 100644 index 0000000000..68f2b39813 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/100-usb-phy-Add-Qualcomm-DWC3-HS-SS-PHY-drivers.patch @@ -0,0 +1,510 @@ +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -390,4 +390,15 @@ + Enable this to support the Broadcom Cygnus PCIe PHY. + If unsure, say N. + ++config PHY_QCOM_DWC3 ++ tristate "QCOM DWC3 USB PHY support" ++ depends on ARCH_QCOM ++ depends on HAS_IOMEM ++ depends on OF ++ select GENERIC_PHY ++ help ++ This option enables support for the Synopsis PHYs present inside the ++ Qualcomm USB3.0 DWC3 controller. This driver supports both HS and SS ++ PHY controllers. ++ + endmenu +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -48,3 +48,4 @@ obj-$(CONFIG_PHY_TUSB1210) += + obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o + obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o + obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o ++obj-$(CONFIG_PHY_QCOM_DWC3) += phy-qcom-dwc3.o +--- /dev/null ++++ b/drivers/phy/phy-qcom-dwc3.c +@@ -0,0 +1,482 @@ ++/* Copyright (c) 2013-2014, Code Aurora Forum. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/phy/phy.h> ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++ ++/** ++ * USB QSCRATCH Hardware registers ++ */ ++#define QSCRATCH_GENERAL_CFG (0x08) ++#define HSUSB_PHY_CTRL_REG (0x10) ++ ++/* PHY_CTRL_REG */ ++#define HSUSB_CTRL_DMSEHV_CLAMP BIT(24) ++#define HSUSB_CTRL_USB2_SUSPEND BIT(23) ++#define HSUSB_CTRL_UTMI_CLK_EN BIT(21) ++#define HSUSB_CTRL_UTMI_OTG_VBUS_VALID BIT(20) ++#define HSUSB_CTRL_USE_CLKCORE BIT(18) ++#define HSUSB_CTRL_DPSEHV_CLAMP BIT(17) ++#define HSUSB_CTRL_COMMONONN BIT(11) ++#define HSUSB_CTRL_ID_HV_CLAMP BIT(9) ++#define HSUSB_CTRL_OTGSESSVLD_CLAMP BIT(8) ++#define HSUSB_CTRL_CLAMP_EN BIT(7) ++#define HSUSB_CTRL_RETENABLEN BIT(1) ++#define HSUSB_CTRL_POR BIT(0) ++ ++/* QSCRATCH_GENERAL_CFG */ ++#define HSUSB_GCFG_XHCI_REV BIT(2) ++ ++/** ++ * USB QSCRATCH Hardware registers ++ */ ++#define SSUSB_PHY_CTRL_REG (0x00) ++#define SSUSB_PHY_PARAM_CTRL_1 (0x04) ++#define SSUSB_PHY_PARAM_CTRL_2 (0x08) ++#define CR_PROTOCOL_DATA_IN_REG (0x0c) ++#define CR_PROTOCOL_DATA_OUT_REG (0x10) ++#define CR_PROTOCOL_CAP_ADDR_REG (0x14) ++#define CR_PROTOCOL_CAP_DATA_REG (0x18) ++#define CR_PROTOCOL_READ_REG (0x1c) ++#define CR_PROTOCOL_WRITE_REG (0x20) ++ ++/* PHY_CTRL_REG */ ++#define SSUSB_CTRL_REF_USE_PAD BIT(28) ++#define SSUSB_CTRL_TEST_POWERDOWN BIT(27) ++#define SSUSB_CTRL_LANE0_PWR_PRESENT BIT(24) ++#define SSUSB_CTRL_SS_PHY_EN BIT(8) ++#define SSUSB_CTRL_SS_PHY_RESET BIT(7) ++ ++/* SSPHY control registers */ ++#define SSPHY_CTRL_RX_OVRD_IN_HI(lane) (0x1006 + 0x100 * lane) ++#define SSPHY_CTRL_TX_OVRD_DRV_LO(lane) (0x1002 + 0x100 * lane) ++ ++/* RX OVRD IN HI bits */ ++#define RX_OVRD_IN_HI_RX_RESET_OVRD BIT(13) ++#define RX_OVRD_IN_HI_RX_RX_RESET BIT(12) ++#define RX_OVRD_IN_HI_RX_EQ_OVRD BIT(11) ++#define RX_OVRD_IN_HI_RX_EQ_MASK 0x0700 ++#define RX_OVRD_IN_HI_RX_EQ_SHIFT 8 ++#define RX_OVRD_IN_HI_RX_EQ_EN_OVRD BIT(7) ++#define RX_OVRD_IN_HI_RX_EQ_EN BIT(6) ++#define RX_OVRD_IN_HI_RX_LOS_FILTER_OVRD BIT(5) ++#define RX_OVRD_IN_HI_RX_LOS_FILTER_MASK 0x0018 ++#define RX_OVRD_IN_HI_RX_RATE_OVRD BIT(2) ++#define RX_OVRD_IN_HI_RX_RATE_MASK 0x0003 ++ ++/* TX OVRD DRV LO register bits */ ++#define TX_OVRD_DRV_LO_AMPLITUDE_MASK 0x007F ++#define TX_OVRD_DRV_LO_PREEMPH_MASK 0x3F80 ++#define TX_OVRD_DRV_LO_PREEMPH_SHIFT 7 ++#define TX_OVRD_DRV_LO_EN BIT(14) ++ ++struct qcom_dwc3_usb_phy { ++ void __iomem *base; ++ struct device *dev; ++ struct phy *phy; ++ ++ int (*phy_init)(struct qcom_dwc3_usb_phy *phy_dwc3); ++ int (*phy_exit)(struct qcom_dwc3_usb_phy *phy_dwc3); ++ ++ struct clk *xo_clk; ++ struct clk *ref_clk; ++}; ++ ++/** ++ * Write register and read back masked value to confirm it is written ++ * ++ * @base - QCOM DWC3 PHY base virtual address. ++ * @offset - register offset. ++ * @mask - register bitmask specifying what should be updated ++ * @val - value to write. ++ */ ++static inline void qcom_dwc3_phy_write_readback( ++ struct qcom_dwc3_usb_phy *phy_dwc3, u32 offset, ++ const u32 mask, u32 val) ++{ ++ u32 write_val, tmp = readl(phy_dwc3->base + offset); ++ ++ tmp &= ~mask; /* retain other bits */ ++ write_val = tmp | val; ++ ++ writel(write_val, phy_dwc3->base + offset); ++ ++ /* Read back to see if val was written */ ++ tmp = readl(phy_dwc3->base + offset); ++ tmp &= mask; /* clear other bits */ ++ ++ if (tmp != val) ++ dev_err(phy_dwc3->dev, "write: %x to QSCRATCH: %x FAILED\n", ++ val, offset); ++} ++ ++static int wait_for_latch(void __iomem *addr) ++{ ++ u32 retry = 10; ++ ++ while (true) { ++ if (!readl(addr)) ++ break; ++ ++ if (--retry == 0) ++ return -ETIMEDOUT; ++ ++ usleep_range(10, 20); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Write SSPHY register ++ * ++ * @base - QCOM DWC3 PHY base virtual address. ++ * @addr - SSPHY address to write. ++ * @val - value to write. ++ */ ++static int qcom_dwc3_ss_write_phycreg(void __iomem *base, u32 addr, u32 val) ++{ ++ int ret; ++ ++ writel(addr, base + CR_PROTOCOL_DATA_IN_REG); ++ writel(0x1, base + CR_PROTOCOL_CAP_ADDR_REG); ++ ++ ret = wait_for_latch(base + CR_PROTOCOL_CAP_ADDR_REG); ++ if (ret) ++ goto err_wait; ++ ++ writel(val, base + CR_PROTOCOL_DATA_IN_REG); ++ writel(0x1, base + CR_PROTOCOL_CAP_DATA_REG); ++ ++ ret = wait_for_latch(base + CR_PROTOCOL_CAP_DATA_REG); ++ if (ret) ++ goto err_wait; ++ ++ writel(0x1, base + CR_PROTOCOL_WRITE_REG); ++ ++ ret = wait_for_latch(base + CR_PROTOCOL_WRITE_REG); ++ ++err_wait: ++ return ret; ++} ++ ++/** ++ * Read SSPHY register. ++ * ++ * @base - QCOM DWC3 PHY base virtual address. ++ * @addr - SSPHY address to read. ++ */ ++static int qcom_dwc3_ss_read_phycreg(void __iomem *base, u32 addr, u32 *val) ++{ ++ int ret; ++ bool first_read = true; ++ ++ writel(addr, base + CR_PROTOCOL_DATA_IN_REG); ++ writel(0x1, base + CR_PROTOCOL_CAP_ADDR_REG); ++ ++ ret = wait_for_latch(base + CR_PROTOCOL_CAP_ADDR_REG); ++ if (ret) ++ goto err_wait; ++ ++ /* ++ * Due to hardware bug, first read of SSPHY register might be ++ * incorrect. Hence as workaround, SW should perform SSPHY register ++ * read twice, but use only second read and ignore first read. ++ */ ++retry: ++ writel(0x1, base + CR_PROTOCOL_READ_REG); ++ ++ ret = wait_for_latch(base + CR_PROTOCOL_READ_REG); ++ if (ret) ++ goto err_wait; ++ ++ if (first_read) { ++ readl(base + CR_PROTOCOL_DATA_OUT_REG); ++ first_read = false; ++ goto retry; ++ } ++ ++ *val = readl(base + CR_PROTOCOL_DATA_OUT_REG); ++ ++err_wait: ++ return ret; ++} ++ ++static int qcom_dwc3_phy_power_on(struct phy *phy) ++{ ++ int ret; ++ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); ++ ++ ret = clk_prepare_enable(phy_dwc3->xo_clk); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(phy_dwc3->ref_clk); ++ if (ret) ++ clk_disable_unprepare(phy_dwc3->xo_clk); ++ ++ return ret; ++} ++ ++static int qcom_dwc3_phy_power_off(struct phy *phy) ++{ ++ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); ++ ++ clk_disable_unprepare(phy_dwc3->ref_clk); ++ clk_disable_unprepare(phy_dwc3->xo_clk); ++ ++ return 0; ++} ++ ++static int qcom_dwc3_hs_phy_init(struct qcom_dwc3_usb_phy *phy_dwc3) ++{ ++ u32 val; ++ ++ /* ++ * HSPHY Initialization: Enable UTMI clock, select 19.2MHz fsel ++ * enable clamping, and disable RETENTION (power-on default is ENABLED) ++ */ ++ val = HSUSB_CTRL_DPSEHV_CLAMP | HSUSB_CTRL_DMSEHV_CLAMP | ++ HSUSB_CTRL_RETENABLEN | HSUSB_CTRL_COMMONONN | ++ HSUSB_CTRL_OTGSESSVLD_CLAMP | HSUSB_CTRL_ID_HV_CLAMP | ++ HSUSB_CTRL_DPSEHV_CLAMP | HSUSB_CTRL_UTMI_OTG_VBUS_VALID | ++ HSUSB_CTRL_UTMI_CLK_EN | HSUSB_CTRL_CLAMP_EN | 0x70; ++ ++ /* use core clock if external reference is not present */ ++ if (!phy_dwc3->xo_clk) ++ val |= HSUSB_CTRL_USE_CLKCORE; ++ ++ writel(val, phy_dwc3->base + HSUSB_PHY_CTRL_REG); ++ usleep_range(2000, 2200); ++ ++ /* Disable (bypass) VBUS and ID filters */ ++ writel(HSUSB_GCFG_XHCI_REV, phy_dwc3->base + QSCRATCH_GENERAL_CFG); ++ ++ return 0; ++} ++ ++static int qcom_dwc3_ss_phy_init(struct qcom_dwc3_usb_phy *phy_dwc3) ++{ ++ int ret; ++ u32 data = 0; ++ ++ /* reset phy */ ++ data = readl_relaxed(phy_dwc3->base + SSUSB_PHY_CTRL_REG); ++ writel_relaxed(data | SSUSB_CTRL_SS_PHY_RESET, ++ phy_dwc3->base + SSUSB_PHY_CTRL_REG); ++ usleep_range(2000, 2200); ++ writel_relaxed(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); ++ ++ /* clear REF_PAD if we don't have XO clk */ ++ if (!phy_dwc3->xo_clk) ++ data &= ~SSUSB_CTRL_REF_USE_PAD; ++ else ++ data |= SSUSB_CTRL_REF_USE_PAD; ++ ++ writel_relaxed(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); ++ msleep(30); ++ ++ data |= SSUSB_CTRL_SS_PHY_EN | SSUSB_CTRL_LANE0_PWR_PRESENT; ++ writel_relaxed(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); ++ ++ /* ++ * Fix RX Equalization setting as follows ++ * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 ++ * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 ++ * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 ++ * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 ++ */ ++ ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, ++ SSPHY_CTRL_RX_OVRD_IN_HI(0), &data); ++ if (ret) ++ goto err_phy_trans; ++ ++ data &= ~RX_OVRD_IN_HI_RX_EQ_EN; ++ data |= RX_OVRD_IN_HI_RX_EQ_EN_OVRD; ++ data &= ~RX_OVRD_IN_HI_RX_EQ_MASK; ++ data |= 0x3 << RX_OVRD_IN_HI_RX_EQ_SHIFT; ++ data |= RX_OVRD_IN_HI_RX_EQ_OVRD; ++ ret = qcom_dwc3_ss_write_phycreg(phy_dwc3->base, ++ SSPHY_CTRL_RX_OVRD_IN_HI(0), data); ++ if (ret) ++ goto err_phy_trans; ++ ++ /* ++ * Set EQ and TX launch amplitudes as follows ++ * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 ++ * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 ++ * LANE0.TX_OVRD_DRV_LO.EN set to 1. ++ */ ++ ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, ++ SSPHY_CTRL_TX_OVRD_DRV_LO(0), &data); ++ if (ret) ++ goto err_phy_trans; ++ ++ data &= ~TX_OVRD_DRV_LO_PREEMPH_MASK; ++ data |= 0x16 << TX_OVRD_DRV_LO_PREEMPH_SHIFT; ++ data &= ~TX_OVRD_DRV_LO_AMPLITUDE_MASK; ++ data |= 0x7f; ++ data |= TX_OVRD_DRV_LO_EN; ++ ret = qcom_dwc3_ss_write_phycreg(phy_dwc3->base, ++ SSPHY_CTRL_TX_OVRD_DRV_LO(0), data); ++ if (ret) ++ goto err_phy_trans; ++ ++ /* ++ * Set the QSCRATCH PHY_PARAM_CTRL1 parameters as follows ++ * TX_FULL_SWING [26:20] amplitude to 127 ++ * TX_DEEMPH_3_5DB [13:8] to 22 ++ * LOS_BIAS [2:0] to 0x5 ++ */ ++ qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_PARAM_CTRL_1, ++ 0x07f03f07, 0x07f01605); ++ ++err_phy_trans: ++ return ret; ++} ++ ++static int qcom_dwc3_ss_phy_exit(struct qcom_dwc3_usb_phy *phy_dwc3) ++{ ++ /* Sequence to put SSPHY in low power state: ++ * 1. Clear REF_PHY_EN in PHY_CTRL_REG ++ * 2. Clear REF_USE_PAD in PHY_CTRL_REG ++ * 3. Set TEST_POWERED_DOWN in PHY_CTRL_REG to enable PHY retention ++ * 4. Disable SSPHY ref clk ++ */ ++ qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, ++ SSUSB_CTRL_SS_PHY_EN, 0x0); ++ qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, ++ SSUSB_CTRL_REF_USE_PAD, 0x0); ++ qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, ++ 0x0, SSUSB_CTRL_TEST_POWERDOWN); ++ ++ return 0; ++} ++ ++static int qcom_dwc3_phy_init(struct phy *phy) ++{ ++ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); ++ ++ if (phy_dwc3->phy_init) ++ return phy_dwc3->phy_init(phy_dwc3); ++ ++ return 0; ++} ++ ++static int qcom_dwc3_phy_exit(struct phy *phy) ++{ ++ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); ++ ++ if (phy_dwc3->phy_exit) ++ return qcom_dwc3_ss_phy_exit(phy_dwc3); ++ ++ return 0; ++} ++ ++static struct phy_ops qcom_dwc3_phy_ops = { ++ .init = qcom_dwc3_phy_init, ++ .exit = qcom_dwc3_phy_exit, ++ .power_on = qcom_dwc3_phy_power_on, ++ .power_off = qcom_dwc3_phy_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct of_device_id qcom_dwc3_phy_table[] = { ++ { .compatible = "qcom,dwc3-hs-usb-phy", }, ++ { .compatible = "qcom,dwc3-ss-usb-phy", }, ++ { /* Sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, qcom_dwc3_phy_table); ++ ++static int qcom_dwc3_phy_probe(struct platform_device *pdev) ++{ ++ struct qcom_dwc3_usb_phy *phy_dwc3; ++ struct phy_provider *phy_provider; ++ struct resource *res; ++ ++ phy_dwc3 = devm_kzalloc(&pdev->dev, sizeof(*phy_dwc3), GFP_KERNEL); ++ if (!phy_dwc3) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phy_dwc3); ++ ++ phy_dwc3->dev = &pdev->dev; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ phy_dwc3->base = devm_ioremap_resource(phy_dwc3->dev, res); ++ if (IS_ERR(phy_dwc3->base)) ++ return PTR_ERR(phy_dwc3->base); ++ ++ phy_dwc3->ref_clk = devm_clk_get(phy_dwc3->dev, "ref"); ++ if (IS_ERR(phy_dwc3->ref_clk)) { ++ dev_dbg(phy_dwc3->dev, "cannot get reference clock\n"); ++ return PTR_ERR(phy_dwc3->ref_clk); ++ } ++ ++ if (of_device_is_compatible(pdev->dev.of_node, ++ "qcom,dwc3-hs-usb-phy")) { ++ clk_set_rate(phy_dwc3->ref_clk, 60000000); ++ phy_dwc3->phy_init = qcom_dwc3_hs_phy_init; ++ } else if (of_device_is_compatible(pdev->dev.of_node, ++ "qcom,dwc3-ss-usb-phy")) { ++ phy_dwc3->phy_init = qcom_dwc3_ss_phy_init; ++ phy_dwc3->phy_exit = qcom_dwc3_ss_phy_exit; ++ clk_set_rate(phy_dwc3->ref_clk, 125000000); ++ } else { ++ dev_err(phy_dwc3->dev, "Unknown phy\n"); ++ return -EINVAL; ++ } ++ ++ phy_dwc3->xo_clk = devm_clk_get(phy_dwc3->dev, "xo"); ++ if (IS_ERR(phy_dwc3->xo_clk)) { ++ dev_dbg(phy_dwc3->dev, "cannot get TCXO clock\n"); ++ phy_dwc3->xo_clk = NULL; ++ } ++ ++ phy_dwc3->phy = devm_phy_create(phy_dwc3->dev, NULL, &qcom_dwc3_phy_ops); ++ ++ if (IS_ERR(phy_dwc3->phy)) ++ return PTR_ERR(phy_dwc3->phy); ++ ++ phy_set_drvdata(phy_dwc3->phy, phy_dwc3); ++ ++ phy_provider = devm_of_phy_provider_register(phy_dwc3->dev, ++ of_phy_simple_xlate); ++ ++ if (IS_ERR(phy_provider)) ++ return PTR_ERR(phy_provider); ++ ++ return 0; ++} ++ ++static struct platform_driver qcom_dwc3_phy_driver = { ++ .probe = qcom_dwc3_phy_probe, ++ .driver = { ++ .name = "qcom-dwc3-usb-phy", ++ .owner = THIS_MODULE, ++ .of_match_table = qcom_dwc3_phy_table, ++ }, ++}; ++ ++module_platform_driver(qcom_dwc3_phy_driver); ++ ++MODULE_ALIAS("platform:phy-qcom-dwc3"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>"); ++MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>"); ++MODULE_DESCRIPTION("DesignWare USB3 QCOM PHY driver"); diff --git a/target/linux/ipq806x/patches-4.4/101-ARM-qcom-add-USB-nodes-to-ipq806x-ap148.patch b/target/linux/ipq806x/patches-4.4/101-ARM-qcom-add-USB-nodes-to-ipq806x-ap148.patch new file mode 100644 index 0000000000..6e6f10d549 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/101-ARM-qcom-add-USB-nodes-to-ipq806x-ap148.patch @@ -0,0 +1,125 @@ +--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts ++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts +@@ -92,5 +92,29 @@ + sata@29000000 { + status = "ok"; + }; ++ ++ phy@100f8800 { /* USB3 port 1 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@100f8830 { /* USB3 port 1 SS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8800 { /* USB3 port 0 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8830 { /* USB3 port 0 SS phy */ ++ status = "ok"; ++ }; ++ ++ usb30@0 { ++ status = "ok"; ++ }; ++ ++ usb30@1 { ++ status = "ok"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi +@@ -333,6 +333,90 @@ + compatible = "syscon"; + reg = <0x01200600 0x100>; + }; ++ ++ hs_phy_1: phy@100f8800 { ++ compatible = "qcom,dwc3-hs-usb-phy"; ++ reg = <0x100f8800 0x30>; ++ clocks = <&gcc USB30_1_UTMI_CLK>; ++ clock-names = "ref"; ++ #phy-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ ++ ss_phy_1: phy@100f8830 { ++ compatible = "qcom,dwc3-ss-usb-phy"; ++ reg = <0x100f8830 0x30>; ++ clocks = <&gcc USB30_1_MASTER_CLK>; ++ clock-names = "ref"; ++ #phy-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ ++ hs_phy_0: phy@110f8800 { ++ compatible = "qcom,dwc3-hs-usb-phy"; ++ reg = <0x110f8800 0x30>; ++ clocks = <&gcc USB30_0_UTMI_CLK>; ++ clock-names = "ref"; ++ #phy-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ ++ ss_phy_0: phy@110f8830 { ++ compatible = "qcom,dwc3-ss-usb-phy"; ++ reg = <0x110f8830 0x30>; ++ clocks = <&gcc USB30_0_MASTER_CLK>; ++ clock-names = "ref"; ++ #phy-cells = <0>; ++ ++ status = "disabled"; ++ }; ++ ++ usb3_0: usb30@0 { ++ compatible = "qcom,dwc3"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&gcc USB30_0_MASTER_CLK>; ++ clock-names = "core"; ++ ++ ranges; ++ ++ status = "disabled"; ++ ++ dwc3@11000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x11000000 0xcd00>; ++ interrupts = <0 110 0x4>; ++ phys = <&hs_phy_0>, <&ss_phy_0>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ tx-fifo-resize; ++ dr_mode = "host"; ++ }; ++ }; ++ ++ usb3_1: usb30@1 { ++ compatible = "qcom,dwc3"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&gcc USB30_1_MASTER_CLK>; ++ clock-names = "core"; ++ ++ ranges; ++ ++ status = "disabled"; ++ ++ dwc3@10000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x10000000 0xcd00>; ++ interrupts = <0 205 0x4>; ++ phys = <&hs_phy_1>, <&ss_phy_1>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ tx-fifo-resize; ++ dr_mode = "host"; ++ }; ++ }; + }; + + sfpb_mutex: sfpb-mutex { diff --git a/target/linux/ipq806x/patches-4.1/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch b/target/linux/ipq806x/patches-4.4/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch index 41f91fae7c..41f91fae7c 100644 --- a/target/linux/ipq806x/patches-4.1/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch +++ b/target/linux/ipq806x/patches-4.4/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch diff --git a/target/linux/ipq806x/patches-4.1/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch b/target/linux/ipq806x/patches-4.4/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch index dbf16a303a..ad1a1b9cb3 100644 --- a/target/linux/ipq806x/patches-4.1/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch +++ b/target/linux/ipq806x/patches-4.4/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch @@ -34,25 +34,25 @@ MAINTAINERS | 7 + --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -7599,6 +7599,13 @@ L: linux-pci@vger.kernel.org - S: Maintained - F: drivers/pci/host/*spear* +@@ -8253,6 +8253,13 @@ + F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt + F: drivers/pci/host/pcie-hisi.c +PCIE DRIVER FOR QUALCOMM MSM -+M: Stanimir Varbanov <svarbanov@mm-sol.com> -+L: linux-pci@vger.kernel.org -+L: linux-arm-msm@vger.kernel.org -+S: Maintained -+F: drivers/pci/host/*qcom* ++M: Stanimir Varbanov <svarbanov@mm-sol.com> ++L: linux-pci@vger.kernel.org ++L: linux-arm-msm@vger.kernel.org ++S: Maintained ++F: drivers/pci/host/*qcom* + PCMCIA SUBSYSTEM P: Linux PCMCIA Team L: linux-pcmcia@lists.infradead.org --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig -@@ -125,4 +125,13 @@ config PCIE_IPROC_PLATFORM - Say Y here if you want to use the Broadcom iProc PCIe controller - through the generic platform bus interface +@@ -173,4 +173,13 @@ + help + Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC +config PCIE_QCOM + bool "Qualcomm PCIe controller" @@ -66,7 +66,7 @@ MAINTAINERS | 7 + endmenu --- /dev/null +++ b/drivers/pci/host/pcie-qcom.c -@@ -0,0 +1,677 @@ +@@ -0,0 +1,676 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * @@ -613,8 +613,7 @@ MAINTAINERS | 7 + + return PCIBIOS_SUCCESSFUL; + } + -+ return dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where, -+ size, val); ++ return dw_pcie_cfg_read(pp->dbi_base + where, size, val); +} + +static struct pcie_host_ops qcom_pcie_ops = { @@ -648,7 +647,7 @@ MAINTAINERS | 7 + + + pcie->version = (unsigned int)match->data; + -+ pcie->reset = devm_gpiod_get_optional(dev, "perst"); ++ pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW); + if (IS_ERR(pcie->reset) && PTR_ERR(pcie->reset) == -EPROBE_DEFER) + return PTR_ERR(pcie->reset); + @@ -746,8 +745,8 @@ MAINTAINERS | 7 + +MODULE_ALIAS("platform:qcom-pcie"); --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile -@@ -15,3 +15,4 @@ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-laye - obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o - obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o - obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o +@@ -20,3 +20,4 @@ + obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o + obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o + obj-$(CONFIG_PCI_HISI) += pcie-hisi.o +obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o diff --git a/target/linux/ipq806x/patches-4.1/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-4.4/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch index 6ccb7d8080..1246bfeda9 100644 --- a/target/linux/ipq806x/patches-4.1/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch +++ b/target/linux/ipq806x/patches-4.4/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch @@ -15,8 +15,8 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> --- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts +++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -91,5 +91,15 @@ - sata@29000000 { +@@ -116,5 +116,15 @@ + usb30@1 { status = "ok"; }; + @@ -97,9 +97,9 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> }; intc: interrupt-controller@2000000 { -@@ -333,6 +363,144 @@ - compatible = "syscon"; - reg = <0x01200600 0x100>; +@@ -417,6 +447,144 @@ + dr_mode = "host"; + }; }; + + pcie0: pci@1b500000 { diff --git a/target/linux/ipq806x/patches-4.1/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch b/target/linux/ipq806x/patches-4.4/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch index e2d31354ed..e2d31354ed 100644 --- a/target/linux/ipq806x/patches-4.1/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch +++ b/target/linux/ipq806x/patches-4.4/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch diff --git a/target/linux/ipq806x/patches-4.1/114-pcie-add-ctlr-init.patch b/target/linux/ipq806x/patches-4.4/114-pcie-add-ctlr-init.patch index c00abca753..6328113c06 100644 --- a/target/linux/ipq806x/patches-4.1/114-pcie-add-ctlr-init.patch +++ b/target/linux/ipq806x/patches-4.4/114-pcie-add-ctlr-init.patch @@ -223,9 +223,9 @@ + + writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->dbi + PCIE20_PLR_IATU_CTRL1); + writel(PCIE20_PLR_IATU_ENABLE, pcie->dbi + PCIE20_PLR_IATU_CTRL2); -+ writel(pp->cfg0_mod_base, pcie->dbi + PCIE20_PLR_IATU_LBAR); -+ writel((pp->cfg0_mod_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR); -+ writel((pp->cfg0_mod_base + pp->cfg0_size - 1), ++ writel(pp->cfg0_base, pcie->dbi + PCIE20_PLR_IATU_LBAR); ++ writel((pp->cfg0_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR); ++ writel((pp->cfg0_base + pp->cfg0_size - 1), + pcie->dbi + PCIE20_PLR_IATU_LAR); + writel(busdev, pcie->dbi + PCIE20_PLR_IATU_LTAR); + writel(0, pcie->dbi + PCIE20_PLR_IATU_UTAR); @@ -246,9 +246,9 @@ + + writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->dbi + PCIE20_PLR_IATU_CTRL1); + writel(PCIE20_PLR_IATU_ENABLE, pcie->dbi + PCIE20_PLR_IATU_CTRL2); -+ writel(pp->mem_mod_base, pcie->dbi + PCIE20_PLR_IATU_LBAR); -+ writel((pp->mem_mod_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR); -+ writel(pp->mem_mod_base + pp->mem_size - 1, ++ writel(pp->mem_base, pcie->dbi + PCIE20_PLR_IATU_LBAR); ++ writel((pp->mem_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR); ++ writel(pp->mem_base + pp->mem_size - 1, + pcie->dbi + PCIE20_PLR_IATU_LAR); + writel(pp->mem_bus_addr, pcie->dbi + PCIE20_PLR_IATU_LTAR); + writel(upper_32_bits(pp->mem_bus_addr), diff --git a/target/linux/ipq806x/patches-4.1/115-add-pcie-aux-clk-dts.patch b/target/linux/ipq806x/patches-4.4/115-add-pcie-aux-clk-dts.patch index a99857e314..8ceace9523 100644 --- a/target/linux/ipq806x/patches-4.1/115-add-pcie-aux-clk-dts.patch +++ b/target/linux/ipq806x/patches-4.4/115-add-pcie-aux-clk-dts.patch @@ -1,6 +1,6 @@ --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -392,15 +392,21 @@ +@@ -476,15 +476,21 @@ clocks = <&gcc PCIE_A_CLK>, <&gcc PCIE_H_CLK>, @@ -26,7 +26,7 @@ pinctrl-0 = <&pcie0_pins>; pinctrl-names = "default"; -@@ -438,15 +444,21 @@ +@@ -522,15 +528,21 @@ clocks = <&gcc PCIE_1_A_CLK>, <&gcc PCIE_1_H_CLK>, @@ -52,7 +52,7 @@ pinctrl-0 = <&pcie1_pins>; pinctrl-names = "default"; -@@ -484,15 +496,21 @@ +@@ -568,15 +580,21 @@ clocks = <&gcc PCIE_2_A_CLK>, <&gcc PCIE_2_H_CLK>, diff --git a/target/linux/ipq806x/patches-4.1/126-add-rpm-to-ipq8064-dts.patch b/target/linux/ipq806x/patches-4.4/126-add-rpm-to-ipq8064-dts.patch index 7daa93163b..7daa93163b 100644 --- a/target/linux/ipq806x/patches-4.1/126-add-rpm-to-ipq8064-dts.patch +++ b/target/linux/ipq806x/patches-4.4/126-add-rpm-to-ipq8064-dts.patch diff --git a/target/linux/ipq806x/patches-4.1/133-ARM-Add-Krait-L2-register-accessor-functions.patch b/target/linux/ipq806x/patches-4.4/133-ARM-Add-Krait-L2-register-accessor-functions.patch index 36a92c858a..01bd7497d1 100644 --- a/target/linux/ipq806x/patches-4.1/133-ARM-Add-Krait-L2-register-accessor-functions.patch +++ b/target/linux/ipq806x/patches-4.4/133-ARM-Add-Krait-L2-register-accessor-functions.patch @@ -38,7 +38,7 @@ arch/arm/common/Kconfig | 3 ++ --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig -@@ -9,6 +9,9 @@ config DMABOUNCE +@@ -9,6 +9,9 @@ bool select ZONE_DMA @@ -50,7 +50,7 @@ arch/arm/common/Kconfig | 3 ++ --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile -@@ -7,6 +7,7 @@ obj-y += firmware.o +@@ -7,6 +7,7 @@ obj-$(CONFIG_ICST) += icst.o obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o diff --git a/target/linux/ipq806x/patches-4.1/134-clk-mux-Split-out-register-accessors-for-reuse.patch b/target/linux/ipq806x/patches-4.4/134-clk-mux-Split-out-register-accessors-for-reuse.patch index 3a475fba3d..acf5820e6c 100644 --- a/target/linux/ipq806x/patches-4.1/134-clk-mux-Split-out-register-accessors-for-reuse.patch +++ b/target/linux/ipq806x/patches-4.4/134-clk-mux-Split-out-register-accessors-for-reuse.patch @@ -1,15 +1,7 @@ -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v3,02/13] clk: mux: Split out register accessors for reuse +From 4c28a15ea536281c8d619e5c6716ade914c79a6e Mon Sep 17 00:00:00 2001 From: Stephen Boyd <sboyd@codeaurora.org> -X-Patchwork-Id: 6063111 -Message-Id: <1426920332-9340-3-git-send-email-sboyd@codeaurora.org> -To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org> -Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, - linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, - Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 20 Mar 2015 23:45:21 -0700 +Subject: [PATCH 1/2] clk: mux: Split out register accessors for reuse We want to reuse the logic in clk-mux.c for other clock drivers that don't use readl as register accessors. Fortunately, there @@ -20,15 +12,17 @@ that operate on an optional table and some flags so that other drivers can use the same logic. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> - +Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org> --- -drivers/clk/clk-mux.c | 76 +++++++++++++++++++++++++++----------------- + drivers/clk/clk-mux.c | 74 +++++++++++++++++++++++++++----------------- include/linux/clk-provider.h | 9 ++++-- - 2 files changed, 54 insertions(+), 31 deletions(-) + 2 files changed, 53 insertions(+), 30 deletions(-) +diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c +index 7129c86..b03a34d 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c -@@ -29,35 +29,24 @@ +@@ -28,35 +28,24 @@ #define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) @@ -37,7 +31,7 @@ drivers/clk/clk-mux.c | 76 +++++++++++++++++++++++++++----------------- + unsigned int *table, unsigned long flags) { - struct clk_mux *mux = to_clk_mux(hw); - int num_parents = __clk_get_num_parents(hw->clk); + int num_parents = clk_hw_get_num_parents(hw); - u32 val; - /* @@ -70,7 +64,7 @@ drivers/clk/clk-mux.c | 76 +++++++++++++++++++++++++++----------------- val--; if (val >= num_parents) -@@ -65,24 +54,53 @@ static u8 clk_mux_get_parent(struct clk_ +@@ -64,24 +53,53 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) return val; } @@ -86,23 +80,23 @@ drivers/clk/clk-mux.c | 76 +++++++++++++++++++++++++++----------------- - if (mux->table) - index = mux->table[index]; + /* -+ * FIXME need a mux-specific flag to determine if val is bitwise or numeric -+ * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 -+ * to 0x7 (index starts at one) -+ * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so -+ * val = 0x4 really means "bit 2, index starts at bit 0" -+ */ ++ * FIXME need a mux-specific flag to determine if val is bitwise or numeric ++ * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 ++ * to 0x7 (index starts at one) ++ * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so ++ * val = 0x4 really means "bit 2, index starts at bit 0" ++ */ + val = clk_readl(mux->reg) >> mux->shift; + val &= mux->mask; -+ -+ return clk_mux_get_parent(hw, val, mux->table, mux->flags); -+} - else { - if (mux->flags & CLK_MUX_INDEX_BIT) - index = 1 << index; ++ return clk_mux_get_parent(hw, val, mux->table, mux->flags); ++} ++ +unsigned int clk_mux_reindex(u8 index, unsigned int *table, -+ unsigned long flags) ++ unsigned long flags) +{ + unsigned int val = index; @@ -114,8 +108,8 @@ drivers/clk/clk-mux.c | 76 +++++++++++++++++++++++++++----------------- + if (flags & CLK_MUX_INDEX_BIT) + val = 1 << index; + -+ if (flags & CLK_MUX_INDEX_ONE) -+ val++; ++ if (flags & CLK_MUX_INDEX_ONE) ++ val++; } + return val; @@ -132,8 +126,8 @@ drivers/clk/clk-mux.c | 76 +++++++++++++++++++++++++++----------------- + if (mux->lock) spin_lock_irqsave(mux->lock, flags); - -@@ -102,21 +120,21 @@ static int clk_mux_set_parent(struct clk + else +@@ -105,7 +123,7 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) } const struct clk_ops clk_mux_ops = { @@ -142,51 +136,49 @@ drivers/clk/clk-mux.c | 76 +++++++++++++++++++++++++++----------------- .set_parent = clk_mux_set_parent, .determine_rate = __clk_mux_determine_rate, }; - EXPORT_SYMBOL_GPL(clk_mux_ops); - - const struct clk_ops clk_mux_ro_ops = { -- .get_parent = clk_mux_get_parent, -+ .get_parent = _clk_mux_get_parent, - }; - EXPORT_SYMBOL_GPL(clk_mux_ro_ops); - - struct clk *clk_register_mux_table(struct device *dev, const char *name, - const char **parent_names, u8 num_parents, unsigned long flags, +@@ -120,7 +138,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, void __iomem *reg, u8 shift, u32 mask, - u8 clk_mux_flags, u32 *table, spinlock_t *lock) + u8 clk_mux_flags, unsigned int *table, spinlock_t *lock) { struct clk_mux *mux; struct clk *clk; +diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h +index c56988a..b6b17b5 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h -@@ -409,7 +409,7 @@ void clk_unregister_divider(struct clk * +@@ -432,7 +432,7 @@ void clk_unregister_divider(struct clk *clk); struct clk_mux { struct clk_hw hw; void __iomem *reg; - u32 *table; -+ unsigned int *table; ++ unsigned int *table; u32 mask; u8 shift; u8 flags; -@@ -425,6 +425,11 @@ struct clk_mux { +@@ -448,6 +448,11 @@ struct clk_mux { extern const struct clk_ops clk_mux_ops; extern const struct clk_ops clk_mux_ro_ops; +unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val, + unsigned int *table, unsigned long flags); +unsigned int clk_mux_reindex(u8 index, unsigned int *table, -+ unsigned long flags); ++ unsigned long flags); + struct clk *clk_register_mux(struct device *dev, const char *name, - const char **parent_names, u8 num_parents, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, -@@ -433,7 +438,7 @@ struct clk *clk_register_mux(struct devi - struct clk *clk_register_mux_table(struct device *dev, const char *name, - const char **parent_names, u8 num_parents, unsigned long flags, + const char * const *parent_names, u8 num_parents, + unsigned long flags, +@@ -458,7 +463,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, void __iomem *reg, u8 shift, u32 mask, - u8 clk_mux_flags, u32 *table, spinlock_t *lock); + u8 clk_mux_flags, unsigned int *table, spinlock_t *lock); void clk_unregister_mux(struct clk *clk); +-- +2.7.2 + diff --git a/target/linux/ipq806x/patches-4.1/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch b/target/linux/ipq806x/patches-4.4/135-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch index 143e0795f0..5df0a5613e 100644 --- a/target/linux/ipq806x/patches-4.1/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch +++ b/target/linux/ipq806x/patches-4.4/135-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch @@ -1,16 +1,8 @@ -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v3, 03/13] clk: Avoid sending high rates to downstream clocks during - set_rate +From 39d42ce5031d2a4f92fa203b87acfbab340b15a2 Mon Sep 17 00:00:00 2001 From: Stephen Boyd <sboyd@codeaurora.org> -X-Patchwork-Id: 6063271 -Message-Id: <1426920332-9340-4-git-send-email-sboyd@codeaurora.org> -To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org> -Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, - linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, - Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 20 Mar 2015 23:45:22 -0700 +Subject: [PATCH 2/2] clk: Avoid sending high rates to downstream clocks during + set_rate If a clock is on and we call clk_set_rate() on it we may get into a situation where the clock temporarily increases in rate @@ -40,20 +32,22 @@ dividers if necessary. We assume that there isn't such a thing as minimum rate requirements. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> - +Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org> --- -drivers/clk/clk.c | 34 ++++++++++++++++++++++------------ + drivers/clk/clk.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) +diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c +index f13c3f4..8404c3c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c -@@ -1744,21 +1744,24 @@ static struct clk_core *clk_propagate_ra +@@ -1427,21 +1427,24 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *core, * walk down a subtree and set the new rates notifying the rate * change on the way */ --static void clk_change_rate(struct clk_core *clk) +-static void clk_change_rate(struct clk_core *core) +static void -+clk_change_rate(struct clk_core *clk, unsigned long best_parent_rate) ++clk_change_rate(struct clk_core *core, unsigned long best_parent_rate) { struct clk_core *child; struct hlist_node *tmp; @@ -62,58 +56,58 @@ drivers/clk/clk.c | 34 ++++++++++++++++++++++------------ bool skip_set_rate = false; struct clk_core *old_parent; -- old_rate = clk->rate; -+ hlist_for_each_entry(child, &clk->children, child_node) { +- old_rate = core->rate; ++ hlist_for_each_entry(child, &core->children, child_node) { + /* Skip children who will be reparented to another clock */ -+ if (child->new_parent && child->new_parent != clk) ++ if (child->new_parent && child->new_parent != core) + continue; + if (child->new_rate > child->rate) -+ clk_change_rate(child, clk->new_rate); ++ clk_change_rate(child, core->new_rate); + } -- if (clk->new_parent) -- best_parent_rate = clk->new_parent->rate; -- else if (clk->parent) -- best_parent_rate = clk->parent->rate; -+ old_rate = clk->rate; +- if (core->new_parent) +- best_parent_rate = core->new_parent->rate; +- else if (core->parent) +- best_parent_rate = core->parent->rate; ++ old_rate = core->rate; - if (clk->new_parent && clk->new_parent != clk->parent) { - old_parent = __clk_set_parent_before(clk, clk->new_parent); -@@ -1784,7 +1787,7 @@ static void clk_change_rate(struct clk_c + if (core->new_parent && core->new_parent != core->parent) { + old_parent = __clk_set_parent_before(core, core->new_parent); +@@ -1467,7 +1470,7 @@ static void clk_change_rate(struct clk_core *core) - trace_clk_set_rate_complete(clk, clk->new_rate); + trace_clk_set_rate_complete(core, core->new_rate); -- clk->rate = clk_recalc(clk, best_parent_rate); -+ clk->rate = clk->new_rate; +- core->rate = clk_recalc(core, best_parent_rate); ++ core->rate = core->new_rate; - if (clk->notifier_count && old_rate != clk->rate) - __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); -@@ -1797,12 +1800,13 @@ static void clk_change_rate(struct clk_c + if (core->notifier_count && old_rate != core->rate) + __clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate); +@@ -1483,12 +1486,13 @@ static void clk_change_rate(struct clk_core *core) /* Skip children who will be reparented to another clock */ - if (child->new_parent && child->new_parent != clk) + if (child->new_parent && child->new_parent != core) continue; - clk_change_rate(child); + if (child->new_rate != child->rate) -+ clk_change_rate(child, clk->new_rate); ++ clk_change_rate(child, core->new_rate); } - /* handle the new child who might not be in clk->children yet */ -- if (clk->new_child) -- clk_change_rate(clk->new_child); -+ if (clk->new_child && clk->new_child->new_rate != clk->new_child->rate) -+ clk_change_rate(clk->new_child, clk->new_rate); + /* handle the new child who might not be in core->children yet */ +- if (core->new_child) +- clk_change_rate(core->new_child); ++ if (core->new_child && core->new_child->new_rate != core->new_child->rate) ++ clk_change_rate(core->new_child, core->new_rate); } - static int clk_core_set_rate_nolock(struct clk_core *clk, -@@ -1811,6 +1815,7 @@ static int clk_core_set_rate_nolock(stru + static int clk_core_set_rate_nolock(struct clk_core *core, +@@ -1497,6 +1501,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core, struct clk_core *top, *fail_clk; unsigned long rate = req_rate; int ret = 0; + unsigned long parent_rate; - if (!clk) + if (!core) return 0; -@@ -1836,8 +1841,13 @@ static int clk_core_set_rate_nolock(stru +@@ -1522,8 +1527,13 @@ static int clk_core_set_rate_nolock(struct clk_core *core, return -EBUSY; } @@ -126,5 +120,8 @@ drivers/clk/clk.c | 34 ++++++++++++++++++++++------------ - clk_change_rate(top); + clk_change_rate(top, parent_rate); - clk->req_rate = req_rate; + core->req_rate = req_rate; +-- +2.7.2 + diff --git a/target/linux/ipq806x/patches-4.4/136-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.4/136-clk-Add-safe-switch-hook.patch new file mode 100644 index 0000000000..e969f6bca4 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/136-clk-Add-safe-switch-hook.patch @@ -0,0 +1,158 @@ +From f7a00ea959be31f9b742042294a359d508edce94 Mon Sep 17 00:00:00 2001 +From: Stephen Boyd <sboyd@codeaurora.org> +Date: Fri, 20 Mar 2015 23:45:23 -0700 +Subject: [PATCH] clk: Add safe switch hook + +Sometimes clocks can't accept their parent source turning off +while the source is reprogrammed to a different rate. Most +notably CPU clocks require a way to switch away from the current +PLL they're running on, reprogram that PLL to a new rate, and +then switch back to the PLL with the new rate once they're done. +Add a hook that drivers can implement allowing them to return a +'safe parent' that they can switch their parent to while the +upstream source is reprogrammed to support this. + +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org> +--- + drivers/clk/clk.c | 61 ++++++++++++++++++++++++++++++++++++++------ + include/linux/clk-provider.h | 1 + + 2 files changed, 54 insertions(+), 8 deletions(-) + +diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c +index 8404c3c..a29319a 100644 +--- a/drivers/clk/clk.c ++++ b/drivers/clk/clk.c +@@ -51,9 +51,12 @@ struct clk_core { + struct clk_core **parents; + u8 num_parents; + u8 new_parent_index; ++ u8 safe_parent_index; + unsigned long rate; + unsigned long req_rate; ++ unsigned long old_rate; + unsigned long new_rate; ++ struct clk_core *safe_parent; + struct clk_core *new_parent; + struct clk_core *new_child; + unsigned long flags; +@@ -1271,7 +1274,8 @@ out: + static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate, + struct clk_core *new_parent, u8 p_index) + { +- struct clk_core *child; ++ struct clk_core *child, *parent; ++ struct clk_hw *parent_hw; + + core->new_rate = new_rate; + core->new_parent = new_parent; +@@ -1281,6 +1285,18 @@ static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate, + if (new_parent && new_parent != core->parent) + new_parent->new_child = core; + ++ if (core->ops->get_safe_parent) { ++ parent_hw = core->ops->get_safe_parent(core->hw); ++ if (parent_hw) { ++ parent = parent_hw->core; ++ p_index = clk_fetch_parent_index(core, parent); ++ core->safe_parent_index = p_index; ++ core->safe_parent = parent; ++ } ++ } else { ++ core->safe_parent = NULL; ++ } ++ + hlist_for_each_entry(child, &core->children, child_node) { + child->new_rate = clk_recalc(child, new_rate); + clk_calc_subtree(child, child->new_rate, NULL, 0); +@@ -1393,14 +1409,43 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *core, + unsigned long event) + { + struct clk_core *child, *tmp_clk, *fail_clk = NULL; ++ struct clk_core *old_parent; + int ret = NOTIFY_DONE; + +- if (core->rate == core->new_rate) ++ if (core->rate == core->new_rate && event != POST_RATE_CHANGE) + return NULL; + ++ switch (event) { ++ case PRE_RATE_CHANGE: ++ if (core->safe_parent) ++ core->ops->set_parent(core->hw, core->safe_parent_index); ++ core->old_rate = core->rate; ++ break; ++ case POST_RATE_CHANGE: ++ if (core->safe_parent) { ++ old_parent = __clk_set_parent_before(core, ++ core->new_parent); ++ if (core->ops->set_rate_and_parent) { ++ core->ops->set_rate_and_parent(core->hw, ++ core->new_rate, ++ core->new_parent ? ++ core->new_parent->rate : 0, ++ core->new_parent_index); ++ } else if (core->ops->set_parent) { ++ core->ops->set_parent(core->hw, ++ core->new_parent_index); ++ } ++ __clk_set_parent_after(core, core->new_parent, ++ old_parent); ++ } ++ break; ++ } ++ + if (core->notifier_count) { +- ret = __clk_notify(core, event, core->rate, core->new_rate); +- if (ret & NOTIFY_STOP_MASK) ++ if (event != POST_RATE_CHANGE || core->old_rate != core->rate) ++ ret = __clk_notify(core, event, core->old_rate, ++ core->new_rate); ++ if (ret & NOTIFY_STOP_MASK && event != POST_RATE_CHANGE) + fail_clk = core; + } + +@@ -1446,7 +1491,8 @@ clk_change_rate(struct clk_core *core, unsigned long best_parent_rate) + + old_rate = core->rate; + +- if (core->new_parent && core->new_parent != core->parent) { ++ if (core->new_parent && core->new_parent != core->parent && ++ !core->safe_parent) { + old_parent = __clk_set_parent_before(core, core->new_parent); + trace_clk_set_parent(core, core->new_parent); + +@@ -1472,9 +1518,6 @@ clk_change_rate(struct clk_core *core, unsigned long best_parent_rate) + + core->rate = core->new_rate; + +- if (core->notifier_count && old_rate != core->rate) +- __clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate); +- + if (core->flags & CLK_RECALC_NEW_RATES) + (void)clk_calc_new_rates(core, core->new_rate); + +@@ -1537,6 +1580,8 @@ static int clk_core_set_rate_nolock(struct clk_core *core, + + core->req_rate = req_rate; + ++ clk_propagate_rate_change(top, POST_RATE_CHANGE); ++ + return ret; + } + +diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h +index b6b17b5..5d49262 100644 +--- a/include/linux/clk-provider.h ++++ b/include/linux/clk-provider.h +@@ -202,6 +202,7 @@ struct clk_ops { + struct clk_rate_request *req); + int (*set_parent)(struct clk_hw *hw, u8 index); + u8 (*get_parent)(struct clk_hw *hw); ++ struct clk_hw *(*get_safe_parent)(struct clk_hw *hw); + int (*set_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate); + int (*set_rate_and_parent)(struct clk_hw *hw, +-- +2.7.2 + diff --git a/target/linux/ipq806x/patches-4.1/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch b/target/linux/ipq806x/patches-4.4/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch index 6fad6e8a0c..a1b1f4b1f7 100644 --- a/target/linux/ipq806x/patches-4.1/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch +++ b/target/linux/ipq806x/patches-4.4/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch @@ -28,14 +28,14 @@ I'd really like to get rid of __clk_hfpll_init_once() if possible... --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile -@@ -8,6 +8,7 @@ clk-qcom-y += clk-rcg2.o +@@ -8,6 +8,7 @@ clk-qcom-y += clk-branch.o clk-qcom-y += clk-regmap-divider.o clk-qcom-y += clk-regmap-mux.o +clk-qcom-y += clk-hfpll.o clk-qcom-y += reset.o + clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o - obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o --- /dev/null +++ b/drivers/clk/qcom/clk-hfpll.c @@ -0,0 +1,253 @@ @@ -86,7 +86,7 @@ I'd really like to get rid of __clk_hfpll_init_once() if possible... + u32 regval = hd->user_val; + unsigned long rate; + -+ rate = __clk_get_rate(hw->clk); ++ rate = clk_hw_get_rate(hw->clk); + + /* Pick the right VCO. */ + if (hd->user_vco_mask && rate > hd->low_vco_max_rate) diff --git a/target/linux/ipq806x/patches-4.1/138-clk-qcom-Add-HFPLL-driver.patch b/target/linux/ipq806x/patches-4.4/138-clk-qcom-Add-HFPLL-driver.patch index 4056784287..5a452dbcbc 100644 --- a/target/linux/ipq806x/patches-4.1/138-clk-qcom-Add-HFPLL-driver.patch +++ b/target/linux/ipq806x/patches-4.4/138-clk-qcom-Add-HFPLL-driver.patch @@ -73,7 +73,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + }; --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig -@@ -97,3 +97,11 @@ config MSM_MMCC_8974 +@@ -106,3 +106,11 @@ Support for the multimedia clock controller on msm8974 devices. Say Y if you want to support multimedia devices such as display, graphics, video encode/decode, camera, etc. @@ -87,7 +87,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + such as MSM8974, APQ8084, etc. --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile -@@ -22,3 +22,4 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm896 +@@ -23,3 +23,4 @@ obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o diff --git a/target/linux/ipq806x/patches-4.1/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch b/target/linux/ipq806x/patches-4.4/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch index ffcd462d12..5b191b5597 100644 --- a/target/linux/ipq806x/patches-4.1/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch +++ b/target/linux/ipq806x/patches-4.4/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch @@ -29,7 +29,7 @@ drivers/clk/qcom/gcc-ipq806x.c | 83 ++++++++++++++++++++++++++++++++++++++++++ #include "reset.h" static struct clk_pll pll0 = { -@@ -113,6 +114,85 @@ static struct clk_regmap pll8_vote = { +@@ -113,6 +114,85 @@ }, }; @@ -100,8 +100,8 @@ drivers/clk/qcom/gcc-ipq806x.c | 83 ++++++++++++++++++++++++++++++++++++++++++ +}; + +static struct clk_hfpll hfpll_l2 = { -+ .d = &hfpll_l2_data, -+ .clkr.hw.init = &(struct clk_init_data){ ++ .d = &hfpll_l2_data, ++ .clkr.hw.init = &(struct clk_init_data){ + .parent_names = (const char *[]){ "pxo" }, + .num_parents = 1, + .name = "hfpll_l2", @@ -115,10 +115,10 @@ drivers/clk/qcom/gcc-ipq806x.c | 83 ++++++++++++++++++++++++++++++++++++++++++ static struct clk_pll pll14 = { .l_reg = 0x31c4, .m_reg = 0x31c8, -@@ -2307,6 +2387,9 @@ static struct clk_regmap *gcc_ipq806x_cl - [USB_FS1_SYSTEM_CLK] = &usb_fs1_sys_clk.clkr, - [EBI2_CLK] = &ebi2_clk.clkr, - [EBI2_AON_CLK] = &ebi2_aon_clk.clkr, +@@ -2837,6 +2917,9 @@ + [UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr, + [NSSTCM_CLK_SRC] = &nss_tcm_src.clkr, + [NSSTCM_CLK] = &nss_tcm_clk.clkr, + [PLL9] = &hfpll0.clkr, + [PLL10] = &hfpll1.clkr, + [PLL12] = &hfpll_l2.clkr, diff --git a/target/linux/ipq806x/patches-4.1/140-clk-qcom-Add-support-for-Krait-clocks.patch b/target/linux/ipq806x/patches-4.4/140-clk-qcom-Add-support-for-Krait-clocks.patch index 5fcc787c89..522482d841 100644 --- a/target/linux/ipq806x/patches-4.1/140-clk-qcom-Add-support-for-Krait-clocks.patch +++ b/target/linux/ipq806x/patches-4.4/140-clk-qcom-Add-support-for-Krait-clocks.patch @@ -30,7 +30,7 @@ drivers/clk/qcom/Kconfig | 4 ++ --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig -@@ -105,3 +105,7 @@ config QCOM_HFPLL +@@ -114,3 +114,7 @@ Support for the high-frequency PLLs present on Qualcomm devices. Say Y if you want to support CPU frequency scaling on devices such as MSM8974, APQ8084, etc. @@ -40,13 +40,14 @@ drivers/clk/qcom/Kconfig | 4 ++ + select KRAIT_L2_ACCESSORS --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile -@@ -8,6 +8,7 @@ clk-qcom-y += clk-rcg2.o +@@ -8,6 +8,7 @@ clk-qcom-y += clk-branch.o clk-qcom-y += clk-regmap-divider.o clk-qcom-y += clk-regmap-mux.o +clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o clk-qcom-y += clk-hfpll.o clk-qcom-y += reset.o + clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o --- /dev/null +++ b/drivers/clk/qcom/clk-krait.c @@ -132,14 +133,14 @@ drivers/clk/qcom/Kconfig | 4 ++ +{ + int i; + struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ int num_parents = __clk_get_num_parents(hw->clk); ++ int num_parents = clk_hw_get_num_parents(hw->clk); + + i = mux->safe_sel; + for (i = 0; i < num_parents; i++) + if (mux->safe_sel == mux->parent_map[i]) + break; + -+ return __clk_get_hw(clk_get_parent_by_index(hw->clk, i)); ++ return __clk_get_hw(clk_hw_get_parent_by_index(hw->clk, i)); +} + +static int krait_mux_enable(struct clk_hw *hw) @@ -172,7 +173,7 @@ drivers/clk/qcom/Kconfig | 4 ++ +static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ -+ *parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), rate * 2); ++ *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw->clk), rate * 2); + return DIV_ROUND_UP(*parent_rate, 2); +} + diff --git a/target/linux/ipq806x/patches-4.1/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch b/target/linux/ipq806x/patches-4.4/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch index db4388812b..b2ddbc8a68 100644 --- a/target/linux/ipq806x/patches-4.1/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch +++ b/target/linux/ipq806x/patches-4.4/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch @@ -31,7 +31,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> --- a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt +++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt -@@ -21,10 +21,17 @@ PROPERTIES +@@ -21,10 +21,17 @@ the register region. An optional second element specifies the base address and size of the alias register region. @@ -82,7 +82,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + }; --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig -@@ -106,6 +106,14 @@ config QCOM_HFPLL +@@ -115,6 +115,14 @@ Say Y if you want to support CPU frequency scaling on devices such as MSM8974, APQ8084, etc. @@ -99,12 +99,14 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> select KRAIT_L2_ACCESSORS --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile -@@ -23,4 +23,5 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm896 - obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o - obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o - obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o +@@ -9,6 +9,7 @@ + clk-qcom-y += clk-regmap-divider.o + clk-qcom-y += clk-regmap-mux.o + clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o +obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o - obj-$(CONFIG_QCOM_HFPLL) += hfpll.o + clk-qcom-y += clk-hfpll.o + clk-qcom-y += reset.o + clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o --- /dev/null +++ b/drivers/clk/qcom/kpss-xcc.c @@ -0,0 +1,95 @@ diff --git a/target/linux/ipq806x/patches-4.1/142-clk-qcom-Add-Krait-clock-controller-driver.patch b/target/linux/ipq806x/patches-4.4/142-clk-qcom-Add-Krait-clock-controller-driver.patch index 59fc44f1cb..f0e946781b 100644 --- a/target/linux/ipq806x/patches-4.1/142-clk-qcom-Add-Krait-clock-controller-driver.patch +++ b/target/linux/ipq806x/patches-4.4/142-clk-qcom-Add-Krait-clock-controller-driver.patch @@ -56,7 +56,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + }; --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig -@@ -114,6 +114,14 @@ config KPSS_XCC +@@ -123,6 +123,14 @@ if you want to support CPU frequency scaling on devices such as MSM8960, APQ8064, etc. @@ -73,9 +73,9 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> select KRAIT_L2_ACCESSORS --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile -@@ -25,3 +25,4 @@ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8 +@@ -26,3 +26,4 @@ + obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o - obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o +obj-$(CONFIG_KRAITCC) += krait-cc.o --- /dev/null diff --git a/target/linux/ipq806x/patches-4.1/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch b/target/linux/ipq806x/patches-4.4/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch index fd37c05425..d4c43f412a 100644 --- a/target/linux/ipq806x/patches-4.1/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch +++ b/target/linux/ipq806x/patches-4.4/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch @@ -69,7 +69,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> + }; --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm -@@ -146,6 +146,15 @@ config ARM_OMAP2PLUS_CPUFREQ +@@ -95,6 +95,15 @@ depends on ARCH_OMAP2PLUS default ARCH_OMAP2PLUS @@ -87,11 +87,11 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> help --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -66,6 +66,7 @@ obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += ki +@@ -61,6 +61,7 @@ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o -+obj-$(CONFIG_ARM_QCOM_CPUFREQ) += qcom-cpufreq.o ++obj-$(CONFIG_ARM_QCOM_CPUFREQ) += qcom-cpufreq.o obj-$(CONFIG_ARM_S3C24XX_CPUFREQ) += s3c24xx-cpufreq.o obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o diff --git a/target/linux/ipq806x/patches-4.1/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch b/target/linux/ipq806x/patches-4.4/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch index aaf140126c..aaf140126c 100644 --- a/target/linux/ipq806x/patches-4.1/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch +++ b/target/linux/ipq806x/patches-4.4/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch diff --git a/target/linux/ipq806x/patches-4.1/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch b/target/linux/ipq806x/patches-4.4/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch index 84f856bbf6..f33c9e0d8c 100644 --- a/target/linux/ipq806x/patches-4.1/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch +++ b/target/linux/ipq806x/patches-4.4/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch @@ -21,7 +21,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig -@@ -198,6 +198,19 @@ config CPUFREQ_DT +@@ -198,6 +198,19 @@ If in doubt, say N. @@ -43,11 +43,11 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> endif --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -14,6 +14,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) +@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o -+obj-$(CONFIG_GENERIC_CPUFREQ_KRAIT) += cpufreq-krait.o ++obj-$(CONFIG_GENERIC_CPUFREQ_KRAIT) += cpufreq-krait.o ################################################################################## # x86 drivers. @@ -446,7 +446,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +MODULE_LICENSE("GPL v2"); --- a/drivers/cpufreq/qcom-cpufreq.c +++ b/drivers/cpufreq/qcom-cpufreq.c -@@ -168,11 +168,8 @@ static int __init qcom_cpufreq_populate_ +@@ -168,11 +168,8 @@ static int __init qcom_cpufreq_driver_init(void) { diff --git a/target/linux/ipq806x/patches-4.1/155-dt-bindings-qcom_adm-Fix-channel-specifiers.patch b/target/linux/ipq806x/patches-4.4/155-dt-bindings-qcom_adm-Fix-channel-specifiers.patch index 4f5c0efb7b..4f5c0efb7b 100644 --- a/target/linux/ipq806x/patches-4.1/155-dt-bindings-qcom_adm-Fix-channel-specifiers.patch +++ b/target/linux/ipq806x/patches-4.4/155-dt-bindings-qcom_adm-Fix-channel-specifiers.patch diff --git a/target/linux/ipq806x/patches-4.1/156-dmaengine-Add-ADM-driver.patch b/target/linux/ipq806x/patches-4.4/156-dmaengine-Add-ADM-driver.patch index 29e8eaaec4..805f28f323 100644 --- a/target/linux/ipq806x/patches-4.1/156-dmaengine-Add-ADM-driver.patch +++ b/target/linux/ipq806x/patches-4.4/156-dmaengine-Add-ADM-driver.patch @@ -35,9 +35,9 @@ drivers/dma/Kconfig | 10 + --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig -@@ -492,4 +492,14 @@ config QCOM_BAM_DMA - Enable support for the QCOM BAM DMA controller. This controller - provides DMA capabilities for a variety of on-chip devices. +@@ -558,4 +558,14 @@ + config DMA_ENGINE_RAID + bool +config QCOM_ADM + tristate "Qualcomm ADM support" @@ -955,8 +955,10 @@ drivers/dma/Kconfig | 10 + +MODULE_LICENSE("GPL v2"); --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile -@@ -54,3 +54,4 @@ obj-$(CONFIG_NBPFAXI_DMA) += nbpfaxi.o - obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o - obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o +@@ -65,5 +65,6 @@ + obj-$(CONFIG_TI_EDMA) += edma.o obj-$(CONFIG_XGENE_DMA) += xgene-dma.o + obj-$(CONFIG_ZX_DMA) += zx296702_dma.o +obj-$(CONFIG_QCOM_ADM) += qcom_adm.o + + obj-y += xilinx/ diff --git a/target/linux/ipq806x/patches-4.1/157-ARM-DT-ipq8064-Add-ADM-device-node.patch b/target/linux/ipq806x/patches-4.4/157-ARM-DT-ipq8064-Add-ADM-device-node.patch index 6f1013e32e..b8abd0a4b2 100644 --- a/target/linux/ipq806x/patches-4.1/157-ARM-DT-ipq8064-Add-ADM-device-node.patch +++ b/target/linux/ipq806x/patches-4.4/157-ARM-DT-ipq8064-Add-ADM-device-node.patch @@ -13,7 +13,7 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -643,6 +643,26 @@ +@@ -727,6 +727,26 @@ status = "disabled"; }; diff --git a/target/linux/ipq806x/patches-4.1/161-mtd-nand-Create-a-BBT-flag-to-access-bad-block-markers-in-raw-mode.patch b/target/linux/ipq806x/patches-4.4/161-mtd-nand-Create-a-BBT-flag-to-access-bad-block-markers-in-raw-mode.patch index 088b8cb5a1..21fe405b90 100644 --- a/target/linux/ipq806x/patches-4.1/161-mtd-nand-Create-a-BBT-flag-to-access-bad-block-markers-in-raw-mode.patch +++ b/target/linux/ipq806x/patches-4.4/161-mtd-nand-Create-a-BBT-flag-to-access-bad-block-markers-in-raw-mode.patch @@ -38,7 +38,7 @@ drivers/mtd/nand/nand_base.c | 6 +++++- --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c -@@ -395,7 +395,11 @@ static int nand_default_block_markbad(st +@@ -394,7 +394,11 @@ } else { ops.len = ops.ooblen = 1; } @@ -53,7 +53,7 @@ drivers/mtd/nand/nand_base.c | 6 +++++- if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c -@@ -423,7 +423,11 @@ static int scan_block_fast(struct mtd_in +@@ -420,7 +420,11 @@ ops.oobbuf = buf; ops.ooboffs = 0; ops.datbuf = NULL; @@ -68,7 +68,7 @@ drivers/mtd/nand/nand_base.c | 6 +++++- /* --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h -@@ -116,6 +116,13 @@ struct nand_bbt_descr { +@@ -116,6 +116,12 @@ #define NAND_BBT_NO_OOB_BBM 0x00080000 /* @@ -76,8 +76,7 @@ drivers/mtd/nand/nand_base.c | 6 +++++- + * be used by controllers which can access BBM only when ECC is disabled, i.e, + * when in RAW access mode + */ -+#define NAND_BBT_ACCESS_BBM_RAW 0x00100000 -+ ++#define NAND_BBT_ACCESS_BBM_RAW 0x00100000 +/* * Flag set by nand_create_default_bbt_descr(), marking that the nand_bbt_descr * was allocated dynamicaly and must be freed in nand_release(). Has no meaning diff --git a/target/linux/ipq806x/patches-4.1/162-mtd-nand-Qualcomm-NAND-controller-driver.patch b/target/linux/ipq806x/patches-4.4/162-mtd-nand-Qualcomm-NAND-controller-driver.patch index 4be7ecb1b9..19e5f91812 100644 --- a/target/linux/ipq806x/patches-4.1/162-mtd-nand-Qualcomm-NAND-controller-driver.patch +++ b/target/linux/ipq806x/patches-4.4/162-mtd-nand-Qualcomm-NAND-controller-driver.patch @@ -80,7 +80,7 @@ drivers/mtd/nand/Kconfig | 7 + --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig -@@ -530,4 +530,11 @@ config MTD_NAND_HISI504 +@@ -546,4 +546,11 @@ help Enables support for NAND controller on Hisilicon SoC Hip04. @@ -2015,10 +2015,10 @@ drivers/mtd/nand/Kconfig | 7 + +MODULE_LICENSE("GPL v2"); --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile -@@ -52,5 +52,6 @@ obj-$(CONFIG_MTD_NAND_XWAY) += xway_nan - obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ +@@ -55,5 +55,6 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o -+obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o + obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ ++obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o nand-objs := nand_base.o nand_bbt.o nand_timings.o diff --git a/target/linux/ipq806x/patches-4.1/163-dt-bindings-qcom_nandc-Add-DT-bindings.patch b/target/linux/ipq806x/patches-4.4/163-dt-bindings-qcom_nandc-Add-DT-bindings.patch index 6530eb1c86..6530eb1c86 100644 --- a/target/linux/ipq806x/patches-4.1/163-dt-bindings-qcom_nandc-Add-DT-bindings.patch +++ b/target/linux/ipq806x/patches-4.4/163-dt-bindings-qcom_nandc-Add-DT-bindings.patch diff --git a/target/linux/ipq806x/patches-4.1/164-arm-qcom-dts-Add-NAND-controller-node-for-ipq806x.patch b/target/linux/ipq806x/patches-4.4/164-arm-qcom-dts-Add-NAND-controller-node-for-ipq806x.patch index 6bdd5e05cc..4fc8a8ce90 100644 --- a/target/linux/ipq806x/patches-4.1/164-arm-qcom-dts-Add-NAND-controller-node-for-ipq806x.patch +++ b/target/linux/ipq806x/patches-4.4/164-arm-qcom-dts-Add-NAND-controller-node-for-ipq806x.patch @@ -26,7 +26,7 @@ arch/arm/boot/dts/qcom-ipq8064.dtsi | 15 +++++++++++++++ --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -663,6 +663,22 @@ +@@ -747,6 +747,22 @@ status = "disabled"; }; diff --git a/target/linux/ipq806x/patches-4.1/165-arm-qcom-dts-Enable-NAND-node-on-IPQ8064-AP148-platform.patch b/target/linux/ipq806x/patches-4.4/165-arm-qcom-dts-Enable-NAND-node-on-IPQ8064-AP148-platform.patch index da1ec46c4e..9de3d8fe81 100644 --- a/target/linux/ipq806x/patches-4.1/165-arm-qcom-dts-Enable-NAND-node-on-IPQ8064-AP148-platform.patch +++ b/target/linux/ipq806x/patches-4.4/165-arm-qcom-dts-Enable-NAND-node-on-IPQ8064-AP148-platform.patch @@ -54,7 +54,7 @@ arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 36 ++++++++++++++++++++++++++++++++ }; gsbi@16300000 { -@@ -101,5 +123,19 @@ +@@ -126,5 +148,19 @@ status = "ok"; phy-tx0-term-offset = <7>; }; diff --git a/target/linux/ipq806x/patches-4.1/166-arch-qcom-dts-enable-qcom-smem-on-AP148-NAND.patch b/target/linux/ipq806x/patches-4.4/166-arch-qcom-dts-enable-qcom-smem-on-AP148-NAND.patch index 9005de4eb5..706028259d 100644 --- a/target/linux/ipq806x/patches-4.1/166-arch-qcom-dts-enable-qcom-smem-on-AP148-NAND.patch +++ b/target/linux/ipq806x/patches-4.4/166-arch-qcom-dts-enable-qcom-smem-on-AP148-NAND.patch @@ -1,6 +1,6 @@ --- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts +++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -132,6 +132,8 @@ +@@ -157,6 +157,8 @@ nand-ecc-strength = <4>; nand-bus-width = <8>; diff --git a/target/linux/ipq806x/patches-4.4/167-ARM-qcom_rpm_fix_support_for_smb208.patch b/target/linux/ipq806x/patches-4.4/167-ARM-qcom_rpm_fix_support_for_smb208.patch new file mode 100644 index 0000000000..8da70340de --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/167-ARM-qcom_rpm_fix_support_for_smb208.patch @@ -0,0 +1,50 @@ + +In commit "regulator: qcom: Rework to single platform device" the smb208 regulator +used in IPQ8064 was left out. + +Add it to that new framework and update Docs accordingly. + +Signed-off-by: Adrian Panella <ianchi74@outlook.com> + +--- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt ++++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt +@@ -59,6 +59,7 @@ Regulator nodes are identified by their + "qcom,rpm-pm8058-regulators" + "qcom,rpm-pm8901-regulators" + "qcom,rpm-pm8921-regulators" ++ "qcom,rpm-smb208-regulators" + + - vdd_l0_l1_lvs-supply: + - vdd_l2_l11_l12-supply: +@@ -156,6 +157,9 @@ pm8921: + l29, lvs1, lvs2, lvs3, lvs4, lvs5, lvs6, lvs7, usb-switch, hdmi-switch, + ncp + ++smb208: ++ s1a, s1b, s2a, s2b ++ + The content of each sub-node is defined by the standard binding for regulators - + see regulator.txt - with additional custom properties described below: + +--- a/drivers/regulator/qcom_rpm-regulator.c ++++ b/drivers/regulator/qcom_rpm-regulator.c +@@ -869,10 +869,19 @@ static const struct rpm_regulator_data r + { } + }; + ++static const struct rpm_regulator_data rpm_smb208_regulators[] = { ++ { "s1a", QCOM_RPM_SMB208_S1a, &smb208_smps, "vin_s1a" }, ++ { "s1b", QCOM_RPM_SMB208_S1b, &smb208_smps, "vin_s1b" }, ++ { "s2a", QCOM_RPM_SMB208_S2a, &smb208_smps, "vin_s2a" }, ++ { "s2b", QCOM_RPM_SMB208_S2b, &smb208_smps, "vin_s2b" }, ++ { } ++}; ++ + static const struct of_device_id rpm_of_match[] = { + { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators }, + { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators }, + { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators }, ++ { .compatible = "qcom,rpm-smb208-regulators", .data = &rpm_smb208_regulators }, + { } + }; + MODULE_DEVICE_TABLE(of, rpm_of_match); diff --git a/target/linux/ipq806x/patches-4.4/168-ARM-qcom-add-smb208-DT.patch b/target/linux/ipq806x/patches-4.4/168-ARM-qcom-add-smb208-DT.patch new file mode 100644 index 0000000000..503654d988 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/168-ARM-qcom-add-smb208-DT.patch @@ -0,0 +1,74 @@ +Change DT to use new smb208 regulator driver. + +Signed-off-by: Adrian Panella <ianchi74@outlook.com> + +--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi +@@ -167,45 +167,37 @@ + #address-cells = <1>; + #size-cells = <0>; + +- smb208_s1a: smb208-s1a { +- compatible = "qcom,rpm-smb208"; +- reg = <QCOM_RPM_SMB208_S1a>; +- +- regulator-min-microvolt = <1050000>; +- regulator-max-microvolt = <1150000>; ++ regulators { ++ compatible = "qcom,rpm-smb208-regulators"; + +- qcom,switch-mode-frequency = <1200000>; +- +- }; ++ smb208_s1a: s1a { ++ regulator-min-microvolt = <1050000>; ++ regulator-max-microvolt = <1150000>; + +- smb208_s1b: smb208-s1b { +- compatible = "qcom,rpm-smb208"; +- reg = <QCOM_RPM_SMB208_S1b>; ++ qcom,switch-mode-frequency = <1200000>; + +- regulator-min-microvolt = <1050000>; +- regulator-max-microvolt = <1150000>; +- +- qcom,switch-mode-frequency = <1200000>; +- }; ++ }; + +- smb208_s2a: smb208-s2a { +- compatible = "qcom,rpm-smb208"; +- reg = <QCOM_RPM_SMB208_S2a>; ++ smb208_s1b: s1b { ++ regulator-min-microvolt = <1050000>; ++ regulator-max-microvolt = <1150000>; + +- regulator-min-microvolt = < 800000>; +- regulator-max-microvolt = <1250000>; ++ qcom,switch-mode-frequency = <1200000>; ++ }; + +- qcom,switch-mode-frequency = <1200000>; +- }; ++ smb208_s2a: s2a { ++ regulator-min-microvolt = < 800000>; ++ regulator-max-microvolt = <1250000>; + +- smb208_s2b: smb208-s2b { +- compatible = "qcom,rpm-smb208"; +- reg = <QCOM_RPM_SMB208_S2b>; ++ qcom,switch-mode-frequency = <1200000>; ++ }; + +- regulator-min-microvolt = < 800000>; +- regulator-max-microvolt = <1250000>; ++ smb208_s2b: s2b { ++ regulator-min-microvolt = < 800000>; ++ regulator-max-microvolt = <1250000>; + +- qcom,switch-mode-frequency = <1200000>; ++ qcom,switch-mode-frequency = <1200000>; ++ }; + }; + }; + diff --git a/target/linux/ipq806x/patches-4.1/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch b/target/linux/ipq806x/patches-4.4/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch index 18b7a80b12..c0281ff070 100644 --- a/target/linux/ipq806x/patches-4.1/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch +++ b/target/linux/ipq806x/patches-4.4/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch @@ -33,7 +33,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -320,7 +320,7 @@ config ARCH_MULTIPLATFORM +@@ -323,7 +323,7 @@ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_HAS_SG_CHAIN select ARM_PATCH_PHYS_VIRT @@ -44,7 +44,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> select GENERIC_CLOCKEVENTS --- a/arch/arm/Makefile +++ b/arch/arm/Makefile -@@ -248,9 +248,11 @@ MACHINE := arch/arm/mach-$(word 1,$(mac +@@ -256,9 +256,11 @@ else MACHINE := endif diff --git a/target/linux/ipq806x/patches-4.1/302-mtd-qcom-smem-rename-rootfs-ubi.patch b/target/linux/ipq806x/patches-4.4/302-mtd-qcom-smem-rename-rootfs-ubi.patch index 471a87ba68..8890a91731 100644 --- a/target/linux/ipq806x/patches-4.1/302-mtd-qcom-smem-rename-rootfs-ubi.patch +++ b/target/linux/ipq806x/patches-4.4/302-mtd-qcom-smem-rename-rootfs-ubi.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/qcom_smem_part.c +++ b/drivers/mtd/qcom_smem_part.c -@@ -192,6 +192,10 @@ static int parse_qcom_smem_partitions(st +@@ -189,6 +189,10 @@ static int parse_qcom_smem_partitions(st m_part->size = le32_to_cpu(s_part->size) * (*smem_blksz); m_part->offset = le32_to_cpu(s_part->start) * (*smem_blksz); diff --git a/target/linux/ipq806x/patches-4.4/400-dsa-add-qca.patch b/target/linux/ipq806x/patches-4.4/400-dsa-add-qca.patch new file mode 100644 index 0000000000..f1bdf1aa6f --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/400-dsa-add-qca.patch @@ -0,0 +1,1521 @@ +From patchwork Fri May 29 01:42:16 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [1/7] net: dsa: add new driver for ar8xxx family +From: Mathieu Olivari <mathieu@codeaurora.org> +X-Patchwork-Id: 477523 +X-Patchwork-Delegate: davem@davemloft.net +Message-Id: <1432863742-18427-2-git-send-email-mathieu@codeaurora.org> +To: robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, + ijc+devicetree@hellion.org.uk, galak@codeaurora.org, + davem@davemloft.net, mathieu@codeaurora.org, andrew@lunn.ch, + f.fainelli@gmail.com, linux@roeck-us.net, gang.chen.5i5j@gmail.com, + jiri@resnulli.us, leitec@staticky.com, fabf@skynet.be, + alexander.h.duyck@intel.com, pavel.nakonechny@skitlab.ru, + joe@perches.com, sfeldma@gmail.com, nbd@openwrt.org, juhosg@openwrt.org +Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Date: Thu, 28 May 2015 18:42:16 -0700 + +This patch contains initial init & registration code for QCA8337. It +will detect a QCA8337 switch, if present and declared in DT/platform. + +Each port will be represented through a standalone net_device interface, +as for other DSA switches. CPU can communicate with any of the ports by +setting an IP@ on ethN interface. Ports cannot communicate with each +other just yet. + +Link status will be reported through polling, and we don't use any +encapsulation. + +Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +--- + drivers/net/dsa/Kconfig | 7 ++ + drivers/net/dsa/Makefile | 1 + + drivers/net/dsa/ar8xxx.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/ar8xxx.h | 82 +++++++++++++ + net/dsa/dsa.c | 1 + + 5 files changed, 394 insertions(+) + create mode 100644 drivers/net/dsa/ar8xxx.c + create mode 100644 drivers/net/dsa/ar8xxx.h + +diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig +index 7ad0a4d..2aae541 100644 +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -65,4 +65,11 @@ config NET_DSA_BCM_SF2 + This enables support for the Broadcom Starfighter 2 Ethernet + switch chips. + ++config NET_DSA_AR8XXX ++ tristate "Qualcomm Atheros AR8XXX Ethernet switch family support" ++ depends on NET_DSA ++ ---help--- ++ This enables support for the Qualcomm Atheros AR8XXX Ethernet ++ switch chips. ++ + endmenu +diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile +index e2d51c4..7647687 100644 +--- a/drivers/net/dsa/Makefile ++++ b/drivers/net/dsa/Makefile +@@ -14,3 +14,4 @@ ifdef CONFIG_NET_DSA_MV88E6171 + mv88e6xxx_drv-y += mv88e6171.o + endif + obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm_sf2.o ++obj-$(CONFIG_NET_DSA_AR8XXX) += ar8xxx.o +diff --git a/drivers/net/dsa/ar8xxx.c b/drivers/net/dsa/ar8xxx.c +new file mode 100644 +index 0000000..4ce3ffc +--- /dev/null ++++ b/drivers/net/dsa/ar8xxx.c +@@ -0,0 +1,303 @@ ++/* ++ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/module.h> ++#include <linux/phy.h> ++#include <linux/netdevice.h> ++#include <net/dsa.h> ++#include <linux/phy.h> ++#include <linux/of_net.h> ++ ++#include "ar8xxx.h" ++ ++u32 ++ar8xxx_mii_read32(struct mii_bus *bus, int phy_id, int regnum) ++{ ++ u16 lo, hi; ++ ++ lo = bus->read(bus, phy_id, regnum); ++ hi = bus->read(bus, phy_id, regnum + 1); ++ ++ return (hi << 16) | lo; ++} ++ ++void ++ar8xxx_mii_write32(struct mii_bus *bus, int phy_id, int regnum, u32 val) ++{ ++ u16 lo, hi; ++ ++ lo = val & 0xffff; ++ hi = (u16)(val >> 16); ++ ++ bus->write(bus, phy_id, regnum, lo); ++ bus->write(bus, phy_id, regnum + 1, hi); ++} ++ ++u32 ar8xxx_read(struct dsa_switch *ds, int reg) ++{ ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); ++ u16 r1, r2, page; ++ u32 val; ++ ++ split_addr((u32)reg, &r1, &r2, &page); ++ ++ mutex_lock(&bus->mdio_lock); ++ ++ bus->write(bus, 0x18, 0, page); ++ wait_for_page_switch(); ++ val = ar8xxx_mii_read32(bus, 0x10 | r2, r1); ++ ++ mutex_unlock(&bus->mdio_lock); ++ ++ return val; ++} ++ ++void ar8xxx_write(struct dsa_switch *ds, int reg, u32 val) ++{ ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); ++ u16 r1, r2, page; ++ ++ split_addr((u32)reg, &r1, &r2, &page); ++ ++ mutex_lock(&bus->mdio_lock); ++ ++ bus->write(bus, 0x18, 0, page); ++ wait_for_page_switch(); ++ ar8xxx_mii_write32(bus, 0x10 | r2, r1, val); ++ ++ mutex_unlock(&bus->mdio_lock); ++} ++ ++u32 ++ar8xxx_rmw(struct dsa_switch *ds, int reg, u32 mask, u32 val) ++{ ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); ++ u16 r1, r2, page; ++ u32 ret; ++ ++ split_addr((u32)reg, &r1, &r2, &page); ++ ++ mutex_lock(&bus->mdio_lock); ++ ++ bus->write(bus, 0x18, 0, page); ++ wait_for_page_switch(); ++ ++ ret = ar8xxx_mii_read32(bus, 0x10 | r2, r1); ++ ret &= ~mask; ++ ret |= val; ++ ar8xxx_mii_write32(bus, 0x10 | r2, r1, ret); ++ ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static char *ar8xxx_probe(struct device *host_dev, int sw_addr) ++{ ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); ++ u32 phy_id; ++ ++ if (!bus) ++ return NULL; ++ ++ /* sw_addr is irrelevant as the switch occupies the MDIO bus from ++ * addresses 0 to 4 (PHYs) and 16-23 (for MDIO 32bits protocol). So ++ * we'll probe address 0 to see if we see the right switch family. ++ */ ++ phy_id = mdiobus_read(bus, 0, MII_PHYSID1) << 16; ++ phy_id |= mdiobus_read(bus, 0, MII_PHYSID2); ++ ++ switch (phy_id) { ++ case PHY_ID_QCA8337: ++ return "QCA8337"; ++ default: ++ return NULL; ++ } ++} ++ ++static int ar8xxx_set_pad_ctrl(struct dsa_switch *ds, int port, int mode) ++{ ++ int reg; ++ ++ switch (port) { ++ case 0: ++ reg = AR8327_REG_PORT0_PAD_CTRL; ++ break; ++ case 6: ++ reg = AR8327_REG_PORT6_PAD_CTRL; ++ break; ++ default: ++ pr_err("Can't set PAD_CTRL on port %d\n", port); ++ return -EINVAL; ++ } ++ ++ /* DSA only supports 1 CPU port for now, so we'll take the assumption ++ * that P0 is connected to the CPU master_dev. ++ */ ++ switch (mode) { ++ case PHY_INTERFACE_MODE_RGMII: ++ ar8xxx_write(ds, reg, ++ AR8327_PORT_PAD_RGMII_EN | ++ AR8327_PORT_PAD_RGMII_TX_DELAY(3) | ++ AR8327_PORT_PAD_RGMII_RX_DELAY(3)); ++ ++ /* According to the datasheet, RGMII delay is enabled through ++ * PORT5_PAD_CTRL for all ports, rather than individual port ++ * registers ++ */ ++ ar8xxx_write(ds, AR8327_REG_PORT5_PAD_CTRL, ++ AR8327_PORT_PAD_RGMII_RX_DELAY_EN); ++ break; ++ default: ++ pr_err("xMII mode %d not supported\n", mode); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ar8xxx_setup(struct dsa_switch *ds) ++{ ++ struct net_device *netdev = ds->dst->pd->of_netdev; ++ int ret, i, phy_mode; ++ ++ /* Initialize CPU port pad mode (xMII type, delays...) */ ++ phy_mode = of_get_phy_mode(netdev->dev.parent->of_node); ++ if (phy_mode < 0) { ++ pr_err("Can't find phy-mode for master device\n"); ++ return phy_mode; ++ } ++ ++ ret = ar8xxx_set_pad_ctrl(ds, 0, phy_mode); ++ if (ret < 0) ++ return ret; ++ ++ /* Disable forwarding by default on all ports */ ++ for (i = 0; i < AR8327_NUM_PORTS; i++) ++ ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(i), ++ AR8327_PORT_LOOKUP_MEMBER, 0); ++ ++ /* Setup connection between CPU ports & PHYs */ ++ for (i = 0; i < DSA_MAX_PORTS; i++) { ++ /* CPU port gets connected to all PHYs in the switch */ ++ if (dsa_is_cpu_port(ds, i)) { ++ ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(0), ++ AR8327_PORT_LOOKUP_MEMBER, ++ ds->phys_port_mask << 1); ++ } ++ ++ /* Invividual PHYs gets connected to CPU port only */ ++ if (ds->phys_port_mask & BIT(i)) { ++ ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(phy_to_port(i)), ++ AR8327_PORT_LOOKUP_MEMBER, BIT(0)); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ar8xxx_set_addr(struct dsa_switch *ds, u8 *addr) ++{ ++ return 0; ++} ++ ++static int ar8xxx_phy_read(struct dsa_switch *ds, int phy, int regnum) ++{ ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); ++ ++ return mdiobus_read(bus, phy, regnum); ++} ++ ++static int ++ar8xxx_phy_write(struct dsa_switch *ds, int phy, int regnum, u16 val) ++{ ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); ++ ++ return mdiobus_write(bus, phy, regnum, val); ++} ++ ++static void ar8xxx_poll_link(struct dsa_switch *ds) ++{ ++ int i = 0; ++ struct net_device *dev; ++ ++ while ((dev = ds->ports[i++]) != NULL) { ++ u32 status; ++ int link; ++ int speed; ++ int duplex; ++ ++ status = ar8xxx_read(ds, AR8327_REG_PORT_STATUS(i)); ++ link = !!(status & AR8XXX_PORT_STATUS_LINK_UP); ++ duplex = !!(status & AR8XXX_PORT_STATUS_DUPLEX); ++ ++ switch (status & AR8XXX_PORT_STATUS_SPEED) { ++ case AR8XXX_PORT_SPEED_10M: ++ speed = 10; ++ break; ++ case AR8XXX_PORT_SPEED_100M: ++ speed = 100; ++ break; ++ case AR8XXX_PORT_SPEED_1000M: ++ speed = 1000; ++ break; ++ default: ++ speed = 0; ++ } ++ ++ if (!link) { ++ /* This poll happens every ~1s, so we don't want to ++ * print the status every time. Only when the device ++ * transitions from Link UP to Link DOWN ++ */ ++ if (netif_carrier_ok(dev)) ++ netif_carrier_off(dev); ++ continue; ++ } else { ++ /* Same thing here. But we detect a Link UP event */ ++ if (!netif_carrier_ok(dev)) ++ netif_carrier_on(dev); ++ continue; ++ } ++ } ++} ++ ++static struct dsa_switch_driver ar8xxx_switch_driver = { ++ .tag_protocol = DSA_TAG_PROTO_NONE, ++ .probe = ar8xxx_probe, ++ .setup = ar8xxx_setup, ++ .set_addr = ar8xxx_set_addr, ++ .poll_link = ar8xxx_poll_link, ++ .phy_read = ar8xxx_phy_read, ++ .phy_write = ar8xxx_phy_write, ++}; ++ ++static int __init ar8xxx_init(void) ++{ ++ register_switch_driver(&ar8xxx_switch_driver); ++ return 0; ++} ++module_init(ar8xxx_init); ++ ++static void __exit ar8xxx_cleanup(void) ++{ ++ unregister_switch_driver(&ar8xxx_switch_driver); ++} ++module_exit(ar8xxx_cleanup); ++ ++MODULE_AUTHOR("Mathieu Olivari <mathieu@codeaurora.org>"); ++MODULE_DESCRIPTION("Driver for AR8XXX ethernet switch family"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:ar8xxx"); +diff --git a/drivers/net/dsa/ar8xxx.h b/drivers/net/dsa/ar8xxx.h +new file mode 100644 +index 0000000..a29b6d3 +--- /dev/null ++++ b/drivers/net/dsa/ar8xxx.h +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __AR8XXX_H ++#define __AR8XXX_H ++ ++#include <linux/delay.h> ++ ++#define AR8327_NUM_PORTS 7 ++ ++#define PHY_ID_QCA8337 0x004dd036 ++ ++#define AR8327_REG_PORT0_PAD_CTRL 0x004 ++#define AR8327_REG_PORT5_PAD_CTRL 0x008 ++#define AR8327_REG_PORT6_PAD_CTRL 0x00c ++#define AR8327_PORT_PAD_RGMII_EN BIT(26) ++#define AR8327_PORT_PAD_RGMII_TX_DELAY(x) ((0x8 + (x & 0x3)) << 22) ++#define AR8327_PORT_PAD_RGMII_RX_DELAY(x) ((0x10 + (x & 0x3)) << 20) ++#define AR8327_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) ++#define AR8327_PORT_PAD_SGMII_EN BIT(7) ++ ++#define AR8327_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) ++#define AR8XXX_PORT_STATUS_SPEED GENMASK(2, 0) ++#define AR8XXX_PORT_STATUS_SPEED_S 0 ++#define AR8XXX_PORT_STATUS_TXMAC BIT(2) ++#define AR8XXX_PORT_STATUS_RXMAC BIT(3) ++#define AR8XXX_PORT_STATUS_TXFLOW BIT(4) ++#define AR8XXX_PORT_STATUS_RXFLOW BIT(5) ++#define AR8XXX_PORT_STATUS_DUPLEX BIT(6) ++#define AR8XXX_PORT_STATUS_LINK_UP BIT(8) ++#define AR8XXX_PORT_STATUS_LINK_AUTO BIT(9) ++#define AR8XXX_PORT_STATUS_LINK_PAUSE BIT(10) ++ ++#define AR8327_PORT_LOOKUP_CTRL(_i) (0x660 + (_i) * 0xc) ++#define AR8327_PORT_LOOKUP_MEMBER GENMASK(6, 0) ++#define AR8327_PORT_LOOKUP_IN_MODE GENMASK(9, 8) ++#define AR8327_PORT_LOOKUP_IN_MODE_S 8 ++#define AR8327_PORT_LOOKUP_STATE GENMASK(18, 16) ++#define AR8327_PORT_LOOKUP_STATE_S 16 ++#define AR8327_PORT_LOOKUP_LEARN BIT(20) ++#define AR8327_PORT_LOOKUP_ING_MIRROR_EN BIT(25) ++ ++/* port speed */ ++enum { ++ AR8XXX_PORT_SPEED_10M = 0, ++ AR8XXX_PORT_SPEED_100M = 1, ++ AR8XXX_PORT_SPEED_1000M = 2, ++ AR8XXX_PORT_SPEED_ERR = 3, ++}; ++ ++static inline void ++split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) ++{ ++ regaddr >>= 1; ++ *r1 = regaddr & 0x1e; ++ ++ regaddr >>= 5; ++ *r2 = regaddr & 0x7; ++ ++ regaddr >>= 3; ++ *page = regaddr & 0x1ff; ++} ++ ++static inline void ++wait_for_page_switch(void) ++{ ++ udelay(5); ++} ++ ++#endif /* __AR8XXX_H */ +diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c +index e6f6cc3..fffb9aa 100644 +--- a/net/dsa/dsa.c ++++ b/net/dsa/dsa.c +@@ -893,6 +893,7 @@ static SIMPLE_DEV_PM_OPS(dsa_pm_ops, dsa_suspend, dsa_resume); + + static const struct of_device_id dsa_of_match_table[] = { + { .compatible = "brcm,bcm7445-switch-v4.0" }, ++ { .compatible = "qca,ar8xxx", }, + { .compatible = "marvell,dsa", }, + {} + }; + +From patchwork Fri May 29 01:42:17 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [2/7] net: dsa: ar8xxx: add ethtool hw statistics support +From: Mathieu Olivari <mathieu@codeaurora.org> +X-Patchwork-Id: 477524 +X-Patchwork-Delegate: davem@davemloft.net +Message-Id: <1432863742-18427-3-git-send-email-mathieu@codeaurora.org> +To: robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, + ijc+devicetree@hellion.org.uk, galak@codeaurora.org, + davem@davemloft.net, mathieu@codeaurora.org, andrew@lunn.ch, + f.fainelli@gmail.com, linux@roeck-us.net, gang.chen.5i5j@gmail.com, + jiri@resnulli.us, leitec@staticky.com, fabf@skynet.be, + alexander.h.duyck@intel.com, pavel.nakonechny@skitlab.ru, + joe@perches.com, sfeldma@gmail.com, nbd@openwrt.org, juhosg@openwrt.org +Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Date: Thu, 28 May 2015 18:42:17 -0700 + +MIB counters can now be reported through each switch port by using +"ethtool -S". + +Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +--- + drivers/net/dsa/ar8xxx.c | 106 +++++++++++++++++++++++++++++++++++++++++++---- + drivers/net/dsa/ar8xxx.h | 47 +++++++++++++++++++++ + 2 files changed, 146 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/dsa/ar8xxx.c b/drivers/net/dsa/ar8xxx.c +index 4ce3ffc..2f0fa4d 100644 +--- a/drivers/net/dsa/ar8xxx.c ++++ b/drivers/net/dsa/ar8xxx.c +@@ -22,6 +22,55 @@ + + #include "ar8xxx.h" + ++#define MIB_DESC(_s, _o, _n) \ ++ { \ ++ .size = (_s), \ ++ .offset = (_o), \ ++ .name = (_n), \ ++ } ++ ++static const struct ar8xxx_mib_desc ar8327_mib[] = { ++ MIB_DESC(1, 0x00, "RxBroad"), ++ MIB_DESC(1, 0x04, "RxPause"), ++ MIB_DESC(1, 0x08, "RxMulti"), ++ MIB_DESC(1, 0x0c, "RxFcsErr"), ++ MIB_DESC(1, 0x10, "RxAlignErr"), ++ MIB_DESC(1, 0x14, "RxRunt"), ++ MIB_DESC(1, 0x18, "RxFragment"), ++ MIB_DESC(1, 0x1c, "Rx64Byte"), ++ MIB_DESC(1, 0x20, "Rx128Byte"), ++ MIB_DESC(1, 0x24, "Rx256Byte"), ++ MIB_DESC(1, 0x28, "Rx512Byte"), ++ MIB_DESC(1, 0x2c, "Rx1024Byte"), ++ MIB_DESC(1, 0x30, "Rx1518Byte"), ++ MIB_DESC(1, 0x34, "RxMaxByte"), ++ MIB_DESC(1, 0x38, "RxTooLong"), ++ MIB_DESC(2, 0x3c, "RxGoodByte"), ++ MIB_DESC(2, 0x44, "RxBadByte"), ++ MIB_DESC(1, 0x4c, "RxOverFlow"), ++ MIB_DESC(1, 0x50, "Filtered"), ++ MIB_DESC(1, 0x54, "TxBroad"), ++ MIB_DESC(1, 0x58, "TxPause"), ++ MIB_DESC(1, 0x5c, "TxMulti"), ++ MIB_DESC(1, 0x60, "TxUnderRun"), ++ MIB_DESC(1, 0x64, "Tx64Byte"), ++ MIB_DESC(1, 0x68, "Tx128Byte"), ++ MIB_DESC(1, 0x6c, "Tx256Byte"), ++ MIB_DESC(1, 0x70, "Tx512Byte"), ++ MIB_DESC(1, 0x74, "Tx1024Byte"), ++ MIB_DESC(1, 0x78, "Tx1518Byte"), ++ MIB_DESC(1, 0x7c, "TxMaxByte"), ++ MIB_DESC(1, 0x80, "TxOverSize"), ++ MIB_DESC(2, 0x84, "TxByte"), ++ MIB_DESC(1, 0x8c, "TxCollision"), ++ MIB_DESC(1, 0x90, "TxAbortCol"), ++ MIB_DESC(1, 0x94, "TxMultiCol"), ++ MIB_DESC(1, 0x98, "TxSingleCol"), ++ MIB_DESC(1, 0x9c, "TxExcDefer"), ++ MIB_DESC(1, 0xa0, "TxDefer"), ++ MIB_DESC(1, 0xa4, "TxLateCol"), ++}; ++ + u32 + ar8xxx_mii_read32(struct mii_bus *bus, int phy_id, int regnum) + { +@@ -184,6 +233,10 @@ static int ar8xxx_setup(struct dsa_switch *ds) + if (ret < 0) + return ret; + ++ /* Enable MIB counters */ ++ ar8xxx_reg_set(ds, AR8327_REG_MIB, AR8327_MIB_CPU_KEEP); ++ ar8xxx_write(ds, AR8327_REG_MODULE_EN, AR8327_MODULE_EN_MIB); ++ + /* Disable forwarding by default on all ports */ + for (i = 0; i < AR8327_NUM_PORTS; i++) + ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(i), +@@ -228,6 +281,42 @@ ar8xxx_phy_write(struct dsa_switch *ds, int phy, int regnum, u16 val) + return mdiobus_write(bus, phy, regnum, val); + } + ++static void ar8xxx_get_strings(struct dsa_switch *ds, int phy, uint8_t *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { ++ strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name, ++ ETH_GSTRING_LEN); ++ } ++} ++ ++static void ar8xxx_get_ethtool_stats(struct dsa_switch *ds, int phy, ++ uint64_t *data) ++{ ++ const struct ar8xxx_mib_desc *mib; ++ uint32_t reg, i, port; ++ u64 hi; ++ ++ port = phy_to_port(phy); ++ ++ for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { ++ mib = &ar8327_mib[i]; ++ reg = AR8327_PORT_MIB_COUNTER(port) + mib->offset; ++ ++ data[i] = ar8xxx_read(ds, reg); ++ if (mib->size == 2) { ++ hi = ar8xxx_read(ds, reg + 4); ++ data[i] |= hi << 32; ++ } ++ } ++} ++ ++static int ar8xxx_get_sset_count(struct dsa_switch *ds) ++{ ++ return ARRAY_SIZE(ar8327_mib); ++} ++ + static void ar8xxx_poll_link(struct dsa_switch *ds) + { + int i = 0; +@@ -275,13 +364,16 @@ static void ar8xxx_poll_link(struct dsa_switch *ds) + } + + static struct dsa_switch_driver ar8xxx_switch_driver = { +- .tag_protocol = DSA_TAG_PROTO_NONE, +- .probe = ar8xxx_probe, +- .setup = ar8xxx_setup, +- .set_addr = ar8xxx_set_addr, +- .poll_link = ar8xxx_poll_link, +- .phy_read = ar8xxx_phy_read, +- .phy_write = ar8xxx_phy_write, ++ .tag_protocol = DSA_TAG_PROTO_NONE, ++ .probe = ar8xxx_probe, ++ .setup = ar8xxx_setup, ++ .set_addr = ar8xxx_set_addr, ++ .poll_link = ar8xxx_poll_link, ++ .phy_read = ar8xxx_phy_read, ++ .phy_write = ar8xxx_phy_write, ++ .get_strings = ar8xxx_get_strings, ++ .get_ethtool_stats = ar8xxx_get_ethtool_stats, ++ .get_sset_count = ar8xxx_get_sset_count, + }; + + static int __init ar8xxx_init(void) +diff --git a/drivers/net/dsa/ar8xxx.h b/drivers/net/dsa/ar8xxx.h +index a29b6d3..7c7a125 100644 +--- a/drivers/net/dsa/ar8xxx.h ++++ b/drivers/net/dsa/ar8xxx.h +@@ -18,6 +18,12 @@ + + #include <linux/delay.h> + ++struct ar8xxx_mib_desc { ++ unsigned int size; ++ unsigned int offset; ++ const char *name; ++}; ++ + #define AR8327_NUM_PORTS 7 + + #define PHY_ID_QCA8337 0x004dd036 +@@ -31,6 +37,14 @@ + #define AR8327_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) + #define AR8327_PORT_PAD_SGMII_EN BIT(7) + ++#define AR8327_REG_MODULE_EN 0x030 ++#define AR8327_MODULE_EN_MIB BIT(0) ++#define AR8327_MODULE_EN_ACL BIT(1) ++#define AR8327_MODULE_EN_L3 BIT(2) ++ ++#define AR8327_REG_MIB 0x034 ++#define AR8327_MIB_CPU_KEEP BIT(20) ++ + #define AR8327_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) + #define AR8XXX_PORT_STATUS_SPEED GENMASK(2, 0) + #define AR8XXX_PORT_STATUS_SPEED_S 0 +@@ -52,6 +66,8 @@ + #define AR8327_PORT_LOOKUP_LEARN BIT(20) + #define AR8327_PORT_LOOKUP_ING_MIRROR_EN BIT(25) + ++#define AR8327_PORT_MIB_COUNTER(_i) (0x1000 + (_i) * 0x100) ++ + /* port speed */ + enum { + AR8XXX_PORT_SPEED_10M = 0, +@@ -60,6 +76,25 @@ enum { + AR8XXX_PORT_SPEED_ERR = 3, + }; + ++static inline int port_to_phy(int port) ++{ ++ if (port >= 1 && port <= 6) ++ return port - 1; ++ ++ return -1; ++} ++ ++static inline int phy_to_port(int phy) ++{ ++ if (phy < 5) ++ return phy + 1; ++ ++ return -1; ++} ++ ++u32 ++ar8xxx_rmw(struct dsa_switch *ds, int reg, u32 mask, u32 val); ++ + static inline void + split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) + { +@@ -79,4 +114,16 @@ wait_for_page_switch(void) + udelay(5); + } + ++static inline void ++ar8xxx_reg_set(struct dsa_switch *ds, int reg, u32 val) ++{ ++ ar8xxx_rmw(ds, reg, 0, val); ++} ++ ++static inline void ++ar8xxx_reg_clear(struct dsa_switch *ds, int reg, u32 val) ++{ ++ ar8xxx_rmw(ds, reg, val, 0); ++} ++ + #endif /* __AR8XXX_H */ + +From patchwork Fri May 29 01:42:18 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [3/7] net: dsa: ar8xxx: add regmap support +From: Mathieu Olivari <mathieu@codeaurora.org> +X-Patchwork-Id: 477522 +X-Patchwork-Delegate: davem@davemloft.net +Message-Id: <1432863742-18427-4-git-send-email-mathieu@codeaurora.org> +To: robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, + ijc+devicetree@hellion.org.uk, galak@codeaurora.org, + davem@davemloft.net, mathieu@codeaurora.org, andrew@lunn.ch, + f.fainelli@gmail.com, linux@roeck-us.net, gang.chen.5i5j@gmail.com, + jiri@resnulli.us, leitec@staticky.com, fabf@skynet.be, + alexander.h.duyck@intel.com, pavel.nakonechny@skitlab.ru, + joe@perches.com, sfeldma@gmail.com, nbd@openwrt.org, juhosg@openwrt.org +Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Date: Thu, 28 May 2015 18:42:18 -0700 + +All switch registers can now be dumped using regmap/debugfs. + +\# cat /sys/kernel/debug/regmap/<mdiobus>/registers +0000: 00001302 +0004: ... +... + +Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +--- + drivers/net/dsa/Kconfig | 1 + + drivers/net/dsa/ar8xxx.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/ar8xxx.h | 5 ++++ + 3 files changed, 66 insertions(+) + +diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig +index 2aae541..17fb296 100644 +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -68,6 +68,7 @@ config NET_DSA_BCM_SF2 + config NET_DSA_AR8XXX + tristate "Qualcomm Atheros AR8XXX Ethernet switch family support" + depends on NET_DSA ++ select REGMAP + ---help--- + This enables support for the Qualcomm Atheros AR8XXX Ethernet + switch chips. +diff --git a/drivers/net/dsa/ar8xxx.c b/drivers/net/dsa/ar8xxx.c +index 2f0fa4d..327abd4 100644 +--- a/drivers/net/dsa/ar8xxx.c ++++ b/drivers/net/dsa/ar8xxx.c +@@ -176,6 +176,57 @@ static char *ar8xxx_probe(struct device *host_dev, int sw_addr) + } + } + ++static int ar8xxx_regmap_read(void *ctx, uint32_t reg, uint32_t *val) ++{ ++ struct dsa_switch *ds = (struct dsa_switch *)ctx; ++ ++ *val = ar8xxx_read(ds, reg); ++ ++ return 0; ++} ++ ++static int ar8xxx_regmap_write(void *ctx, uint32_t reg, uint32_t val) ++{ ++ struct dsa_switch *ds = (struct dsa_switch *)ctx; ++ ++ ar8xxx_write(ds, reg, val); ++ ++ return 0; ++} ++ ++static const struct regmap_range ar8xxx_readable_ranges[] = { ++ regmap_reg_range(0x0000, 0x00e4), /* Global control */ ++ regmap_reg_range(0x0100, 0x0168), /* EEE control */ ++ regmap_reg_range(0x0200, 0x0270), /* Parser control */ ++ regmap_reg_range(0x0400, 0x0454), /* ACL */ ++ regmap_reg_range(0x0600, 0x0718), /* Lookup */ ++ regmap_reg_range(0x0800, 0x0b70), /* QM */ ++ regmap_reg_range(0x0C00, 0x0c80), /* PKT */ ++ regmap_reg_range(0x1000, 0x10ac), /* MIB - Port0 */ ++ regmap_reg_range(0x1100, 0x11ac), /* MIB - Port1 */ ++ regmap_reg_range(0x1200, 0x12ac), /* MIB - Port2 */ ++ regmap_reg_range(0x1300, 0x13ac), /* MIB - Port3 */ ++ regmap_reg_range(0x1400, 0x14ac), /* MIB - Port4 */ ++ regmap_reg_range(0x1500, 0x15ac), /* MIB - Port5 */ ++ regmap_reg_range(0x1600, 0x16ac), /* MIB - Port6 */ ++ ++}; ++ ++static struct regmap_access_table ar8xxx_readable_table = { ++ .yes_ranges = ar8xxx_readable_ranges, ++ .n_yes_ranges = ARRAY_SIZE(ar8xxx_readable_ranges), ++}; ++ ++struct regmap_config ar8xxx_regmap_config = { ++ .reg_bits = 16, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = 0x16ac, /* end MIB - Port6 range */ ++ .reg_read = ar8xxx_regmap_read, ++ .reg_write = ar8xxx_regmap_write, ++ .rd_table = &ar8xxx_readable_table, ++}; ++ + static int ar8xxx_set_pad_ctrl(struct dsa_switch *ds, int port, int mode) + { + int reg; +@@ -219,9 +270,17 @@ static int ar8xxx_set_pad_ctrl(struct dsa_switch *ds, int port, int mode) + + static int ar8xxx_setup(struct dsa_switch *ds) + { ++ struct ar8xxx_priv *priv = ds_to_priv(ds); + struct net_device *netdev = ds->dst->pd->of_netdev; + int ret, i, phy_mode; + ++ /* Start by setting up the register mapping */ ++ priv->regmap = devm_regmap_init(ds->master_dev, NULL, ds, ++ &ar8xxx_regmap_config); ++ ++ if (IS_ERR(priv->regmap)) ++ pr_warn("regmap initialization failed"); ++ + /* Initialize CPU port pad mode (xMII type, delays...) */ + phy_mode = of_get_phy_mode(netdev->dev.parent->of_node); + if (phy_mode < 0) { +@@ -365,6 +424,7 @@ static void ar8xxx_poll_link(struct dsa_switch *ds) + + static struct dsa_switch_driver ar8xxx_switch_driver = { + .tag_protocol = DSA_TAG_PROTO_NONE, ++ .priv_size = sizeof(struct ar8xxx_priv), + .probe = ar8xxx_probe, + .setup = ar8xxx_setup, + .set_addr = ar8xxx_set_addr, +diff --git a/drivers/net/dsa/ar8xxx.h b/drivers/net/dsa/ar8xxx.h +index 7c7a125..98cc7ed 100644 +--- a/drivers/net/dsa/ar8xxx.h ++++ b/drivers/net/dsa/ar8xxx.h +@@ -17,6 +17,11 @@ + #define __AR8XXX_H + + #include <linux/delay.h> ++#include <linux/regmap.h> ++ ++struct ar8xxx_priv { ++ struct regmap *regmap; ++}; + + struct ar8xxx_mib_desc { + unsigned int size; + +From patchwork Fri May 29 01:42:19 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [4/7] net: dsa: add QCA tag support +From: Mathieu Olivari <mathieu@codeaurora.org> +X-Patchwork-Id: 477521 +X-Patchwork-Delegate: davem@davemloft.net +Message-Id: <1432863742-18427-5-git-send-email-mathieu@codeaurora.org> +To: robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, + ijc+devicetree@hellion.org.uk, galak@codeaurora.org, + davem@davemloft.net, mathieu@codeaurora.org, andrew@lunn.ch, + f.fainelli@gmail.com, linux@roeck-us.net, gang.chen.5i5j@gmail.com, + jiri@resnulli.us, leitec@staticky.com, fabf@skynet.be, + alexander.h.duyck@intel.com, pavel.nakonechny@skitlab.ru, + joe@perches.com, sfeldma@gmail.com, nbd@openwrt.org, juhosg@openwrt.org +Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Date: Thu, 28 May 2015 18:42:19 -0700 + +QCA tags are used on QCA ar8xxx switch family. This change adds support +for encap/decap using 2 bytes header mode. + +Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +--- + include/net/dsa.h | 1 + + net/dsa/Kconfig | 3 + + net/dsa/Makefile | 1 + + net/dsa/dsa.c | 5 ++ + net/dsa/dsa_priv.h | 2 + + net/dsa/slave.c | 5 ++ + net/dsa/tag_qca.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 7 files changed, 175 insertions(+) + create mode 100644 net/dsa/tag_qca.c + +diff --git a/include/net/dsa.h b/include/net/dsa.h +index fbca63b..64ddf6f 100644 +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -26,6 +26,7 @@ enum dsa_tag_protocol { + DSA_TAG_PROTO_TRAILER, + DSA_TAG_PROTO_EDSA, + DSA_TAG_PROTO_BRCM, ++ DSA_TAG_PROTO_QCA, + }; + + #define DSA_MAX_SWITCHES 4 +diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig +index ff7736f..4f3cce1 100644 +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -26,6 +26,9 @@ config NET_DSA_HWMON + via the hwmon sysfs interface and exposes the onboard sensors. + + # tagging formats ++config NET_DSA_TAG_QCA ++ bool ++ + config NET_DSA_TAG_BRCM + bool + +diff --git a/net/dsa/Makefile b/net/dsa/Makefile +index da06ed1..9feb86c 100644 +--- a/net/dsa/Makefile ++++ b/net/dsa/Makefile +@@ -3,6 +3,7 @@ obj-$(CONFIG_NET_DSA) += dsa_core.o + dsa_core-y += dsa.o slave.o + + # tagging formats ++dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o + dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o + dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o + dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o +diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c +index fffb9aa..6010a7d 100644 +--- a/net/dsa/dsa.c ++++ b/net/dsa/dsa.c +@@ -249,6 +249,11 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) + dst->rcv = brcm_netdev_ops.rcv; + break; + #endif ++#ifdef CONFIG_NET_DSA_TAG_QCA ++ case DSA_TAG_PROTO_QCA: ++ dst->rcv = qca_netdev_ops.rcv; ++ break; ++#endif + case DSA_TAG_PROTO_NONE: + break; + default: +diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h +index d5f1f9b..350c94b 100644 +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -74,5 +74,7 @@ extern const struct dsa_device_ops trailer_netdev_ops; + /* tag_brcm.c */ + extern const struct dsa_device_ops brcm_netdev_ops; + ++/* tag_qca.c */ ++extern const struct dsa_device_ops qca_netdev_ops; + + #endif +diff --git a/net/dsa/slave.c b/net/dsa/slave.c +index 04ffad3..cd8f552 100644 +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -925,6 +925,11 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, + p->xmit = brcm_netdev_ops.xmit; + break; + #endif ++#ifdef CONFIG_NET_DSA_TAG_QCA ++ case DSA_TAG_PROTO_QCA: ++ p->xmit = qca_netdev_ops.xmit; ++ break; ++#endif + default: + p->xmit = dsa_slave_notag_xmit; + break; +diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c +new file mode 100644 +index 0000000..8f02196 +--- /dev/null ++++ b/net/dsa/tag_qca.c +@@ -0,0 +1,158 @@ ++/* ++ * Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/etherdevice.h> ++#include "dsa_priv.h" ++ ++#define QCA_HDR_LEN 2 ++#define QCA_HDR_VERSION 0x2 ++ ++#define QCA_HDR_RECV_VERSION_MASK GENMASK(15, 14) ++#define QCA_HDR_RECV_VERSION_S 14 ++#define QCA_HDR_RECV_PRIORITY_MASK GENMASK(13, 11) ++#define QCA_HDR_RECV_PRIORITY_S 11 ++#define QCA_HDR_RECV_TYPE_MASK GENMASK(10, 6) ++#define QCA_HDR_RECV_TYPE_S 6 ++#define QCA_HDR_RECV_FRAME_IS_TAGGED BIT(3) ++#define QCA_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0) ++ ++#define QCA_HDR_XMIT_VERSION_MASK GENMASK(15, 14) ++#define QCA_HDR_XMIT_VERSION_S 14 ++#define QCA_HDR_XMIT_PRIORITY_MASK GENMASK(13, 11) ++#define QCA_HDR_XMIT_PRIORITY_S 11 ++#define QCA_HDR_XMIT_CONTROL_MASK GENMASK(10, 8) ++#define QCA_HDR_XMIT_CONTROL_S 8 ++#define QCA_HDR_XMIT_FROM_CPU BIT(7) ++#define QCA_HDR_XMIT_DP_BIT_MASK GENMASK(6, 0) ++ ++static inline int reg_to_port(int reg) ++{ ++ if (reg < 5) ++ return reg + 1; ++ ++ return -1; ++} ++ ++static inline int port_to_reg(int port) ++{ ++ if (port >= 1 && port <= 6) ++ return port - 1; ++ ++ return -1; ++} ++ ++static netdev_tx_t qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct dsa_slave_priv *p = netdev_priv(dev); ++ u16 *phdr, hdr; ++ ++ dev->stats.tx_packets++; ++ dev->stats.tx_bytes += skb->len; ++ ++ if (skb_cow_head(skb, 0) < 0) ++ goto out_free; ++ ++ skb_push(skb, QCA_HDR_LEN); ++ ++ memmove(skb->data, skb->data + QCA_HDR_LEN, 2 * ETH_ALEN); ++ phdr = (u16 *)(skb->data + 2 * ETH_ALEN); ++ ++ /* Set the version field, and set destination port information */ ++ hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S | ++ QCA_HDR_XMIT_FROM_CPU | ++ 1 << reg_to_port(p->port); ++ ++ *phdr = htons(hdr); ++ ++ skb->dev = p->parent->dst->master_netdev; ++ dev_queue_xmit(skb); ++ ++ return NETDEV_TX_OK; ++ ++out_free: ++ kfree_skb(skb); ++ return NETDEV_TX_OK; ++} ++ ++static int qca_tag_rcv(struct sk_buff *skb, struct net_device *dev, ++ struct packet_type *pt, struct net_device *orig_dev) ++{ ++ struct dsa_switch_tree *dst = dev->dsa_ptr; ++ struct dsa_switch *ds; ++ u8 ver; ++ int port, phy; ++ __be16 *phdr, hdr; ++ ++ if (unlikely(!dst)) ++ goto out_drop; ++ ++ skb = skb_unshare(skb, GFP_ATOMIC); ++ if (!skb) ++ goto out; ++ ++ if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN))) ++ goto out_drop; ++ ++ /* Ethernet is added by the switch between src addr and Ethertype ++ * At this point, skb->data points to ethertype so header should be ++ * right before ++ */ ++ phdr = (__be16 *)(skb->data - 2); ++ hdr = ntohs(*phdr); ++ ++ /* Make sure the version is correct */ ++ ver = (hdr & QCA_HDR_RECV_VERSION_MASK) >> QCA_HDR_RECV_VERSION_S; ++ if (unlikely(ver != QCA_HDR_VERSION)) ++ goto out_drop; ++ ++ /* Remove QCA tag and recalculate checksum */ ++ skb_pull_rcsum(skb, QCA_HDR_LEN); ++ memmove(skb->data - ETH_HLEN, skb->data - ETH_HLEN - QCA_HDR_LEN, ++ ETH_HLEN - QCA_HDR_LEN); ++ ++ /* This protocol doesn't support cascading multiple switches so it's ++ * safe to assume the switch is first in the tree ++ */ ++ ds = dst->ds[0]; ++ if (!ds) ++ goto out_drop; ++ ++ /* Get source port information */ ++ port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK); ++ phy = port_to_reg(port); ++ if (unlikely(phy < 0) || !ds->ports[phy]) ++ goto out_drop; ++ ++ /* Update skb & forward the frame accordingly */ ++ skb_push(skb, ETH_HLEN); ++ skb->pkt_type = PACKET_HOST; ++ skb->dev = ds->ports[phy]; ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ ++ skb->dev->stats.rx_packets++; ++ skb->dev->stats.rx_bytes += skb->len; ++ ++ netif_receive_skb(skb); ++ ++ return 0; ++ ++out_drop: ++ kfree_skb(skb); ++out: ++ return 0; ++} ++ ++const struct dsa_device_ops qca_netdev_ops = { ++ .xmit = qca_tag_xmit, ++ .rcv = qca_tag_rcv, ++}; + +From patchwork Fri May 29 01:42:20 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [5/7] net: dsa: ar8xxx: enable QCA header support on AR8xxx +From: Mathieu Olivari <mathieu@codeaurora.org> +X-Patchwork-Id: 477527 +X-Patchwork-Delegate: davem@davemloft.net +Message-Id: <1432863742-18427-6-git-send-email-mathieu@codeaurora.org> +To: robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, + ijc+devicetree@hellion.org.uk, galak@codeaurora.org, + davem@davemloft.net, mathieu@codeaurora.org, andrew@lunn.ch, + f.fainelli@gmail.com, linux@roeck-us.net, gang.chen.5i5j@gmail.com, + jiri@resnulli.us, leitec@staticky.com, fabf@skynet.be, + alexander.h.duyck@intel.com, pavel.nakonechny@skitlab.ru, + joe@perches.com, sfeldma@gmail.com, nbd@openwrt.org, juhosg@openwrt.org +Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Date: Thu, 28 May 2015 18:42:20 -0700 + +This change enable support for the QCA headers in QCA83337 driver. +A 2 bytes header will be added by the switch on every incoming packet +to identify the ingress port, and the DSA tagging code will add a +similar 2 bytes header to control which port is used to send a +particular packet. + +Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +--- + drivers/net/dsa/Kconfig | 1 + + drivers/net/dsa/ar8xxx.c | 28 ++++++++++++++++++++++++++-- + drivers/net/dsa/ar8xxx.h | 22 ++++++++++++++++++++++ + 3 files changed, 49 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig +index 17fb296..fa8b484 100644 +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -68,6 +68,7 @@ config NET_DSA_BCM_SF2 + config NET_DSA_AR8XXX + tristate "Qualcomm Atheros AR8XXX Ethernet switch family support" + depends on NET_DSA ++ select NET_DSA_TAG_QCA + select REGMAP + ---help--- + This enables support for the Qualcomm Atheros AR8XXX Ethernet +diff --git a/drivers/net/dsa/ar8xxx.c b/drivers/net/dsa/ar8xxx.c +index 327abd4..4044614 100644 +--- a/drivers/net/dsa/ar8xxx.c ++++ b/drivers/net/dsa/ar8xxx.c +@@ -292,15 +292,31 @@ static int ar8xxx_setup(struct dsa_switch *ds) + if (ret < 0) + return ret; + ++ /* Enable CPU Port */ ++ ar8xxx_reg_set(ds, AR8327_REG_GLOBAL_FW_CTRL0, ++ AR8327_GLOBAL_FW_CTRL0_CPU_PORT_EN); ++ + /* Enable MIB counters */ + ar8xxx_reg_set(ds, AR8327_REG_MIB, AR8327_MIB_CPU_KEEP); + ar8xxx_write(ds, AR8327_REG_MODULE_EN, AR8327_MODULE_EN_MIB); + ++ /* Enable QCA header mode on Port 0 */ ++ ar8xxx_write(ds, AR8327_REG_PORT_HDR_CTRL(0), ++ AR8327_PORT_HDR_CTRL_ALL << AR8327_PORT_HDR_CTRL_TX_S | ++ AR8327_PORT_HDR_CTRL_ALL << AR8327_PORT_HDR_CTRL_RX_S); ++ + /* Disable forwarding by default on all ports */ + for (i = 0; i < AR8327_NUM_PORTS; i++) + ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(i), + AR8327_PORT_LOOKUP_MEMBER, 0); + ++ /* Forward all unknown frames to CPU port for Linux processing */ ++ ar8xxx_write(ds, AR8327_REG_GLOBAL_FW_CTRL1, ++ BIT(0) << AR8327_GLOBAL_FW_CTRL1_IGMP_DP_S | ++ BIT(0) << AR8327_GLOBAL_FW_CTRL1_BC_DP_S | ++ BIT(0) << AR8327_GLOBAL_FW_CTRL1_MC_DP_S | ++ BIT(0) << AR8327_GLOBAL_FW_CTRL1_UC_DP_S); ++ + /* Setup connection between CPU ports & PHYs */ + for (i = 0; i < DSA_MAX_PORTS; i++) { + /* CPU port gets connected to all PHYs in the switch */ +@@ -312,8 +328,16 @@ static int ar8xxx_setup(struct dsa_switch *ds) + + /* Invividual PHYs gets connected to CPU port only */ + if (ds->phys_port_mask & BIT(i)) { +- ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(phy_to_port(i)), ++ int phy = phy_to_port(i); ++ ++ ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(phy), + AR8327_PORT_LOOKUP_MEMBER, BIT(0)); ++ ++ /* Disable Auto-learning by default so the switch ++ * doesn't try to forward the frame to another port ++ */ ++ ar8xxx_reg_clear(ds, AR8327_PORT_LOOKUP_CTRL(phy), ++ AR8327_PORT_LOOKUP_LEARN); + } + } + +@@ -423,7 +447,7 @@ static void ar8xxx_poll_link(struct dsa_switch *ds) + } + + static struct dsa_switch_driver ar8xxx_switch_driver = { +- .tag_protocol = DSA_TAG_PROTO_NONE, ++ .tag_protocol = DSA_TAG_PROTO_QCA, + .priv_size = sizeof(struct ar8xxx_priv), + .probe = ar8xxx_probe, + .setup = ar8xxx_setup, +diff --git a/drivers/net/dsa/ar8xxx.h b/drivers/net/dsa/ar8xxx.h +index 98cc7ed..e68b92a 100644 +--- a/drivers/net/dsa/ar8xxx.h ++++ b/drivers/net/dsa/ar8xxx.h +@@ -62,6 +62,28 @@ struct ar8xxx_mib_desc { + #define AR8XXX_PORT_STATUS_LINK_AUTO BIT(9) + #define AR8XXX_PORT_STATUS_LINK_PAUSE BIT(10) + ++#define AR8327_REG_PORT_HDR_CTRL(_i) (0x9c + (_i * 4)) ++#define AR8327_PORT_HDR_CTRL_RX_MASK GENMASK(3, 2) ++#define AR8327_PORT_HDR_CTRL_RX_S 2 ++#define AR8327_PORT_HDR_CTRL_TX_MASK GENMASK(1, 0) ++#define AR8327_PORT_HDR_CTRL_TX_S 0 ++#define AR8327_PORT_HDR_CTRL_ALL 2 ++#define AR8327_PORT_HDR_CTRL_MGMT 1 ++#define AR8327_PORT_HDR_CTRL_NONE 0 ++ ++#define AR8327_REG_GLOBAL_FW_CTRL0 0x620 ++#define AR8327_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10) ++ ++#define AR8327_REG_GLOBAL_FW_CTRL1 0x624 ++#define AR8327_GLOBAL_FW_CTRL1_IGMP_DP_MASK GENMASK(30, 24) ++#define AR8327_GLOBAL_FW_CTRL1_IGMP_DP_S 24 ++#define AR8327_GLOBAL_FW_CTRL1_BC_DP_MASK GENMASK(22, 16) ++#define AR8327_GLOBAL_FW_CTRL1_BC_DP_S 16 ++#define AR8327_GLOBAL_FW_CTRL1_MC_DP_MASK GENMASK(14, 8) ++#define AR8327_GLOBAL_FW_CTRL1_MC_DP_S 8 ++#define AR8327_GLOBAL_FW_CTRL1_UC_DP_MASK GENMASK(6, 0) ++#define AR8327_GLOBAL_FW_CTRL1_UC_DP_S 0 ++ + #define AR8327_PORT_LOOKUP_CTRL(_i) (0x660 + (_i) * 0xc) + #define AR8327_PORT_LOOKUP_MEMBER GENMASK(6, 0) + #define AR8327_PORT_LOOKUP_IN_MODE GENMASK(9, 8) + +From patchwork Fri May 29 01:42:21 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [6/7] net: dsa: ar8xxx: add support for second xMII interfaces + through DT +From: Mathieu Olivari <mathieu@codeaurora.org> +X-Patchwork-Id: 477525 +X-Patchwork-Delegate: davem@davemloft.net +Message-Id: <1432863742-18427-7-git-send-email-mathieu@codeaurora.org> +To: robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, + ijc+devicetree@hellion.org.uk, galak@codeaurora.org, + davem@davemloft.net, mathieu@codeaurora.org, andrew@lunn.ch, + f.fainelli@gmail.com, linux@roeck-us.net, gang.chen.5i5j@gmail.com, + jiri@resnulli.us, leitec@staticky.com, fabf@skynet.be, + alexander.h.duyck@intel.com, pavel.nakonechny@skitlab.ru, + joe@perches.com, sfeldma@gmail.com, nbd@openwrt.org, juhosg@openwrt.org +Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Date: Thu, 28 May 2015 18:42:21 -0700 + +This patch is adding support for port6 specific options to device tree. +They can be used to setup the second xMII interface, and connect it to +one of the switch port. + +Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +--- + drivers/net/dsa/ar8xxx.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/drivers/net/dsa/ar8xxx.c b/drivers/net/dsa/ar8xxx.c +index 4044614..7559249 100644 +--- a/drivers/net/dsa/ar8xxx.c ++++ b/drivers/net/dsa/ar8xxx.c +@@ -19,6 +19,7 @@ + #include <net/dsa.h> + #include <linux/phy.h> + #include <linux/of_net.h> ++#include <linux/of_platform.h> + + #include "ar8xxx.h" + +@@ -260,6 +261,9 @@ static int ar8xxx_set_pad_ctrl(struct dsa_switch *ds, int port, int mode) + ar8xxx_write(ds, AR8327_REG_PORT5_PAD_CTRL, + AR8327_PORT_PAD_RGMII_RX_DELAY_EN); + break; ++ case PHY_INTERFACE_MODE_SGMII: ++ ar8xxx_write(ds, reg, AR8327_PORT_PAD_SGMII_EN); ++ break; + default: + pr_err("xMII mode %d not supported\n", mode); + return -EINVAL; +@@ -268,6 +272,48 @@ static int ar8xxx_set_pad_ctrl(struct dsa_switch *ds, int port, int mode) + return 0; + } + ++static int ar8xxx_of_setup(struct dsa_switch *ds) ++{ ++ struct device_node *dn = ds->pd->of_node; ++ const char *s_phymode; ++ int ret, mode; ++ u32 phy_id, ctrl; ++ ++ /* If port6-phy-mode property exists, configure it accordingly */ ++ if (!of_property_read_string(dn, "qca,port6-phy-mode", &s_phymode)) { ++ for (mode = 0; mode < PHY_INTERFACE_MODE_MAX; mode++) ++ if (!strcasecmp(s_phymode, phy_modes(mode))) ++ break; ++ ++ if (mode == PHY_INTERFACE_MODE_MAX) ++ pr_err("Unknown phy-mode: \"%s\"\n", s_phymode); ++ ++ ret = ar8xxx_set_pad_ctrl(ds, 6, mode); ++ if (ret < 0) ++ return ret; ++ } ++ ++ /* If a phy ID is specified for PORT6 mac, connect them together */ ++ if (!of_property_read_u32(dn, "qca,port6-phy-id", &phy_id)) { ++ ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(6), ++ AR8327_PORT_LOOKUP_MEMBER, BIT(phy_to_port(phy_id))); ++ ar8xxx_rmw(ds, AR8327_PORT_LOOKUP_CTRL(phy_to_port(phy_id)), ++ AR8327_PORT_LOOKUP_MEMBER, BIT(6)); ++ ++ /* We want the switch to be pass-through and act like a PHY on ++ * these ports. So BC/MC/UC & IGMP frames need to be accepted ++ */ ++ ctrl = BIT(phy_to_port(phy_id)) | BIT(6); ++ ar8xxx_reg_set(ds, AR8327_REG_GLOBAL_FW_CTRL1, ++ ctrl << AR8327_GLOBAL_FW_CTRL1_IGMP_DP_S | ++ ctrl << AR8327_GLOBAL_FW_CTRL1_BC_DP_S | ++ ctrl << AR8327_GLOBAL_FW_CTRL1_MC_DP_S | ++ ctrl << AR8327_GLOBAL_FW_CTRL1_UC_DP_S); ++ } ++ ++ return 0; ++} ++ + static int ar8xxx_setup(struct dsa_switch *ds) + { + struct ar8xxx_priv *priv = ds_to_priv(ds); +@@ -341,6 +387,10 @@ static int ar8xxx_setup(struct dsa_switch *ds) + } + } + ++ ret = ar8xxx_of_setup(ds); ++ if (ret < 0) ++ return ret; ++ + return 0; + } + + +From patchwork Fri May 29 01:42:22 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [7/7] Documentation: devicetree: add ar8xxx binding +From: Mathieu Olivari <mathieu@codeaurora.org> +X-Patchwork-Id: 477528 +X-Patchwork-Delegate: davem@davemloft.net +Message-Id: <1432863742-18427-8-git-send-email-mathieu@codeaurora.org> +To: robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, + ijc+devicetree@hellion.org.uk, galak@codeaurora.org, + davem@davemloft.net, mathieu@codeaurora.org, andrew@lunn.ch, + f.fainelli@gmail.com, linux@roeck-us.net, gang.chen.5i5j@gmail.com, + jiri@resnulli.us, leitec@staticky.com, fabf@skynet.be, + alexander.h.duyck@intel.com, pavel.nakonechny@skitlab.ru, + joe@perches.com, sfeldma@gmail.com, nbd@openwrt.org, juhosg@openwrt.org +Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Date: Thu, 28 May 2015 18:42:22 -0700 + +Add device-tree binding for ar8xxx switch families. + +Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> +--- + .../devicetree/bindings/net/dsa/qca-ar8xxx.txt | 70 ++++++++++++++++++++++ + 1 file changed, 70 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/dsa/qca-ar8xxx.txt + +diff --git a/Documentation/devicetree/bindings/net/dsa/qca-ar8xxx.txt b/Documentation/devicetree/bindings/net/dsa/qca-ar8xxx.txt +new file mode 100644 +index 0000000..f4fd3f1 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/dsa/qca-ar8xxx.txt +@@ -0,0 +1,70 @@ ++* Qualcomm Atheros AR8xxx switch family ++ ++Required properties: ++ ++- compatible: should be "qca,ar8xxx" ++- dsa,mii-bus: phandle to the MDIO bus controller, see dsa/dsa.txt ++- dsa,ethernet: phandle to the CPU network interface controller, see dsa/dsa.txt ++- #size-cells: must be 0 ++- #address-cells: must be 2, see dsa/dsa.txt ++ ++Subnodes: ++ ++The integrated switch subnode should be specified according to the binding ++described in dsa/dsa.txt. ++ ++Optional properties: ++ ++- qca,port6-phy-mode: if specified, the driver will configure Port 6 in the ++ given phy-mode. See Documentation/devicetree/bindings/net/ethernet.txt for ++ the list of valid phy-mode. ++ ++- qca,port6-phy-id: if specified, the driver will connect Port 6 to the PHY ++ given as a parameter. In this case, Port6 and the corresponding PHY will be ++ isolated from the rest of the switch. From a system perspective, they will ++ act as a regular PHY. ++ ++Example: ++ ++ dsa@0 { ++ compatible = "qca,ar8xxx"; ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ dsa,ethernet = <ðernet0>; ++ dsa,mii-bus = <&mii_bus0>; ++ ++ switch@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0 0>; /* MDIO address 0, switch 0 in tree */ ++ ++ qca,port6-phy-mode = "sgmii"; ++ qca,port6-phy-id = <4>; ++ ++ port@0 { ++ reg = <11>; ++ label = "cpu"; ++ }; ++ ++ port@1 { ++ reg = <0>; ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ reg = <1>; ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ reg = <2>; ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ reg = <3>; ++ label = "lan4"; ++ }; ++ }; ++ }; diff --git a/target/linux/ipq806x/patches-4.1/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch b/target/linux/ipq806x/patches-4.4/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch index 5126e9061e..625ff0a275 100644 --- a/target/linux/ipq806x/patches-4.1/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch +++ b/target/linux/ipq806x/patches-4.4/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch @@ -38,7 +38,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> }; gsbi@16300000 { -@@ -135,6 +145,34 @@ +@@ -160,6 +170,34 @@ linux,part-probe = "qcom-smem"; }; diff --git a/target/linux/ipq806x/patches-4.1/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-4.4/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch index 37dfaabf05..691ebb66ba 100644 --- a/target/linux/ipq806x/patches-4.1/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch +++ b/target/linux/ipq806x/patches-4.4/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch @@ -29,7 +29,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> }; gsbi@16300000 { -@@ -173,6 +183,31 @@ +@@ -198,6 +208,31 @@ reg = <4>; }; }; @@ -121,7 +121,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> }; --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -679,6 +679,92 @@ +@@ -763,6 +763,92 @@ status = "disabled"; }; diff --git a/target/linux/ipq806x/patches-4.4/709-spi-qup-Fix-fifo-and-dma-support-for-IPQ806x.patch b/target/linux/ipq806x/patches-4.4/709-spi-qup-Fix-fifo-and-dma-support-for-IPQ806x.patch new file mode 100644 index 0000000000..8c4718e2a6 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/709-spi-qup-Fix-fifo-and-dma-support-for-IPQ806x.patch @@ -0,0 +1,134 @@ +From 16d2871830ff3fe12a6bff582549a9264adff278 Mon Sep 17 00:00:00 2001 +From: Ram Chandra Jangir <rjangi@codeaurora.org> +Date: Tue, 10 May 2016 20:19:31 +0530 +Subject: [PATCH] spi: qup: Fix fifo and dma support for IPQ806x + +Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org> +--- + drivers/spi/spi-qup.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 52 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c +index 810a7fa..0808017 100644 +--- a/drivers/spi/spi-qup.c ++++ b/drivers/spi/spi-qup.c +@@ -24,6 +24,7 @@ + #include <linux/spi/spi.h> + #include <linux/dmaengine.h> + #include <linux/dma-mapping.h> ++#include <linux/gpio.h> + + #define QUP_CONFIG 0x0000 + #define QUP_STATE 0x0004 +@@ -152,6 +153,7 @@ struct spi_qup { + int use_dma; + struct dma_slave_config rx_conf; + struct dma_slave_config tx_conf; ++ int mode; + }; + + +@@ -370,7 +372,8 @@ static int spi_qup_do_pio(struct spi_master *master, struct spi_transfer *xfer) + return ret; + } + +- spi_qup_fifo_write(qup, xfer); ++ if (qup->mode == QUP_IO_M_MODE_FIFO) ++ spi_qup_fifo_write(qup, xfer); + + return 0; + } +@@ -448,6 +451,7 @@ spi_qup_get_mode(struct spi_master *master, struct spi_transfer *xfer) + { + struct spi_qup *qup = spi_master_get_devdata(master); + u32 mode; ++ size_t dma_align = dma_get_cache_alignment(); + + qup->w_size = 4; + +@@ -458,6 +462,14 @@ spi_qup_get_mode(struct spi_master *master, struct spi_transfer *xfer) + + qup->n_words = xfer->len / qup->w_size; + ++ if (!IS_ERR_OR_NULL(master->dma_rx) && ++ IS_ALIGNED((size_t)xfer->tx_buf, dma_align) && ++ IS_ALIGNED((size_t)xfer->rx_buf, dma_align) && ++ !is_vmalloc_addr(xfer->tx_buf) && ++ !is_vmalloc_addr(xfer->rx_buf) && ++ (xfer->len > 3*qup->in_blk_sz)) ++ qup->use_dma = 1; ++ + if (qup->n_words <= (qup->in_fifo_sz / sizeof(u32))) + mode = QUP_IO_M_MODE_FIFO; + else +@@ -491,7 +503,7 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) + return -EIO; + } + +- mode = spi_qup_get_mode(spi->master, xfer); ++ controller->mode = mode = spi_qup_get_mode(spi->master, xfer); + n_words = controller->n_words; + + if (mode == QUP_IO_M_MODE_FIFO) { +@@ -500,6 +512,7 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) + /* must be zero for FIFO */ + writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); + writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); ++ controller->use_dma = 0; + } else if (!controller->use_dma) { + writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT); + writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT); +@@ -750,6 +763,38 @@ err_tx: + return ret; + } + ++static void spi_qup_set_cs(struct spi_device *spi, bool val) ++{ ++ struct spi_qup *controller; ++ u32 spi_ioc; ++ u32 spi_ioc_orig; ++ ++ controller = spi_master_get_devdata(spi->master); ++ spi_ioc = readl_relaxed(controller->base + SPI_IO_CONTROL); ++ spi_ioc_orig = spi_ioc; ++ if (!val) ++ spi_ioc |= SPI_IO_C_FORCE_CS; ++ else ++ spi_ioc &= ~SPI_IO_C_FORCE_CS; ++ ++ if (spi_ioc != spi_ioc_orig) ++ writel_relaxed(spi_ioc, controller->base + SPI_IO_CONTROL); ++} ++ ++static int spi_qup_setup(struct spi_device *spi) ++{ ++ if (spi->cs_gpio >= 0) { ++ if (spi->mode & SPI_CS_HIGH) ++ gpio_set_value(spi->cs_gpio, 0); ++ else ++ gpio_set_value(spi->cs_gpio, 1); ++ ++ udelay(10); ++ } ++ ++ return 0; ++} ++ + static int spi_qup_probe(struct platform_device *pdev) + { + struct spi_master *master; +@@ -846,6 +891,11 @@ static int spi_qup_probe(struct platform_device *pdev) + if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1")) + controller->qup_v1 = 1; + ++ if (!controller->qup_v1) ++ master->set_cs = spi_qup_set_cs; ++ else ++ master->setup = spi_qup_setup; ++ + spin_lock_init(&controller->lock); + init_completion(&controller->done); + +-- +2.7.2 + diff --git a/target/linux/ipq806x/patches-4.4/710-watchdog-qcom-set-WDT_BARK_TIME-register-offset-to-o.patch b/target/linux/ipq806x/patches-4.4/710-watchdog-qcom-set-WDT_BARK_TIME-register-offset-to-o.patch new file mode 100644 index 0000000000..7573c963a7 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/710-watchdog-qcom-set-WDT_BARK_TIME-register-offset-to-o.patch @@ -0,0 +1,43 @@ +From abc9f55079169806bcc31f29ec27f7df11c6184c Mon Sep 17 00:00:00 2001 +From: Ram Chandra Jangir <rjangi@codeaurora.org> +Date: Thu, 4 Feb 2016 12:41:56 +0530 +Subject: [PATCH 2/2] watchdog: qcom: set WDT_BARK_TIME register offset to one + second less of bite time + +Currently WDT_BARK_TIME register offset is not configured with bark +timeout during wdt_start,and it is taking bark timeout's default value. +For some versions of TZ (secure mode) will consider a BARK the same +as BITE and reset the board. + +So instead let's just configure the BARK time to be less than a second +of the bite timeout so the board does not reset in this scenario + +Change-Id: Ie09850ad7e0470ed721e6924911ca2a81fd9ff8a +Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org> +--- + drivers/watchdog/qcom-wdt.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c +index 773dcfa..002274a 100644 +--- a/drivers/watchdog/qcom-wdt.c ++++ b/drivers/watchdog/qcom-wdt.c +@@ -22,6 +22,7 @@ + + #define WDT_RST 0x38 + #define WDT_EN 0x40 ++#define WDT_BARK_TIME 0x4C + #define WDT_BITE_TIME 0x5C + + struct qcom_wdt { +@@ -44,6 +45,7 @@ static int qcom_wdt_start(struct watchdog_device *wdd) + + writel(0, wdt->base + WDT_EN); + writel(1, wdt->base + WDT_RST); ++ writel((wdd->timeout - 1) * wdt->rate, wdt->base + WDT_BARK_TIME); + writel(wdd->timeout * wdt->rate, wdt->base + WDT_BITE_TIME); + writel(1, wdt->base + WDT_EN); + return 0; +-- +2.7.2 + diff --git a/target/linux/ipq806x/patches-4.1/301-ARM-qcom-add-Netgear-Nighthawk-X4-R7500-device-tree.patch b/target/linux/ipq806x/patches-4.4/800-ARM-qcom-add-Netgear-Nighthawk-X4-R7500-device-tree.patch index 1f5eba8377..1f5eba8377 100644 --- a/target/linux/ipq806x/patches-4.1/301-ARM-qcom-add-Netgear-Nighthawk-X4-R7500-device-tree.patch +++ b/target/linux/ipq806x/patches-4.4/800-ARM-qcom-add-Netgear-Nighthawk-X4-R7500-device-tree.patch diff --git a/target/linux/ipq806x/patches-4.4/801-ARM-qcom-add-Netgear-Nighthawk-X4-D7800-device-tree.patch b/target/linux/ipq806x/patches-4.4/801-ARM-qcom-add-Netgear-Nighthawk-X4-D7800-device-tree.patch new file mode 100644 index 0000000000..eaf037f57e --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/801-ARM-qcom-add-Netgear-Nighthawk-X4-D7800-device-tree.patch @@ -0,0 +1,381 @@ +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -362,6 +362,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-ipq8064-ap148.dtb \ + qcom-ipq8064-db149.dtb \ + qcom-ipq8064-r7500.dtb \ ++ qcom-ipq8064-d7800.dtb \ + qcom-msm8660-surf.dtb \ + qcom-msm8960-cdp.dtb \ + qcom-msm8974-sony-xperia-honami.dtb +--- /dev/null ++++ b/arch/arm/boot/dts/qcom-ipq8064-d7800.dts +@@ -0,0 +1,368 @@ ++#include "qcom-ipq8064-v1.0.dtsi" ++ ++#include <dt-bindings/input/input.h> ++ ++/ { ++ model = "Netgear Nighthawk X4 D7800"; ++ compatible = "netgear,d7800", "qcom,ipq8064"; ++ ++ memory@0 { ++ reg = <0x42000000 0xe000000>; ++ device_type = "memory"; ++ }; ++ ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ rsvd@41200000 { ++ reg = <0x41200000 0x300000>; ++ no-map; ++ }; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ mdio-gpio0 = &mdio0; ++ }; ++ ++ chosen { ++ bootargs = "rootfstype=squashfs noinitrd"; ++ linux,stdout-path = "serial0:115200n8"; ++ }; ++ ++ soc { ++ pinmux@800000 { ++ i2c4_pins: i2c4_pinmux { ++ pins = "gpio12", "gpio13"; ++ function = "gsbi4"; ++ bias-disable; ++ }; ++ ++ pcie0_pins: pcie0_pinmux { ++ mux { ++ pins = "gpio3"; ++ function = "pcie1_rst"; ++ drive-strength = <12>; ++ bias-disable; ++ }; ++ }; ++ ++ pcie1_pins: pcie1_pinmux { ++ mux { ++ pins = "gpio48"; ++ function = "pcie2_rst"; ++ drive-strength = <12>; ++ bias-disable; ++ }; ++ }; ++ ++ nand_pins: nand_pins { ++ mux { ++ pins = "gpio34", "gpio35", "gpio36", ++ "gpio37", "gpio38", "gpio39", ++ "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ function = "nand"; ++ drive-strength = <10>; ++ bias-disable; ++ }; ++ pullups { ++ pins = "gpio39"; ++ bias-pull-up; ++ }; ++ hold { ++ pins = "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ bias-bus-hold; ++ }; ++ }; ++ ++ mdio0_pins: mdio0_pins { ++ mux { ++ pins = "gpio0", "gpio1"; ++ function = "gpio"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ ++ rgmii2_pins: rgmii2_pins { ++ mux { ++ pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", ++ "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; ++ function = "rgmii2"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ }; ++ ++ gsbi@16300000 { ++ qcom,mode = <GSBI_PROT_I2C_UART>; ++ status = "ok"; ++ serial@16340000 { ++ status = "ok"; ++ }; ++ /* ++ * The i2c device on gsbi4 should not be enabled. ++ * On ipq806x designs gsbi4 i2c is meant for exclusive ++ * RPM usage. Turning this on in kernel manifests as ++ * i2c failure for the RPM. ++ */ ++ }; ++ ++ sata-phy@1b400000 { ++ status = "ok"; ++ }; ++ ++ sata@29000000 { ++ status = "ok"; ++ }; ++ ++ phy@100f8800 { /* USB3 port 1 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@100f8830 { /* USB3 port 1 SS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8800 { /* USB3 port 0 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8830 { /* USB3 port 0 SS phy */ ++ status = "ok"; ++ }; ++ ++ usb30@0 { ++ status = "ok"; ++ }; ++ ++ usb30@1 { ++ status = "ok"; ++ }; ++ ++ pcie0: pci@1b500000 { ++ status = "ok"; ++ reset-gpio = <&qcom_pinmux 3 0>; ++ pinctrl-0 = <&pcie0_pins>; ++ pinctrl-names = "default"; ++ }; ++ ++ pcie1: pci@1b700000 { ++ status = "ok"; ++ reset-gpio = <&qcom_pinmux 48 0>; ++ pinctrl-0 = <&pcie1_pins>; ++ pinctrl-names = "default"; ++ }; ++ ++ nand@1ac00000 { ++ status = "ok"; ++ ++ pinctrl-0 = <&nand_pins>; ++ pinctrl-names = "default"; ++ ++ nand-ecc-strength = <4>; ++ nand-bus-width = <8>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ qcadata@0 { ++ label = "qcadata"; ++ reg = <0x0000000 0x0c80000>; ++ read-only; ++ }; ++ ++ APPSBL@c80000 { ++ label = "APPSBL"; ++ reg = <0x0c80000 0x0500000>; ++ read-only; ++ }; ++ ++ APPSBLENV@1180000 { ++ label = "APPSBLENV"; ++ reg = <0x1180000 0x0080000>; ++ read-only; ++ }; ++ ++ art: art@1200000 { ++ label = "art"; ++ reg = <0x1200000 0x0140000>; ++ read-only; ++ }; ++ ++ artbak: art@1340000 { ++ label = "artbak"; ++ reg = <0x1340000 0x0140000>; ++ read-only; ++ }; ++ ++ kernel@1480000 { ++ label = "kernel"; ++ reg = <0x1480000 0x0200000>; ++ }; ++ ++ ubi@1680000 { ++ label = "ubi"; ++ reg = <0x1680000 0x1E00000>; ++ }; ++ ++ netgear@3480000 { ++ label = "netgear"; ++ reg = <0x3480000 0x4480000>; ++ read-only; ++ }; ++ ++ reserve@7900000 { ++ label = "reserve"; ++ reg = <0x7900000 0x0700000>; ++ read-only; ++ }; ++ ++ firmware@1480000 { ++ label = "firmware"; ++ reg = <0x1480000 0x2000000>; ++ }; ++ ++ }; ++ ++ mdio0: mdio { ++ compatible = "virtual,mdio-gpio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>; ++ pinctrl-0 = <&mdio0_pins>; ++ pinctrl-names = "default"; ++ ++ phy0: ethernet-phy@0 { ++ device_type = "ethernet-phy"; ++ reg = <0>; ++ qca,ar8327-initvals = < ++ 0x00004 0x7600000 /* PAD0_MODE */ ++ 0x00008 0x1000000 /* PAD5_MODE */ ++ 0x0000c 0x80 /* PAD6_MODE */ ++ 0x000e4 0xaa545 /* MAC_POWER_SEL */ ++ 0x000e0 0xc74164de /* SGMII_CTRL */ ++ 0x0007c 0x4e /* PORT0_STATUS */ ++ 0x00094 0x4e /* PORT6_STATUS */ ++ >; ++ }; ++ ++ phy4: ethernet-phy@4 { ++ device_type = "ethernet-phy"; ++ reg = <4>; ++ }; ++ }; ++ ++ gmac1: ethernet@37200000 { ++ status = "ok"; ++ phy-mode = "rgmii"; ++ phy-handle = <&phy4>; ++ qcom,id = <1>; ++ ++ pinctrl-0 = <&rgmii2_pins>; ++ pinctrl-names = "default"; ++ ++ mtd-mac-address = <&art 6>; ++ }; ++ ++ gmac2: ethernet@37400000 { ++ status = "ok"; ++ phy-mode = "sgmii"; ++ qcom,id = <2>; ++ ++ mtd-mac-address = <&art 0>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ wifi { ++ label = "wifi"; ++ gpios = <&qcom_pinmux 6 1>; ++ linux,code = <KEY_WLAN>; ++ }; ++ ++ reset { ++ label = "reset"; ++ gpios = <&qcom_pinmux 54 1>; ++ linux,code = <KEY_RESTART>; ++ }; ++ ++ wps { ++ label = "wps"; ++ gpios = <&qcom_pinmux 65 1>; ++ linux,code = <KEY_WPS_BUTTON>; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ usb1 { ++ label = "d7800:amber:usb1"; ++ gpios = <&qcom_pinmux 7 0>; ++ }; ++ ++ usb3 { ++ label = "d7800:amber:usb3"; ++ gpios = <&qcom_pinmux 8 0>; ++ }; ++ ++ status { ++ label = "d7800:amber:status"; ++ gpios = <&qcom_pinmux 9 0>; ++ }; ++ ++ internet { ++ label = "d7800:white:internet"; ++ gpios = <&qcom_pinmux 22 0>; ++ }; ++ ++ wan { ++ label = "d7800:white:wan"; ++ gpios = <&qcom_pinmux 23 0>; ++ }; ++ ++ wps { ++ label = "d7800:white:wps"; ++ gpios = <&qcom_pinmux 24 0>; ++ }; ++ ++ esata { ++ label = "d7800:white:esata"; ++ gpios = <&qcom_pinmux 26 0>; ++ }; ++ ++ power { ++ label = "d7800:white:power"; ++ gpios = <&qcom_pinmux 53 0>; ++ default-state = "on"; ++ }; ++ ++ rfkill { ++ label = "d7800:white:rfkill"; ++ gpios = <&qcom_pinmux 64 0>; ++ }; ++ ++ wifi5g { ++ label = "d7800:white:wifi5g"; ++ gpios = <&qcom_pinmux 67 0>; ++ }; ++ }; ++}; ++ ++&adm_dma { ++ status = "ok"; ++}; diff --git a/target/linux/ipq806x/patches-4.4/802-ARM-qcom-add-TPLink-C2600-device-tree.patch b/target/linux/ipq806x/patches-4.4/802-ARM-qcom-add-TPLink-C2600-device-tree.patch new file mode 100644 index 0000000000..8952f3339d --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/802-ARM-qcom-add-TPLink-C2600-device-tree.patch @@ -0,0 +1,425 @@ +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -506,6 +506,7 @@ + qcom-apq8084-ifc6540.dtb \ + qcom-apq8084-mtp.dtb \ + qcom-ipq8064-ap148.dtb \ ++ qcom-ipq8064-c2600.dtb \ + qcom-ipq8064-db149.dtb \ + qcom-ipq8064-r7500.dtb \ + qcom-ipq8064-d7800.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/qcom-ipq8064-c2600.dts +@@ -0,0 +1,412 @@ ++#include "qcom-ipq8064-v1.0.dtsi" ++#include <dt-bindings/input/input.h> ++ ++/ { ++ model = "TP-Link Archer C2600"; ++ compatible = "tplink,c2600", "qcom,ipq8064"; ++ ++ memory@0 { ++ reg = <0x42000000 0x1e000000>; ++ device_type = "memory"; ++ }; ++ ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ rsvd@41200000 { ++ reg = <0x41200000 0x300000>; ++ no-map; ++ }; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ mdio-gpio0 = &mdio0; ++ }; ++ ++ chosen { ++ linux,stdout-path = "serial0:115200n8"; ++ }; ++ ++ soc { ++ pinmux@800000 { ++ i2c4_pins: i2c4_pinmux { ++ pins = "gpio12", "gpio13"; ++ function = "gsbi4"; ++ bias-disable; ++ }; ++ ++ spi_pins: spi_pins { ++ mux { ++ pins = "gpio18", "gpio19", "gpio21"; ++ function = "gsbi5"; ++ drive-strength = <10>; ++ bias-none; ++ }; ++ }; ++ ++ nand_pins: nand_pins { ++ mux { ++ pins = "gpio34", "gpio35", "gpio36", ++ "gpio37", "gpio38", "gpio39", ++ "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ function = "nand"; ++ drive-strength = <10>; ++ bias-disable; ++ }; ++ ++ pullups { ++ pins = "gpio39"; ++ bias-pull-up; ++ }; ++ ++ hold { ++ pins = "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ bias-bus-hold; ++ }; ++ }; ++ ++ mdio0_pins: mdio0_pins { ++ mux { ++ pins = "gpio0", "gpio1"; ++ function = "gpio"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ ++ rgmii2_pins: rgmii2_pins { ++ mux { ++ pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", ++ "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; ++ function = "rgmii2"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ }; ++ ++ gsbi@16300000 { ++ qcom,mode = <GSBI_PROT_I2C_UART>; ++ status = "ok"; ++ serial@16340000 { ++ status = "ok"; ++ }; ++ /* ++ * The i2c device on gsbi4 should not be enabled. ++ * On ipq806x designs gsbi4 i2c is meant for exclusive ++ * RPM usage. Turning this on in kernel manifests as ++ * i2c failure for the RPM. ++ */ ++ }; ++ ++ gsbi5: gsbi@1a200000 { ++ qcom,mode = <GSBI_PROT_SPI>; ++ status = "ok"; ++ ++ spi4: spi@1a280000 { ++ status = "ok"; ++ spi-max-frequency = <50000000>; ++ ++ pinctrl-0 = <&spi_pins>; ++ pinctrl-names = "default"; ++ ++ cs-gpios = <&qcom_pinmux 20 0>; ++ ++ flash: m25p80@0 { ++ compatible = "s25fl256s1"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ spi-max-frequency = <50000000>; ++ reg = <0>; ++ ++ SBL1@0 { ++ label = "SBL1"; ++ reg = <0x0 0x20000>; ++ read-only; ++ }; ++ MIBIB@20000 { ++ label = "MIBIB"; ++ reg = <0x20000 0x20000>; ++ read-only; ++ }; ++ SBL2@40000 { ++ label = "SBL2"; ++ reg = <0x40000 0x20000>; ++ read-only; ++ }; ++ SBL3@60000 { ++ label = "SBL3"; ++ reg = <0x60000 0x30000>; ++ read-only; ++ }; ++ DDRCONFIG@90000 { ++ label = "DDRCONFIG"; ++ reg = <0x90000 0x10000>; ++ read-only; ++ }; ++ SSD@a0000 { ++ label = "SSD"; ++ reg = <0xa0000 0x10000>; ++ read-only; ++ }; ++ TZ@b0000 { ++ label = "TZ"; ++ reg = <0xb0000 0x30000>; ++ read-only; ++ }; ++ RPM@e0000 { ++ label = "RPM"; ++ reg = <0xe0000 0x20000>; ++ read-only; ++ }; ++ fs-uboot@100000 { ++ label = "fs-uboot"; ++ reg = <0x100000 0x70000>; ++ read-only; ++ }; ++ uboot-env@170000 { ++ label = "uboot-env"; ++ reg = <0x170000 0x40000>; ++ read-only; ++ }; ++ radio@1b0000 { ++ label = "radio"; ++ reg = <0x1b0000 0x40000>; ++ read-only; ++ }; ++ os-image@1f0000 { ++ label = "os-image"; ++ reg = <0x1f0000 0x200000>; ++ }; ++ rootfs@3f0000 { ++ label = "rootfs"; ++ reg = <0x3f0000 0x1b00000>; ++ }; ++ defaultmac: default-mac@1ef0000 { ++ label = "default-mac"; ++ reg = <0x1ef0000 0x00200>; ++ read-only; ++ }; ++ pin@1ef0200 { ++ label = "pin"; ++ reg = <0x1ef0200 0x00200>; ++ read-only; ++ }; ++ product-info@1ef0400 { ++ label = "product-info"; ++ reg = <0x1ef0400 0x0fc00>; ++ read-only; ++ }; ++ partition-table@1f00000 { ++ label = "partition-table"; ++ reg = <0x1f00000 0x10000>; ++ read-only; ++ }; ++ soft-version@1f10000 { ++ label = "soft-version"; ++ reg = <0x1f10000 0x10000>; ++ read-only; ++ }; ++ support-list@1f20000 { ++ label = "support-list"; ++ reg = <0x1f20000 0x10000>; ++ read-only; ++ }; ++ profile@1f30000 { ++ label = "profile"; ++ reg = <0x1f30000 0x10000>; ++ read-only; ++ }; ++ default-config@1f40000 { ++ label = "default-config"; ++ reg = <0x1f40000 0x10000>; ++ read-only; ++ }; ++ user-config@1f50000 { ++ label = "user-config"; ++ reg = <0x1f50000 0x40000>; ++ read-only; ++ }; ++ qos-db@1f90000 { ++ label = "qos-db"; ++ reg = <0x1f90000 0x40000>; ++ read-only; ++ }; ++ usb-config@1fd0000 { ++ label = "usb-config"; ++ reg = <0x1fd0000 0x10000>; ++ read-only; ++ }; ++ log@1fe0000 { ++ label = "log"; ++ reg = <0x1fe0000 0x20000>; ++ read-only; ++ }; ++ }; ++ }; ++ }; ++ ++ phy@100f8800 { /* USB3 port 1 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@100f8830 { /* USB3 port 1 SS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8800 { /* USB3 port 0 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8830 { /* USB3 port 0 SS phy */ ++ status = "ok"; ++ }; ++ ++ usb30@0 { ++ status = "ok"; ++ }; ++ ++ usb30@1 { ++ status = "ok"; ++ }; ++ ++ pcie0: pci@1b500000 { ++ status = "ok"; ++ phy-tx0-term-offset = <7>; ++ }; ++ ++ pcie1: pci@1b700000 { ++ status = "ok"; ++ phy-tx0-term-offset = <7>; ++ }; ++ ++ mdio0: mdio { ++ compatible = "virtual,mdio-gpio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>; ++ pinctrl-0 = <&mdio0_pins>; ++ pinctrl-names = "default"; ++ ++ phy0: ethernet-phy@0 { ++ device_type = "ethernet-phy"; ++ reg = <0>; ++ qca,ar8327-initvals = < ++ 0x00004 0x7600000 /* PAD0_MODE */ ++ 0x00008 0x1000000 /* PAD5_MODE */ ++ 0x0000c 0x80 /* PAD6_MODE */ ++ 0x000e4 0xaa545 /* MAC_POWER_SEL */ ++ 0x000e0 0xc74164de /* SGMII_CTRL */ ++ 0x0007c 0x4e /* PORT0_STATUS */ ++ 0x00094 0x4e /* PORT6_STATUS */ ++ >; ++ }; ++ ++ phy4: ethernet-phy@4 { ++ device_type = "ethernet-phy"; ++ reg = <4>; ++ }; ++ }; ++ ++ gmac1: ethernet@37200000 { ++ status = "ok"; ++ phy-mode = "rgmii"; ++ qcom,id = <1>; ++ ++ pinctrl-0 = <&rgmii2_pins>; ++ pinctrl-names = "default"; ++ ++ mtd-mac-address = <&defaultmac 0x8>; ++ mtd-mac-address-increment = <1>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ gmac2: ethernet@37400000 { ++ status = "ok"; ++ phy-mode = "sgmii"; ++ qcom,id = <2>; ++ ++ mtd-mac-address = <&defaultmac 0x8>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ wifi { ++ label = "wifi"; ++ gpios = <&qcom_pinmux 49 1>; ++ linux,code = <KEY_WLAN>; ++ }; ++ ++ reset { ++ label = "reset"; ++ gpios = <&qcom_pinmux 64 1>; ++ linux,code = <KEY_RESTART>; ++ }; ++ ++ wps { ++ label = "wps"; ++ gpios = <&qcom_pinmux 65 1>; ++ linux,code = <KEY_WPS_BUTTON>; ++ }; ++ ledgeneral { ++ label = "ledgeneral"; ++ gpios = <&qcom_pinmux 16 1>; ++ linux,code = <KEY_DOLLAR>; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ lan { ++ label = "lan:blue"; ++ gpios = <&qcom_pinmux 6 0>; ++ }; ++ usb4 { ++ label = "usb_4:blue"; ++ gpios = <&qcom_pinmux 7 0>; ++ }; ++ usb2 { ++ label = "usb_2:blue"; ++ gpios = <&qcom_pinmux 8 0>; ++ }; ++ wps { ++ label = "wps:blue"; ++ gpios = <&qcom_pinmux 9 0>; ++ }; ++ wan_blue { ++ label = "wan:blue"; ++ gpios = <&qcom_pinmux 33 1>; ++ }; ++ status { ++ label = "status:blue"; ++ gpios = <&qcom_pinmux 53 0>; ++ default-state = "on"; ++ }; ++ ledgnr { ++ label = "ledgnr:blue"; ++ gpios = <&qcom_pinmux 66 0>; ++ }; ++ }; ++}; ++ ++&adm_dma { ++ status = "ok"; ++}; diff --git a/target/linux/ipq806x/profiles/00-default.mk b/target/linux/ipq806x/profiles/00-default.mk new file mode 100644 index 0000000000..26bc8b502b --- /dev/null +++ b/target/linux/ipq806x/profiles/00-default.mk @@ -0,0 +1,9 @@ +define Profile/Default + NAME:=Default Profile + PRIORITY:=1 +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ipq806x/profiles/default.mk b/target/linux/ipq806x/profiles/default.mk deleted file mode 100644 index 6469bcb5f1..0000000000 --- a/target/linux/ipq806x/profiles/default.mk +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (c) 2014 The Linux Foundation. All rights reserved. -# Copyright (C) 2009 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -define Profile/Default - NAME:=Default Profile (minimum package set) - PACKAGES:= \ - kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ - kmod-usb3 kmod-usb-dwc3-qcom kmod-usb-phy-qcom-dwc3 -endef - -define Profile/Default/Description - Default package set compatible with most boards. -endef -$(eval $(call Profile,Default)) diff --git a/target/linux/ipq806x/profiles/netgear.mk b/target/linux/ipq806x/profiles/netgear.mk deleted file mode 100644 index 25258cdca3..0000000000 --- a/target/linux/ipq806x/profiles/netgear.mk +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2014 The Linux Foundation. All rights reserved. -# Copyright (C) 2009 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -define Profile/D7800 - NAME:=Netgear Nighthawk X4 D7800 - PACKAGES:= \ - kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ - kmod-usb3 kmod-usb-dwc3-qcom kmod-usb-phy-qcom-dwc3 \ - kmod-ath10k wpad-mini ath10k-firmware-qca99x0 -endef - -define Profile/D7800/Description - Package set for the Netgear Nighthawk X4 D7800. -endef - -define Profile/R7500 - NAME:=Netgear Nighthawk X4 R7500 - PACKAGES:= \ - kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ - kmod-usb3 kmod-usb-dwc3-qcom kmod-usb-phy-qcom-dwc3 \ - kmod-ath10k wpad-mini -endef - -define Profile/R7500/Description - Package set for the Netgear Nighthawk X4 R7500. -endef -$(eval $(call Profile,D7800)) -$(eval $(call Profile,R7500)) |