From 464fb0c122143f761349b16a7505df9ff6f6ab6d Mon Sep 17 00:00:00 2001 From: AmadeusGhost <42570690+AmadeusGhost@users.noreply.github.com> Date: Tue, 11 Feb 2020 17:26:50 +0800 Subject: [PATCH] ipq806x: add support for ruijie_rg-mtfi-m520 (#3025) Signed-off-by: AmadeusGhost <42570690+AmadeusGhost@users.noreply.github.com> --- .../ipq806x/base-files/etc/board.d/01_leds | 4 + .../ipq806x/base-files/etc/board.d/02_network | 7 + .../etc/hotplug.d/firmware/11-ath10k-caldata | 16 + .../lib/preinit/05_set_iface_mac_ipq806x.sh | 15 + .../base-files/lib/upgrade/platform.sh | 4 + .../ipq806x/base-files/lib/upgrade/ruijie.sh | 53 +++ target/linux/ipq806x/config-4.14 | 1 + target/linux/ipq806x/config-4.19 | 1 + .../arm/boot/dts/qcom-ipq8064-mtfi-m520.dts | 395 ++++++++++++++++++ .../arm/boot/dts/qcom-ipq8064-mtfi-m520.dts | 395 ++++++++++++++++++ target/linux/ipq806x/image/Makefile | 19 + .../0069-arm-boot-add-dts-files.patch | 3 +- .../851-ata-add-sata-driver.patch | 308 ++++++++++++++ .../0069-arm-boot-add-dts-files.patch | 3 +- .../851-ata-add-sata-driver.patch | 308 ++++++++++++++ 15 files changed, 1530 insertions(+), 2 deletions(-) create mode 100644 target/linux/ipq806x/base-files/lib/preinit/05_set_iface_mac_ipq806x.sh create mode 100644 target/linux/ipq806x/base-files/lib/upgrade/ruijie.sh create mode 100644 target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8064-mtfi-m520.dts create mode 100644 target/linux/ipq806x/files-4.19/arch/arm/boot/dts/qcom-ipq8064-mtfi-m520.dts create mode 100644 target/linux/ipq806x/patches-4.14/851-ata-add-sata-driver.patch create mode 100644 target/linux/ipq806x/patches-4.19/851-ata-add-sata-driver.patch 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 f8b6c3235..82a9e9536 100755 --- a/target/linux/ipq806x/base-files/etc/board.d/01_leds +++ b/target/linux/ipq806x/base-files/etc/board.d/01_leds @@ -33,6 +33,10 @@ netgear,r7800) ucidef_set_led_switch "wan" "WAN" "${boardname}:white:wan" "switch0" "0x20" ucidef_set_led_ide "esata" "eSATA" "${boardname}:white:esata" ;; +ruijie,rg-mtfi-m520) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:green:wlan2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "${boardname}:green:wlan5g" "phy0tpt" + ;; tplink,c2600) ucidef_set_led_usbport "usb1" "USB 1" "${boardname}:white:usb_2" "usb1-port1" "usb2-port1" ucidef_set_led_usbport "usb2" "USB 2" "${boardname}:white:usb_4" "usb3-port1" "usb4-port1" 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 a3aa0fce7..a241f3321 100755 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -48,6 +48,13 @@ qcom,ipq8064-db149) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "6u@eth1" "5:wan" "0u@eth0" ;; +ruijie,rg-mtfi-m520) + hw_mac_addr=$(mtd_get_mac_ascii PRODUCTINFO ethaddr) + ucidef_add_switch "switch0" \ + "1:lan" "6@eth1" "5:wan" "0@eth0" + ucidef_set_interface_macaddr "wan" "$hw_mac_addr" + ucidef_set_interface_macaddr "lan" "$(macaddr_add $hw_mac_addr 1)" + ;; zyxel,nbg6817) hw_mac_addr=$(mtd_get_mac_ascii 0:APPSBLENV ethaddr) ucidef_add_switch "switch0" \ 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 index e05f2b2c7..808994d1e 100644 --- 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 @@ -77,6 +77,22 @@ ath10kcal_patch_mac_crc() { board=$(board_name) case "$FIRMWARE" in +"ath10k/cal-pci-0000:01:00.0.bin") + case "$board" in + ruijie,rg-mtfi-m520) + ath10kcal_extract "ART" 4096 2116 + ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii PRODUCTINFO ethaddr) +2) + ;; + esac + ;; +"ath10k/cal-pci-0001:01:00.0.bin") + case "$board" in + ruijie,rg-mtfi-m520) + ath10kcal_extract "ART" 20480 2116 + ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii PRODUCTINFO ethaddr) +3) + ;; + esac + ;; "ath10k/pre-cal-pci-0000:01:00.0.bin") case $board in buffalo,wxr-2533dhp) diff --git a/target/linux/ipq806x/base-files/lib/preinit/05_set_iface_mac_ipq806x.sh b/target/linux/ipq806x/base-files/lib/preinit/05_set_iface_mac_ipq806x.sh new file mode 100644 index 000000000..808753422 --- /dev/null +++ b/target/linux/ipq806x/base-files/lib/preinit/05_set_iface_mac_ipq806x.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +. /lib/functions.sh + +preinit_set_mac_address() { + case $(board_name) in + ruijie,rg-mtfi-m520) + base_mac=$(mtd_get_mac_ascii PRODUCTINFO ethaddr) + ip link set dev eth0 address $(macaddr_add "$base_mac" +1) + ip link set dev eth1 address $(macaddr_add "$base_mac" +2) + ;; + esac +} + +boot_hook_add preinit_main preinit_set_mac_address diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 2f0190629..d825ae434 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -22,6 +22,7 @@ platform_do_upgrade() { netgear,r7800 |\ qcom,ipq8064-ap148 |\ qcom,ipq8064-ap161 |\ + ruijie,rg-mtfi-m520 |\ zyxel,nbg6817) nand_do_upgrade "$ARGV" ;; @@ -47,6 +48,9 @@ platform_do_upgrade() { platform_nand_pre_upgrade() { case "$(board_name)" in + ruijie,rg-mtfi-m520) + ruijie_do_upgrade "$1" + ;; zyxel,nbg6817) zyxel_do_upgrade "$1" ;; diff --git a/target/linux/ipq806x/base-files/lib/upgrade/ruijie.sh b/target/linux/ipq806x/base-files/lib/upgrade/ruijie.sh new file mode 100644 index 000000000..2725de432 --- /dev/null +++ b/target/linux/ipq806x/base-files/lib/upgrade/ruijie.sh @@ -0,0 +1,53 @@ +# +# Copyright (C) 2016 lede-project.org +# Copyright (C) 2020 AnYun +# + +ruijie_do_flash() { + local tar_file=$1 + local kernel=$2 + local rootfs=$3 + + # keep sure its unbound + losetup --detach-all || { + echo Failed to detach all loop devices. Skip this try. + reboot -f + } + + # use the first found directory in the tar archive + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + + echo "flashing kernel to $kernel" + tar xf $tar_file ${board_dir}/kernel -O > $kernel + + echo "flashing rootfs to $rootfs" + tar xf $tar_file ${board_dir}/root -O > $rootfs + + # Cleanup + losetup -d /dev/loop0 >/dev/null 2>&1 + sync + umount -a + reboot -f +} + +ruijie_do_upgrade() { + local tar_file="$1" + local board=$(board_name) + local kernel= + local rootfs= + + case "$board" in + ruijie,rg-mtfi-m520) + kernel="/dev/mmcblk0p2" + rootfs="/dev/mmcblk0p3" + ;; + *) + return 1 + ;; + esac + + ruijie_do_flash $tar_file $kernel $rootfs + + return 0 +} diff --git a/target/linux/ipq806x/config-4.14 b/target/linux/ipq806x/config-4.14 index 38f5c9450..eee0c9f0a 100644 --- a/target/linux/ipq806x/config-4.14 +++ b/target/linux/ipq806x/config-4.14 @@ -1,3 +1,4 @@ +CONFIG_AHCI_IPQ=y CONFIG_ALIGNMENT_TRAP=y # CONFIG_AMBA_PL08X is not set # CONFIG_APQ_GCC_8084 is not set diff --git a/target/linux/ipq806x/config-4.19 b/target/linux/ipq806x/config-4.19 index f4c27d7ae..367d25f77 100644 --- a/target/linux/ipq806x/config-4.19 +++ b/target/linux/ipq806x/config-4.19 @@ -1,3 +1,4 @@ +CONFIG_AHCI_IPQ=y CONFIG_ALIGNMENT_TRAP=y # CONFIG_APQ_GCC_8084 is not set # CONFIG_APQ_MMCC_8084 is not set diff --git a/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8064-mtfi-m520.dts b/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8064-mtfi-m520.dts new file mode 100644 index 000000000..b89201e57 --- /dev/null +++ b/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8064-mtfi-m520.dts @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq8064-v2.0.dtsi" + +#include + +/ { + model = "Ruijie RG-MTFi-M520"; + compatible = "ruijie,rg-mtfi-m520", "qcom,ipq8064"; + + memory@0 { + reg = <0x42000000 0x7e000000>; + device_type = "memory"; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + rsvd@41200000 { + reg = <0x41200000 0x300000>; + no-map; + }; + }; + + aliases { + serial0 = &gsbi4_serial; + mdio-gpio0 = &mdio0; + sdcc1 = &sdcc1; + }; + + chosen { + bootargs = "root=/dev/mmcblk0p3 rootfstype=squashfs,ext4 rootwait noinitrd"; + stdout-path = "serial0:115200n8"; + }; + + soc { + pinmux@800000 { + button_pins: button_pins { + mux { + pins = "gpio54"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + i2c4_pins: i2c4_pinmux { + mux { + pins = "gpio12", "gpio13"; + function = "gsbi4"; + drive-strength = <12>; + bias-disable; + }; + }; + + led_pins: led_pins { + mux { + pins = "gpio7", "gpio8", "gpio9", "gpio53"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + mdio0_pins: mdio0_pins { + mux { + pins = "gpio0", "gpio1"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + clk { + pins = "gpio1"; + input-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; + }; + + tx { + pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32"; + input-disable; + }; + }; + + sdcc1_pins: sdcc1_pinmux { + mux { + pins = "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47"; + function = "sdc1"; + }; + + cmd { + pins = "gpio45"; + drive-strength = <10>; + bias-pull-up; + }; + + data { + pins = "gpio38", "gpio39", "gpio40", "gpio41", + "gpio43", "gpio44", "gpio46", "gpio47"; + drive-strength = <10>; + bias-pull-up; + }; + + clk { + pins = "gpio42"; + drive-strength = <16>; + bias-disable; + }; + }; + + spi_pins: spi_pins { + mux { + pins = "gpio18", "gpio19", "gpio21"; + function = "gsbi5"; + drive-strength = <10>; + bias-none; + }; + + cs { + pins = "gpio20"; + drive-strength = <12>; + }; + }; + }; + + gsbi@16300000 { + qcom,mode = ; + 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 = ; + status = "ok"; + + spi4: spi@1a280000 { + status = "ok"; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + + cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; + + flash: m25p80@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <51200000>; + reg = <0>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x10000>; + read-only; + }; + + MIBIB@10000 { + label = "MIBIB"; + reg = <0x10000 0x10000>; + read-only; + }; + + SBL2@20000 { + label = "SBL2"; + reg = <0x20000 0x20000>; + read-only; + }; + + SBL3@40000 { + label = "SBL3"; + reg = <0x40000 0x30000>; + read-only; + }; + + DDRCONFIG@70000 { + label = "DDRCONFIG"; + reg = <0x70000 0x10000>; + read-only; + }; + + PRODUCTINFO: PRODUCTINFO@80000 { + label = "PRODUCTINFO"; + reg = <0x80000 0x10000>; + read-only; + }; + + TZ@90000 { + label = "TZ"; + reg = <0x90000 0x30000>; + read-only; + }; + + RPM@c0000 { + label = "RPM"; + reg = <0xc0000 0x20000>; + read-only; + }; + + APPSBL@e0000 { + label = "APPSBL"; + reg = <0xe0000 0x80000>; + read-only; + }; + + APPSBLENV@160000 { + label = "APPSBLENV"; + reg = <0x160000 0x10000>; + read-only; + }; + + BOOTCONFIG@170000 { + label = "BOOTCONFIG"; + reg = <0x170000 0x10000>; + read-only; + }; + + ART@180000 { + label = "ART"; + reg = <0x180000 0x40000>; + read-only; + }; + }; + }; + }; + + sata-phy@1b400000 { + status = "ok"; + }; + + sata@29000000 { + ports-implemented = <0x1>; + 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 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&pcie0_pins>; + pinctrl-names = "default"; + }; + + pcie1: pci@1b700000 { + status = "ok"; + reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&pcie1_pins>; + pinctrl-names = "default"; + force_gen1 = <1>; + }; + + mdio0: mdio { + compatible = "virtual,mdio-gpio"; + #address-cells = <1>; + #size-cells = <0>; + gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + + phy0: ethernet-phy@0 { + reg = <0>; + qca,ar8327-initvals = < + 0x00004 0x7600000 /* PAD0_MODE */ + 0x00008 0x1000000 /* PAD5_MODE */ + 0x0000c 0x80 /* PAD6_MODE */ + 0x000e4 0x6a545 /* MAC_POWER_SEL */ + 0x000e0 0xc74164de /* SGMII_CTRL */ + 0x0007c 0x4e /* PORT0_STATUS */ + 0x00094 0x4e /* PORT6_STATUS */ + >; + }; + + phy4: ethernet-phy@4 { + reg = <4>; + }; + }; + + gmac1: ethernet@37200000 { + status = "ok"; + phy-mode = "rgmii"; + qcom,id = <1>; + + pinctrl-0 = <&rgmii2_pins>; + pinctrl-names = "default"; + + mtd-mac-address-ascii = <&PRODUCTINFO 0x86a>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + gmac2: ethernet@37400000 { + status = "ok"; + phy-mode = "sgmii"; + qcom,id = <2>; + + mtd-mac-address-ascii = <&PRODUCTINFO 0x86a>; + mtd-mac-address-increment = <1>; + mtd-mac-address-increment-byte = <0>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + amba { + sdcc1: sdcc@12400000 { + status = "okay"; + pinctrl-0 = <&sdcc1_pins>; + pinctrl-names = "default"; + }; + }; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + usb_1 { + label = "m520:green:usb_1"; + gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; + }; + + usb_3 { + label = "m520:green:usb_3"; + gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; + }; + + status_green { + label = "m520:green:status"; + gpios = <&qcom_pinmux 9 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&adm_dma { + status = "ok"; +}; diff --git a/target/linux/ipq806x/files-4.19/arch/arm/boot/dts/qcom-ipq8064-mtfi-m520.dts b/target/linux/ipq806x/files-4.19/arch/arm/boot/dts/qcom-ipq8064-mtfi-m520.dts new file mode 100644 index 000000000..b89201e57 --- /dev/null +++ b/target/linux/ipq806x/files-4.19/arch/arm/boot/dts/qcom-ipq8064-mtfi-m520.dts @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq8064-v2.0.dtsi" + +#include + +/ { + model = "Ruijie RG-MTFi-M520"; + compatible = "ruijie,rg-mtfi-m520", "qcom,ipq8064"; + + memory@0 { + reg = <0x42000000 0x7e000000>; + device_type = "memory"; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + rsvd@41200000 { + reg = <0x41200000 0x300000>; + no-map; + }; + }; + + aliases { + serial0 = &gsbi4_serial; + mdio-gpio0 = &mdio0; + sdcc1 = &sdcc1; + }; + + chosen { + bootargs = "root=/dev/mmcblk0p3 rootfstype=squashfs,ext4 rootwait noinitrd"; + stdout-path = "serial0:115200n8"; + }; + + soc { + pinmux@800000 { + button_pins: button_pins { + mux { + pins = "gpio54"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + i2c4_pins: i2c4_pinmux { + mux { + pins = "gpio12", "gpio13"; + function = "gsbi4"; + drive-strength = <12>; + bias-disable; + }; + }; + + led_pins: led_pins { + mux { + pins = "gpio7", "gpio8", "gpio9", "gpio53"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + mdio0_pins: mdio0_pins { + mux { + pins = "gpio0", "gpio1"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + clk { + pins = "gpio1"; + input-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; + }; + + tx { + pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32"; + input-disable; + }; + }; + + sdcc1_pins: sdcc1_pinmux { + mux { + pins = "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47"; + function = "sdc1"; + }; + + cmd { + pins = "gpio45"; + drive-strength = <10>; + bias-pull-up; + }; + + data { + pins = "gpio38", "gpio39", "gpio40", "gpio41", + "gpio43", "gpio44", "gpio46", "gpio47"; + drive-strength = <10>; + bias-pull-up; + }; + + clk { + pins = "gpio42"; + drive-strength = <16>; + bias-disable; + }; + }; + + spi_pins: spi_pins { + mux { + pins = "gpio18", "gpio19", "gpio21"; + function = "gsbi5"; + drive-strength = <10>; + bias-none; + }; + + cs { + pins = "gpio20"; + drive-strength = <12>; + }; + }; + }; + + gsbi@16300000 { + qcom,mode = ; + 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 = ; + status = "ok"; + + spi4: spi@1a280000 { + status = "ok"; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + + cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; + + flash: m25p80@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <51200000>; + reg = <0>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x10000>; + read-only; + }; + + MIBIB@10000 { + label = "MIBIB"; + reg = <0x10000 0x10000>; + read-only; + }; + + SBL2@20000 { + label = "SBL2"; + reg = <0x20000 0x20000>; + read-only; + }; + + SBL3@40000 { + label = "SBL3"; + reg = <0x40000 0x30000>; + read-only; + }; + + DDRCONFIG@70000 { + label = "DDRCONFIG"; + reg = <0x70000 0x10000>; + read-only; + }; + + PRODUCTINFO: PRODUCTINFO@80000 { + label = "PRODUCTINFO"; + reg = <0x80000 0x10000>; + read-only; + }; + + TZ@90000 { + label = "TZ"; + reg = <0x90000 0x30000>; + read-only; + }; + + RPM@c0000 { + label = "RPM"; + reg = <0xc0000 0x20000>; + read-only; + }; + + APPSBL@e0000 { + label = "APPSBL"; + reg = <0xe0000 0x80000>; + read-only; + }; + + APPSBLENV@160000 { + label = "APPSBLENV"; + reg = <0x160000 0x10000>; + read-only; + }; + + BOOTCONFIG@170000 { + label = "BOOTCONFIG"; + reg = <0x170000 0x10000>; + read-only; + }; + + ART@180000 { + label = "ART"; + reg = <0x180000 0x40000>; + read-only; + }; + }; + }; + }; + + sata-phy@1b400000 { + status = "ok"; + }; + + sata@29000000 { + ports-implemented = <0x1>; + 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 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&pcie0_pins>; + pinctrl-names = "default"; + }; + + pcie1: pci@1b700000 { + status = "ok"; + reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&pcie1_pins>; + pinctrl-names = "default"; + force_gen1 = <1>; + }; + + mdio0: mdio { + compatible = "virtual,mdio-gpio"; + #address-cells = <1>; + #size-cells = <0>; + gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + + phy0: ethernet-phy@0 { + reg = <0>; + qca,ar8327-initvals = < + 0x00004 0x7600000 /* PAD0_MODE */ + 0x00008 0x1000000 /* PAD5_MODE */ + 0x0000c 0x80 /* PAD6_MODE */ + 0x000e4 0x6a545 /* MAC_POWER_SEL */ + 0x000e0 0xc74164de /* SGMII_CTRL */ + 0x0007c 0x4e /* PORT0_STATUS */ + 0x00094 0x4e /* PORT6_STATUS */ + >; + }; + + phy4: ethernet-phy@4 { + reg = <4>; + }; + }; + + gmac1: ethernet@37200000 { + status = "ok"; + phy-mode = "rgmii"; + qcom,id = <1>; + + pinctrl-0 = <&rgmii2_pins>; + pinctrl-names = "default"; + + mtd-mac-address-ascii = <&PRODUCTINFO 0x86a>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + gmac2: ethernet@37400000 { + status = "ok"; + phy-mode = "sgmii"; + qcom,id = <2>; + + mtd-mac-address-ascii = <&PRODUCTINFO 0x86a>; + mtd-mac-address-increment = <1>; + mtd-mac-address-increment-byte = <0>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + amba { + sdcc1: sdcc@12400000 { + status = "okay"; + pinctrl-0 = <&sdcc1_pins>; + pinctrl-names = "default"; + }; + }; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + usb_1 { + label = "m520:green:usb_1"; + gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; + }; + + usb_3 { + label = "m520:green:usb_3"; + gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; + }; + + status_green { + label = "m520:green:status"; + gpios = <&qcom_pinmux 9 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&adm_dma { + status = "ok"; +}; diff --git a/target/linux/ipq806x/image/Makefile b/target/linux/ipq806x/image/Makefile index e41335780..cb39da6f1 100644 --- a/target/linux/ipq806x/image/Makefile +++ b/target/linux/ipq806x/image/Makefile @@ -260,6 +260,25 @@ define Device/qcom_ipq8064-db149 endef TARGET_DEVICES += qcom_ipq8064-db149 +define Device/ruijie_rg-mtfi-m520 + DEVICE_VENDOR := Ruijie + DEVICE_MODEL := RG-MTFi-M520 + DEVICE_DTS := qcom-ipq8064-mtfi-m520 + KERNEL_SIZE := 4096k + BLOCKSIZE := 64k + BOARD_NAME := rg-mtfi-m520 + KERNEL_SUFFIX := -uImage + KERNEL = kernel-bin | append-dtb | uImage none | pad-to $${KERNEL_SIZE} + KERNEL_NAME := zImage + IMAGES := factory.bin sysupgrade.bin mmcblk0p2-kernel.bin mmcblk0p3-rootfs.bin + IMAGE/factory.bin := qsdk-ipq-factory-nor + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-to $$$${BLOCKSIZE} | sysupgrade-tar rootfs=$$$$@ | append-metadata + IMAGE/mmcblk0p2-kernel.bin := append-kernel | pad-to $$$${KERNEL_SIZE} + IMAGE/mmcblk0p3-rootfs.bin := append-rootfs | pad-rootfs + DEVICE_PACKAGES := ath10k-firmware-qca988x-ct blockd e2fsprogs f2fs-tools kmod-fs-ext4 kmod-fs-f2fs losetup +endef +TARGET_DEVICES += ruijie_rg-mtfi-m520 + define Device/tplink_c2600 $(call Device/TpSafeImage) DEVICE_VENDOR := TP-Link diff --git a/target/linux/ipq806x/patches-4.14/0069-arm-boot-add-dts-files.patch b/target/linux/ipq806x/patches-4.14/0069-arm-boot-add-dts-files.patch index 07bdd5c3f..800bba67b 100644 --- a/target/linux/ipq806x/patches-4.14/0069-arm-boot-add-dts-files.patch +++ b/target/linux/ipq806x/patches-4.14/0069-arm-boot-add-dts-files.patch @@ -10,7 +10,7 @@ Signed-off-by: John Crispin --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -699,6 +699,18 @@ dtb-$(CONFIG_ARCH_QCOM) += \ +@@ -699,6 +699,19 @@ dtb-$(CONFIG_ARCH_QCOM) += \ qcom-apq8084-mtp.dtb \ qcom-ipq4019-ap.dk01.1-c1.dtb \ qcom-ipq8064-ap148.dtb \ @@ -19,6 +19,7 @@ Signed-off-by: John Crispin + qcom-ipq8064-d7800.dtb \ + qcom-ipq8064-db149.dtb \ + qcom-ipq8064-ea8500.dtb \ ++ qcom-ipq8064-mtfi-m520.dtb \ + qcom-ipq8064-r7500.dtb \ + qcom-ipq8064-r7500v2.dtb \ + qcom-ipq8064-wg2600hp.dtb \ diff --git a/target/linux/ipq806x/patches-4.14/851-ata-add-sata-driver.patch b/target/linux/ipq806x/patches-4.14/851-ata-add-sata-driver.patch new file mode 100644 index 000000000..998e99c72 --- /dev/null +++ b/target/linux/ipq806x/patches-4.14/851-ata-add-sata-driver.patch @@ -0,0 +1,308 @@ +From c5ea64dcf7b5d45e402e78b9f291d521669b7b80 Mon Sep 17 00:00:00 2001 +From: Kumar Gala +Date: Fri, 30 May 2014 15:35:40 -0500 +Subject: [PATCH] ata: Add Qualcomm ARM SoC AHCI SATA host controller driver + +Add support for the Qualcomm AHCI SATA controller that exists on several +SoC and specifically the IPQ806x family of chips. The IPQ806x SATA support +requires the associated IPQ806x SATA PHY Driver to be enabled as well. + +Signed-off-by: Kumar Gala +Signed-off-by: Gokul Sriram Palanisamy +--- + drivers/ata/ahci.h | 2 +- + drivers/ata/ahci_ipq.c | 248 ++++++++++++++++++++++++++++++++++++++ + drivers/ata/Kconfig | 8 ++++++++ + drivers/ata/Makefile | 1 + + 4 files changed, 258 insertions(+), 1 deletions(-) + create mode 100644 drivers/ata/ahci_ipq.c + +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -54,7 +54,7 @@ + + enum { + AHCI_MAX_PORTS = 32, +- AHCI_MAX_CLKS = 5, ++ AHCI_MAX_CLKS = 6, + AHCI_MAX_SG = 168, /* hardware max is 64K */ + AHCI_DMA_BOUNDARY = 0xffffffff, + AHCI_MAX_CMDS = 32, +--- a/dev/null ++++ b/drivers/ata/ahci_ipq.c +@@ -0,0 +1,248 @@ ++/* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "libata.h" ++#include "ahci.h" ++ ++#define IPQ_DRV_NAME "ahci-ipq" ++ ++struct ipq_ahci_priv { ++ struct platform_device *ahci_pdev; ++ struct ahci_host_priv *hpriv; ++ void *preg_reset; ++ int pstate; ++}; ++ ++struct ipq_ahci_priv *ipqpriv; ++ ++static const struct ata_port_info ipq_ahci_port_info = { ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_platform_ops, ++}; ++ ++static struct scsi_host_template ahci_platform_sht = { ++ AHCI_SHT(IPQ_DRV_NAME), ++}; ++ ++#define SATA_PWR_STATE_DOWN 0x1 ++#define SATA_PWR_STATE_UP 0x2 ++#define SATA_RESET 0x00902c1c ++ ++static void ipq_ahci_hard_reset(struct device *dev) ++{ ++ u32 reg; ++ ++ reg = readl_relaxed(ipqpriv->preg_reset); ++ writel_relaxed(reg | BIT(0), ipqpriv->preg_reset); ++ /* To make sure the write is complete before we move on */ ++ mb(); ++ ++ reg = readl_relaxed(ipqpriv->preg_reset); ++ writel_relaxed(reg & (~BIT(0)), ipqpriv->preg_reset); ++ /* To make sure the write is complete before we move on */ ++ mb(); ++} ++ ++static int ipq_ahci_suspend(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct device_type *apt = &ata_port_type; ++ const struct dev_pm_ops *pm = apt->pm; ++ struct ata_port *ap; ++ int ret = 0, i; ++ ++ if (ipqpriv->pstate == SATA_PWR_STATE_UP) { ++ for (i = 0; i < host->n_ports; i++) { ++ ap = host->ports[i]; ++ /* Issue Port PM Suspend */ ++ ret = pm->runtime_suspend(&ap->tdev); ++ if (ret) { ++ dev_err(dev, "SATA controller port suspend failed\n"); ++ return ret; ++ } ++ } ++ ++ /* Issue Contoller PM Suspend */ ++ ret = ahci_platform_suspend_host(dev); ++ if (ret) { ++ dev_err(dev, "SATA controller host suspend failed\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < ipqpriv->hpriv->nports; i++) { ++ if (!ipqpriv->hpriv->phys[i]) ++ continue; ++ ++ phy_power_off(ipqpriv->hpriv->phys[i]); ++ phy_exit(ipqpriv->hpriv->phys[i]); ++ } ++ ++ ahci_platform_disable_clks(ipqpriv->hpriv); ++ ipqpriv->pstate = SATA_PWR_STATE_DOWN; ++ } else { ++ dev_warn(dev, "SATA device already in suspended state"); ++ } ++ ++ return ret; ++} ++ ++static int ipq_ahci_resume(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct device_type *apt = &ata_port_type; ++ const struct dev_pm_ops *pm = apt->pm; ++ struct ata_port *ap; ++ int ret = 0, i; ++ ++ if (ipqpriv->pstate == SATA_PWR_STATE_DOWN) { ++ ++ ahci_platform_enable_clks(ipqpriv->hpriv); ++ ++ /* Issue SATA clock hard reset */ ++ ipq_ahci_hard_reset(dev); ++ ++ for (i = 0; i < ipqpriv->hpriv->nports; i++) { ++ if (!ipqpriv->hpriv->phys[i]) ++ continue; ++ ++ phy_init(ipqpriv->hpriv->phys[i]); ++ phy_power_on(ipqpriv->hpriv->phys[i]); ++ } ++ ++ /* Issue Contoller PM Resume */ ++ ret = ahci_platform_resume_host(dev); ++ if (ret) { ++ dev_err(dev, "SATA controller resume failed\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < host->n_ports; i++) { ++ /* Issue Port PM Resume */ ++ ap = host->ports[i]; ++ ret = pm->runtime_resume(&ap->tdev); ++ if (ret) { ++ dev_err(dev, "SATA controller port resume failed\n"); ++ return ret; ++ } ++ } ++ ipqpriv->pstate = SATA_PWR_STATE_UP; ++ } else { ++ dev_warn(dev, "SATA device already in resume state"); ++ } ++ ++ return ret; ++} ++ ++static int ipq_ahci_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct ahci_host_priv *hpriv; ++ int rc; ++ ++ hpriv = ahci_platform_get_resources(pdev); ++ if (IS_ERR(hpriv)) ++ return PTR_ERR(hpriv); ++ ++ rc = ahci_platform_enable_resources(hpriv); ++ if (rc) ++ return rc; ++ ++ of_property_read_u32(dev->of_node, ++ "ports-implemented", &hpriv->force_port_map); ++ ++ rc = ahci_platform_init_host(pdev, hpriv, &ipq_ahci_port_info, ++ &ahci_platform_sht); ++ ++ if (rc) ++ goto disable_resources; ++ ++ ipqpriv = devm_kzalloc(dev, sizeof(*ipqpriv), GFP_KERNEL); ++ if (!ipqpriv) { ++ dev_err(dev, "can't alloc ahci_host_priv\n"); ++ rc = -ENOMEM; ++ goto disable_resources; ++ } ++ ++ ipqpriv->ahci_pdev = pdev; ++ ipqpriv->hpriv = hpriv; ++ ipqpriv->pstate = SATA_PWR_STATE_UP; ++ ++ ipqpriv->preg_reset = devm_ioremap(dev, SATA_RESET, ++ sizeof(*(ipqpriv->preg_reset))); ++ ++ if (IS_ERR(ipqpriv->preg_reset)) { ++ dev_err(dev, "can't ioremap for preg_reset\n"); ++ rc = -ENOMEM; ++ goto disable_resources; ++ } ++ ++ return 0; ++ ++ disable_resources: ++ ahci_platform_disable_resources(hpriv); ++ return rc; ++} ++ ++int ipq_ahci_remove(struct platform_device *pdev) ++{ ++ ata_platform_remove_one(pdev); ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(ipq_ahci_pm_ops, ahci_platform_suspend, ++ ahci_platform_resume); ++ ++static const struct of_device_id ipq_ahci_of_match[] = { ++ { .compatible = "qcom,ipq806x-ahci", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, ipq_ahci_of_match); ++ ++static const struct acpi_device_id ahci_acpi_match[] = { ++ { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); ++ ++static struct platform_driver ipq_ahci_driver = { ++ .probe = ipq_ahci_probe, ++ .remove = ipq_ahci_remove, ++ .driver = { ++ .name = IPQ_DRV_NAME, ++ .of_match_table = ipq_ahci_of_match, ++ .acpi_match_table = ahci_acpi_match, ++ .pm = &ipq_ahci_pm_ops, ++ }, ++}; ++ ++module_platform_driver(ipq_ahci_driver); ++ ++MODULE_DESCRIPTION("IPQ806x AHCI SATA platform driver"); ++MODULE_ALIAS("platform:ahci-ipq"); ++MODULE_LICENSE("Dual BSD/GPL"); +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -162,6 +162,14 @@ config AHCI_IMX + + If unsure, say N. + ++config AHCI_IPQ ++ tristate "Qualcomm Atheros IPQ806X AHCI SATA support" ++ help ++ This option enables support for the IPQ806X SoC's ++ onboard AHCI SATA. ++ ++ If unsure, say N. ++ + config AHCI_CEVA + tristate "CEVA AHCI SATA support" + depends on OF +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -18,6 +18,7 @@ + obj-$(CONFIG_AHCI_DA850) += ahci_da850.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_DM816) += ahci_dm816.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o ++obj-$(CONFIG_AHCI_IPQ) += ahci_ipq.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_MTK) += ahci_mtk.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_OCTEON) += ahci_octeon.o diff --git a/target/linux/ipq806x/patches-4.19/0069-arm-boot-add-dts-files.patch b/target/linux/ipq806x/patches-4.19/0069-arm-boot-add-dts-files.patch index 8e77e34fe..96db8c595 100644 --- a/target/linux/ipq806x/patches-4.19/0069-arm-boot-add-dts-files.patch +++ b/target/linux/ipq806x/patches-4.19/0069-arm-boot-add-dts-files.patch @@ -10,7 +10,7 @@ Signed-off-by: John Crispin --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -791,6 +791,18 @@ dtb-$(CONFIG_ARCH_QCOM) += \ +@@ -791,6 +791,19 @@ dtb-$(CONFIG_ARCH_QCOM) += \ qcom-ipq4019-ap.dk07.1-c1.dtb \ qcom-ipq4019-ap.dk07.1-c2.dtb \ qcom-ipq8064-ap148.dtb \ @@ -19,6 +19,7 @@ Signed-off-by: John Crispin + qcom-ipq8064-d7800.dtb \ + qcom-ipq8064-db149.dtb \ + qcom-ipq8064-ea8500.dtb \ ++ qcom-ipq8064-mtfi-m520.dtb \ + qcom-ipq8064-r7500.dtb \ + qcom-ipq8064-r7500v2.dtb \ + qcom-ipq8064-wg2600hp.dtb \ diff --git a/target/linux/ipq806x/patches-4.19/851-ata-add-sata-driver.patch b/target/linux/ipq806x/patches-4.19/851-ata-add-sata-driver.patch new file mode 100644 index 000000000..998e99c72 --- /dev/null +++ b/target/linux/ipq806x/patches-4.19/851-ata-add-sata-driver.patch @@ -0,0 +1,308 @@ +From c5ea64dcf7b5d45e402e78b9f291d521669b7b80 Mon Sep 17 00:00:00 2001 +From: Kumar Gala +Date: Fri, 30 May 2014 15:35:40 -0500 +Subject: [PATCH] ata: Add Qualcomm ARM SoC AHCI SATA host controller driver + +Add support for the Qualcomm AHCI SATA controller that exists on several +SoC and specifically the IPQ806x family of chips. The IPQ806x SATA support +requires the associated IPQ806x SATA PHY Driver to be enabled as well. + +Signed-off-by: Kumar Gala +Signed-off-by: Gokul Sriram Palanisamy +--- + drivers/ata/ahci.h | 2 +- + drivers/ata/ahci_ipq.c | 248 ++++++++++++++++++++++++++++++++++++++ + drivers/ata/Kconfig | 8 ++++++++ + drivers/ata/Makefile | 1 + + 4 files changed, 258 insertions(+), 1 deletions(-) + create mode 100644 drivers/ata/ahci_ipq.c + +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -54,7 +54,7 @@ + + enum { + AHCI_MAX_PORTS = 32, +- AHCI_MAX_CLKS = 5, ++ AHCI_MAX_CLKS = 6, + AHCI_MAX_SG = 168, /* hardware max is 64K */ + AHCI_DMA_BOUNDARY = 0xffffffff, + AHCI_MAX_CMDS = 32, +--- a/dev/null ++++ b/drivers/ata/ahci_ipq.c +@@ -0,0 +1,248 @@ ++/* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "libata.h" ++#include "ahci.h" ++ ++#define IPQ_DRV_NAME "ahci-ipq" ++ ++struct ipq_ahci_priv { ++ struct platform_device *ahci_pdev; ++ struct ahci_host_priv *hpriv; ++ void *preg_reset; ++ int pstate; ++}; ++ ++struct ipq_ahci_priv *ipqpriv; ++ ++static const struct ata_port_info ipq_ahci_port_info = { ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_platform_ops, ++}; ++ ++static struct scsi_host_template ahci_platform_sht = { ++ AHCI_SHT(IPQ_DRV_NAME), ++}; ++ ++#define SATA_PWR_STATE_DOWN 0x1 ++#define SATA_PWR_STATE_UP 0x2 ++#define SATA_RESET 0x00902c1c ++ ++static void ipq_ahci_hard_reset(struct device *dev) ++{ ++ u32 reg; ++ ++ reg = readl_relaxed(ipqpriv->preg_reset); ++ writel_relaxed(reg | BIT(0), ipqpriv->preg_reset); ++ /* To make sure the write is complete before we move on */ ++ mb(); ++ ++ reg = readl_relaxed(ipqpriv->preg_reset); ++ writel_relaxed(reg & (~BIT(0)), ipqpriv->preg_reset); ++ /* To make sure the write is complete before we move on */ ++ mb(); ++} ++ ++static int ipq_ahci_suspend(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct device_type *apt = &ata_port_type; ++ const struct dev_pm_ops *pm = apt->pm; ++ struct ata_port *ap; ++ int ret = 0, i; ++ ++ if (ipqpriv->pstate == SATA_PWR_STATE_UP) { ++ for (i = 0; i < host->n_ports; i++) { ++ ap = host->ports[i]; ++ /* Issue Port PM Suspend */ ++ ret = pm->runtime_suspend(&ap->tdev); ++ if (ret) { ++ dev_err(dev, "SATA controller port suspend failed\n"); ++ return ret; ++ } ++ } ++ ++ /* Issue Contoller PM Suspend */ ++ ret = ahci_platform_suspend_host(dev); ++ if (ret) { ++ dev_err(dev, "SATA controller host suspend failed\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < ipqpriv->hpriv->nports; i++) { ++ if (!ipqpriv->hpriv->phys[i]) ++ continue; ++ ++ phy_power_off(ipqpriv->hpriv->phys[i]); ++ phy_exit(ipqpriv->hpriv->phys[i]); ++ } ++ ++ ahci_platform_disable_clks(ipqpriv->hpriv); ++ ipqpriv->pstate = SATA_PWR_STATE_DOWN; ++ } else { ++ dev_warn(dev, "SATA device already in suspended state"); ++ } ++ ++ return ret; ++} ++ ++static int ipq_ahci_resume(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct device_type *apt = &ata_port_type; ++ const struct dev_pm_ops *pm = apt->pm; ++ struct ata_port *ap; ++ int ret = 0, i; ++ ++ if (ipqpriv->pstate == SATA_PWR_STATE_DOWN) { ++ ++ ahci_platform_enable_clks(ipqpriv->hpriv); ++ ++ /* Issue SATA clock hard reset */ ++ ipq_ahci_hard_reset(dev); ++ ++ for (i = 0; i < ipqpriv->hpriv->nports; i++) { ++ if (!ipqpriv->hpriv->phys[i]) ++ continue; ++ ++ phy_init(ipqpriv->hpriv->phys[i]); ++ phy_power_on(ipqpriv->hpriv->phys[i]); ++ } ++ ++ /* Issue Contoller PM Resume */ ++ ret = ahci_platform_resume_host(dev); ++ if (ret) { ++ dev_err(dev, "SATA controller resume failed\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < host->n_ports; i++) { ++ /* Issue Port PM Resume */ ++ ap = host->ports[i]; ++ ret = pm->runtime_resume(&ap->tdev); ++ if (ret) { ++ dev_err(dev, "SATA controller port resume failed\n"); ++ return ret; ++ } ++ } ++ ipqpriv->pstate = SATA_PWR_STATE_UP; ++ } else { ++ dev_warn(dev, "SATA device already in resume state"); ++ } ++ ++ return ret; ++} ++ ++static int ipq_ahci_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct ahci_host_priv *hpriv; ++ int rc; ++ ++ hpriv = ahci_platform_get_resources(pdev); ++ if (IS_ERR(hpriv)) ++ return PTR_ERR(hpriv); ++ ++ rc = ahci_platform_enable_resources(hpriv); ++ if (rc) ++ return rc; ++ ++ of_property_read_u32(dev->of_node, ++ "ports-implemented", &hpriv->force_port_map); ++ ++ rc = ahci_platform_init_host(pdev, hpriv, &ipq_ahci_port_info, ++ &ahci_platform_sht); ++ ++ if (rc) ++ goto disable_resources; ++ ++ ipqpriv = devm_kzalloc(dev, sizeof(*ipqpriv), GFP_KERNEL); ++ if (!ipqpriv) { ++ dev_err(dev, "can't alloc ahci_host_priv\n"); ++ rc = -ENOMEM; ++ goto disable_resources; ++ } ++ ++ ipqpriv->ahci_pdev = pdev; ++ ipqpriv->hpriv = hpriv; ++ ipqpriv->pstate = SATA_PWR_STATE_UP; ++ ++ ipqpriv->preg_reset = devm_ioremap(dev, SATA_RESET, ++ sizeof(*(ipqpriv->preg_reset))); ++ ++ if (IS_ERR(ipqpriv->preg_reset)) { ++ dev_err(dev, "can't ioremap for preg_reset\n"); ++ rc = -ENOMEM; ++ goto disable_resources; ++ } ++ ++ return 0; ++ ++ disable_resources: ++ ahci_platform_disable_resources(hpriv); ++ return rc; ++} ++ ++int ipq_ahci_remove(struct platform_device *pdev) ++{ ++ ata_platform_remove_one(pdev); ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(ipq_ahci_pm_ops, ahci_platform_suspend, ++ ahci_platform_resume); ++ ++static const struct of_device_id ipq_ahci_of_match[] = { ++ { .compatible = "qcom,ipq806x-ahci", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, ipq_ahci_of_match); ++ ++static const struct acpi_device_id ahci_acpi_match[] = { ++ { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); ++ ++static struct platform_driver ipq_ahci_driver = { ++ .probe = ipq_ahci_probe, ++ .remove = ipq_ahci_remove, ++ .driver = { ++ .name = IPQ_DRV_NAME, ++ .of_match_table = ipq_ahci_of_match, ++ .acpi_match_table = ahci_acpi_match, ++ .pm = &ipq_ahci_pm_ops, ++ }, ++}; ++ ++module_platform_driver(ipq_ahci_driver); ++ ++MODULE_DESCRIPTION("IPQ806x AHCI SATA platform driver"); ++MODULE_ALIAS("platform:ahci-ipq"); ++MODULE_LICENSE("Dual BSD/GPL"); +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -162,6 +162,14 @@ config AHCI_IMX + + If unsure, say N. + ++config AHCI_IPQ ++ tristate "Qualcomm Atheros IPQ806X AHCI SATA support" ++ help ++ This option enables support for the IPQ806X SoC's ++ onboard AHCI SATA. ++ ++ If unsure, say N. ++ + config AHCI_CEVA + tristate "CEVA AHCI SATA support" + depends on OF +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -18,6 +18,7 @@ + obj-$(CONFIG_AHCI_DA850) += ahci_da850.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_DM816) += ahci_dm816.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o ++obj-$(CONFIG_AHCI_IPQ) += ahci_ipq.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_MTK) += ahci_mtk.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o libahci.o libahci_platform.o + obj-$(CONFIG_AHCI_OCTEON) += ahci_octeon.o